diff options
Diffstat (limited to 'src/usr/isteps/nvdimm/nvdimm_update.C')
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm_update.C | 687 |
1 files changed, 589 insertions, 98 deletions
diff --git a/src/usr/isteps/nvdimm/nvdimm_update.C b/src/usr/isteps/nvdimm/nvdimm_update.C index 2e1f61c8c..6075a660f 100644 --- a/src/usr/isteps/nvdimm/nvdimm_update.C +++ b/src/usr/isteps/nvdimm/nvdimm_update.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018,2019 */ +/* Contributors Listed Below - COPYRIGHT 2018,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -26,6 +26,7 @@ #include "nvdimm.H" #include <isteps/nvdimm/nvdimm.H> #include <isteps/nvdimm/nvdimmreasoncodes.H> +#include "bpm_update.H" #include <initservice/istepdispatcherif.H> // sendProgressCode #include <util/utilmclmgr.H> // secure LID manager @@ -33,6 +34,7 @@ #include <devicefw/userif.H> #include <vpd/spdenums.H> #include <sys/time.h> +#include <vector> // Unique tracing for nvdimm update process const char NVDIMM_UPD[] = "NVDIMM_UPD"; @@ -41,7 +43,7 @@ TRAC_INIT(&g_trac_nvdimm_upd, NVDIMM_UPD, 2*KILOBYTE); // Easy macro replace for unit testing -// #define TRACUCOMP(args...) TRACFCOMP(args) +//#define TRACUCOMP(args...) TRACFCOMP(args) #define TRACUCOMP(args...) namespace NVDIMM @@ -144,8 +146,10 @@ typedef union { } nvdimm_cmd_status0_t; // A code update block is composed of this many bytes -const uint8_t BYTES_PER_BLOCK = 32; +constexpr uint8_t BYTES_PER_BLOCK = 32; +// Maximum allowed region write retries +constexpr uint8_t MAX_REGION_WRITE_RETRY_ATTEMPTS = 3; /////////////////////////////////////////////////////////////////////////////// // NVDIMM LID Image @@ -182,6 +186,7 @@ uint16_t NvdimmLidImage::getVersion() return o_version; } + const uint8_t * NvdimmLidImage::getHeaderAndSmartSignature(uint16_t & o_size) { o_size = 0; @@ -264,7 +269,10 @@ NvdimmInstalledImage::NvdimmInstalledImage(TARGETING::Target * i_nvDimm) : iv_dimm(i_nvDimm), iv_version(INVALID_VERSION), iv_manufacturer_id(INVALID_ID), iv_product_id(INVALID_ID), iv_timeout(INVALID_TIMEOUT), - iv_max_blocks_per_region(INVALID_REGION_BLOCK_SIZE) + iv_max_blocks_per_region(INVALID_REGION_BLOCK_SIZE), + iv_fw_update_mode_enabled(false), + iv_region_write_retries(0), + iv_blockSizeSupported(INVALID_BLOCK_SIZE) { // initialize to invalid values } @@ -350,12 +358,50 @@ errlHndl_t NvdimmInstalledImage::getVersion(uint16_t & o_version, return l_err; } +errlHndl_t NvdimmInstalledImage::getBlockWriteSizeSupported(uint64_t & o_blockSize) +{ + errlHndl_t l_err = nullptr; + + do { + if (iv_blockSizeSupported == INVALID_BLOCK_SIZE) + { + uint16_t version = INVALID_VERSION; + l_err = getVersion(version, 0); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"getBlockWriteSizeSupported: " + "Failed to get version for 0x%.8X NVDIMM", + TARGETING::get_huid(iv_dimm)); + break; + } + + // The block write is more prone to random system interrupt + // which does something funny to the i2c bus. + // v3.A has the timeout increased to mitigate that + if (version >= 0x3A00) + { + // version supports 32-byte block size + iv_blockSizeSupported = 32; + } + else + { + // default to word size max write + iv_blockSizeSupported = sizeof(uint16_t); + } + TRACFCOMP( g_trac_nvdimm_upd, ERR_MRK"getBlockWriteSizeSupported: " + "block size %d supported for 0x%.8X NVDIMM (version 0x%04X)", + iv_blockSizeSupported, TARGETING::get_huid(iv_dimm), + version ); + } + } while (0); + o_blockSize = iv_blockSizeSupported; + return l_err; +} errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) { errlHndl_t l_err = nullptr; - // need to always disable this after it gets enabled - bool l_fw_update_mode_enabled = false; + do { INITSERVICE::sendProgressCode(); //////////////////////////////////////////////////////////////////////// @@ -381,7 +427,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) TRACFCOMP(g_trac_nvdimm_upd,ERR_MRK"updateImage: " "NV controller is busy (0x%08X) for NVDIMM 0x%.8X", l_status.whole, TARGETING::get_huid(iv_dimm)); - /* + /*@ *@errortype *@moduleid UPDATE_IMAGE *@reasoncode NVDIMM_OPERATION_IN_PROGRESS @@ -398,11 +444,14 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) l_status.whole, ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace( NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); break; } @@ -427,8 +476,6 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) TARGETING::get_huid(iv_dimm)); break; } - // Set this flag so we will disable the update mode on error - l_fw_update_mode_enabled = true; // 5. Clear the Firmware Operation status TRACUCOMP(g_trac_nvdimm_upd, "updateImage: step 5"); @@ -549,7 +596,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) "NVDIMM 0x%.8X: data checksums mismatch (calc host: 0x%X " "and nv: 0x%X) for first part (header + SMART signature)", TARGETING::get_huid(iv_dimm), hostCksm, nvCksm); - /* + /*@ *@errortype *@moduleid UPDATE_IMAGE *@reasoncode NVDIMM_CHECKSUM_ERROR @@ -571,6 +618,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) 0x0000), ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace( NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); // maybe some data was altered on the NV controller l_err->addPartCallout( iv_dimm, @@ -579,6 +627,8 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) // possible code issue l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); break; } @@ -641,7 +691,6 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) // 12. Disable firmware update mode TRACUCOMP(g_trac_nvdimm_upd, "updateImage: step 12"); - l_fw_update_mode_enabled = false; // don't retry the disable on error l_err = changeFwUpdateMode(FW_UPDATE_MODE_DISABLED); if (l_err) { @@ -668,7 +717,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) // Reset controller to activate new firmware TRACUCOMP(g_trac_nvdimm_upd, "updateImage: resetController"); - l_err = resetController(); + l_err = nvdimmResetController(iv_dimm); if (l_err) { TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK "updateImage: " @@ -701,7 +750,7 @@ errlHndl_t NvdimmInstalledImage::updateImage(NvdimmLidImage * i_lidImage) } while (0); // If update operation is aborted, we need to disable update mode - if (l_fw_update_mode_enabled) + if (iv_fw_update_mode_enabled) { TRACFCOMP(g_trac_nvdimm_upd, "updateImage: update was aborted, so disable FW_UPDATE_MODE"); errlHndl_t l_err2 = changeFwUpdateMode(FW_UPDATE_MODE_DISABLED); @@ -765,7 +814,7 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage) } if (fw_img_total_regions == 0) { - /* + /*@ *@errortype *@moduleid UPDATE_IMAGE_DATA *@reasoncode NVDIMM_ZERO_TOTAL_REGIONS @@ -787,6 +836,8 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage) 0x00000000), ERRORLOG::ErrlEntry::ADD_SW_CALLOUT ); l_err->collectTrace( NVDIMM_COMP_NAME, 256 ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); break; } @@ -812,11 +863,15 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage) break; } + uint8_t l_region_write_retries = 0; // local region write retry count uint16_t region = 0; while (region < fw_img_total_regions) { - if (region % 10 == 0) + if (region % 100 == 0) { + TRACFCOMP(g_trac_nvdimm_upd, + "updateImage: progress code for sending region %d", + region); INITSERVICE::sendProgressCode(); } TRACUCOMP(g_trac_nvdimm_upd, "updateImage: step 10.a - region 0x%04X", @@ -914,15 +969,17 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage) if (hostCksm != nvCksm) { TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"updateImageData: " - "Region %d of NVDIMM 0x%.8X: data checksums mismatch " + "Region %d out of %d on NVDIMM 0x%.8X: data checksums mismatch " "(calc host: 0x%X and nv: 0x%X)", - region, TARGETING::get_huid(iv_dimm), hostCksm, nvCksm); + region, fw_img_total_regions, + TARGETING::get_huid(iv_dimm), hostCksm, nvCksm); - /* + /*@ *@errortype *@moduleid UPDATE_IMAGE_DATA *@reasoncode NVDIMM_CHECKSUM_ERROR - *@userdata1 NVDIMM Target Huid + *@userdata1[0:31] NVDIMM Target Huid + *@userdata1[32:63] Retry count for this region *@userdata2[0:15] Host checksum calculated *@userdata2[16:31] NV checksum returned *@userdata2[32:47] size of data for checksum @@ -934,18 +991,44 @@ errlHndl_t NvdimmInstalledImage::updateImageData(NvdimmLidImage * i_lidImage) ERRORLOG::ERRL_SEV_PREDICTIVE, UPDATE_IMAGE_DATA, NVDIMM_CHECKSUM_ERROR, - TARGETING::get_huid(iv_dimm), + TWO_UINT32_TO_UINT64( + TARGETING::get_huid(iv_dimm), + l_region_write_retries), FOUR_UINT16_TO_UINT64( hostCksm, nvCksm, region, data_len), ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); - l_err->collectTrace( NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); + + // Under the total retry attempts per region? + if (l_region_write_retries < MAX_REGION_WRITE_RETRY_ATTEMPTS) + { + TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"updateImageData: " + "Region %d on NVDIMM 0x%.8X failed, retry %d", + region, TARGETING::get_huid(iv_dimm),l_region_write_retries); + l_err->collectTrace(NVDIMM_UPD, 512); + + // Change PREDICTIVE to INFORMATIONAL as this might be recoverable + l_err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + + // Commit this log and retry region write + ERRORLOG::errlCommit(l_err, NVDIMM_COMP_ID); + l_err = nullptr; + + // Update total for this region + l_region_write_retries++; + // update total retries for entire NVDIMM + iv_region_write_retries++; + continue; + } break; } @@ -989,7 +1072,7 @@ errlHndl_t NvdimmInstalledImage::changeFwUpdateMode(fw_update_mode i_mode) ((i_mode == FW_UPDATE_MODE_DISABLED) && (opStatus.fw_ops_update_mode == 0))) ) { - /* + /*@ *@errortype *@moduleid CHANGE_FW_UPDATE_MODE *@reasoncode NVDIMM_UPDATE_MODE_UNCHANGED @@ -1009,11 +1092,25 @@ errlHndl_t NvdimmInstalledImage::changeFwUpdateMode(fw_update_mode i_mode) 0x00, 0x00), ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace( NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); + } + else + { + if (opStatus.fw_ops_update_mode == 1) + { + iv_fw_update_mode_enabled = true; + } + else + { + iv_fw_update_mode_enabled = false; + } } } } @@ -1025,8 +1122,9 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsBlockReceived() { errlHndl_t l_err = nullptr; - // retry for a total of 100ms - uint32_t timeout_ms_val = 100; + // retry for a total of 500ms + const uint32_t MAX_WAIT_FOR_OPS_BLOCK_RECEIVED = 500; + uint32_t timeout_ms_val = MAX_WAIT_FOR_OPS_BLOCK_RECEIVED; bool blockReceived = false; fw_ops_status_t opStatus; @@ -1042,6 +1140,7 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsBlockReceived() TARGETING::get_huid(iv_dimm), timeout_ms_val); break; } + if (!opStatus.fw_ops_block_received) { // wait 1 millisecond between checking status @@ -1066,7 +1165,13 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsBlockReceived() if (!blockReceived && !l_err) { - /* + TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"waitFwOpsBlockReceived: " + "NVDIMM 0x%.8X FIRMWARE_OPS_STATUS (timeout: %d ms) " + "-- Last status: 0x%02X", + TARGETING::get_huid(iv_dimm), MAX_WAIT_FOR_OPS_BLOCK_RECEIVED, + opStatus.whole); + + /*@ *@errortype *@moduleid WAIT_FW_OPS_BLOCK_RECEIVED *@reasoncode NVDIMM_BLOCK_NOT_RECEIVED @@ -1086,16 +1191,19 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsBlockReceived() ( TWO_UINT8_TO_UINT16( 0x00, opStatus.whole), - 100, + MAX_WAIT_FOR_OPS_BLOCK_RECEIVED, timeout_ms_val ), ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace(NVDIMM_COMP_NAME, 512 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); } return l_err; @@ -1145,7 +1253,7 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsComplete() if (!opsComplete && !l_err) { - /* + /*@ *@errortype *@moduleid WAIT_FW_OPS_COMPLETE *@reasoncode NVDIMM_FW_OPS_IN_PROGRESS_TIMEOUT @@ -1169,11 +1277,14 @@ errlHndl_t NvdimmInstalledImage::waitFwOpsComplete() ), ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace(NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); } } return l_err; @@ -1234,6 +1345,103 @@ errlHndl_t NvdimmInstalledImage::clearFwOpsStatus() "NVDIMM 0x%.8X clear FIRMWARE_OPS_STATUS register failed", TARGETING::get_huid(iv_dimm)); } + else + { + // Verify expected bits cleared + + // Setup expected cleared status byte + fw_ops_status_t l_cleared_ops_status; + l_cleared_ops_status.whole = 0x00; + if (iv_fw_update_mode_enabled) + { + // set BIT 2 -- this should not be cleared by the command + l_cleared_ops_status.fw_ops_update_mode = 1; + } + + // Set some timeout so this doesn't cause endless loop + uint16_t timeout_val = INVALID_TIMEOUT; + l_err = getFwOpsTimeout(timeout_val); + // Note: potential error will just exit the while loop and be returned + + // convert seconds to ms value + // double the timeout to ensure enough time has elapsed for the clear + // note: doubling here instead of just doubling timeout_val since that + // variable is only a bit16 vs bit32 + uint32_t timeout_ms_val = timeout_val * 1000 * 2; + + fw_ops_status_t l_ops_status; + + while (!l_err) + { + l_err = nvdimmReadReg(iv_dimm, FIRMWARE_OPS_STATUS, l_ops_status.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"clearFwOpsStatus: " + "NVDIMM 0x%.8X read FIRMWARE_OPS_STATUS register failed " + " (0x%02X)", + TARGETING::get_huid(iv_dimm), l_ops_status.whole); + break; + } + + // Exit if expected cleared status is found + if (l_ops_status.whole == l_cleared_ops_status.whole) + { + break; + } + + // wait 1 millisecond between checking status + if (timeout_ms_val > 0) + { + timeout_ms_val -= 1; + nanosleep(0, NS_PER_MSEC); + } + else + { + // timeout hit + TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"clearFwOpsStatus: " + "NVDIMM 0x%.8X FIRMWARE_OPS_STATUS register reads 0x%02X " + "instead of cleared value of 0x%02X after %lld seconds", + TARGETING::get_huid(iv_dimm), l_ops_status.whole, + l_cleared_ops_status.whole, timeout_val*2); + + /*@ + *@errortype + *@moduleid CLEAR_FW_OPS_STATUS + *@reasoncode NVDIMM_CLEAR_FW_OPS_STATUS_TIMEOUT + *@userdata1 NVDIMM Target Huid + *@userdata2[0:7] Last FIRMWARE_OPS_STATUS read + *@userdata2[8:15] Expected cleared status + *@userdata2[16:31] Reserved + *@userdata2[32:63] Timeout (seconds) + *@devdesc FIRMWARE_OPS_STATUS not cleared + *@custdesc NVDIMM not updated + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + CLEAR_FW_OPS_STATUS, + NVDIMM_CLEAR_FW_OPS_STATUS_TIMEOUT, + TARGETING::get_huid(iv_dimm), + TWO_UINT16_ONE_UINT32_TO_UINT64 + ( + TWO_UINT8_TO_UINT16( + l_ops_status.whole, + l_cleared_ops_status.whole), + 0x0000, + timeout_val * 2 + ), + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + l_err->collectTrace(NVDIMM_COMP_NAME, 256); + l_err->addPartCallout( iv_dimm, + HWAS::NV_CONTROLLER_PART_TYPE, + HWAS::SRCI_PRIORITY_HIGH ); + l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_LOW ); + + break; + } + } // end of while (!l_err) loop + } // end of Verify expected bits cleared + return l_err; } @@ -1317,7 +1525,7 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data, } if (blocks_per_region > max_blocks_per_region) { - /* + /*@ *@errortype *@moduleid BYTE_REGION_BLOCK_TRANSFER *@reasoncode NVDIMM_DATA_SIZE_TOO_LARGE @@ -1352,7 +1560,7 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data, if (i_data_size > (BYTES_PER_BLOCK*blocks_per_region)) { - /* + /*@ *@errortype *@moduleid BYTE_REGION_BLOCK_TRANSFER *@reasoncode NVDIMM_DATA_SIZE_INVALID @@ -1421,15 +1629,29 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data, TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: " "Unable to open page for BLOCK %d transfer of NVDIMM " "0x%.8X", blockNum, TARGETING::get_huid(iv_dimm)); + break; } size_t l_numBytes = BYTES_PER_BLOCK; uint8_t l_reg_addr = ADDRESS(TYPED_BLOCK_DATA_BYTE0); + + // Grab whether word or 32-byte block write is supported + uint64_t blockSizeSupported = INVALID_BLOCK_SIZE; + l_err = getBlockWriteSizeSupported(blockSizeSupported); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: " + "Unable to grab maximum block write size for NVDIMM 0x%.8X", + TARGETING::get_huid(iv_dimm)); + break; + } + l_err = DeviceFW::deviceOp( DeviceFW::WRITE, iv_dimm, pCurrentBlockData, l_numBytes, - DEVICE_NVDIMM_ADDRESS(l_reg_addr) ); + DEVICE_NVDIMM_RAW_ADDRESS_WITH_BLOCKSIZE(l_reg_addr, blockSizeSupported) + ); if (l_err) { TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: " @@ -1437,8 +1659,6 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data, blockNum, l_reg_addr, TARGETING::get_huid(iv_dimm)); break; } - // increment to next block - pCurrentBlockData += BYTES_PER_BLOCK; // After a block has been transferred, verify that the 32-byte block // was received by polling FIRMWARE_OPS_STATUS offset for @@ -1449,10 +1669,39 @@ errlHndl_t NvdimmInstalledImage::byteRegionBlockTransfer(const uint8_t * i_data, TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: " "Block %d read of FIRMWARE_OPS_STATUS failed on NVDIMM " " 0x%.8X", blockNum, TARGETING::get_huid(iv_dimm)); + + size_t tmpNumBytes = l_numBytes; + uint8_t tmpBuffer[tmpNumBytes]; + errlHndl_t l_err2 = DeviceFW::deviceOp( DeviceFW::READ, + iv_dimm, + tmpBuffer, + tmpNumBytes, + DEVICE_NVDIMM_ADDRESS(l_reg_addr) ); + if (l_err2) + { + TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"byteRegionBlockTransfer: " + "Block %d read from 0x%02X failed on NVDIMM 0x%.8X", + blockNum, l_reg_addr, TARGETING::get_huid(iv_dimm)); + l_err2->plid(l_err->plid()); + l_err2->collectTrace(NVDIMM_COMP_NAME); + l_err2->collectTrace(NVDIMM_UPD); + errlCommit(l_err2, NVDIMM_COMP_ID); + break; + } + else + { + TRACFBIN(g_trac_nvdimm_upd, "byteRegionBlockTransfer: Wrote block", pCurrentBlockData, l_numBytes); + TRACFBIN(g_trac_nvdimm_upd, "byteRegionBlockTransfer: Read-back block", tmpBuffer, l_numBytes); + } + break; } + // block of data successfully sent to NV controller TRACUCOMP(g_trac_nvdimm_upd,"byteRegionBlockTransfer: block 0x%02X successfully sent to NV controller", blockNum); + + // increment to next block + pCurrentBlockData += BYTES_PER_BLOCK; blockNum++; } @@ -1516,7 +1765,7 @@ errlHndl_t NvdimmInstalledImage::validateFwHeader() l_err = isFwOpsSuccess(opsSuccessful); if (!l_err && !opsSuccessful) { - /* + /*@ *@errortype *@moduleid VALIDATE_FW_HEADER *@reasoncode NVDIMM_FW_OPS_NOT_SUCCESSFUL @@ -1533,11 +1782,14 @@ errlHndl_t NvdimmInstalledImage::validateFwHeader() opsCmd.whole, ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace(NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); } } } @@ -1565,7 +1817,7 @@ errlHndl_t NvdimmInstalledImage::commitFwRegion() l_err = isFwOpsSuccess(opsSuccessful); if (!l_err && !opsSuccessful) { - /* + /*@ *@errortype *@moduleid COMMIT_FW_REGION *@reasoncode NVDIMM_FW_OPS_NOT_SUCCESSFUL @@ -1582,11 +1834,14 @@ errlHndl_t NvdimmInstalledImage::commitFwRegion() opsCmd.whole, ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace(NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); } } } @@ -1615,7 +1870,7 @@ errlHndl_t NvdimmInstalledImage::clearFwDataBlock() l_err = isFwOpsSuccess(ops_success); if (!l_err && !ops_success) { - /* + /*@ *@errortype *@moduleid CLEAR_FW_DATA_BLOCK *@reasoncode NVDIMM_FW_OPS_NOT_SUCCESSFUL @@ -1632,11 +1887,14 @@ errlHndl_t NvdimmInstalledImage::clearFwDataBlock() opsCmd.whole, ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace(NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); } } } @@ -1664,7 +1922,7 @@ errlHndl_t NvdimmInstalledImage::validateFwImage() // create an error if operation not successful if (!l_err && !opsSuccessful) { - /* + /*@ *@errortype *@moduleid VALIDATE_FW_IMAGE *@reasoncode NVDIMM_FW_OPS_NOT_SUCCESSFUL @@ -1681,12 +1939,14 @@ errlHndl_t NvdimmInstalledImage::validateFwImage() opsCmd.whole, ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace(NVDIMM_COMP_NAME, 256 ); + nvdimmAddVendorLog(iv_dimm, l_err); l_err->addPartCallout( iv_dimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); - + nvdimmAddPage4Regs(iv_dimm,l_err); + nvdimmAddUpdateRegs(iv_dimm,l_err); } } } @@ -1694,41 +1954,6 @@ errlHndl_t NvdimmInstalledImage::validateFwImage() return l_err; } -errlHndl_t NvdimmInstalledImage::resetController() -{ - errlHndl_t l_err = nullptr; - - // If bit 0 is set, the module shall start a Reset Controller operation - l_err = nvdimmWriteReg(iv_dimm, NVDIMM_MGT_CMD0, 0x01); - if (l_err) - { - TRACFCOMP(g_trac_nvdimm_upd,ERR_MRK"resetController: NVDIMM 0x%.8X " - "write of 0x01 to NVDIMM_MGT_CMD0 register failed", - TARGETING::get_huid(iv_dimm)); - } - else - { - TRACUCOMP(g_trac_nvdimm_upd,"resetController: waiting 5 seconds after controller 0x%.8X reset", - TARGETING::get_huid(iv_dimm)); - - // sleep 5 seconds to allow for i2c controller to come back online - nanosleep(5,0); - - TRACUCOMP(g_trac_nvdimm_upd,"resetController: now check if NV controller is ready again", - TARGETING::get_huid(iv_dimm)); - - // Now wait until NV controller is ready again after reset - l_err = nvdimmReady(iv_dimm); - if (l_err) - { - TRACFCOMP(g_trac_nvdimm_upd,ERR_MRK"resetController: NV controller for " - "NVDIMM 0x%.8X is not reporting as ready after reset", - TARGETING::get_huid(iv_dimm)); - } - } - return l_err; -} - uint16_t NvdimmInstalledImage::crc16(const uint8_t * i_data, int i_data_size) { // From JEDEC JESD245B.01 document @@ -1769,6 +1994,9 @@ bool NvdimmsUpdate::runUpdateUsingLid(NvdimmLidImage * i_lidImage, errlHndl_t l_err = nullptr; for (auto pInstalledImage : i_list) { + TARGETING::Target * l_nvdimm = pInstalledImage->getNvdimmTarget(); + uint64_t l_nvdimm_huid = TARGETING::get_huid(l_nvdimm); + INITSERVICE::sendProgressCode(); bool updateNeeded = false; l_err = isUpdateNeeded(updateNeeded, i_lidImage, pInstalledImage); @@ -1785,14 +2013,69 @@ bool NvdimmsUpdate::runUpdateUsingLid(NvdimmLidImage * i_lidImage, } else if (updateNeeded) { + // shared trace variables + uint32_t l_installed_type = INVALID_TYPE; + l_err = pInstalledImage->getType(l_installed_type); + if (l_err) + { + // Continue updating other dimms + TRACFCOMP(g_trac_nvdimm_upd, + ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - " + "Unable to get nvdimm[0x%.8X] installed image type. " + "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid, + ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err)); + commitPredictiveNvdimmError(l_err); + l_err = nullptr; + continue; + } + + uint16_t l_oldVersion = INVALID_VERSION; + l_err = pInstalledImage->getVersion(l_oldVersion); + if (l_err) + { + // This shouldn't happen as getVersion should return a + // cached version + TRACFCOMP(g_trac_nvdimm_upd, + ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - " + "Failed to find current NVDIMM level of %.8X. " + "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid, + ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err)); + commitPredictiveNvdimmError(l_err); + l_err = nullptr; + o_no_error_found = false; + continue; + } + // perform update for this DIMM with the current LID image TRACFCOMP(g_trac_nvdimm_upd, "NvdimmsUpdate::runUpdateUsingLid() - " - "now update nvdimm[0x%.8X]", - TARGETING::get_huid(pInstalledImage->getNvdimmTarget())); + "now update nvdimm[0x%.8X]", l_nvdimm_huid); TRACFCOMP(g_trac_nvdimm_upd,"Updating with flash size: 0x%08X", i_lidImage->getFlashImageSize()); + /*@ + *@errortype INFORMATIONAL + *@reasoncode NVDIMM_START_UPDATE + *@moduleid NVDIMM_RUN_UPDATE_USING_LID + *@userdata1 NVDIMM Target Huid + *@userdata2[0:15] Old level (current) + *@userdata2[16:31] Update image level (new) + *@userdata2[32:63] Installed type (manufacturer and product) + *@devdesc Start of the NVDIMM update of this controller + *@custdesc NVDIMM update started + */ + l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_INFORMATIONAL, + NVDIMM_RUN_UPDATE_USING_LID, + NVDIMM_START_UPDATE, + l_nvdimm_huid, + TWO_UINT16_ONE_UINT32_TO_UINT64( + l_oldVersion, i_lidImage->getVersion(), + l_installed_type), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + l_err->collectTrace(NVDIMM_UPD, 256); + ERRORLOG::errlCommit(l_err, NVDIMM_COMP_ID); + l_err = nullptr; + l_err = pInstalledImage->updateImage(i_lidImage); if (l_err) { @@ -1803,14 +2086,150 @@ bool NvdimmsUpdate::runUpdateUsingLid(NvdimmLidImage * i_lidImage, TRACFCOMP(g_trac_nvdimm_upd, ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - " "NVDIMM 0x%.8X NV controller update failed. " - "RC=0x%X, PLID=0x%.8X", - TARGETING::get_huid(pInstalledImage->getNvdimmTarget()), + "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid, ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err)); commitPredictiveNvdimmError(l_err); l_err = nullptr; o_no_error_found = false; + continue; + } + else + { + // successfully updated this NVDIMM + + // Note: call for version should just return a saved value + uint16_t curVersion = INVALID_VERSION; + l_err = pInstalledImage->getVersion(curVersion); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm_upd, + ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - " + "Failed to find current NVDIMM level of %.8X after " + "successful update. RC=0x%X, PLID=0x%.8X", + l_nvdimm_huid, + ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err)); + commitPredictiveNvdimmError(l_err); + l_err = nullptr; + } + + /*@ + *@errortype INFORMATIONAL + *@reasoncode NVDIMM_UPDATE_COMPLETE + *@moduleid NVDIMM_RUN_UPDATE_USING_LID + *@userdata1[0:31] NVDIMM Target Huid + *@userdata1[32:63] Total region write retries + *@userdata2[0:15] Previous level + *@userdata2[16:31] Current updated level + *@userdata2[32:63] Installed type (manufacturer and product) + *@devdesc Successful update of NVDIMM code + *@custdesc NVDIMM was successfully updated + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + NVDIMM_RUN_UPDATE_USING_LID, + NVDIMM_UPDATE_COMPLETE, + TWO_UINT32_TO_UINT64( + l_nvdimm_huid, + pInstalledImage->getRegionWriteRetries()), + TWO_UINT16_ONE_UINT32_TO_UINT64( + l_oldVersion, curVersion, + l_installed_type), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT ); + l_err->collectTrace(NVDIMM_UPD, 512); + ERRORLOG::errlCommit(l_err, NVDIMM_COMP_ID); } } // end of updateNeeded + + ///////////////////////////////////////////////////////////////// + // Should not exit the nvdimm update stage until each nvdimm + // is running at the lid's code level + // (or a predictive error was logged for that nvdimm) + ///////////////////////////////////////////////////////////////// + + // Check NVDIMM is at the latest level and it is running from slot 1 + uint16_t l_curVersion = INVALID_VERSION; + l_err = pInstalledImage->getVersion(l_curVersion, true); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm_upd, + ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - " + "Failed to find current level of NVDIMM %.8X. " + "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid, + ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err)); + commitPredictiveNvdimmError(l_err); + l_err = nullptr; + o_no_error_found = false; + continue; + } + uint8_t l_slot_running = 0; + l_err = nvdimmGetRunningSlot(l_nvdimm, l_slot_running); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm_upd, + ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - " + "Failed to find running slot of NVDIMM %.8X. " + "RC=0x%X, PLID=0x%.8X", l_nvdimm_huid, + ERRL_GETRC_SAFE(l_err), ERRL_GETPLID_SAFE(l_err)); + commitPredictiveNvdimmError(l_err); + l_err = nullptr; + o_no_error_found = false; + continue; + } + + if ((l_slot_running == 0) || (l_curVersion != i_lidImage->getVersion())) + { + // Not running latest code on this NVDIMM + TRACFCOMP(g_trac_nvdimm_upd, + ERR_MRK"NvdimmsUpdate::runUpdateUsingLid() - " + "NVDIMM %.8X running from slot %d with code level " + "0x%04X (lid level: 0x%04X)", + l_nvdimm_huid, l_slot_running, l_curVersion, + i_lidImage->getVersion()); + /*@ + *@errortype + *@reasoncode NVDIMM_NOT_RUNNING_LATEST_LEVEL + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_RUN_UPDATE_USING_LID + *@userdata1 NVDIMM Target Huid + *@userdata2[0:15] NVDIMM slot + *@userdata2[16:31] slot1 version + *@userdata2[32:47] latest version from lid + *@devdesc Encountered error after update while checking + * if NVDIMM is running latest code level + *@custdesc NVDIMM not running latest firmware level + */ + l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_RUN_UPDATE_USING_LID, + NVDIMM_NOT_RUNNING_LATEST_LEVEL, + l_nvdimm_huid, + FOUR_UINT16_TO_UINT64( + l_slot_running, + l_curVersion, + i_lidImage->getVersion(), + 0x0000), + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + + l_err->collectTrace( NVDIMM_COMP_NAME ); + + // Add callout of nvdimm with no deconfig/gard + l_err->addHwCallout( l_nvdimm, + HWAS::SRCI_PRIORITY_LOW, + HWAS::NO_DECONFIG, + HWAS::GARD_NULL); + + // Maybe vendor log will tell why it isn't running latest code level + nvdimmAddVendorLog(l_nvdimm, l_err); + commitPredictiveNvdimmError(l_err); + l_err = nullptr; + o_no_error_found = false; + } + else + { + TRACFCOMP(g_trac_nvdimm_upd, + "NvdimmsUpdate::runUpdateUsingLid() - " + "NVDIMM %.8X running from slot %d with latest level 0x%04X", + l_nvdimm_huid, l_slot_running, l_curVersion); + } } return o_no_error_found; } @@ -1826,12 +2245,15 @@ bool NvdimmsUpdate::runUpdate(void) // List of each installed NVDIMM type std::vector<NvdimmInstalledImage*> v_NVDIMM_16GB_list; std::vector<NvdimmInstalledImage*> v_NVDIMM_32GB_list; + BPM::bpmList_t NVDIMM_BPM_16GB_list; + BPM::bpmList_t NVDIMM_BPM_32GB_list; // Build up installed NVDIMM image lists for (auto l_nvdimm : iv_nvdimmList) { NvdimmInstalledImage * l_installed_image = new NvdimmInstalledImage(l_nvdimm); + l_err = l_installed_image->getType(l_installed_type); if (l_err) { @@ -1843,6 +2265,10 @@ bool NvdimmsUpdate::runUpdate(void) ERRL_GETPLID_SAFE(l_err)); commitPredictiveNvdimmError(l_err); o_no_error_found = false; + + // Delete the unused NvdimmInstalledImage pointer + delete l_installed_image; + continue; } @@ -1852,6 +2278,10 @@ bool NvdimmsUpdate::runUpdate(void) "0x%.8X NVDIMM is SMART_NVDIMM_16GB_TYPE", get_huid(l_nvdimm)); v_NVDIMM_16GB_list.push_back(l_installed_image); + + BPM::Bpm l_16gbBpm(l_nvdimm); + NVDIMM_BPM_16GB_list.push_back(l_16gbBpm); + } else if (l_installed_type == SMART_NVDIMM_32GB_TYPE) { @@ -1859,6 +2289,9 @@ bool NvdimmsUpdate::runUpdate(void) "0x%.8X NVDIMM is SMART_NVDIMM_32GB_TYPE", get_huid(l_nvdimm)); v_NVDIMM_32GB_list.push_back(l_installed_image); + + BPM::Bpm l_32gbBpm(l_nvdimm); + NVDIMM_BPM_32GB_list.push_back(l_32gbBpm); } else { @@ -1866,7 +2299,7 @@ bool NvdimmsUpdate::runUpdate(void) TRACFCOMP(g_trac_nvdimm_upd, "NvdimmsUpdate::runUpdate() - unknown " "nvdimm[%X] installed type 0x%04X, skipping update", TARGETING::get_huid(l_nvdimm), l_installed_type); - /* + /*@ *@errortype *@reasoncode NVDIMM_UNSUPPORTED_NVDIMM_TYPE *@moduleid NVDIMM_RUN_UPDATE @@ -1889,36 +2322,34 @@ bool NvdimmsUpdate::runUpdate(void) ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace(NVDIMM_COMP_NAME, 256 ); l_err->collectTrace(NVDIMM_UPD, 256); + nvdimmAddVendorLog(l_nvdimm, l_err); l_err->addPartCallout( l_nvdimm, HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); + nvdimmAddPage4Regs(l_nvdimm,l_err); + nvdimmAddUpdateRegs(l_nvdimm,l_err); ERRORLOG::errlCommit(l_err, NVDIMM_COMP_ID); + + // Delete the unused NvdimmInstalledImage object + delete l_installed_image; + continue; } } do { - // First check that updatable NVDIMMs exist on the system - if ((v_NVDIMM_16GB_list.size() == 0) && - (v_NVDIMM_32GB_list.size() == 0)) - { - TRACFCOMP(g_trac_nvdimm_upd, "NvdimmsUpdate::runUpdate() - " - "No updatable NVDIMMs present on the system"); - break; - } - - ///////////////////////// - // @todo: remove this check when SMART provides updated 32GB image - // The current 32GB image will cause the future updating to fail - if (v_NVDIMM_16GB_list.size() == 0) + // First check that updatable NVDIMMs or BPMs exist on the system + if ( (v_NVDIMM_16GB_list.size() == 0) + && (v_NVDIMM_32GB_list.size() == 0) + && (NVDIMM_BPM_16GB_list.size() == 0) + && (NVDIMM_BPM_32GB_list.size() == 0)) { TRACFCOMP(g_trac_nvdimm_upd, "NvdimmsUpdate::runUpdate() - " - "Only 16GB NVDIMM type is supported right now for update"); + "No updatable NVDIMMs or BPMs present on the system"); break; } - ///////////////////////// if (INITSERVICE::spBaseServicesEnabled()) { @@ -1935,7 +2366,15 @@ bool NvdimmsUpdate::runUpdate(void) break; } - for(const auto& lid : info.lidIds) + // Both the config and firmware images are needed to perform an + // update on a BPM. So, get pointers to each in the CompInfo + // struct's vector of LID IDs. + MCL::LidInfo * bpm_16gb_fw = nullptr; + MCL::LidInfo * bpm_16gb_config = nullptr; + MCL::LidInfo * bpm_32gb_fw = nullptr; + MCL::LidInfo * bpm_32gb_config = nullptr; + + for(auto& lid : info.lidIds) { TRACFCOMP(g_trac_nvdimm,"LID ID=0x%08X, size=%d, vAddr=%p", lid.id, lid.size, lid.vAddr); @@ -1966,6 +2405,22 @@ bool NvdimmsUpdate::runUpdate(void) v_NVDIMM_32GB_list); } } + else if (lid.id == NVDIMM_32GB_BPM_FW_LIDID) + { + bpm_32gb_fw = &lid; + } + else if (lid.id == NVDIMM_32GB_BPM_CONFIG_LIDID) + { + bpm_32gb_config = &lid; + } + else if (lid.id == NVDIMM_16GB_BPM_FW_LIDID) + { + bpm_16gb_fw = &lid; + } + else if (lid.id == NVDIMM_16GB_BPM_CONFIG_LIDID) + { + bpm_16gb_config = &lid; + } else if (lid.id != NVDIMM_SIGNATURE_LIDID) { TRACFCOMP(g_trac_nvdimm, "NvdimmsUpdate::runUpdate() - " @@ -1975,6 +2430,26 @@ bool NvdimmsUpdate::runUpdate(void) } } + // Run BPM updates on NVDIMMs + BPM::BpmFirmwareLidImage fwImage_16gb(bpm_16gb_fw->vAddr, + bpm_16gb_fw->size); + + BPM::BpmFirmwareLidImage fwImage_32gb(bpm_32gb_fw->vAddr, + bpm_32gb_fw->size); + + BPM::BpmConfigLidImage configImage_16gb(bpm_16gb_config->vAddr, + bpm_16gb_config->size); + + BPM::BpmConfigLidImage configImage_32gb(bpm_32gb_config->vAddr, + bpm_32gb_config->size); + + BPM::runBpmUpdates(&NVDIMM_BPM_16GB_list, + &NVDIMM_BPM_32GB_list, + &fwImage_16gb, + &fwImage_32gb, + &configImage_16gb, + &configImage_32gb); + // Destructor automatically unloads the NVDIMM flash binary } else @@ -1987,6 +2462,16 @@ bool NvdimmsUpdate::runUpdate(void) } } while (0); // end of flash update section + // Clean up the pointers used in v_NVDIMM_16GB_list and v_NVDIMM_32GB_list + for (const auto& pInstalledImage : v_NVDIMM_16GB_list) + { + delete pInstalledImage; + } + for (const auto& pInstalledImage : v_NVDIMM_32GB_list) + { + delete pInstalledImage; + } + return o_no_error_found; } @@ -2001,7 +2486,7 @@ errlHndl_t NvdimmsUpdate::isUpdateNeeded(bool & o_update_needed, uint32_t curType = INVALID_TYPE; do { - const TARGETING::Target * l_dimm = i_cur_image->getNvdimmTarget(); + TARGETING::Target * l_dimm = i_cur_image->getNvdimmTarget(); // check Types match (same manufacturer and product) lidType = i_lid_image->getType(); @@ -2038,7 +2523,7 @@ errlHndl_t NvdimmsUpdate::isUpdateNeeded(bool & o_update_needed, "isUpdateNeeded(): non-updatable SMART NVDIMM 0x%.8X " "(0x%04X)", TARGETING::get_huid(l_dimm), le16toh(curVersion)); - /* + /*@ *@errortype *@reasoncode NVDIMM_UPDATE_NOT_SUPPORTED *@moduleid NVDIMM_IS_UPDATE_NEEDED @@ -2046,9 +2531,9 @@ errlHndl_t NvdimmsUpdate::isUpdateNeeded(bool & o_update_needed, *@userdata1[32:63] NVDIMM Target Huid *@userdata2 NVDIMM type (manufacturer and product) *@devdesc Unable to update an NVDIMM at this code level - *@custdesc NVDIMM not updated + *@custdesc Unsupported level of NVDIMM hardware */ - l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE, + l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, NVDIMM_IS_UPDATE_NEEDED, NVDIMM_UPDATE_NOT_SUPPORTED, TWO_UINT32_TO_UINT64( @@ -2057,9 +2542,15 @@ errlHndl_t NvdimmsUpdate::isUpdateNeeded(bool & o_update_needed, curType, ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace( NVDIMM_UPD, 256 ); + nvdimmAddVendorLog(const_cast<TARGETING::Target*>(l_dimm), + l_err); + l_err->addHwCallout( l_dimm, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DECONFIG, + HWAS::GARD_Fatal); l_err->addPartCallout( l_dimm, HWAS::NV_CONTROLLER_PART_TYPE, - HWAS::SRCI_PRIORITY_HIGH ); + HWAS::SRCI_PRIORITY_MED ); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); break; |