diff options
| author | Evan Lojewski <github@meklort.com> | 2020-09-30 21:28:28 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-30 21:28:28 -0600 |
| commit | 93f10e40a087329503bf747aeccb088754b1f668 (patch) | |
| tree | d959f246af1dfc8152182f92e4d57687af2df17b /utils | |
| parent | 0608d5adf9952770c08237dcf8eb823768c013f3 (diff) | |
| download | bcm5719-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.txt | 4 | ||||
| -rw-r--r-- | utils/bcmflash/bcmflash.h | 60 | ||||
| -rw-r--r-- | utils/bcmflash/fileio.cpp | 100 | ||||
| -rw-r--r-- | utils/bcmflash/main.cpp | 677 | ||||
| -rw-r--r-- | utils/bcmflash/nvm.cpp | 110 |
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(); +} |

