From a96914fab1c366bb8945fbd08c44e90ecbc0454b Mon Sep 17 00:00:00 2001 From: Corey Swenson Date: Wed, 25 Sep 2019 22:33:26 -0500 Subject: Add support for NVDIMM secure erase verify Add nvdimm operations to interface Add wrapper for factory default function Add secure erase verify start function Add secure erase verify status function Change-Id: I84774e679593e7df1907c1a442c831b2f4df88d9 CQ:SW475562 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/84301 Reviewed-by: Matt Derksen Tested-by: Jenkins Server Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Tested-by: FSP CI Jenkins Reviewed-by: Roland Veloz Reviewed-by: Daniel M Crowell --- src/include/runtime/interface.h | 12 +- src/include/usr/isteps/nvdimm/nvdimm.H | 34 +- src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H | 5 +- src/usr/isteps/nvdimm/ReadMe.md | 54 +++ src/usr/isteps/nvdimm/nvdimm.C | 464 +++++++++++++++++---- src/usr/isteps/nvdimm/nvdimm.H | 38 +- .../targeting/common/xmltohb/attribute_types.xml | 4 +- src/usr/util/runtime/rt_fwnotify.C | 53 ++- 8 files changed, 556 insertions(+), 108 deletions(-) (limited to 'src') diff --git a/src/include/runtime/interface.h b/src/include/runtime/interface.h index 2d54dd1f3..6304ec6ba 100644 --- a/src/include/runtime/interface.h +++ b/src/include/runtime/interface.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2019 */ +/* Contributors Listed Below - COPYRIGHT 2013,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -599,7 +599,15 @@ typedef struct hostInterfaces // Manufacturing(MNFG) energy source(ES) health check request HBRT_FW_MNFG_ES_HEALTH_CHECK = 0x0020, // Manufacturing(MNFG) non-volatile memory(NVM) health check request - HBRT_FW_MNFG_NVM_HEALTH_CHECK = 0x0040 + HBRT_FW_MNFG_NVM_HEALTH_CHECK = 0x0040, + + /// The following operations pertain to the decommission of an NVDIMM + // Factory Default returns the NVDIMM to the factory default state + HBRT_FW_NVDIMM_FACTORY_DEFAULT = 0x0080, + // Secure Erase Verify all NAND flash blocks have been erased + HBRT_FW_NVDIMM_SECURE_EV_START = 0x0100, + // Secure Erase Verify Status checks if SEV operation has completed + HBRT_FW_NVDIMM_SECURE_EV_STATUS = 0x0200, }; // NVDIMM (PHYP -> HBRT) message to request NVDIMM operation(s) diff --git a/src/include/usr/isteps/nvdimm/nvdimm.H b/src/include/usr/isteps/nvdimm/nvdimm.H index 97655b24b..966d4fd17 100644 --- a/src/include/usr/isteps/nvdimm/nvdimm.H +++ b/src/include/usr/isteps/nvdimm/nvdimm.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018,2019 */ +/* Contributors Listed Below - COPYRIGHT 2018,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -131,6 +131,33 @@ bool nvdimm_encrypt_enable(TARGETING::TargetHandleList &i_nvdimmList); */ bool nvdimm_crypto_erase(TARGETING::TargetHandleList &i_nvdimmList); +/** + * @brief Entry function to NVDIMM factory default + * + * @param[in] i_nvdimmList - list of nvdimm targets + * + * @return true if no errors logged, else false + */ +bool nvdimmFactoryDefault(TARGETING::TargetHandleList &i_nvdimmList); + +/** + * @brief Entry function to NVDIMM secure erase verify + * + * @param[in] i_nvdimmList - list of nvdimm targets + * + * @return true if no errors logged, else false + */ +bool nvdimmSecureEraseVerifyStart(TARGETING::TargetHandleList &i_nvdimmList); + +/** + * @brief Entry function to NVDIMM secure erase verify status + * + * @param[in] i_nvdimmList - list of nvdimm targets + * + * @return true if no errors logged, else false + */ +bool nvdimmSecureEraseVerifyStatus(TARGETING::TargetHandleList &i_nvdimmList); + /** * @brief Helper function to get list of nvdimm target pointers * @@ -293,6 +320,8 @@ void nvdimmSendNvStatus(); * PROTECTED status until power is cycled again * ENCRYPTION_ENABLED - contents of nvdimm are encrypted * ENCRYPTION_DISABLED - contents of nvdimm are not encrypted + * ERASE_VERIFY_STARTED - set secure_erase_verify_complete to 0 + * ERASE_VERIFY_COMPLETE = set secure_erase_verify_complete to 1 */ enum nvdimm_protection_t { @@ -305,6 +334,8 @@ enum nvdimm_protection_t NVDIMM_ENCRYPTION_ERROR = 6, ENCRYPTION_ENABLED = 7, ENCRYPTION_DISABLED = 8, + ERASE_VERIFY_STARTED = 9, + ERASE_VERIFY_COMPLETED = 10, SEND_NV_STATUS = 11, /* deprecated, still used by PRD */ UNPROTECTED_BECAUSE_ERROR = 4, @@ -465,6 +496,7 @@ void nvdimmAddPage4Regs(TARGETING::Target *i_nvdimm, errlHndl_t& io_err); */ void nvdimm_init(TARGETING::Target *i_nvdimm); + } #endif // NVDIMM_EXT_H__ diff --git a/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H b/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H index c0215db17..134988be6 100644 --- a/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H +++ b/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -110,6 +110,7 @@ enum nvdimmModuleId NVDIMM_ARM_PRE_CHECK = 0x3C, NVDIMM_ARM = 0x3D, CLEAR_FW_OPS_STATUS = 0x3E, + NVDIMM_SECURE_ERASE_VERIFY_STATUS = 0x3F, }; /** @@ -207,6 +208,8 @@ enum nvdimmReasonCode NVDIMM_ARM_RETRY = NVDIMM_COMP_ID | 0x54, NVDIMM_CLEAR_FW_OPS_STATUS_TIMEOUT = NVDIMM_COMP_ID | 0x55, // Failed to clear FW_OPS_STATUS NVDIMM_NOT_RUNNING_LATEST_LEVEL = NVDIMM_COMP_ID | 0x56, // Either running from slot 0 or level was not updated + NVDIMM_ERASE_VERIFY_STATUS_NONZERO = NVDIMM_COMP_ID | 0x57, + NVDIMM_ERASE_VERIFY_RESULT_NONZERO = NVDIMM_COMP_ID | 0x58, }; enum UserDetailsTypes diff --git a/src/usr/isteps/nvdimm/ReadMe.md b/src/usr/isteps/nvdimm/ReadMe.md index 2b4fd4901..1f98438b2 100644 --- a/src/usr/isteps/nvdimm/ReadMe.md +++ b/src/usr/isteps/nvdimm/ReadMe.md @@ -222,3 +222,57 @@ in the JEDEC document JESD245B 12. Disable firmware update mode 13. Switch from slot0 to slot1 which contains the new image code 14. Validate running new code level + +# NVDIMM Secure Erase Verify Flow +DS8K lpar -> HBRT NVDIMM operation = factory_default + secure_erase_verify_start + HBRT executes factory_default and steps 1) and 2) +DS8K lpar -> HBRT NVDIMM operation = secure_erase_verify_complete + HBRT executes step 3) + If secure erase verify has not completed, return status with verify_complete bit = 0 + DS8K lpar is responsible for monitoring elapsed time (2/4 hours) and restart process (step 6) + If secure erase verify has completed + HBRT executes steps 4) and 5), generating error logs for any non-zero register values + Return status with verify_complete bit = 1 + +## Procedure Flow for NVDIMM Secure Erase Verify + *Note: Secure Erase Verify should only be run after a Factory Default operation. + Secure Erase Verify is intended to verify whether all NAND blocks have been erased. + *Note: Full breakout of all Page 5 Secure Erase Verify registers can be found in + SMART document "JEDEC NVDIMM Vendor Page 2 Extensions". + 1) Set Page 5 Register 0x1B to value "0x00" + // this clears the status register + 2) Set Page 5 Register 0x1A to value "0xC0" + // this kicks off the erase verify operation + 3) Wait for Page 5 Register 0x1A Bit 7 to be reset to value "0" + // i.e., the overall register value should be "0x40"; + this means that erase verify has completed + a. If Page 5 Register 0x1A Bit 7 has not reset to value "0" + after 2 hours (16GB NVDIMM) or after 4 hours (32GB NVDIMM), + report a timeout error and skip to step (6) + 4) Read Page 5 Register 0x1B; value should be "0x00" + // this is the erase verify status register + a. If Page 5 Register 0x1B value is not "0x00", + report any/all errors as outlined in the table at the end of this document, + then skip to step (6) + 5) Read Page 5 Registers 0x1D (MSB) and 0x1C (LSB); + combined the two registers should have a value of "0x0000" + // this is the number of chunks failing Secure Erase Verify + a. If the combined value of the two registers is not "0x0000", + report a threshold exceeded error along with the combined value of the two registers, + then skip to step (6) + 6) If any errors have been reported in steps (3), (4), or (5), + retry the secure erase verify operation starting again from step (1) + a. If the secure erase verify operation fails even after retrying, + report that secure erase verify operation has failed + 7) If no errors have been reported, report that secure erase verify operation + has been completed successfully + *Addendum: Breakout of Page 5 Register 0x1B Erase Verify Status bit values referenced in step (4) above. + All these bits should return as "0". Any bits returning as "1" should be reported with the error name below. + Bits 7:6 - Reserved + Bit 5 - BAD BLOCK + Bit 4 - OTHER + Bit 3 - ENCRYPTION LOCKED + Bit 2 - INVALID PARAMETER + Bit 1 - INTERRUPTED + Bit 0 - NAND ERROR + diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C index 2f9f96c2b..a7e263cf3 100644 --- a/src/usr/isteps/nvdimm/nvdimm.C +++ b/src/usr/isteps/nvdimm/nvdimm.C @@ -119,6 +119,8 @@ static constexpr uint8_t NV_STATUS_UNPROTECTED_SET = 0x01; static constexpr uint8_t NV_STATUS_UNPROTECTED_CLR = 0xFE; static constexpr uint8_t NV_STATUS_ENCRYPTION_SET = 0x10; static constexpr uint8_t NV_STATUS_ENCRYPTION_CLR = 0xEF; +static constexpr uint8_t NV_STATUS_ERASE_VERIFY_SET = 0x20; +static constexpr uint8_t NV_STATUS_ERASE_VERIFY_CLR = 0xDF; static constexpr uint8_t NV_STATUS_POSSIBLY_UNPROTECTED_SET = 0x40; // NVDIMM key consts @@ -157,6 +159,11 @@ static constexpr uint8_t RUNNING_FW_SLOT = 0xF0; static constexpr size_t ARM_MAX_RETRY_COUNT = 1; static constexpr uint8_t FW_OPS_UPDATE = 0x04; +// Secure erase verify operations +static constexpr uint8_t ERASE_VERIFY_CLEAR = 0x00; +static constexpr uint8_t ERASE_VERIFY_START = 0xC0; +static constexpr uint8_t ERASE_VERIFY_TRIGGER = 0x80; + #ifndef __HOSTBOOT_RUNTIME // Warning thresholds static constexpr uint8_t THRESHOLD_ES_LIFETIME = 0x07; // 7% @@ -1953,95 +1960,6 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_restore()"); } -/** - * @brief Force a factory reset of the NV logic and flash - * - * @param[in] i_nvdimm - NVDIMM Target - */ -errlHndl_t nvdimm_factory_reset(Target *i_nvdimm) -{ - TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_factory_reset() nvdimm[%X]", - get_huid(i_nvdimm)); - errlHndl_t l_err = nullptr; - - do - { - // Send the reset command - l_err = nvdimmWriteReg(i_nvdimm, NVDIMM_FUNC_CMD, FACTORY_DEFAULT); - if( l_err ) - { - break; - } - - // Poll 2 minutes for completion - // We could get the timeout value from the dimm but since we're - // doing a hard reset anyway I just want to use a big number that - // can handle any lies that the controller might tell us. - uint8_t l_data = 0; - constexpr uint64_t MAX_POLL_SECONDS = 120; - uint64_t poll = 0; - for( poll = 0; poll < MAX_POLL_SECONDS; poll++ ) - { - l_err = nvdimmReadReg(i_nvdimm, NVDIMM_CMD_STATUS0, l_data); - if( l_err ) - { - break; - } - - if( l_data != FACTORY_RESET_IN_PROGRESS ) - { - break; - } - -#ifndef __HOSTBOOT_RUNTIME - // kick the watchdog since this can take awhile - INITSERVICE::sendProgressCode(); -#endif - - // sleep 1 second - nanosleep(1, 0); - } - if( l_err ) { break; } - - // Make an error if it never finished - if( poll >= MAX_POLL_SECONDS ) - { - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_factory_reset() nvdimm[%X] - factory reset never completed[%d]", - get_huid(i_nvdimm), l_data); - /*@ - *@errortype - *@reasoncode NVDIMM_NOT_READY - *@severity ERRORLOG_SEV_UNRECOVERABLE - *@moduleid NVDIMM_FACTORY_RESET - *@userdata1[0:31] Ret value from ready register - *@userdata1[32:63] Target Huid - *@userdata2 Number of seconds waited - *@devdesc NVDIMM factory reset never completed - *@custdesc NVDIMM still in reset - */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - NVDIMM_FACTORY_RESET, - NVDIMM_NOT_READY, - NVDIMM_SET_USER_DATA_1(l_data, get_huid(i_nvdimm)), - MAX_POLL_SECONDS, - ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); - - l_err->collectTrace(NVDIMM_COMP_NAME); - nvdimmAddVendorLog(i_nvdimm, l_err); - - // If nvdimm is not ready for access by now, this is - // a failing indication on the NV controller - l_err->addPartCallout( i_nvdimm, - HWAS::NV_CONTROLLER_PART_TYPE, - HWAS::SRCI_PRIORITY_HIGH); - nvdimmAddPage4Regs(i_nvdimm,l_err); - } - } while(0); - - return l_err; -} - /** * @brief NVDIMM initialization * - Checks for ready state @@ -2544,6 +2462,96 @@ errlHndl_t nvdimm_getTPM(Target*& o_tpm) #endif +/** + * @brief Force a factory reset of the NV logic and flash + * + * @param[in] i_nvdimm - NVDIMM Target + */ +errlHndl_t nvdimm_factory_reset(Target *i_nvdimm) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_factory_reset() nvdimm[%X]", + get_huid(i_nvdimm)); + errlHndl_t l_err = nullptr; + + do + { + // Send the reset command + l_err = nvdimmWriteReg(i_nvdimm, NVDIMM_FUNC_CMD, FACTORY_DEFAULT); + if( l_err ) + { + break; + } + + // Poll 2 minutes for completion + // We could get the timeout value from the dimm but since we're + // doing a hard reset anyway I just want to use a big number that + // can handle any lies that the controller might tell us. + uint8_t l_data = 0; + constexpr uint64_t MAX_POLL_SECONDS = 120; + uint64_t poll = 0; + for( poll = 0; poll < MAX_POLL_SECONDS; poll++ ) + { + l_err = nvdimmReadReg(i_nvdimm, NVDIMM_CMD_STATUS0, l_data); + if( l_err ) + { + break; + } + + if( l_data != FACTORY_RESET_IN_PROGRESS ) + { + break; + } + +#ifndef __HOSTBOOT_RUNTIME + // kick the watchdog since this can take awhile + INITSERVICE::sendProgressCode(); +#endif + + // sleep 1 second + nanosleep(1, 0); + } + if( l_err ) { break; } + + // Make an error if it never finished + if( poll >= MAX_POLL_SECONDS ) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_factory_reset() nvdimm[%X] - factory reset never completed[%d]", + get_huid(i_nvdimm), l_data); + /*@ + *@errortype + *@reasoncode NVDIMM_NOT_READY + *@severity ERRORLOG_SEV_UNRECOVERABLE + *@moduleid NVDIMM_FACTORY_RESET + *@userdata1[0:31] Ret value from ready register + *@userdata1[32:63] Target Huid + *@userdata2 Number of seconds waited + *@devdesc NVDIMM factory reset never completed + *@custdesc NVDIMM still in reset + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + NVDIMM_FACTORY_RESET, + NVDIMM_NOT_READY, + NVDIMM_SET_USER_DATA_1(l_data, get_huid(i_nvdimm)), + MAX_POLL_SECONDS, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + + l_err->collectTrace(NVDIMM_COMP_NAME); + nvdimmAddVendorLog(i_nvdimm, l_err); + + // If nvdimm is not ready for access by now, this is + // a failing indication on the NV controller + l_err->addPartCallout( i_nvdimm, + HWAS::NV_CONTROLLER_PART_TYPE, + HWAS::SRCI_PRIORITY_HIGH); + nvdimmAddPage4Regs(i_nvdimm,l_err); + } + } while(0); + + return l_err; +} + + bool nvdimm_encrypt_unlock(TargetHandleList &i_nvdimmList) { TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_encrypt_unlock()"); @@ -3663,6 +3671,8 @@ errlHndl_t notifyNvdimmProtectionChange(Target* i_target, bool l_armed_change = false; bool l_set_encryption = false; bool l_clr_encryption = false; + bool l_sev_started = false; + bool l_sev_completed = false; switch (i_state) { @@ -3695,6 +3705,12 @@ errlHndl_t notifyNvdimmProtectionChange(Target* i_target, case ENCRYPTION_DISABLED: l_clr_encryption = true; break; + case ERASE_VERIFY_STARTED: + l_sev_started = true; + break; + case ERASE_VERIFY_COMPLETED: + l_sev_completed = true; + break; case SEND_NV_STATUS: // no action, just send status break; @@ -3737,6 +3753,18 @@ errlHndl_t notifyNvdimmProtectionChange(Target* i_target, l_nv_status &= NV_STATUS_ENCRYPTION_CLR; } + // Clear bit 5 if secure erase verify started + if (l_sev_started) + { + l_nv_status &= NV_STATUS_ERASE_VERIFY_CLR; + } + + // Set bit 5 if secure erase verify comlpleted + if (l_sev_completed) + { + l_nv_status |= NV_STATUS_ERASE_VERIFY_SET; + } + // Set bit 6 if risky error if (l_armed_state.risky_error_detected) { @@ -5585,7 +5613,263 @@ bool nvdimmDisarm(TargetHandleList &i_nvdimmTargetList) TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmDisarm() returning %d", o_disarm_successful); - return o_disarm_successful; + + return o_disarm_successful; + +} + + +/* + * @brief Wrapper function to return NVDIMMs to factory default + */ +bool nvdimmFactoryDefault(TargetHandleList &i_nvdimmList) +{ + errlHndl_t l_err = nullptr; + bool l_success = true; + + // Factory default for all nvdimms in the list + for (const auto & l_nvdimm : i_nvdimmList) + { + l_err = nvdimm_factory_reset(l_nvdimm); + if (l_err) + { + l_success = false; + errlCommit( l_err, NVDIMM_COMP_ID ); + continue; + } + + // Update nvdimm status + l_err = notifyNvdimmProtectionChange(l_nvdimm, NVDIMM_DISARMED); + if (l_err) + { + errlCommit( l_err, NVDIMM_COMP_ID ); + } + } + + return l_success; +} + + +/* + * @brief Function to start secure erase verify of NVDIMMs + */ +bool nvdimmSecureEraseVerifyStart(TargetHandleList &i_nvdimmList) +{ + errlHndl_t l_err = nullptr; + bool l_success = true; + + // Secure erase verify for all nvdimms in the list + for (const auto & l_nvdimm : i_nvdimmList) + { + // Clear the erase_verify_status reg + l_err = nvdimmWriteReg(l_nvdimm, + ERASE_VERIFY_STATUS, + ERASE_VERIFY_CLEAR); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK + "nvdimmSecureEraseVerifyStart() HUID 0x%X" + "Failed to write ERASE_VERIFY_STATUS register", + get_huid(l_nvdimm)); + l_success = false; + errlCommit( l_err, NVDIMM_COMP_ID ); + continue; + } + + // Start the erase verify operation + l_err = nvdimmWriteReg(l_nvdimm, + ERASE_VERIFY_CONTROL, + ERASE_VERIFY_START); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK + "nvdimmSecureEraseVerifyStart() HUID 0x%X" + "Failed to write ERASE_VERIFY_CONTROL register", + get_huid(l_nvdimm)); + l_success = false; + errlCommit( l_err, NVDIMM_COMP_ID ); + continue; + } + + // Call notify to clear NV_STATUS bit + l_err = notifyNvdimmProtectionChange(l_nvdimm, + ERASE_VERIFY_STARTED); + if (l_err) + { + l_success = false; + errlCommit(l_err, NVDIMM_COMP_ID); + continue; + } + } + + return l_success; +} + + +/* + * @brief Function to check status of secure erase verify of NVDIMMs + */ +bool nvdimmSecureEraseVerifyStatus(TargetHandleList &i_nvdimmList) +{ + errlHndl_t l_err = nullptr; + bool l_success = true; + uint8_t l_data = 0; + + // Check secure erase verify status for all nvdimms in the list + for (const auto & l_nvdimm : i_nvdimmList) + { + // Check if secure-erase-verify is already complete for this nvdimm + ATTR_NV_STATUS_FLAG_type l_nv_status = + l_nvdimm->getAttr(); + if (l_nv_status & NV_STATUS_ERASE_VERIFY_SET) + { + continue; + } + + l_err = nvdimmReadReg(l_nvdimm, ERASE_VERIFY_CONTROL, l_data); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK + "nvdimmSecureEraseVerifyStatus() HUID 0x%X" + "Failed to read ERASE_VERIFY_CONTROL register", + get_huid(l_nvdimm)); + l_success = false; + errlCommit( l_err, NVDIMM_COMP_ID ); + continue; // Continue to next nvdimm + } + + // If trigger is set the operation is not yet complete + if (l_data & ERASE_VERIFY_TRIGGER) + { + continue; // Continue to next nvdimm + } + + // Secure erase verify on this nvdimm is complete + // Call notify to set NV_STATUS bit + l_err = notifyNvdimmProtectionChange(l_nvdimm, + ERASE_VERIFY_COMPLETED); + if (l_err) + { + l_success = false; + errlCommit(l_err, NVDIMM_COMP_ID); + } + + + // Check the status register + l_err = nvdimmReadReg(l_nvdimm, ERASE_VERIFY_STATUS, l_data); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK + "nvdimmSecureEraseVerifyStatus() HUID 0x%X" + "Failed to read ERASE_VERIFY_STATUS register", + get_huid(l_nvdimm)); + l_success = false; + errlCommit( l_err, NVDIMM_COMP_ID ); + continue; // Continue to next nvdimm + } + + // Non-zero status is an error + if (l_data) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmSecureEraseVerifyStatus() " + "HUID 0x%X ERASE_VERIFY_STATUS returned non-zero status", + get_huid(l_nvdimm)); + /*@ + *@errortype + *@reasoncode NVDIMM_ERASE_VERIFY_STATUS_NONZERO + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_SECURE_ERASE_VERIFY_STATUS + *@userdata1 NVDIMM HUID + *@userdata2 ERASE_VERIFY_STATUS + *@devdesc Error detected during secure erase verify + *@custdesc NVDIMM erase error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_SECURE_ERASE_VERIFY_STATUS, + NVDIMM_ERASE_VERIFY_STATUS_NONZERO, + get_huid(l_nvdimm), + l_data, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + l_err->collectTrace(NVDIMM_COMP_NAME); + l_err->addPartCallout( l_nvdimm, + HWAS::NV_CONTROLLER_PART_TYPE, + HWAS::SRCI_PRIORITY_HIGH); + nvdimmAddVendorLog(l_nvdimm, l_err); + errlCommit( l_err, NVDIMM_COMP_ID ); + l_success = false; + continue; // Continue to next nvdimm + } + + + // Check the result registers + uint16_t l_result = 0; + l_err = nvdimmReadReg(l_nvdimm, ERASE_VERIFY_RESULT_MSB, l_data); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK + "nvdimmSecureEraseVerifyStatus() HUID 0x%X" + "Failed to read ERASE_VERIFY_RESULT_MSB register", + get_huid(l_nvdimm)); + l_success = false; + errlCommit( l_err, NVDIMM_COMP_ID ); + continue; // Continue to next nvdimm + } + + // Save result + l_result = l_data << 8; + + l_err = nvdimmReadReg(l_nvdimm, ERASE_VERIFY_RESULT_LSB, l_data); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK + "nvdimmSecureEraseVerifyStatus() HUID 0x%X" + "Failed to read ERASE_VERIFY_RESULT_LSB register", + get_huid(l_nvdimm)); + l_success = false; + errlCommit( l_err, NVDIMM_COMP_ID ); + continue; // Continue to next nvdimm + } + + // Save result + l_result |= l_data; + + // Non-zero result is an error + if (l_result) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmSecureEraseVerifyStatus() " + "HUID 0x%X ERASE_VERIFY_RESULT returned non-zero data", + get_huid(l_nvdimm)); + /*@ + *@errortype + *@reasoncode NVDIMM_ERASE_VERIFY_RESULT_NONZERO + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_SECURE_ERASE_VERIFY_STATUS + *@userdata1 NVDIMM HUID + *@userdata2 ERASE_VERIFY_RESULT + *@devdesc Error detected during secure erase verify + *@custdesc NVDIMM erase error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_SECURE_ERASE_VERIFY_STATUS, + NVDIMM_ERASE_VERIFY_RESULT_NONZERO, + get_huid(l_nvdimm), + l_result, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + l_err->collectTrace(NVDIMM_COMP_NAME); + l_err->addPartCallout( l_nvdimm, + HWAS::NV_CONTROLLER_PART_TYPE, + HWAS::SRCI_PRIORITY_HIGH); + nvdimmAddVendorLog(l_nvdimm, l_err); + errlCommit( l_err, NVDIMM_COMP_ID ); + l_success = false; + continue; // Continue to next nvdimm + } + + } + + return l_success; } diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H index 1e4e1596c..e66e42470 100644 --- a/src/usr/isteps/nvdimm/nvdimm.H +++ b/src/usr/isteps/nvdimm/nvdimm.H @@ -305,18 +305,23 @@ enum i2cReg : uint16_t BPM_PAYLOAD_LENGTH = 0x442, BPM_REG_ERR_STATUS = 0x443, BPM_REG_PAYLOAD_START = 0x444, - ENCRYPTION_COMMAND = 0x51F, - ENCRYPTION_CONFIG_STATUS = 0x520, - ENCRYPTION_ACCESS_KEY_SET = 0x521, - ENCRYPTION_ACCESS_KEY_VERIFY = 0x522, - ENCRYPTION_ACCESS_KEY_UNLOCK = 0x523, - ENCRYPTION_RAMDOM_STRING_SET = 0x524, - ENCRYPTION_RANDOM_STRING_VERIFY = 0x525, - ENCRYPTION_ERASE_KEY_SET = 0x526, - ENCRYPTION_ERASE_KEY_VERIFY = 0x527, - ENCRYPTION_ERASE_KEY_TEST = 0x528, + ERASE_VERIFY_CONTROL = 0x51A, + ERASE_VERIFY_STATUS = 0x51B, + ERASE_VERIFY_RESULT_LSB = 0x51C, + ERASE_VERIFY_RESULT_MSB = 0x51D, + ERASE_VERIFY_TEST = 0x51E, + ENCRYPTION_COMMAND = 0x51F, + ENCRYPTION_CONFIG_STATUS = 0x520, + ENCRYPTION_ACCESS_KEY_SET = 0x521, + ENCRYPTION_ACCESS_KEY_VERIFY = 0x522, + ENCRYPTION_ACCESS_KEY_UNLOCK = 0x523, + ENCRYPTION_RAMDOM_STRING_SET = 0x524, + ENCRYPTION_RANDOM_STRING_VERIFY = 0x525, + ENCRYPTION_ERASE_KEY_SET = 0x526, + ENCRYPTION_ERASE_KEY_VERIFY = 0x527, + ENCRYPTION_ERASE_KEY_TEST = 0x528, ENCRYPTION_ERASE_KEY_TEST_VERIFY = 0x529, - ENCRYPTION_KEY_VALIDATION = 0x52A, + ENCRYPTION_KEY_VALIDATION = 0x52A, }; // i2cReg macros @@ -715,6 +720,17 @@ void nvdimmSetEncryptionError(TARGETING::Target *i_nvdimm); errlHndl_t nvdimmResetController(TARGETING::Target *i_nvdimm); +/** + * @brief Helper function to factory reset NVDIMM + * + * @param[in] i_nvdimm - nvdimm target + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_factory_reset(TARGETING::Target *i_nvdimm); + + #ifndef __HOSTBOOT_RUNTIME /** diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 0fb3ff9aa..e15880f87 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -5,7 +5,7 @@ - + @@ -5454,7 +5454,7 @@ 0x04: Contents preserved 0x08: Contents not preserved 0x10: Contents are encrypted - 0x20: Reserved + 0x20: Secure erase verify complete 0x40: Error detected, but save/restore might work 0x80: Reserved 0xFF: Memory is invalid diff --git a/src/usr/util/runtime/rt_fwnotify.C b/src/usr/util/runtime/rt_fwnotify.C index 6ef3e8fc4..148d3bbeb 100644 --- a/src/usr/util/runtime/rt_fwnotify.C +++ b/src/usr/util/runtime/rt_fwnotify.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017,2019 */ +/* Contributors Listed Below - COPYRIGHT 2017,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -645,6 +645,57 @@ int doNvDimmOperation(const hostInterfaces::nvdimm_operation_t& i_nvDimmOp) } } + // Perform the factory default operation + if (i_nvDimmOp.opType & hostInterfaces::HBRT_FW_NVDIMM_FACTORY_DEFAULT) + { + if (!nvdimmFactoryDefault(l_nvDimmTargetList)) + { + TRACFCOMP(g_trac_runtime, "doNvDimmOperation: " + "Call to do NVDIMM Factory Default operation failed."); + rc = -1; + break; + } + else + { + TRACFCOMP(g_trac_runtime, "doNvDimmOperation: " + "Call to do NVDIMM Factory Default operation succeeded."); + } + } + + // Perform the secure erase verify start operation + if (i_nvDimmOp.opType & hostInterfaces::HBRT_FW_NVDIMM_SECURE_EV_START) + { + if (!nvdimmSecureEraseVerifyStart(l_nvDimmTargetList)) + { + TRACFCOMP(g_trac_runtime, "doNvDimmOperation: " + "Call to do NVDIMM Secure Erase Verify Start failed."); + rc = -1; + break; + } + else + { + TRACFCOMP(g_trac_runtime, "doNvDimmOperation: " + "Call to do NVDIMM Secure Erase Verify Start succeeded."); + } + } + + // Perform the secure erase verify status operation + if (i_nvDimmOp.opType & hostInterfaces::HBRT_FW_NVDIMM_SECURE_EV_STATUS) + { + if (!nvdimmSecureEraseVerifyStatus(l_nvDimmTargetList)) + { + TRACFCOMP(g_trac_runtime, "doNvDimmOperation: " + "Call to do NVDIMM Secure Erase Verify Status failed."); + rc = -1; + break; + } + else + { + TRACFCOMP(g_trac_runtime, "doNvDimmOperation: " + "Call to do NVDIMM Secure Erase Verify Status succeeded."); + } + } + } while(0); // end Perform the operations requested if (l_err) -- cgit v1.2.1