summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorEvan Lojewski <github@meklort.com>2020-09-30 21:28:28 -0600
committerGitHub <noreply@github.com>2020-09-30 21:28:28 -0600
commit93f10e40a087329503bf747aeccb088754b1f668 (patch)
treed959f246af1dfc8152182f92e4d57687af2df17b /utils
parent0608d5adf9952770c08237dcf8eb823768c013f3 (diff)
downloadbcm5719-ortega-93f10e40a087329503bf747aeccb088754b1f668.tar.gz
bcm5719-ortega-93f10e40a087329503bf747aeccb088754b1f668.zip
bcmflash: Initial refactor of bcmflash to simplify code (#121)
* bcmflash: refactor stage1 dumping code. * bcmflash: refactor stage2 dumping code. * bcmflash: refactor ape, info and cd dumping code. * bcmflash: refactor io code.
Diffstat (limited to 'utils')
-rw-r--r--utils/bcmflash/CMakeLists.txt4
-rw-r--r--utils/bcmflash/bcmflash.h60
-rw-r--r--utils/bcmflash/fileio.cpp100
-rw-r--r--utils/bcmflash/main.cpp677
-rw-r--r--utils/bcmflash/nvm.cpp110
5 files changed, 574 insertions, 377 deletions
diff --git a/utils/bcmflash/CMakeLists.txt b/utils/bcmflash/CMakeLists.txt
index 38a98a8..7469c38 100644
--- a/utils/bcmflash/CMakeLists.txt
+++ b/utils/bcmflash/CMakeLists.txt
@@ -3,6 +3,10 @@ project(bcmflash)
add_definitions(-Wall -Werror)
set(SOURCES
main.cpp
+ nvm.cpp
+ fileio.cpp
+
+ bcmflash.h
)
simulator_add_executable(${PROJECT_NAME} ${SOURCES})
diff --git a/utils/bcmflash/bcmflash.h b/utils/bcmflash/bcmflash.h
new file mode 100644
index 0000000..55d71ee
--- /dev/null
+++ b/utils/bcmflash/bcmflash.h
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// @file bcmflash.h
+///
+/// @project
+///
+/// @brief Support utilities for flashing firmware.
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+/// @copyright Copyright (c) 2018-2020, Evan Lojewski
+/// @cond
+///
+/// All rights reserved.
+///
+/// Redistribution and use in source and binary forms, with or without
+/// modification, are permitted provided that the following conditions are met:
+/// 1. Redistributions of source code must retain the above copyright notice,
+/// this list of conditions and the following disclaimer.
+/// 2. Redistributions in binary form must reproduce the above copyright notice,
+/// this list of conditions and the following disclaimer in the documentation
+/// and/or other materials provided with the distribution.
+/// 3. Neither the name of the copyright holder nor the
+/// names of its contributors may be used to endorse or promote products
+/// derived from this software without specific prior written permission.
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+/// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+/// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+/// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+/// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+/// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+/// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+/// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+/// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+/// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+/// POSSIBILITY OF SUCH DAMAGE.
+/// @endcond
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef BCMFLASH_H
+#define BCMFLASH_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+bool bcmflash_nvram_read(const char *name, uint32_t *words, uint32_t num_words);
+bool bcmflash_nvram_write(const char *name, void *buffer, size_t len);
+void bcmflash_nvram_unlock(void);
+void bcmflash_nvram_recovery(void);
+
+bool bcmflash_file_read(const char *name, void *buffer, size_t len);
+bool bcmflash_file_write(const char *name, void *buffer, size_t len);
+size_t bcmflash_file_size(const char *name);
+
+#endif /* BCMFLASH_H */
diff --git a/utils/bcmflash/fileio.cpp b/utils/bcmflash/fileio.cpp
new file mode 100644
index 0000000..4030dac
--- /dev/null
+++ b/utils/bcmflash/fileio.cpp
@@ -0,0 +1,100 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// @file fileio.cpp
+///
+/// @project bcm5719-fw
+///
+/// @brief Support routines for accessing files.
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+/// @copyright Copyright (c) 2018-2020, Evan Lojewski
+/// @cond
+///
+/// All rights reserved.
+///
+/// Redistribution and use in source and binary forms, with or without
+/// modification, are permitted provided that the following conditions are met:
+/// 1. Redistributions of source code must retain the above copyright notice,
+/// this list of conditions and the following disclaimer.
+/// 2. Redistributions in binary form must reproduce the above copyright notice,
+/// this list of conditions and the following disclaimer in the documentation
+/// and/or other materials provided with the distribution.
+/// 3. Neither the name of the copyright holder nor the
+/// names of its contributors may be used to endorse or promote products
+/// derived from this software without specific prior written permission.
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+/// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+/// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+/// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+/// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+/// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+/// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+/// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+/// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+/// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+/// POSSIBILITY OF SUCH DAMAGE.
+/// @endcond
+////////////////////////////////////////////////////////////////////////////////
+
+#include "bcmflash.h"
+
+#include <fstream>
+#include <iostream>
+#include <stdio.h>
+
+using std::fstream;
+
+bool bcmflash_file_write(const char *name, void *buffer, size_t len)
+{
+ std::cout << "Writing to " << name << "." << std::endl;
+ FILE *out = fopen(name, "w+");
+ if (out)
+ {
+ fwrite(buffer, len, 1, out);
+ fclose(out);
+ return true;
+ }
+ else
+ {
+ std::cerr << "Unable to open " << name << " for writing." << std::endl;
+ return false;
+ }
+}
+
+size_t bcmflash_file_size(const char *name)
+{
+ fstream infile;
+ infile.open(name, fstream::in | fstream::binary | fstream::ate);
+
+ if (infile.is_open())
+ {
+ return infile.tellg();
+ }
+
+ return 0;
+}
+
+bool bcmflash_file_read(const char *name, void *buffer, size_t len)
+{
+ fstream infile;
+ infile.open(name, fstream::in | fstream::binary);
+
+ if (infile.is_open())
+ {
+ // Overwrite position
+ infile.read((char *)buffer, len);
+ infile.close();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
diff --git a/utils/bcmflash/main.cpp b/utils/bcmflash/main.cpp
index 2cfac87..795c891 100644
--- a/utils/bcmflash/main.cpp
+++ b/utils/bcmflash/main.cpp
@@ -2,7 +2,7 @@
///
/// @file main.cpp
///
-/// @project
+/// @project bcm5719-fw
///
/// @brief Main bcmflash tool for parsing BCM5179 flash images.
///
@@ -43,6 +43,7 @@
////////////////////////////////////////////////////////////////////////////////
#include "HAL.hpp"
+#include "bcmflash.h"
#include <../bcm5719_NVM.h>
#include <NVRam.h>
@@ -53,7 +54,6 @@
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
-#include <fstream>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -71,20 +71,245 @@
using namespace std;
using optparse::OptionParser;
-bool save_to_file(const char *filename, void *buffer, size_t size)
+uint32_t gApeLength = 0;
+uint8_t *gApe = NULL;
+uint32_t *gApeWd = NULL;
+
+void dump_stage1(NVRAMContents_t *nvram, uint8_t *stage1, size_t stage1_length)
+{
+ uint32_t *stage1_wd = (uint32_t *)stage1;
+
+ uint32_t crc_word = stage1_length / 4;
+
+ uint32_t expected_crc = be32toh(~NVRam_crc(stage1, stage1_length, 0xffffffff));
+ uint32_t phys_addr = be32toh(nvram->header.bootstrapPhysAddr);
+ uint32_t ver_addr = be32toh(stage1_wd[2]) - phys_addr;
+ const char *stage1_ver = NULL;
+ uint32_t stage1_version_num = be32toh(stage1_wd[3]);
+ uint8_t stage1_version_major = stage1_version_num >> 24;
+ uint8_t stage1_version_minor = stage1_version_num >> 16 & 0xff;
+ uint16_t stage1_version_patch = stage1_version_num & 0xffff;
+
+ stage1_ver = NULL;
+ if (ver_addr < stage1_length)
+ {
+ stage1_ver = (char *)&stage1[ver_addr];
+ }
+ else
+ {
+ stage1_ver = "Unknown";
+ }
+
+ printf("=== stage1 ===\n");
+ printf("Version: %s (version %d.%d.%d)\n", stage1_ver, stage1_version_major, stage1_version_minor, stage1_version_patch);
+ printf("Magic: 0x%08X\n", be32toh(nvram->header.magic));
+ printf("Bootstrap Phys Addr: 0x%08X\n", phys_addr);
+ printf("Length (bytes): 0x%08zX\n", stage1_length);
+ // printf("Offset: 0x%08lX\n", ((stage1_wd - nvram.words) * 4));
+ printf("Calculated CRC: 0x%08X\n", expected_crc);
+ printf("CRC: 0x%08X\n", be32toh(stage1_wd[crc_word]));
+
+ if (be32toh(nvram->header.magic) != BCM_NVRAM_MAGIC)
+ {
+ fprintf(stderr, "Error: stage1 magic is invalid.\n");
+ exit(-1);
+ }
+
+ if (be32toh(stage1_wd[crc_word]) != expected_crc)
+ {
+ fprintf(stderr, "Error: stage1 crc is invalid.\n");
+ // exit(-1);
+ }
+}
+
+void dump_stage2(NVRAMStage2_t *stage2)
+{
+ uint32_t stage2_length = be32toh(stage2->header.length); // second word is size (bytes).
+ stage2_length -= 4; // length includes crc.
+ uint32_t stage2_crc_word = stage2_length / 4;
+ printf("=== stage2 ===\n");
+ printf("Magic: 0x%08X\n", be32toh(stage2->header.magic));
+ printf("Length (bytes): 0x%08X\n", stage2_length);
+ // printf("Offset: 0x%08lX\n", ((stage2_wd - nvram.words) * 4));
+ uint32_t stage2_expected_crc = be32toh(~NVRam_crc((uint8_t *)stage2->words, stage2_length, 0xffffffff));
+ printf("Calculated CRC: 0x%08X\n", stage2_expected_crc);
+ printf("CRC: 0x%08X\n", be32toh(stage2->words[stage2_crc_word]));
+
+ if (be32toh(stage2->header.magic) != BCM_NVRAM_MAGIC)
+ {
+ fprintf(stderr, "Error: stage2 magic is invalid.\n");
+ exit(-1);
+ }
+
+ if (be32toh(stage2->words[stage2_crc_word]) != stage2_expected_crc)
+ {
+ fprintf(stderr, "Error: stage2 crc is invalid.\n");
+ exit(-1);
+ }
+}
+
+void dump_code_directory(NVRAMCodeDirectory_t *cd, uint8_t *nvram, const char *outfile)
+{
+
+ uint32_t info = be32toh(cd->codeInfo);
+ if (info)
+ {
+ printf("\n=== Directory (0x%08X)===\n", info);
+ uint32_t addr = be32toh(cd->codeAddress);
+ uint32_t length = BCM_CODE_DIRECTORY_GET_LENGTH(info);
+ uint32_t cpu = BCM_CODE_DIRECTORY_GET_CPU(info);
+ uint32_t type = BCM_CODE_DIRECTORY_GET_TYPE(info);
+
+ uint8_t *cd_loc = &nvram[be32toh(cd->directoryOffset)];
+ uint32_t crc_calc = be32toh(~NVRam_crc(cd_loc, (length - 1) * sizeof(uint32_t), 0xffffffff));
+ uint32_t crc_expect = be32toh(((uint32_t *)cd_loc)[length - 1]);
+
+ printf("Code Address: 0x%08X\n", addr);
+ printf("Code Words: 0x%08X (%ld bytes)\n", length, length * sizeof(uint32_t));
+ printf("Code Offset: 0x%08X\n", be32toh(cd->directoryOffset));
+ printf("Code CPU: 0x%02X\n", cpu);
+ printf("Code Type: 0x%02X\n", type);
+ printf("Calculated CRC: 0x%08X\n", crc_calc);
+ printf("Expected CRC: 0x%08X\n", crc_expect);
+ printf("\n");
+
+ if (BCM_CODE_DIRECTORY_ADDR_APE == addr && BCM_CODE_DIRECTORY_CPU_APE == cpu) /* APE */
+ {
+ gApe = &nvram[be32toh(cd->directoryOffset)];
+ gApeWd = (uint32_t *)gApe;
+ gApeLength = length * sizeof(uint32_t);
+ }
+
+ if (outfile)
+ {
+ if (!bcmflash_file_write(outfile, cd_loc, (length - 1) * sizeof(uint32_t)))
+ {
+ exit(-1);
+ }
+ }
+ }
+}
+
+void dump_info(NVRAMInfo_t *info, NVRAMInfo2_t *info2)
+{
+ printf("\n=== Info ===\n");
+ printf("Firmware Revision: 0x%04X\n", be16toh(info->firmwareRevision));
+
+ printf("Part Number: %s\n", info->partNumber);
+ printf("Part Revision: %c%c\n", info->partRevision[0], info->partRevision[1]);
+
+ printf("Vendor ID: 0x%04X\n", be16toh(info->vendorID));
+ printf("Device ID: 0x%04X\n", be16toh(info->deviceID));
+ printf("Subsystem Vendor ID: 0x%04X\n", be16toh(info->subsystemVendorID));
+ printf("Subsystem Device ID: 0x%04X\n", be16toh(info->subsystemDeviceID));
+ printf("Subsystem ID: 0x%04X\n", be16toh(info->subsystemDeviceID));
+
+ printf("Function 0S Subsystem ID 0x%04X\n", be16toh(info2->pciSubsystemF0SERDES));
+ printf("Function 1S Subsystem ID 0x%04X\n", be16toh(info2->pciSubsystemF1SERDES));
+ printf("Function 2S Subsystem ID 0x%04X\n", be16toh(info2->pciSubsystemF2SERDES));
+ printf("Function 3S Subsystem ID 0x%04X\n", be16toh(info2->pciSubsystemF3SERDES));
+ printf("Function 0G Subsystem ID 0x%04X\n", be16toh(info2->pciSubsystemF0GPHY));
+ printf("Function 1G Subsystem ID 0x%04X\n", be16toh(info2->pciSubsystemF1GPHY));
+ printf("Function 2G Subsystem ID 0x%04X\n", be16toh(info2->pciSubsystemF2GPHY));
+ printf("Function 3G Subsystem ID 0x%04X\n", be16toh(info2->pciSubsystemF3GPHY));
+
+ printf("Shared Cfg: 0x%08X\n", be32toh(info->cfgShared));
+
+ printf("Power Dissipated: 0x%02X 0x%02X 0x%02X 0x%02X\n", info->powerDissipatedD3, info->powerDissipatedD2, info->powerDissipatedD1,
+ info->powerDissipatedD0);
+
+ printf("Power Consumed: 0x%02X 0x%02X 0x%02X 0x%02X\n", info->powerConsumedD3, info->powerConsumedD2, info->powerConsumedD1, info->powerConsumedD0);
+
+ // Print out power budget (and translated values).
+ uint32_t pb_raw[8];
+ pb_raw[0] = be32toh(info->powerBudget0) & 0xffff;
+ pb_raw[1] = be32toh(info->powerBudget0) >> 16;
+ pb_raw[2] = be32toh(info->powerBudget1) & 0xffff;
+ pb_raw[3] = be32toh(info->powerBudget1) >> 16;
+ pb_raw[4] = be32toh(info->powerBudget2) & 0xffff;
+ pb_raw[5] = be32toh(info->powerBudget2) >> 16;
+ pb_raw[6] = be32toh(info->powerBudget3) & 0xffff;
+ pb_raw[7] = be32toh(info->powerBudget3) >> 16;
+ printf("Power Budget0: 0x%04X%04X\n", pb_raw[1], pb_raw[0]);
+ printf("Power Budget1: 0x%04X%04X\n", pb_raw[3], pb_raw[2]);
+ printf("Power Budget2: 0x%04X%04X\n", pb_raw[5], pb_raw[4]);
+ printf("Power Budget3: 0x%04X%04X\n", pb_raw[7], pb_raw[6]);
+
+ for (int i = 0; i < ARRAY_ELEMENTS(pb_raw); i++)
+ {
+ uint32_t raw = pb_raw[i];
+ RegDEVICEPciPowerBudget0_t pb0;
+ pb0.r32 = 0;
+ if (raw)
+ {
+ pb0.bits.BasePower = raw & 0xFF;
+ pb0.bits.DataScale = DEVICE_PCI_POWER_BUDGET_0_DATA_SCALE_0_1X;
+ pb0.bits.PMState = (raw & 0x0300) >> 8;
+ pb0.bits.Type = (raw & 0x1C00) >> 10;
+ pb0.bits.PowerRail = (raw & 0xE000) >> 13;
+ }
+
+ printf("Translated Power Budget[%d]: 0x%08X\n", i, (uint32_t)pb0.r32);
+ }
+
+ printf("\n=== Port 0 ===\n");
+ printf("Subsystem ID: 0x%04X\n", be16toh(info2->pciSubsystemF0GPHY));
+ printf("MAC: 0x%04X%08X\n", be32toh(info->macAddr0[0]), be32toh(info->macAddr0[1]));
+ printf("Feature: 0x%08X\n", be32toh(info->func0CfgFeature));
+ printf("Cfg: 0x%08X\n", be32toh(info->func0CfgHW));
+ printf("Cfg2: 0x%08X\n", be32toh(info2->func0CfgHW2));
+
+ printf("\n=== Port 1 ===\n");
+ printf("Subsystem ID: 0x%04X\n", be16toh(info2->pciSubsystemF1GPHY));
+ printf("MAC: 0x%04X%08X\n", be32toh(info->macAddr1[0]), be32toh(info->macAddr1[1]));
+ printf("Feature: 0x%08X\n", be32toh(info->func1CfgFeature));
+ printf("Cfg: 0x%08X\n", be32toh(info->func1CfgHW));
+ printf("Cfg2: 0x%08X\n", be32toh(info2->func1CfgHW2));
+
+ printf("\n=== Port 2 ===\n");
+ printf("Subsystem ID: 0x%04X\n", be16toh(info2->pciSubsystemF2GPHY));
+ printf("MAC: 0x%04X%08X\n", be32toh(info2->macAddr2[0]), be32toh(info2->macAddr2[1]));
+ printf("Feature: 0x%08X\n", be32toh(info2->func2CfgFeature));
+ printf("Cfg: 0x%08X\n", be32toh(info2->func2CfgHW));
+ printf("Cfg2: 0x%08X\n", be32toh(info2->func2CfgHW2));
+
+ printf("\n=== Port 3 ===\n");
+ printf("Subsystem ID: 0x%04X\n", be16toh(info2->pciSubsystemF3GPHY));
+ printf("MAC: 0x%04X%08X\n", be32toh(info2->macAddr3[0]), be32toh(info2->macAddr3[1]));
+ printf("Feature: 0x%08X\n", be32toh(info2->func3CfgFeature));
+ printf("Cfg: 0x%08X\n", be32toh(info2->func3CfgHW));
+ printf("Cfg2: 0x%08X\n", be32toh(info2->func3CfgHW2));
+}
+
+void dump_vpd(uint8_t *vpd, size_t vpd_len)
{
- cout << "Writing to " << filename << "." << endl;
- FILE *out = fopen(filename, "w+");
- if (out)
+ printf("\n=== VPD ===\n");
+ if (vpd_is_valid(vpd, vpd_len))
{
- fwrite(buffer, size, 1, out);
- fclose(out);
- return true;
+ uint32_t len = vpd_len;
+ printf("Identifier: %s\n", vpd_get_identifier(vpd, &len));
+
+ uint8_t *resource;
+ int index = 0;
+ do
+ {
+ len = vpd_len;
+ uint16_t name;
+ resource = vpd_get_resource_by_index(vpd, &len, &name, index);
+ if (resource)
+ {
+ char *data = (char *)malloc(len + 1);
+ memcpy(data, resource, len);
+ data[len] = 0;
+ printf("[%c%c] %24s: %s\n", name & 0xff, name >> 8, vpd_get_field_name(name), data);
+ free(data);
+ }
+ index++;
+ } while (resource);
}
else
{
- cerr << "Unable to open " << filename << " for writing." << endl;
- return false;
+ printf("VPD is invalid.\n");
}
}
@@ -101,10 +326,6 @@ int main(int argc, char const *argv[])
NVRAMContents_t contents;
} nvram;
- uint32_t ape_length = 0;
- uint8_t *ape = NULL;
- uint32_t *ape_wd = NULL;
-
uint8_t *stage1 = NULL;
uint32_t *stage1_wd = NULL;
@@ -163,15 +384,7 @@ int main(int argc, char const *argv[])
exit(-1);
}
- fstream infile;
- infile.open(options["filename"], fstream::in | fstream::binary);
- if (infile.is_open())
- {
- infile.read((char *)nvram.bytes, NVRAM_SIZE);
-
- infile.close();
- }
- else
+ if (!bcmflash_file_read(options["filename"].c_str(), nvram.bytes, NVRAM_SIZE))
{
cerr << " Unable to open file '" << options["filename"] << "'" << endl;
exit(-1);
@@ -189,42 +402,17 @@ int main(int argc, char const *argv[])
if (options.get("recovery"))
{
- NVRam_acquireLock();
- NVRam_disable();
- // Value pulled form the talos / blackbird. Update as needed.
- uint32_t cfg1 = 0x14080f3;
- uint32_t cfg2 = 0xd70081;
- uint32_t cfg3 = 0x3000a00;
- uint32_t sense = 0x30030;
- printf("Updating NvmCfg1 from %x to %x.\n", (uint32_t)NVM.NvmCfg1.r32, cfg1);
- printf("Updating NvmCfg2 from %x to %x.\n", (uint32_t)NVM.NvmCfg2.r32, cfg2);
- printf("Updating NvmCfg3 from %x to %x.\n", (uint32_t)NVM.NvmCfg3.r32, cfg3);
- printf("Updating AutoSenseStatus from %x to %x.\n", (uint32_t)NVM.AutoSenseStatus.r32, sense);
- NVM.NvmCfg1.r32 = cfg1;
- NVM.NvmCfg2.r32 = cfg2;
- NVM.NvmCfg3.r32 = cfg3;
- NVM.AutoSenseStatus.r32 = sense;
-
- NVRam_releaseLock();
+ bcmflash_nvram_recovery();
exit(0);
}
if (options.get("unlock"))
{
- NVM.SoftwareArbitration.bits.ReqClr0 = 1;
- NVM.SoftwareArbitration.bits.ReqClr1 = 1;
- NVM.SoftwareArbitration.bits.ReqClr2 = 1;
- NVM.SoftwareArbitration.bits.ReqClr3 = 1;
+ bcmflash_nvram_unlock();
}
- NVRam_acquireLock();
-
- NVRam_enable();
-
- NVRam_read(0, nvram.words, NVRAM_SIZE / 4);
-
- NVRam_releaseLock();
+ bcmflash_nvram_read("nvram", nvram.words, NVRAM_SIZE / 4);
}
else
{
@@ -235,15 +423,7 @@ int main(int argc, char const *argv[])
if (options.is_set("restore"))
{
- fstream restoreFile;
- restoreFile.open(options["restore"], fstream::in | fstream::binary);
- if (restoreFile.is_open())
- {
- restoreFile.read((char *)nvram.bytes, NVRAM_SIZE);
-
- restoreFile.close();
- }
- else
+ if (!bcmflash_file_read(options["restore"].c_str(), nvram.bytes, NVRAM_SIZE))
{
cerr << " Unable to open file '" << options["restore"] << "'" << endl;
exit(-1);
@@ -252,16 +432,7 @@ int main(int argc, char const *argv[])
if ("hardware" == options["target"])
{
cout << "Restoring from " << options["restore"] << " to hardware." << endl;
- NVRam_acquireLock();
-
- NVRam_enable();
- NVRam_enableWrites();
-
- NVRam_write(0, nvram.words, NVRAM_SIZE / 4);
-
- NVRam_disableWrites();
-
- NVRam_releaseLock();
+ bcmflash_nvram_write("nvram", nvram.words, NVRAM_SIZE);
}
else
{
@@ -274,7 +445,7 @@ int main(int argc, char const *argv[])
if ("binary" == options["backup"])
{
// Save to file.
- if (!save_to_file("firmware.fw", nvram.bytes, NVRAM_SIZE))
+ if (!bcmflash_file_write("firmware.fw", nvram.bytes, NVRAM_SIZE))
{
exit(-1);
}
@@ -294,52 +465,14 @@ int main(int argc, char const *argv[])
stage1 = &nvram.bytes[be32toh(nvram.contents.header.bootstrapOffset)];
stage1_wd = &nvram.words[be32toh(nvram.contents.header.bootstrapOffset) / 4];
size_t stage1_length = (be32toh(nvram.contents.header.bootstrapWords) * 4) - 4; // last word is CRC
-
uint32_t crc_word = stage1_length / 4;
- uint32_t expected_crc = be32toh(~NVRam_crc(stage1, stage1_length, 0xffffffff));
- uint32_t phys_addr = be32toh(nvram.contents.header.bootstrapPhysAddr);
- uint32_t ver_addr = be32toh(stage1_wd[2]) - phys_addr;
- const char *stage1_ver = NULL;
- uint32_t stage1_version_num = be32toh(stage1_wd[3]);
- uint8_t stage1_version_major = stage1_version_num >> 24;
- uint8_t stage1_version_minor = stage1_version_num >> 16 & 0xff;
- uint16_t stage1_version_patch = stage1_version_num & 0xffff;
-
- if (ver_addr < stage1_length)
- {
- stage1_ver = (char *)&stage1[ver_addr];
- }
- else
- {
- stage1_ver = "Unknown";
- }
-
- printf("=== stage1 ===\n");
- printf("Version: %s (version %d.%d.%d)\n", stage1_ver, stage1_version_major, stage1_version_minor, stage1_version_patch);
- printf("Magic: 0x%08X\n", be32toh(nvram.contents.header.magic));
- printf("Bootstrap Phys Addr: 0x%08X\n", phys_addr);
- printf("Length (bytes): 0x%08zX\n", stage1_length);
- printf("Offset: 0x%08lX\n", ((stage1_wd - nvram.words) * 4));
- printf("Calculated CRC: 0x%08X\n", expected_crc);
- printf("CRC: 0x%08X\n", be32toh(stage1_wd[crc_word]));
-
- if (be32toh(nvram.contents.header.magic) != BCM_NVRAM_MAGIC)
- {
- fprintf(stderr, "Error: stage1 magic is invalid.\n");
- exit(-1);
- }
-
- if (be32toh(stage1_wd[crc_word]) != expected_crc)
- {
- fprintf(stderr, "Error: stage1 crc is invalid.\n");
- // exit(-1);
- }
+ dump_stage1(&nvram.contents, stage1, stage1_length);
if (extract)
{
- if (!save_to_file("stage1.bin", stage1, stage1_length))
+ if (!bcmflash_file_write("stage1.bin", stage1, stage1_length))
{
exit(-1);
}
@@ -350,98 +483,52 @@ int main(int argc, char const *argv[])
const char *stage1_file = options["stage1"].c_str();
printf("Updating stage1 with contents of file %s\n", stage1_file);
- fstream infile;
- infile.open(stage1_file, fstream::in | fstream::binary | fstream::ate);
+ uint32_t new_stage1_length = bcmflash_file_size(stage1_file);
- if (infile.is_open())
+ if (0 == new_stage1_length)
+ {
+ cerr << " Unable to open file '" << options["stage1"] << "'" << endl;
+ exit(-1);
+ }
+ else if (new_stage1_length > stage1_length)
+ {
+ cerr << "Length is longer than original, currently unable to update." << endl;
+ exit(-1);
+ }
+ else
{
- uint32_t new_stage1_length = infile.tellg();
- infile.seekg(0);
+ bcmflash_file_read(stage1_file, stage1, new_stage1_length);
- if (new_stage1_length > stage1_length)
- {
- cerr << "Length is longer than original, currently unable to update." << endl;
- exit(-1);
- }
- else
+ while (new_stage1_length < stage1_length)
{
- // Overwrite position
- infile.read((char *)stage1, new_stage1_length);
- infile.close();
-
- while (new_stage1_length < stage1_length)
- {
- // erase remaining bytes.
- stage1[new_stage1_length] = 0xFF;
- new_stage1_length++;
- }
+ // erase remaining bytes.
+ stage1[new_stage1_length] = 0xFF;
+ new_stage1_length++;
}
uint32_t new_crc = be32toh(~NVRam_crc(stage1, new_stage1_length, 0xffffffff));
printf("New CRC: 0x%08X\n", new_crc);
printf("New Length (bytes): 0x%08X\n", new_stage1_length);
- // Determine new version
- stage1_version_num = be32toh(stage1_wd[3]);
- stage1_version_major = stage1_version_num >> 24;
- stage1_version_minor = stage1_version_num >> 16 & 0xff;
- stage1_version_patch = stage1_version_num & 0xffff;
- phys_addr = be32toh(nvram.contents.header.bootstrapPhysAddr);
- ver_addr = be32toh(stage1_wd[2]) - phys_addr;
- stage1_ver = NULL;
- if (ver_addr < stage1_length)
- {
- stage1_ver = (char *)&stage1[ver_addr];
- }
- else
- {
- stage1_ver = "Unknown";
- }
- printf("New Version: %s (version %d.%d.%d)\n", stage1_ver, stage1_version_major, stage1_version_minor, stage1_version_patch);
-
// Update the CRC in the file copy.
stage1_wd[crc_word] = htobe32(new_crc);
- // TODO: update length (if changed);
+ dump_stage1(&nvram.contents, stage1, new_stage1_length);
should_write = true;
}
- else
- {
- cerr << " Unable to open file '" << options["stage1"] << "'" << endl;
- exit(-1);
- }
}
uint32_t *stage2_wd = &stage1_wd[(crc_word + 1)]; // immediately after stage1 crc
NVRAMStage2_t *stage2 = (NVRAMStage2_t *)stage2_wd;
-
uint32_t stage2_length = be32toh(stage2->header.length); // second word is size (bytes).
stage2_length -= 4; // length includes crc.
- uint32_t stage2_crc_word = stage2_length / 4;
- printf("=== stage2 ===\n");
- printf("Magic: 0x%08X\n", be32toh(stage2->header.magic));
- printf("Length (bytes): 0x%08X\n", stage2_length);
- printf("Offset: 0x%08lX\n", ((stage2_wd - nvram.words) * 4));
- uint32_t stage2_expected_crc = be32toh(~NVRam_crc((uint8_t *)stage2->words, stage2_length, 0xffffffff));
- printf("Calculated CRC: 0x%08X\n", stage2_expected_crc);
- printf("CRC: 0x%08X\n", be32toh(stage2->words[stage2_crc_word]));
-
- if (be32toh(stage2->header.magic) != BCM_NVRAM_MAGIC)
- {
- fprintf(stderr, "Error: stage2 magic is invalid.\n");
- exit(-1);
- }
- if (be32toh(stage2->words[stage2_crc_word]) != stage2_expected_crc)
- {
- fprintf(stderr, "Error: stage2 crc is invalid.\n");
- exit(-1);
- }
+ dump_stage2(stage2);
if (extract)
{
- if (!save_to_file("stage2.bin", stage2->words, stage2_length))
+ if (!bcmflash_file_write("stage2.bin", stage2->words, stage2_length))
{
exit(-1);
}
@@ -449,52 +536,20 @@ int main(int argc, char const *argv[])
for (int i = 0; i < ARRAY_ELEMENTS(nvram.contents.directory); i++)
{
- uint32_t info = be32toh(nvram.contents.directory[i].codeInfo);
- if (info)
+ char *cd_name = NULL;
+ if (extract)
{
- printf("\n=== Directory %d (0x%08X)===\n", i, info);
- uint32_t addr = be32toh(nvram.contents.directory[i].codeAddress);
- uint32_t length = BCM_CODE_DIRECTORY_GET_LENGTH(info);
- uint32_t cpu = BCM_CODE_DIRECTORY_GET_CPU(info);
- uint32_t type = BCM_CODE_DIRECTORY_GET_TYPE(info);
-
- uint8_t *cd_loc = &nvram.bytes[be32toh(nvram.contents.directory[i].directoryOffset)];
- uint32_t crc_calc = be32toh(~NVRam_crc(cd_loc, (length - 1) * sizeof(uint32_t), 0xffffffff));
- uint32_t crc_expect = be32toh(((uint32_t *)cd_loc)[length - 1]);
-
- printf("Code Address: 0x%08X\n", addr);
- printf("Code Words: 0x%08X (%ld bytes)\n", length, length * sizeof(uint32_t));
- printf("Code Offset: 0x%08X\n", be32toh(nvram.contents.directory[i].directoryOffset));
- printf("Code CPU: 0x%02X\n", cpu);
- printf("Code Type: 0x%02X\n", type);
- printf("Calculated CRC: 0x%08X\n", crc_calc);
- printf("Expected CRC: 0x%08X\n", crc_expect);
- printf("\n");
-
- if (BCM_CODE_DIRECTORY_ADDR_APE == addr && BCM_CODE_DIRECTORY_CPU_APE == cpu) /* APE */
- {
- ape = &nvram.bytes[be32toh(nvram.contents.directory[i].directoryOffset)];
- ape_wd = &nvram.words[be32toh(nvram.contents.directory[i].directoryOffset) / 4];
- ape_length = length * sizeof(uint32_t);
- }
-
- if (extract)
- {
- uint8_t *cd_loc = &nvram.bytes[be32toh(nvram.contents.directory[i].directoryOffset)];
- char *cd_name = strdup("cdN.bin");
- cd_name[2] = '0' + i;
- if (!save_to_file(cd_name, cd_loc, (length - 1) * sizeof(uint32_t)))
- {
- exit(-1);
- }
- free(cd_name);
- }
+ cd_name = strdup("cdN.bin");
+ cd_name[2] = '0' + i;
}
+
+ dump_code_directory(&nvram.contents.directory[i], nvram.bytes, cd_name);
+ free(cd_name);
}
if (options.is_set("ape"))
{
- if (NULL == ape)
+ if (NULL == gApe)
{
fprintf(stderr, "Original APE entry was not found in firmware header.");
exit(-1);
@@ -502,62 +557,53 @@ int main(int argc, char const *argv[])
const char *ape_file = options["ape"].c_str();
printf("Updating ape with contents of file %s\n", ape_file);
- fstream infile;
- infile.open(ape_file, fstream::in | fstream::binary | fstream::ate);
+ uint32_t new_ape_length = bcmflash_file_size(ape_file);
- if (infile.is_open())
+ if (0 == new_ape_length)
+ {
+ cerr << " Unable to open file '" << options["ape"] << "'" << endl;
+ exit(-1);
+ }
+ else if (new_ape_length + sizeof(uint32_t) > gApeLength)
{
- uint32_t new_ape_length = infile.tellg();
+ cerr << "Length is longer than original, currently unable to update." << endl;
+ exit(-1);
+ }
+ else
+ {
+ bcmflash_file_read(ape_file, (char *)gApe, new_ape_length);
new_ape_length += sizeof(uint32_t); /* CRC */
- infile.seekg(0);
- if (new_ape_length > ape_length)
+#if 0
+ // Erase the previous APE image
+ while(new_ape_length < ape_length)
{
- cerr << "Length is longer than original, currently unable to update." << endl;
- exit(-1);
+ // erase remaining bytes.
+ ape[new_ape_length] = 0xFF;
+ new_ape_length++;
}
- else
- {
- // Overwrite position
- infile.read((char *)ape, new_ape_length);
- infile.close();
-
-#if 0
- // Erase the previous APE image
- while(new_ape_length < ape_length)
- {
- // erase remaining bytes.
- ape[new_ape_length] = 0xFF;
- new_ape_length++;
- }
#endif
- }
- if (ape_wd[0] == APE_HEADER_MAGIC)
+ if (gApeWd[0] == APE_HEADER_MAGIC)
{
// Ensure everything is in the correct endianness.
for (int i = 0; i < (new_ape_length - 4) / 4; i++)
{
- ape_wd[i] = be32toh(ape_wd[i]);
+ gApeWd[i] = be32toh(gApeWd[i]);
}
}
- uint32_t new_ape_crc = be32toh(~NVRam_crc(ape, ape_length - sizeof(uint32_t), 0xffffffff));
+ uint32_t new_ape_crc = be32toh(~NVRam_crc(gApe, gApeLength - sizeof(uint32_t), 0xffffffff));
printf("New Length (bytes): 0x%08X\n", new_ape_length);
printf("New CRC: 0x%08X\n", new_ape_crc);
- uint32_t *crc_loc = (uint32_t *)&ape[ape_length - sizeof(uint32_t)];
+ uint32_t *crc_loc = (uint32_t *)&gApe[gApeLength - sizeof(uint32_t)];
*crc_loc = htobe32(new_ape_crc);
// TODO: update length (if changed);
should_write = true;
}
- else
- {
- cerr << " Unable to open file '" << options["ape"] << "'" << endl;
- exit(-1);
- }
}
if (should_write)
@@ -565,145 +611,22 @@ int main(int argc, char const *argv[])
if ("file" == options["target"])
{
// write update file.
- if (!save_to_file(options["filename"].c_str(), (char *)nvram.bytes, NVRAM_SIZE))
+ if (!bcmflash_file_write(options["filename"].c_str(), (char *)nvram.bytes, NVRAM_SIZE))
{
exit(-1);
}
}
else if ("hardware" == options["target"])
{
- NVRam_acquireLock();
-
- NVRam_enable();
- NVRam_enableWrites();
-
- NVRam_write(0, nvram.words, NVRAM_SIZE / 4);
-
- NVRam_disableWrites();
-
- NVRam_releaseLock();
+ bcmflash_nvram_write("nvram", nvram.words, NVRAM_SIZE);
}
exit(0);
}
- printf("\n=== Info ===\n");
- printf("Firmware Revision: 0x%04X\n", be16toh(nvram.contents.info.firmwareRevision));
-
- printf("Part Number: %s\n", nvram.contents.info.partNumber);
- printf("Part Revision: %c%c\n", nvram.contents.info.partRevision[0], nvram.contents.info.partRevision[1]);
-
- printf("Vendor ID: 0x%04X\n", be16toh(nvram.contents.info.vendorID));
- printf("Device ID: 0x%04X\n", be16toh(nvram.contents.info.deviceID));
- printf("Subsystem Vendor ID: 0x%04X\n", be16toh(nvram.contents.info.subsystemVendorID));
- printf("Subsystem Device ID: 0x%04X\n", be16toh(nvram.contents.info.subsystemDeviceID));
- printf("Subsystem ID: 0x%04X\n", be16toh(nvram.contents.info.subsystemDeviceID));
-
- printf("Function 0S Subsystem ID 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF0SERDES));
- printf("Function 1S Subsystem ID 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF1SERDES));
- printf("Function 2S Subsystem ID 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF2SERDES));
- printf("Function 3S Subsystem ID 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF3SERDES));
- printf("Function 0G Subsystem ID 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF0GPHY));
- printf("Function 1G Subsystem ID 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF1GPHY));
- printf("Function 2G Subsystem ID 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF2GPHY));
- printf("Function 3G Subsystem ID 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF3GPHY));
-
- printf("Shared Cfg: 0x%08X\n", be32toh(nvram.contents.info.cfgShared));
-
- printf("Power Dissipated: 0x%02X 0x%02X 0x%02X 0x%02X\n", nvram.contents.info.powerDissipatedD3, nvram.contents.info.powerDissipatedD2,
- nvram.contents.info.powerDissipatedD1, nvram.contents.info.powerDissipatedD0);
-
- printf("Power Consumed: 0x%02X 0x%02X 0x%02X 0x%02X\n", nvram.contents.info.powerConsumedD3, nvram.contents.info.powerConsumedD2,
- nvram.contents.info.powerConsumedD1, nvram.contents.info.powerConsumedD0);
-
- // Print out power budget (and translated values).
- uint32_t pb_raw[8];
- pb_raw[0] = be32toh(nvram.contents.info.powerBudget0) & 0xffff;
- pb_raw[1] = be32toh(nvram.contents.info.powerBudget0) >> 16;
- pb_raw[2] = be32toh(nvram.contents.info.powerBudget1) & 0xffff;
- pb_raw[3] = be32toh(nvram.contents.info.powerBudget1) >> 16;
- pb_raw[4] = be32toh(nvram.contents.info.powerBudget2) & 0xffff;
- pb_raw[5] = be32toh(nvram.contents.info.powerBudget2) >> 16;
- pb_raw[6] = be32toh(nvram.contents.info.powerBudget3) & 0xffff;
- pb_raw[7] = be32toh(nvram.contents.info.powerBudget3) >> 16;
- printf("Power Budget0: 0x%04X%04X\n", pb_raw[1], pb_raw[0]);
- printf("Power Budget1: 0x%04X%04X\n", pb_raw[3], pb_raw[2]);
- printf("Power Budget2: 0x%04X%04X\n", pb_raw[5], pb_raw[4]);
- printf("Power Budget3: 0x%04X%04X\n", pb_raw[7], pb_raw[6]);
-
- for (int i = 0; i < ARRAY_ELEMENTS(pb_raw); i++)
- {
- uint32_t raw = pb_raw[i];
- RegDEVICEPciPowerBudget0_t pb0;
- pb0.r32 = 0;
- if (raw)
- {
- pb0.bits.BasePower = raw & 0xFF;
- pb0.bits.DataScale = DEVICE_PCI_POWER_BUDGET_0_DATA_SCALE_0_1X;
- pb0.bits.PMState = (raw & 0x0300) >> 8;
- pb0.bits.Type = (raw & 0x1C00) >> 10;
- pb0.bits.PowerRail = (raw & 0xE000) >> 13;
- }
-
- printf("Translated Power Budget[%d]: 0x%08X\n", i, (uint32_t)pb0.r32);
- }
-
- printf("\n=== Port 0 ===\n");
- printf("Subsystem ID: 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF0GPHY));
- printf("MAC: 0x%04X%08X\n", be32toh(nvram.contents.info.macAddr0[0]), be32toh(nvram.contents.info.macAddr0[1]));
- printf("Feature: 0x%08X\n", be32toh(nvram.contents.info.func0CfgFeature));
- printf("Cfg: 0x%08X\n", be32toh(nvram.contents.info.func0CfgHW));
- printf("Cfg2: 0x%08X\n", be32toh(nvram.contents.info2.func0CfgHW2));
-
- printf("\n=== Port 1 ===\n");
- printf("Subsystem ID: 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF1GPHY));
- printf("MAC: 0x%04X%08X\n", be32toh(nvram.contents.info.macAddr1[0]), be32toh(nvram.contents.info.macAddr1[1]));
- printf("Feature: 0x%08X\n", be32toh(nvram.contents.info.func1CfgFeature));
- printf("Cfg: 0x%08X\n", be32toh(nvram.contents.info.func1CfgHW));
- printf("Cfg2: 0x%08X\n", be32toh(nvram.contents.info2.func1CfgHW2));
-
- printf("\n=== Port 2 ===\n");
- printf("Subsystem ID: 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF2GPHY));
- printf("MAC: 0x%04X%08X\n", be32toh(nvram.contents.info2.macAddr2[0]), be32toh(nvram.contents.info2.macAddr2[1]));
- printf("Feature: 0x%08X\n", be32toh(nvram.contents.info2.func2CfgFeature));
- printf("Cfg: 0x%08X\n", be32toh(nvram.contents.info2.func2CfgHW));
- printf("Cfg2: 0x%08X\n", be32toh(nvram.contents.info2.func2CfgHW2));
-
- printf("\n=== Port 3 ===\n");
- printf("Subsystem ID: 0x%04X\n", be16toh(nvram.contents.info2.pciSubsystemF3GPHY));
- printf("MAC: 0x%04X%08X\n", be32toh(nvram.contents.info2.macAddr3[0]), be32toh(nvram.contents.info2.macAddr3[1]));
- printf("Feature: 0x%08X\n", be32toh(nvram.contents.info2.func3CfgFeature));
- printf("Cfg: 0x%08X\n", be32toh(nvram.contents.info2.func3CfgHW));
- printf("Cfg2: 0x%08X\n", be32toh(nvram.contents.info2.func3CfgHW2));
-
- printf("\n=== VPD ===\n");
- if (vpd_is_valid(nvram.contents.vpd.bytes, sizeof(nvram.contents.vpd)))
- {
- uint32_t vpd_len = sizeof(nvram.contents.vpd);
- printf("Identifier: %s\n", vpd_get_identifier(nvram.contents.vpd.bytes, &vpd_len));
+ dump_info(&nvram.contents.info, &nvram.contents.info2);
- uint8_t *resource;
- int index = 0;
- do
- {
- vpd_len = sizeof(nvram.contents.vpd);
- uint16_t name;
- resource = vpd_get_resource_by_index(nvram.contents.vpd.bytes, &vpd_len, &name, index);
- if (resource)
- {
- char *data = (char *)malloc(vpd_len + 1);
- memcpy(data, resource, vpd_len);
- data[vpd_len] = 0;
- printf("[%c%c] %24s: %s\n", name & 0xff, name >> 8, vpd_get_field_name(name), data);
- free(data);
- }
- index++;
- } while (resource);
- }
- else
- {
- printf("VPD is invalid.\n");
- }
+ dump_vpd(nvram.contents.vpd.bytes, sizeof(nvram.contents.vpd));
return 0;
}
diff --git a/utils/bcmflash/nvm.cpp b/utils/bcmflash/nvm.cpp
new file mode 100644
index 0000000..f6e8cb6
--- /dev/null
+++ b/utils/bcmflash/nvm.cpp
@@ -0,0 +1,110 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// @file nvm.cpp
+///
+/// @project bcm5719-fw
+///
+/// @brief Support routines for accessing nvm.
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+/// @copyright Copyright (c) 2018-2020, Evan Lojewski
+/// @cond
+///
+/// All rights reserved.
+///
+/// Redistribution and use in source and binary forms, with or without
+/// modification, are permitted provided that the following conditions are met:
+/// 1. Redistributions of source code must retain the above copyright notice,
+/// this list of conditions and the following disclaimer.
+/// 2. Redistributions in binary form must reproduce the above copyright notice,
+/// this list of conditions and the following disclaimer in the documentation
+/// and/or other materials provided with the distribution.
+/// 3. Neither the name of the copyright holder nor the
+/// names of its contributors may be used to endorse or promote products
+/// derived from this software without specific prior written permission.
+///
+////////////////////////////////////////////////////////////////////////////////
+///
+/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+/// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+/// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+/// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+/// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+/// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+/// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+/// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+/// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+/// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+/// POSSIBILITY OF SUCH DAMAGE.
+/// @endcond
+////////////////////////////////////////////////////////////////////////////////
+#include "bcmflash.h"
+
+#include <../bcm5719_NVM.h>
+#include <NVRam.h>
+
+bool bcmflash_nvram_read(const char *name, uint32_t *words, uint32_t num_words)
+{
+ NVRam_acquireLock();
+
+ NVRam_enable();
+
+ NVRam_read(0, words, num_words);
+
+ NVRam_releaseLock();
+
+ return true;
+}
+
+bool bcmflash_nvram_write(const char *name, void *buffer, size_t len)
+{
+ (void)name;
+
+ uint32_t *words = (uint32_t *)buffer;
+ uint32_t num_words = len / 4;
+
+ NVRam_acquireLock();
+
+ NVRam_enable();
+ NVRam_enableWrites();
+
+ NVRam_write(0, words, num_words);
+
+ NVRam_disableWrites();
+
+ NVRam_releaseLock();
+
+ return true;
+}
+
+void bcmflash_nvram_unlock(void)
+{
+ NVM.SoftwareArbitration.bits.ReqClr0 = 1;
+ NVM.SoftwareArbitration.bits.ReqClr1 = 1;
+ NVM.SoftwareArbitration.bits.ReqClr2 = 1;
+ NVM.SoftwareArbitration.bits.ReqClr3 = 1;
+}
+
+void bcmflash_nvram_recovery(void)
+{
+ NVRam_acquireLock();
+ NVRam_disable();
+ // Value pulled form the talos / blackbird. Update as needed.
+ uint32_t cfg1 = 0x14080f3;
+ uint32_t cfg2 = 0xd70081;
+ uint32_t cfg3 = 0x3000a00;
+ uint32_t sense = 0x30030;
+ printf("Updating NvmCfg1 from %x to %x.\n", (uint32_t)NVM.NvmCfg1.r32, cfg1);
+ printf("Updating NvmCfg2 from %x to %x.\n", (uint32_t)NVM.NvmCfg2.r32, cfg2);
+ printf("Updating NvmCfg3 from %x to %x.\n", (uint32_t)NVM.NvmCfg3.r32, cfg3);
+ printf("Updating AutoSenseStatus from %x to %x.\n", (uint32_t)NVM.AutoSenseStatus.r32, sense);
+ NVM.NvmCfg1.r32 = cfg1;
+ NVM.NvmCfg2.r32 = cfg2;
+ NVM.NvmCfg3.r32 = cfg3;
+ NVM.AutoSenseStatus.r32 = sense;
+
+ NVRam_releaseLock();
+}
OpenPOWER on IntegriCloud