diff options
author | Corey Swenson <cswenson@us.ibm.com> | 2019-05-02 15:20:15 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2019-06-03 10:26:25 -0500 |
commit | 5fd22b47f8d633b118265bae079793e8d90a51c1 (patch) | |
tree | e923f832604423f163e11b95cd05c49e7442bbac /src/usr/isteps | |
parent | af06bf24063e067ec0c6d7596588fc1716b2d4b9 (diff) | |
download | talos-hostboot-5fd22b47f8d633b118265bae079793e8d90a51c1.tar.gz talos-hostboot-5fd22b47f8d633b118265bae079793e8d90a51c1.zip |
NVDIMM encryption HW function support
Update random number generation, IPL and runtime.
Write encryption regs to enable nvdimm encryption,
crypto-erase, disable encryption. Read config-status
reg to verify encryption state.
Change-Id: I25625b53f90eeb542767fa729ebb47f8f8455a4b
RTC:201474
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/77321
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Matthew Raybuck <matthew.raybuck@ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/isteps')
-rw-r--r-- | src/usr/isteps/istep14/call_mss_power_cleanup.C | 5 | ||||
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm.C | 1571 | ||||
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm.H | 141 | ||||
-rw-r--r-- | src/usr/isteps/nvdimm/runtime/nvdimm_rt.C | 146 |
4 files changed, 1561 insertions, 302 deletions
diff --git a/src/usr/isteps/istep14/call_mss_power_cleanup.C b/src/usr/isteps/istep14/call_mss_power_cleanup.C index c86d172be..db6bdf228 100644 --- a/src/usr/isteps/istep14/call_mss_power_cleanup.C +++ b/src/usr/isteps/istep14/call_mss_power_cleanup.C @@ -131,9 +131,10 @@ void* call_mss_power_cleanup (void *io_pArgs) // Run the nvdimm management functions if the list is not empty if (!l_nvdimmTargetList.empty()){ - // Must generate encryption keys before the restore - NVDIMM::nvdimm_gen_keys(l_nvdimmTargetList); + NVDIMM::nvdimm_gen_keys(); + NVDIMM::nvdimm_encrypt_unlock(l_nvdimmTargetList); NVDIMM::nvdimm_restore(l_nvdimmTargetList); + NVDIMM::nvdimm_encrypt_enable(l_nvdimmTargetList); } } #endif diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C index b4bded78d..1cae5d9f3 100644 --- a/src/usr/isteps/nvdimm/nvdimm.C +++ b/src/usr/isteps/nvdimm/nvdimm.C @@ -85,8 +85,32 @@ constexpr ops_timeoutInfo_t timeoutInfoTable[] = {"CHARGE", {ES_CHARGE_TIMEOUT1, ES_CHARGE_TIMEOUT0}, CHARGE , MODULE_HEALTH_STATUS1, CHARGE_IN_PROGRESS}, }; -const size_t NUM_KEYS_IN_ATTR = 3; -const size_t MAX_KEY_SIZE = 32; +// Definition of ENCRYPTION_CONFIG_STATUS -- page 5 offset 0x20 +typedef union { + uint8_t whole; + struct + { + uint8_t reserved : 2; // [7:6 + uint8_t erase_pending : 1; // [5] + uint8_t encryption_unlocked : 1; // [4] + uint8_t encryption_enabled : 1; // [3] + uint8_t erase_key_present : 1; // [2] + uint8_t random_string_present : 1; // [1] + uint8_t encryption_supported : 1; // [0] + } PACKED; +} encryption_config_status_t; + +// Definition of ENCRYPTION_KEY_VALIDATION -- page 5 offset 0x2A +typedef union { + uint8_t whole; + struct + { + uint8_t reserved : 5; // [7:3] + uint8_t keys_validated : 1; // [2] + uint8_t access_key_valid : 1; // [1] + uint8_t erase_key_valid : 1; // [0] + } PACKED; +} encryption_key_validation_t; /** * @brief Wrapper to call deviceOp to read the NV controller via I2C @@ -108,8 +132,8 @@ errlHndl_t nvdimmReadReg(Target* i_nvdimm, uint8_t & o_data, const bool page_verify) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"NVDIMM Read HUID %X, addr 0x%X", - TARGETING::get_huid(i_nvdimm), i_addr); + TRACUCOMP(g_trac_nvdimm, ENTER_MRK"NVDIMM Read HUID 0x%X, addr 0x%X", + get_huid(i_nvdimm), i_addr); errlHndl_t l_err = nullptr; size_t l_numBytes = 1; @@ -128,7 +152,7 @@ errlHndl_t nvdimmReadReg(Target* i_nvdimm, if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReadReg() nvdimm[%X] - failed to read the current page", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); break; } @@ -139,7 +163,7 @@ errlHndl_t nvdimmReadReg(Target* i_nvdimm, if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReadReg() nvdimm[%X] - failed to verify page", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); break; } } @@ -152,8 +176,8 @@ errlHndl_t nvdimmReadReg(Target* i_nvdimm, DEVICE_NVDIMM_ADDRESS(l_reg_addr)); }while(0); - TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Read HUID %X, page 0x%X, addr 0x%X = %X", - TARGETING::get_huid(i_nvdimm), l_reg_page, l_reg_addr, o_data); + TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Read HUID 0x%X, page 0x%X, addr 0x%X = 0x%X", + get_huid(i_nvdimm), l_reg_page, l_reg_addr, o_data); return l_err; } @@ -178,8 +202,8 @@ errlHndl_t nvdimmWriteReg(Target* i_nvdimm, uint8_t i_data, const bool page_verify) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"NVDIMM Write HUID %X, addr 0x%X = %X", - TARGETING::get_huid(i_nvdimm), i_addr, i_data); + TRACUCOMP(g_trac_nvdimm, ENTER_MRK"NVDIMM Write HUID 0x%X, addr 0x%X = 0x%X", + get_huid(i_nvdimm), i_addr, i_data); errlHndl_t l_err = nullptr; size_t l_numBytes = 1; @@ -198,7 +222,7 @@ errlHndl_t nvdimmWriteReg(Target* i_nvdimm, if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmWriteReg() nvdimm[%X] - failed to read the current page", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); break; } @@ -209,7 +233,7 @@ errlHndl_t nvdimmWriteReg(Target* i_nvdimm, if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmWriteReg() nvdimm[%X] - failed to verify page", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); break; } } @@ -222,8 +246,8 @@ errlHndl_t nvdimmWriteReg(Target* i_nvdimm, DEVICE_NVDIMM_ADDRESS(l_reg_addr)); }while(0); - TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Write HUID %X, page = 0x%X, addr 0x%X = %X", - TARGETING::get_huid(i_nvdimm), l_reg_page, l_reg_addr, i_data); + TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Write HUID 0x%X, page = 0x%X, addr 0x%X = 0x%X", + get_huid(i_nvdimm), l_reg_page, l_reg_addr, i_data); return l_err; } @@ -239,9 +263,9 @@ errlHndl_t nvdimmWriteReg(Target* i_nvdimm, void nvdimmSetStatusFlag(Target *i_nvdimm, const uint8_t i_status_flag) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmSetStatusFlag() HUID[%X], i_status_flag[%X]" - ,TARGETING::get_huid(i_nvdimm), i_status_flag); + ,get_huid(i_nvdimm), i_status_flag); - auto l_statusFlag = i_nvdimm->getAttr<TARGETING::ATTR_NV_STATUS_FLAG>(); + auto l_statusFlag = i_nvdimm->getAttr<ATTR_NV_STATUS_FLAG>(); switch(i_status_flag) { @@ -268,14 +292,14 @@ void nvdimmSetStatusFlag(Target *i_nvdimm, const uint8_t i_status_flag) default: assert(0, "nvdimmSetStatusFlag() HUID[%X], i_status_flag[%X] invalid flag!", - TARGETING::get_huid(i_nvdimm), i_status_flag); + get_huid(i_nvdimm), i_status_flag); break; } - i_nvdimm->setAttr<TARGETING::ATTR_NV_STATUS_FLAG>(l_statusFlag); + i_nvdimm->setAttr<ATTR_NV_STATUS_FLAG>(l_statusFlag); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmSetStatusFlag() HUID[%X], i_status_flag[%X]" - ,TARGETING::get_huid(i_nvdimm), i_status_flag); + ,get_huid(i_nvdimm), i_status_flag); } @@ -289,7 +313,7 @@ void nvdimmSetStatusFlag(Target *i_nvdimm, const uint8_t i_status_flag) */ errlHndl_t nvdimmReady(Target *i_nvdimm) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmReady() HUID[%X]",TARGETING::get_huid(i_nvdimm)); + TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmReady() HUID[%X]",get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; uint8_t l_data = 0x0; @@ -305,12 +329,12 @@ errlHndl_t nvdimmReady(Target *i_nvdimm) DEVICE_SPD_ADDRESS(SPD::NVM_INIT_TIME)); TRACUCOMP(g_trac_nvdimm, "nvdimmReady() HUID[%X] l_nvm_init_time = %u", - TARGETING::get_huid(i_nvdimm), l_nvm_init_time); + get_huid(i_nvdimm), l_nvm_init_time); if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReady() nvdimm[%X] - failed to retrieve NVM_INIT_TIME from SPD", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); break; } @@ -325,7 +349,7 @@ errlHndl_t nvdimmReady(Target *i_nvdimm) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReady() nvdimm[%X] - error getting ready status[%d]", - TARGETING::get_huid(i_nvdimm), l_data); + get_huid(i_nvdimm), l_data); break; } @@ -342,7 +366,7 @@ errlHndl_t nvdimmReady(Target *i_nvdimm) if ((l_data != NV_READY) && !l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReady() nvdimm[%X] - nvdimm not ready[%d]", - TARGETING::get_huid(i_nvdimm), l_data); + get_huid(i_nvdimm), l_data); /*@ *@errortype *@reasoncode NVDIMM_NOT_READY @@ -355,14 +379,15 @@ errlHndl_t nvdimmReady(Target *i_nvdimm) * for host access. (userdata1 != 0xA5) *@custdesc NVDIMM not ready */ - l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - NVDIMM_CHECK_READY, - NVDIMM_NOT_READY, - NVDIMM_SET_USER_DATA_1(l_data, TARGETING::get_huid(i_nvdimm)), - 0x0, - ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + NVDIMM_CHECK_READY, + NVDIMM_NOT_READY, + NVDIMM_SET_USER_DATA_1(l_data, get_huid(i_nvdimm)), + 0x0, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024 ); + l_err->collectTrace(NVDIMM_COMP_NAME); // If nvdimm is not ready for access by now, this is // a failing indication on the NV controller @@ -374,7 +399,7 @@ errlHndl_t nvdimmReady(Target *i_nvdimm) }while(0); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmReady() HUID[%X] ready[%X]", - TARGETING::get_huid(i_nvdimm), l_data); + get_huid(i_nvdimm), l_data); return l_err; } @@ -391,7 +416,7 @@ errlHndl_t nvdimmReady(Target *i_nvdimm) */ errlHndl_t nvdimmResetController(Target *i_nvdimm) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmResetController() HUID[%X]",TARGETING::get_huid(i_nvdimm)); + TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmResetController() HUID[%X]",get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; do @@ -401,7 +426,7 @@ errlHndl_t nvdimmResetController(Target *i_nvdimm) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmResetController() nvdimm[%X] - error reseting the controller", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); break; } @@ -409,12 +434,12 @@ errlHndl_t nvdimmResetController(Target *i_nvdimm) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmResetController() nvdimm[%X] - not ready after reset.", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); } }while(0); - TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmResetController() HUID[%X]",TARGETING::get_huid(i_nvdimm)); + TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmResetController() HUID[%X]",get_huid(i_nvdimm)); return l_err; } @@ -441,8 +466,8 @@ errlHndl_t nvdimmPollStatus ( Target *i_nvdimm, bool l_done = false; // Get the timeout value for ops_id - assert(i_nvdimm->tryGetAttr<TARGETING::ATTR_NV_OPS_TIMEOUT_MSEC>(l_target_timeout_values), - "nvdimmPollStatus() HUID[%X], failed reading ATTR_NV_OPS_TIMEOUT_MSEC!", TARGETING::get_huid(i_nvdimm)); + assert(i_nvdimm->tryGetAttr<ATTR_NV_OPS_TIMEOUT_MSEC>(l_target_timeout_values), + "nvdimmPollStatus() HUID[%X], failed reading ATTR_NV_OPS_TIMEOUT_MSEC!", get_huid(i_nvdimm)); uint32_t l_timeout = l_target_timeout_values[i_ops_id]; do @@ -472,7 +497,7 @@ errlHndl_t nvdimmPollStatus ( Target *i_nvdimm, { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmPollStatus() nvdimm[%X] - Status timed out ops_id[%d]", - TARGETING::get_huid(i_nvdimm), i_ops_id); + get_huid(i_nvdimm), i_ops_id); /*@ *@errortype *@reasoncode NVDIMM_STATUS_TIMEOUT @@ -486,14 +511,15 @@ errlHndl_t nvdimmPollStatus ( Target *i_nvdimm, * Refer to userdata1 for which operation it timed out. *@custdesc NVDIMM timed out */ - l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE, - NVDIMM_POLL_STATUS, - NVDIMM_STATUS_TIMEOUT, - NVDIMM_SET_USER_DATA_1(i_ops_id, TARGETING::get_huid(i_nvdimm)), - NVDIMM_SET_USER_DATA_2_TIMEOUT(o_poll, l_timeout), - ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_POLL_STATUS, + NVDIMM_STATUS_TIMEOUT, + NVDIMM_SET_USER_DATA_1(i_ops_id, get_huid(i_nvdimm)), + NVDIMM_SET_USER_DATA_2_TIMEOUT(o_poll, l_timeout), + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024 ); + l_err->collectTrace(NVDIMM_COMP_NAME); // May have to move the error handling to the caller // as different op could have different error severity @@ -521,14 +547,14 @@ errlHndl_t nvdimmPollBackupDone(Target* i_nvdimm, uint32_t &o_poll) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollBackupDone() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; l_err = nvdimmPollStatus ( i_nvdimm, SAVE, o_poll); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollBackupDone() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); return l_err; } @@ -548,14 +574,14 @@ errlHndl_t nvdimmPollRestoreDone(Target* i_nvdimm, uint32_t &o_poll) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollRestoreDone() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; l_err = nvdimmPollStatus ( i_nvdimm, RESTORE, o_poll ); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollRestoreDone() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); return l_err; } @@ -575,14 +601,14 @@ errlHndl_t nvdimmPollEraseDone(Target* i_nvdimm, uint32_t &o_poll) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollEraseDone() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; l_err = nvdimmPollStatus ( i_nvdimm, ERASE, o_poll); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollEraseDone() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); return l_err; } @@ -603,14 +629,14 @@ errlHndl_t nvdimmPollESChargeStatus(Target* i_nvdimm, uint32_t &o_poll) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollESChargeDone() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; l_err = nvdimmPollStatus ( i_nvdimm, CHARGE, o_poll ); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollESChargeDone() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); return l_err; } @@ -628,7 +654,7 @@ errlHndl_t nvdimmPollESChargeStatus(Target* i_nvdimm, errlHndl_t nvdimmGetRestoreValid(Target* i_nvdimm, uint8_t & o_rstrValid) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmGetRestoreValid() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; @@ -636,11 +662,11 @@ errlHndl_t nvdimmGetRestoreValid(Target* i_nvdimm, uint8_t & o_rstrValid) if (l_err){ TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X], Error getting restore status!", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); } TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmGetRestoreValid() nvdimm[%X], restore_status[%x],", - TARGETING::get_huid(i_nvdimm), o_rstrValid); + get_huid(i_nvdimm), o_rstrValid); return l_err; } @@ -656,7 +682,7 @@ errlHndl_t nvdimmGetRestoreValid(Target* i_nvdimm, uint8_t & o_rstrValid) errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmSetESPolicy() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; uint8_t l_data; @@ -670,7 +696,7 @@ errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm) { nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOBKUP); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmSetESPolicy() nvdimm[%X]" - "failed to write ES register!",TARGETING::get_huid(i_nvdimm)); + "failed to write ES register!",get_huid(i_nvdimm)); break; } @@ -684,14 +710,14 @@ errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm) { nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOBKUP); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmSetESPolicy() nvdimm[%X]" - "failed to read ES register!",TARGETING::get_huid(i_nvdimm)); + "failed to read ES register!",get_huid(i_nvdimm)); break; } if ((l_data & ES_SUCCESS) != ES_SUCCESS) { TRACFCOMP(g_trac_nvdimm, EXIT_MRK"NDVIMM HUID[%X], nvdimmSetESPolicy() " - "failed!",TARGETING::get_huid(i_nvdimm)); + "failed!",get_huid(i_nvdimm)); /*@ *@errortype *@reasoncode NVDIMM_SET_ES_ERROR @@ -705,14 +731,15 @@ errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm) * NVDIMM is intact *@custdesc NVDIMM encountered error setting the energy source policy */ - l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE, - NVDIMM_SET_ES, - NVDIMM_SET_ES_ERROR, - NVDIMM_SET_USER_DATA_1(CHARGE, TARGETING::get_huid(i_nvdimm)), - 0x0, - ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_SET_ES, + NVDIMM_SET_ES_ERROR, + NVDIMM_SET_USER_DATA_1(CHARGE, get_huid(i_nvdimm)), + 0x0, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024 ); + l_err->collectTrace(NVDIMM_COMP_NAME); // Failure setting the energy source policy could mean error on the // battery or even the cabling @@ -726,7 +753,7 @@ errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm) }while(0); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NDVIMM HUID[%X], nvdimmSetESPolicy()," - ,TARGETING::get_huid(i_nvdimm)); + ,get_huid(i_nvdimm)); return l_err; } @@ -744,7 +771,7 @@ errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm) errlHndl_t nvdimmChangeArmState(Target *i_nvdimm, bool i_state) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmChangeArmState() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; @@ -758,11 +785,11 @@ errlHndl_t nvdimmChangeArmState(Target *i_nvdimm, bool i_state) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmChangeArmState() nvdimm[%X] error %s nvdimm!!", - TARGETING::get_huid(i_nvdimm), i_state? "arming" : "disarming"); + get_huid(i_nvdimm), i_state? "arming" : "disarming"); } TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmChangeArmState() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); return l_err; } @@ -779,7 +806,7 @@ errlHndl_t nvdimmChangeArmState(Target *i_nvdimm, bool i_state) errlHndl_t nvdimmValidImage(Target *i_nvdimm, bool &o_imgValid) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmValidImage(): nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; uint8_t l_data = 0x0; @@ -790,7 +817,7 @@ errlHndl_t nvdimmValidImage(Target *i_nvdimm, bool &o_imgValid) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmValidImage() nvdimm[%X]" - "failed to for image!",TARGETING::get_huid(i_nvdimm) ); + "failed to for image!",get_huid(i_nvdimm) ); } else if(l_data & VALID_IMAGE) { @@ -798,7 +825,7 @@ errlHndl_t nvdimmValidImage(Target *i_nvdimm, bool &o_imgValid) } TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmValidImage(): nvdimm[%X] ret[%X]", - TARGETING::get_huid(i_nvdimm), l_data); + get_huid(i_nvdimm), l_data); return l_err; } @@ -845,8 +872,8 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) continue; } - TARGETING::TargetHandleList l_mcaList; - getParentAffinityTargets(l_mcaList, *it, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA); + TargetHandleList l_mcaList; + getParentAffinityTargets(l_mcaList, *it, CLASS_UNIT, TYPE_MCA); assert(l_mcaList.size(), "nvdimmRestore() failed to find parent MCA."); fapi2::Target<fapi2::TARGET_TYPE_MCA> l_fapi_mca(l_mcaList[0]); @@ -860,7 +887,7 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmRestore() HUID[%X] i_mpipl[%u] failed to de-assert resetn!", - TARGETING::get_huid(*it), i_mpipl); + get_huid(*it), i_mpipl); nvdimmSetStatusFlag(*it, NSTD_ERR_NOPRSV); //@TODO RTC 199645 - add HW callout on dimm target @@ -878,7 +905,7 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmRestore() HUID[%X] self_refresh_entry failed!", - TARGETING::get_huid(*it)); + get_huid(*it)); nvdimmSetStatusFlag(*it, NSTD_ERR_NOPRSV); //@TODO RTC 199645 - add HW callout on dimm target @@ -909,7 +936,7 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) { nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV); TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X], error initiating restore!!", - TARGETING::get_huid(l_nvdimm)); + get_huid(l_nvdimm)); break; } } @@ -930,7 +957,7 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) { nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV); TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X], error restoring!", - TARGETING::get_huid(l_nvdimm)); + get_huid(l_nvdimm)); errlCommit(l_err, NVDIMM_COMP_ID); break; } @@ -949,14 +976,14 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) { nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmRestore Target[%X] error validating restore status!", - TARGETING::get_huid(l_nvdimm)); + get_huid(l_nvdimm)); break; } if ((l_rstrValid & RSTR_SUCCESS) != RSTR_SUCCESS){ TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X] restoreValid[%d], restore failed!", - TARGETING::get_huid(l_nvdimm), l_rstrValid); + get_huid(l_nvdimm), l_rstrValid); /*@ *@errortype *@reasoncode NVDIMM_RESTORE_FAILED @@ -969,14 +996,15 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) * restore timeout (Controller error) *@custdesc NVDIMM failed to restore data */ - l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - NVDIMM_RESTORE, - NVDIMM_RESTORE_FAILED, - TARGETING::get_huid(l_nvdimm), - 0x0, - ERRORLOG::ErrlEntry::NO_SW_CALLOUT); - - l_err->collectTrace(NVDIMM_COMP_NAME, 1024 ); + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + NVDIMM_RESTORE, + NVDIMM_RESTORE_FAILED, + get_huid(l_nvdimm), + 0x0, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT); + + l_err->collectTrace(NVDIMM_COMP_NAME); nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV); // Invalid restore could be due to dram not in self-refresh @@ -997,8 +1025,8 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) for (const auto & l_nvdimm : i_nvdimmList) { - TARGETING::TargetHandleList l_mcaList; - getParentAffinityTargets(l_mcaList, l_nvdimm, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA); + TargetHandleList l_mcaList; + getParentAffinityTargets(l_mcaList, l_nvdimm, CLASS_UNIT, TYPE_MCA); assert(l_mcaList.size(), "nvdimmRestore() failed to find parent MCA."); fapi2::Target<fapi2::TARGET_TYPE_MCA> l_fapi_mca(l_mcaList[0]); @@ -1010,7 +1038,7 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmRestore() HUID[%X] post_restore_transition failed!", - TARGETING::get_huid(l_nvdimm)); + get_huid(l_nvdimm)); // Commit the error from the HWP nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV); @@ -1043,7 +1071,7 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl) errlHndl_t nvdimmCheckEraseSuccess(Target *i_nvdimm) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmCheckEraseSuccess() : nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); uint8_t l_data = 0; errlHndl_t l_err = nullptr; @@ -1053,13 +1081,13 @@ errlHndl_t nvdimmCheckEraseSuccess(Target *i_nvdimm) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckEraseSuccess() nvdimm[%X]" - "failed to read erase status reg!",TARGETING::get_huid(i_nvdimm)); + "failed to read erase status reg!",get_huid(i_nvdimm)); } else if ((l_data & ERASE_SUCCESS) != ERASE_SUCCESS) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckEraseSuccess() nvdimm[%X]" - "failed to erase!",TARGETING::get_huid(i_nvdimm)); + "failed to erase!",get_huid(i_nvdimm)); /*@ *@errortype *@reasoncode NVDIMM_ERASE_FAILED @@ -1072,14 +1100,15 @@ errlHndl_t nvdimmCheckEraseSuccess(Target *i_nvdimm) * on NVDIMM. Likely due to timeout and/or controller error *@custdesc NVDIMM error erasing data image */ - l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE, - NVDIMM_CHECK_ERASE, - NVDIMM_ERASE_FAILED, - NVDIMM_SET_USER_DATA_1(ERASE, TARGETING::get_huid(i_nvdimm)), - 0x0, - ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); - - l_err->collectTrace(NVDIMM_COMP_NAME, 1024 ); + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_CHECK_ERASE, + NVDIMM_ERASE_FAILED, + NVDIMM_SET_USER_DATA_1(ERASE, get_huid(i_nvdimm)), + 0x0, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + + l_err->collectTrace(NVDIMM_COMP_NAME); errlCommit( l_err, NVDIMM_COMP_ID ); // Failure to erase could mean internal NV controller error and/or @@ -1091,7 +1120,7 @@ errlHndl_t nvdimmCheckEraseSuccess(Target *i_nvdimm) } TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmCheckEraseSuccess(): nvdimm[%X] ret[%X]", - TARGETING::get_huid(i_nvdimm), l_data); + get_huid(i_nvdimm), l_data); return l_err; } @@ -1107,7 +1136,7 @@ errlHndl_t nvdimmCheckEraseSuccess(Target *i_nvdimm) errlHndl_t nvdimmEraseNF(Target *i_nvdimm) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmEraseNF() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; @@ -1117,7 +1146,7 @@ errlHndl_t nvdimmEraseNF(Target *i_nvdimm) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X] error initiating erase!!", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); break; } @@ -1132,7 +1161,7 @@ errlHndl_t nvdimmEraseNF(Target *i_nvdimm) }while(0); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmEraseNF() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); return l_err; } @@ -1151,15 +1180,15 @@ errlHndl_t nvdimmEraseNF(Target *i_nvdimm) errlHndl_t nvdimmOpenPage(Target *i_nvdimm, uint8_t i_page) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmOpenPage nvdimm[%X]", TARGETING::get_huid(i_nvdimm)); + TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmOpenPage nvdimm[%X]", get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; bool l_success = false; uint8_t l_data; uint32_t l_poll = 0; uint32_t l_target_timeout_values[6]; - assert(i_nvdimm->tryGetAttr<TARGETING::ATTR_NV_OPS_TIMEOUT_MSEC>(l_target_timeout_values), - "nvdimmOpenPage() HUID[%X], failed reading ATTR_NV_OPS_TIMEOUT_MSEC!", TARGETING::get_huid(i_nvdimm)); + assert(i_nvdimm->tryGetAttr<ATTR_NV_OPS_TIMEOUT_MSEC>(l_target_timeout_values), + "nvdimmOpenPage() HUID[%X], failed reading ATTR_NV_OPS_TIMEOUT_MSEC!", get_huid(i_nvdimm)); uint32_t l_timeout = l_target_timeout_values[PAGE_SWITCH]; @@ -1172,7 +1201,7 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm, if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmOpenPage nvdimm[%X]" - "error writing to page change reg", TARGETING::get_huid(i_nvdimm)); + "error writing to page change reg", get_huid(i_nvdimm)); break; } @@ -1205,7 +1234,7 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm, if (!l_success && !l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmOpenPage nvdimm[%X] openpage_success[%d]," - "failure to open page!", TARGETING::get_huid(i_nvdimm), static_cast<uint8_t>(l_success)); + "failure to open page!", get_huid(i_nvdimm), static_cast<uint8_t>(l_success)); /*@ *@errortype @@ -1220,12 +1249,13 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm, *@custdesc Encountered error performing internal operaiton * on NVDIMM */ - l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - NVDIMM_POLL_STATUS, - NVDIMM_STATUS_TIMEOUT, - NVDIMM_SET_USER_DATA_1(PAGE_SWITCH, TARGETING::get_huid(i_nvdimm)), - NVDIMM_SET_USER_DATA_2_TIMEOUT(l_poll, l_timeout), - ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + NVDIMM_OPEN_PAGE, + NVDIMM_OPEN_PAGE_TIMEOUT, + NVDIMM_SET_USER_DATA_1(PAGE_SWITCH, get_huid(i_nvdimm)), + NVDIMM_SET_USER_DATA_2_TIMEOUT(l_poll, l_timeout), + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); l_err->collectTrace(NVDIMM_COMP_NAME, 256 ); @@ -1238,7 +1268,7 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm, }while(0); TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmOpenPage nvdimm[%X] nvdimmOpenPage.success[%d]," - ,TARGETING::get_huid(i_nvdimm), static_cast<uint8_t>(l_success)); + ,get_huid(i_nvdimm), static_cast<uint8_t>(l_success)); return l_err; } @@ -1255,12 +1285,12 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm, errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmGetTimeoutVal() HUID[%X]" - ,TARGETING::get_huid(i_nvdimm)); + ,get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; uint8_t l_data = 0; uint32_t timeout_map[6]; - i_nvdimm->tryGetAttr<TARGETING::ATTR_NV_OPS_TIMEOUT_MSEC>(timeout_map); + i_nvdimm->tryGetAttr<ATTR_NV_OPS_TIMEOUT_MSEC>(timeout_map); //Get the 6 main timeout values for (uint8_t i = SAVE; i <= CHARGE; i++) @@ -1287,7 +1317,7 @@ errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmGetTimeoutVal() HUID[%X] " - "error reading timeout value for op[%d]!", TARGETING::get_huid(i_nvdimm), i); + "error reading timeout value for op[%d]!", get_huid(i_nvdimm), i); break; } @@ -1299,16 +1329,16 @@ errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm) } TRACUCOMP(g_trac_nvdimm, "nvdimmGetTimeoutVal() HUID[%X], timeout_idx[%d], timeout_ms[%d]" - ,TARGETING::get_huid(i_nvdimm), timeoutInfoTable[i].idx, timeout_map[i]); + ,get_huid(i_nvdimm), timeoutInfoTable[i].idx, timeout_map[i]); } if (!l_err) { - i_nvdimm->setAttr<TARGETING::ATTR_NV_OPS_TIMEOUT_MSEC>(timeout_map); + i_nvdimm->setAttr<ATTR_NV_OPS_TIMEOUT_MSEC>(timeout_map); } TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmGetTimeoutVal() HUID[%X]" - ,TARGETING::get_huid(i_nvdimm)); + ,get_huid(i_nvdimm)); return l_err; } @@ -1332,8 +1362,8 @@ errlHndl_t nvdimmEpowSetup(TargetHandleList &i_nvdimmList) for (TargetHandleList::iterator it = i_nvdimmList.begin(); it != i_nvdimmList.end();) { - TARGETING::TargetHandleList l_mcaList; - getParentAffinityTargets(l_mcaList, *it, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA); + TargetHandleList l_mcaList; + getParentAffinityTargets(l_mcaList, *it, CLASS_UNIT, TYPE_MCA); assert(l_mcaList.size(), "nvdimmEpowSetup() failed to find parent MCA."); fapi2::Target<fapi2::TARGET_TYPE_MCA> l_fapi_mca(l_mcaList[0]); @@ -1345,7 +1375,7 @@ errlHndl_t nvdimmEpowSetup(TargetHandleList &i_nvdimmList) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmEpowSetup() HUID[%X] failed to setup epow!", - TARGETING::get_huid(*it)); + get_huid(*it)); nvdimmSetStatusFlag(*it, NSTD_ERR_NOPRSV); break; @@ -1359,6 +1389,8 @@ errlHndl_t nvdimmEpowSetup(TargetHandleList &i_nvdimmList) return l_err; } + + /** * @brief Entry function to NVDIMM restore * - Restore image from NVDIMM NAND flash to DRAM @@ -1371,8 +1403,8 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_restore()"); errlHndl_t l_err = nullptr; - TARGETING::Target* l_sys = nullptr; - TARGETING::targetService().getTopLevelTarget( l_sys ); + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); assert(l_sys, "nvdimm_restore: no TopLevelTarget"); uint8_t l_mpipl = l_sys->getAttr<ATTR_IS_MPIPL_HB>(); @@ -1408,7 +1440,7 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) { nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() nvdimm[%X], error backing up the DRAM!", - TARGETING::get_huid(l_nvdimm)); + get_huid(l_nvdimm)); errlCommit(l_err, NVDIMM_COMP_ID); break; } @@ -1456,13 +1488,565 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) } /** - * @brief Entry function to NVDIMM generate keys - * Generate encryption keys if required and set the FW key attribute + * @brief NVDIMM initialization + * - Checks for ready state + * - Gathers timeout values + * - Waits for the ongoing backup to complete + * - Disarms the trigger for draminit + * + * @param[in] i_nvdimm - nvdimm target + * */ -void nvdimm_gen_keys(TargetHandleList &i_nvdimmList) +void nvdimm_init(Target *i_nvdimm) +{ + TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_init() nvdimm[%X]", + get_huid(i_nvdimm)); + + errlHndl_t l_err = nullptr; + + do + { + l_err = nvdimmReady(i_nvdimm); + + if (l_err) + { + nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR); + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], controller not ready", + get_huid(i_nvdimm)); + errlCommit(l_err, NVDIMM_COMP_ID); + break; + } + + // Get the timeout values for the major ops at init + l_err = nvdimmGetTimeoutVal(i_nvdimm); + if (l_err) + { + nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR); + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], error retrieving timeout values", + get_huid(i_nvdimm)); + errlCommit(l_err, NVDIMM_COMP_ID); + break; + } + + //Check save progress + uint32_t l_poll = 0; + l_err = nvdimmPollBackupDone(i_nvdimm, l_poll); + + if (l_err) + { + nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOPRSV); + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], error backing up the DRAM!", + get_huid(i_nvdimm)); + errlCommit(l_err, NVDIMM_COMP_ID); + break; + } + + // Disarm the ddr_resetn here in case it came in armed. When the nvdimm is + // armed the reset_n is masked off from the host, meaning the drams won't + // be able to get reset properly later, causing training to fail. + l_err = nvdimmChangeArmState(i_nvdimm, DISARM_TRIGGER); + + if (l_err) + { + nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOPRSV); + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_init() nvdimm[%X], error disarming the nvdimm!", + get_huid(i_nvdimm)); + errlCommit(l_err, NVDIMM_COMP_ID); + break; + } + + }while(0); + + TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_init() nvdimm[%X]", + get_huid(i_nvdimm)); +} + + +errlHndl_t nvdimm_getRandom(uint8_t* o_genData) +{ + errlHndl_t l_err = nullptr; + uint8_t l_xtraData[ENC_KEY_SIZE] = {0}; + + do + { + // Get a pointer to the TPM + Target* l_tpm = nullptr; + l_err = nvdimm_getTPM(l_tpm); + if (l_err) + { + break; + } + + // Get a random number from the TPM + l_err = TRUSTEDBOOT::GetRandom(l_tpm, ENC_KEY_SIZE, o_genData); + if (l_err) + { + break; + } + + // Validate and update the random number + // Retry if more randomness required + do + { + //Get replacement data + l_err = TRUSTEDBOOT::GetRandom(l_tpm, ENC_KEY_SIZE, l_xtraData); + if (l_err) + { + break; + } + + }while (nvdimm_keyifyRandomNumber(o_genData, l_xtraData)); + + } while(0); + + return l_err; +} + + +errlHndl_t nvdimm_getTPM(Target*& o_tpm) +{ + errlHndl_t l_err = nullptr; + + do + { + // Get all functional TPMs + TargetHandleList l_tpmList; + TRUSTEDBOOT::getTPMs(l_tpmList, + TRUSTEDBOOT::TPM_FILTER::ALL_FUNCTIONAL); + + if (l_tpmList.size()) + { + o_tpm = l_tpmList[0]; + break; + } + + // No TPMs, generate error + TRACFCOMP(g_trac_nvdimm,ERR_MRK"nvdimm_getTPM() No functional TPMs found"); + + /*@ + *@errortype + *@reasoncode NVDIMM_TPM_NOT_FOUND + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_GET_TPM + *@devdesc Functional TPM required to generate encryption keys + *@custdesc NVDIMM error generating encryption keys + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_GET_TPM, + NVDIMM_TPM_NOT_FOUND, + 0x0, + 0x0, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + + l_err->collectTrace(NVDIMM_COMP_NAME); + + // Get all TPMs + TRUSTEDBOOT::getTPMs(l_tpmList, + TRUSTEDBOOT::TPM_FILTER::ALL_IN_BLUEPRINT); + if (l_tpmList.size() == 0) + { + // No TPMs, we probably have nvdimms enabled + // when they should not be + l_err->addProcedureCallout( + HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH); + } + else + { + // If a TPM exists it must be deconfigured + l_err->addProcedureCallout( + HWAS::EPUB_PRC_FIND_DECONFIGURED_PART, + HWAS::SRCI_PRIORITY_HIGH); + l_err->addProcedureCallout( + HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_MED); + } + + }while(0); + + // Functional TPM not found + return l_err; +} + + +bool nvdimm_encrypt_unlock(TargetHandleList &i_nvdimmList) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_encrypt_unlock()"); + errlHndl_t l_err = nullptr; + bool l_success = true; + + do + { + // Get the sys pointer, attribute keys are system level + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); + assert(l_sys, "nvdimm_encrypt_unlock() no TopLevelTarget"); + + // Exit if encryption is not enabled via the attribute + if (!l_sys->getAttr<ATTR_NVDIMM_ENCRYPTION_ENABLE>()) + { + TRACFCOMP(g_trac_nvdimm,"ATTR_NVDIMM_ENCRYPTION_ENABLE=0"); + break; + } + + // Get the FW key attributes + auto l_attrKeysFw = + l_sys->getAttrAsStdArr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(); + + // Cast to key data struct type for easy access to each key + nvdimmKeyData_t* l_keysFw = + reinterpret_cast<nvdimmKeyData_t*>(&l_attrKeysFw); + + // Check for valid key attribute data + l_err = nvdimm_checkValidAttrKeys(l_keysFw); + if (l_err) + { + break; + } + + // Check encryption unlock for all nvdimms + for (const auto & l_nvdimm : i_nvdimmList) + { + // Get encryption state in the config/status reg + encryption_config_status_t l_encStatus; + l_encStatus.whole = 0; + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_CONFIG_STATUS, + l_encStatus.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_unlock() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + // Already unlocked or not enabled then exit + if (l_encStatus.encryption_unlocked || + !l_encStatus.encryption_enabled) + { + break; + } + + // Else encryption is enabled but needs unlock + TRACFCOMP(g_trac_nvdimm, "nvdimm_encrypt_unlock() nvdimm[%X] enabled, unlocking...",get_huid(l_nvdimm)); + + // Set the Unlock Access Key Reg + l_err = nvdimm_setKeyReg(l_nvdimm, + l_keysFw->ak, + ENCRYPTION_ACCESS_KEY_UNLOCK, + ENCRYPTION_ACCESS_KEY_VERIFY, + false); + if (l_err) + { + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + // Verify encryption is unlocked + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_CONFIG_STATUS, + l_encStatus.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_unlock() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS after unlock",get_huid(l_nvdimm)); + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + if (!l_encStatus.encryption_unlocked) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_unlock() nvdimm[%X] encryption unlock failed, expected ENCRYPTION_CONFIG_STATUS=0x%.02X, expected=0x1F ",get_huid(l_nvdimm),l_encStatus.whole); + /*@ + *@errortype + *@reasoncode NVDIMM_ENCRYPTION_UNLOCK_FAILED + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_ENCRYPT_UNLOCK + *@userdata1 NVDIMM HUID + *@userdata2 ENCRYPTION_CONFIG_STATUS + *@devdesc NVDIMM failed to unlock encryption + *@custdesc NVDIMM encryption error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_ENCRYPT_UNLOCK, + NVDIMM_ENCRYPTION_UNLOCK_FAILED, + get_huid(l_nvdimm), + l_encStatus.whole, + 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); + + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + errlCommit( l_err, NVDIMM_COMP_ID ); + l_success = false; + } + else + { + TRACFCOMP(g_trac_nvdimm, "nvdimm_encrypt_unlock() nvdimm[%X] encryption is unlocked 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + } + } + }while(0); + + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_encrypt_unlock()"); + return l_success; +} + + +#endif + + +bool nvdimm_keyifyRandomNumber(uint8_t* o_genData, uint8_t* i_xtraData) +{ + bool l_failed = false; + uint32_t l_xtraByte = 0; + + for (uint32_t l_byte = 0; l_byte < ENC_KEY_SIZE; l_byte++) + { + if ((o_genData[l_byte] != KEY_TERMINATE_BYTE) && + (o_genData[l_byte] != KEY_ABORT_BYTE)) + { + // This byte is valid + continue; + } + + // This byte is not valid, replace it + // Find a valid byte in the replacement data + while ((i_xtraData[l_xtraByte] == KEY_TERMINATE_BYTE) || + (i_xtraData[l_xtraByte] == KEY_ABORT_BYTE)) + { + l_xtraByte++; + + if (l_xtraByte == ENC_KEY_SIZE) + { + l_failed = true; + break; + } + } + + if (l_failed) + { + break; + } + + // Replace the invalid byte with the valid extra byte + o_genData[l_byte] = i_xtraData[l_xtraByte]; + } + + return l_failed; +} + + +bool nvdimm_validRandomNumber(uint8_t* i_genData) +{ + bool l_valid = true; + for (uint32_t l_byte = 0; l_byte < ENC_KEY_SIZE; l_byte++) + { + if ((i_genData[l_byte] == KEY_TERMINATE_BYTE) || + (i_genData[l_byte] == KEY_ABORT_BYTE)) + { + l_valid = false; + break; + } + } + return l_valid; +} + + +errlHndl_t nvdimm_checkValidAttrKeys( nvdimmKeyData_t* i_attrData ) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_gen_keys()"); errlHndl_t l_err = nullptr; + bool l_valid = false; + + do + { + l_valid = nvdimm_validRandomNumber(i_attrData->rs); + if (!l_valid) + { + break; + } + l_valid = nvdimm_validRandomNumber(i_attrData->ek); + if (!l_valid) + { + break; + } + l_valid = nvdimm_validRandomNumber(i_attrData->ak); + if (!l_valid) + { + break; + } + }while(0); + + if (!l_valid) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_checkValidAttrKeys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW contains invalid data"); + /*@ + *@errortype + *@reasoncode NVDIMM_ENCRYPTION_INVALID_ATTRIBUTE + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_CHECK_VALID_ATTR_DATA + *@devdesc ATTR_NVDIMM_ENCRYPTION_KEYS_FW has invalid data + *@custdesc NVDIMM encryption error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_CHECK_VALID_ATTR_DATA, + NVDIMM_ENCRYPTION_INVALID_ATTRIBUTE, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT ); + + l_err->collectTrace(NVDIMM_COMP_NAME); + } + + return l_err; +} + + +errlHndl_t nvdimm_handleConflictingKeys( + ATTR_NVDIMM_ENCRYPTION_KEYS_FW_typeStdArr& i_attrKeysFw, + ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_typeStdArr& i_attrKeysAnchor) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_handleConflictingKeys()"); + errlHndl_t l_err = nullptr; + bool l_validKeyFound = false; + + // Recast to key data type to simplify parsing + nvdimmKeyData_t* l_keysFw = + reinterpret_cast<nvdimmKeyData_t*>(&i_attrKeysFw); + nvdimmKeyData_t* l_keysAnchor = + reinterpret_cast<nvdimmKeyData_t*>(&i_attrKeysAnchor); + + // Get the nvdimm target pointers + TargetHandleList l_nvdimmTargetList; + nvdimm_getNvdimmList(l_nvdimmTargetList); + for (const auto & l_nvdimm : l_nvdimmTargetList) + { + // Write the EK test reg with the FW attr value + l_err = nvdimm_setKeyReg(l_nvdimm, + l_keysFw->ek, + ENCRYPTION_ERASE_KEY_TEST, + ENCRYPTION_ERASE_KEY_TEST_VERIFY, + false); + if (l_err) + { + // RTC 210689 Handle return values + break; + } + + // Check for erase key valid in the validation reg + encryption_key_validation_t l_keyValid = {0}; + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_KEY_VALIDATION, + l_keyValid.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_handleConflictingKeys() nvdimm[%X] error reading ENCRYPTION_KEY_VALIDATION",get_huid(l_nvdimm)); + // RTC 210689 Handle return values + break; + } + if (l_keyValid.erase_key_valid) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_handleConflictingKeys() nvdimm[%X] ATTR_NVDIMM_ENCRYPTION_KEYS_FW valid",get_huid(l_nvdimm)); + l_validKeyFound = true; + // Send attr to HWSV if at runtime + // RTC:210692 Update HWSV with key attribute value + break; + } + + // Write the EK test reg with the Anchor attr value + l_err = nvdimm_setKeyReg(l_nvdimm, + l_keysAnchor->ek, + ENCRYPTION_ERASE_KEY_TEST, + ENCRYPTION_ERASE_KEY_TEST_VERIFY, + false); + if (l_err) + { + break; + } + + // Check for erase key valid in the validation reg + l_keyValid.whole = 0; + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_KEY_VALIDATION, + l_keyValid.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_handleConflictingKeys() nvdimm[%X] error reading ENCRYPTION_KEY_VALIDATION",get_huid(l_nvdimm)); + break; + } + if (l_keyValid.erase_key_valid) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_handleConflictingKeys() nvdimm[%X] ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR valid",get_huid(l_nvdimm)); + l_validKeyFound = true; + // Copy anchor attr value to FW attribute + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); + assert(l_sys, "nvdimm_handleConflictingKeys: no TopLevelTarget"); + l_sys->setAttr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(reinterpret_cast<ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type&>(i_attrKeysAnchor)); + break; + } + } + + if (!l_validKeyFound) + { + // Neither key attribute is valid + TRACFCOMP(g_trac_nvdimm,ERR_MRK"nvdimm_handleConflictingKeys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW and ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR invalid."); + /*@ + *@errortype + *@reasoncode NVDIMM_ENCRYPTION_KEY_ATTRS_INVALID + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_HANDLE_CONFLICTING_KEYS + *@devdesc NVDIMM encryption key attributes invalid + *@custdesc NVDIMM encryption error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_HANDLE_CONFLICTING_KEYS, + NVDIMM_ENCRYPTION_KEY_ATTRS_INVALID, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT ); + + l_err->collectTrace(NVDIMM_COMP_NAME); + } + + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_handleConflictingKeys()"); + return l_err; +} + + +void nvdimm_getNvdimmList(TargetHandleList &o_nvdimmTargetList) +{ + // Check for any NVDIMMs after the mss_power_cleanup + TargetHandleList l_dimmTargetList; + getAllLogicalCards(l_dimmTargetList, TYPE_DIMM); + + // Walk the dimm list and collect all the nvdimm targets + for (auto const l_dimm : l_dimmTargetList) + { + if (isNVDIMM(l_dimm)) + { + o_nvdimmTargetList.push_back(l_dimm); + } + } +} + + +bool nvdimm_gen_keys(void) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_gen_keys()"); + errlHndl_t l_err = nullptr; + bool l_success = true; do { @@ -1474,235 +2058,634 @@ void nvdimm_gen_keys(TargetHandleList &i_nvdimmList) // Exit if encryption is not enabled via the attribute if (!l_sys->getAttr<ATTR_NVDIMM_ENCRYPTION_ENABLE>()) { + TRACFCOMP(g_trac_nvdimm,"ATTR_NVDIMM_ENCRYPTION_ENABLE=0"); break; } - // Get the FW attribute - ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type l_attrKeysFw = {0}; - assert(l_sys->tryGetAttr - <ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysFw), - "nvdimm_gen_keys() Failed getting ATTR_NVDIMM_ENCRYPTION_KEYS_FW"); - - // FW attribute checks - size_t l_attrSizeFw = sizeof(ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type); - // Attribute size must be a multiple of the key size - assert((l_attrSizeFw % NUM_KEYS_IN_ATTR) == 0, - "nvdimm_gen_keys() Size of ATTR_NVDIMM_ENCRYPTION_KEYS_FW is not a multiple of the key size"); - // Attribute key size must not exceed max size - assert((l_attrSizeFw / NUM_KEYS_IN_ATTR) <= MAX_KEY_SIZE, - "nvdimm_gen_keys() Size of keys in ATTR_NVDIMM_ENCRYPTION_KEYS_FW is greater than MAX_KEY_SIZE"); - - // Check for FW attribute = zero - ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type l_fwCompare = {0}; - bool l_attrIsZeroFw = memcmp(l_attrKeysFw, l_fwCompare, l_attrSizeFw) == 0; - - // Get the anchor attribute - ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_type l_attrKeysAnchor = {0}; - assert(l_sys->tryGetAttr - <ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR>(l_attrKeysAnchor), - "nvdimm_gen_keys() Failed getting ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR"); - - // Anchor attribute checks - size_t l_attrSizeAnchor = sizeof(ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_type); - // Attribute size must be a multiple of the key size - assert((l_attrSizeAnchor % NUM_KEYS_IN_ATTR) == 0, - "nvdimm_gen_keys() Size of ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR is not a multiple of the key size"); - // Attribute key size must not exceed max size - assert((l_attrSizeAnchor / NUM_KEYS_IN_ATTR) <= MAX_KEY_SIZE, - "nvdimm_gen_keys() Size of keys in ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR is greater than MAX_KEY_SIZE"); - - // Check for Anchor attribute = zero - ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_type l_anchorCompare = {0}; - bool l_attrIsZeroAnchor = memcmp(l_attrKeysAnchor, l_anchorCompare, l_attrSizeAnchor) == 0; + // Key size must be less that max TPM random generator size + static_assert(ENC_KEY_SIZE <= MAX_TPM_SIZE, + "nvdimm_gen_keys() ENC_KEY_SIZE is greater than MAX_TPM_SIZE"); + + // Key attributes should be same size + static_assert( sizeof(ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_type) == + sizeof(ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type), + "nvdimm_gen_keys() size of ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_type does not match ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type"); + + // Get the key attributes + auto l_attrKeysFw = + l_sys->getAttrAsStdArr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(); + auto l_attrKeysAn = + l_sys->getAttrAsStdArr<ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR>(); + + // Check the attribute sizes + static_assert(sizeof(l_attrKeysFw) == (NUM_KEYS_IN_ATTR * ENC_KEY_SIZE), + "nvdimm_gen_keys() Size of ATTR_NVDIMM_ENCRYPTION_KEYS_FW does not match NUM_KEYS_IN_ATTR * ENC_KEY_SIZE"); + static_assert(sizeof(l_attrKeysAn) == (NUM_KEYS_IN_ATTR * ENC_KEY_SIZE), + "nvdimm_gen_keys() Size of ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR does not match NUM_KEYS_IN_ATTR * ENC_KEY_SIZE"); + + // Compare attributes to zero + std::array<uint8_t,sizeof(l_attrKeysFw)> l_zero = {0}; + bool l_fwZero = (l_attrKeysFw == l_zero); + bool l_anZero = (l_attrKeysAn == l_zero); // Compare the attribute values - if (!l_attrIsZeroFw && !l_attrIsZeroAnchor) + if (!l_fwZero && !l_anZero) { - if (memcmp(l_attrKeysFw,l_attrKeysAnchor,l_attrSizeFw) == 0) + if (l_attrKeysFw != l_attrKeysAn) { - TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW = ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR"); + // Handle conflicting keys + TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW != ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR"); + l_err = nvdimm_handleConflictingKeys(l_attrKeysFw,l_attrKeysAn); } - if (memcmp(l_attrKeysFw,l_attrKeysAnchor,l_attrSizeFw) != 0) + else { - TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW != ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR"); + TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW == ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR"); } break; } - if (!l_attrIsZeroFw && l_attrIsZeroAnchor) + else if (!l_fwZero && l_anZero) { TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW != 0 and ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR = 0"); break; } - if (l_attrIsZeroFw && !l_attrIsZeroAnchor) + else if (l_fwZero && !l_anZero) { // Set FW attr = Anchor attr TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() Setting ATTR_NVDIMM_ENCRYPTION_KEYS_FW = ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR"); - l_sys->setAttr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysAnchor); + l_sys->setAttrFromStdArr + <ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysAn); break; } - // Both key attributes are zero - // Generate random keys using the TPM hardware - TargetHandleList l_tpmList; - TRUSTEDBOOT::getTPMs(l_tpmList, - TRUSTEDBOOT::TPM_FILTER::ALL_FUNCTIONAL); - if (l_tpmList.size() == 0) + // If we get here then both key attributes are zero, generate new keys + assert(sizeof(l_attrKeysFw) == sizeof(nvdimmKeyData_t), + "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW size does not match nvdimmKeyData_t"); + nvdimmKeyData_t* l_keys = + reinterpret_cast<nvdimmKeyData_t*>(&l_attrKeysFw); + + // Generate Random String (RS) + l_err = nvdimm_getRandom(l_keys->rs); + if (l_err) { - TRACFCOMP(g_trac_nvdimm,ERR_MRK"No functional TPM found, encryption keys not generated."); + break; + } - /*@ - *@errortype - *@reasoncode NVDIMM_TPM_NOT_FOUND - *@severity ERRORLOG_SEV_PREDICTIVE - *@moduleid NVDIMM_GEN_KEYS - *@userdata1 <UNUSED> - *@userdata2 <UNUSED> - *@devdesc Encountered error generating NVDIMM encryption keys - *@custdesc NVDIMM error generating encryption keys - */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_PREDICTIVE, - NVDIMM_GEN_KEYS, - NVDIMM_TPM_NOT_FOUND, - 0x0, - 0x0, - ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + // Generate Erase Key (EK) + l_err = nvdimm_getRandom(l_keys->ek); + if (l_err) + { + break; + } - l_err->collectTrace(NVDIMM_COMP_NAME, 1024 ); + // Generate Access Key (AK) + l_err = nvdimm_getRandom(l_keys->ak); + if (l_err) + { + break; + } - // Get all TPMs - TRUSTEDBOOT::getTPMs(l_tpmList, - TRUSTEDBOOT::TPM_FILTER::ALL_IN_BLUEPRINT); - if (l_tpmList.size() == 0) - { - // No TPMs, we probably have nvdimms enabled - // when they should not be - l_err->addProcedureCallout( - HWAS::EPUB_PRC_HB_CODE, - HWAS::SRCI_PRIORITY_HIGH); - } - else - { - // If a TPM exists it must be deconfigured, - // add callouts accordingly - l_err->addProcedureCallout( - HWAS::EPUB_PRC_FIND_DECONFIGURED_PART, - HWAS::SRCI_PRIORITY_HIGH); - l_err->addProcedureCallout( - HWAS::EPUB_PRC_HB_CODE, - HWAS::SRCI_PRIORITY_MED); - } + // Set the FW attribute + l_sys->setAttrFromStdArr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysFw); - errlCommit( l_err, NVDIMM_COMP_ID ); + }while(0); - // Set the status flag for all nvdimms - for (const auto & l_nvdimm : i_nvdimmList) - { - nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); - } + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_gen_keys() Failed to generate keys, will not set ATTR_NVDIMM_ENCRYPTION_KEYS_FW"); + errlCommit( l_err, NVDIMM_COMP_ID ); + l_success = false; + + // Set the status flag for all nvdimms + TargetHandleList l_nvdimmTargetList; + nvdimm_getNvdimmList(l_nvdimmTargetList); + for (const auto & l_nvdimm : l_nvdimmTargetList) + { + nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + } + } + + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_gen_keys()"); + return l_success; +} + + +bool nvdimm_remove_keys(void) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_remove_keys()"); + bool l_success = true; + + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); + assert(l_sys, "nvdimm_remove_keys() no TopLevelTarget"); + + // Set the FW attribute = 0 + TRACFCOMP(g_trac_nvdimm, "nvdimm_remove_keys() Setting ATTR_NVDIMM_ENCRYPTION_KEYS_FW=0"); + ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type l_attrKeysFw = {0}; + l_sys->setAttr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysFw); + + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_remove_keys()"); + return l_success; +} + + +errlHndl_t nvdimm_setKeyReg(Target* i_nvdimm, + uint8_t* i_keyData, + uint32_t i_keyReg, + uint32_t i_verifyReg, + bool i_secondAttempt) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_setKeyReg(0x%X) reg=0x%X",get_huid(i_nvdimm),i_keyReg); + errlHndl_t l_err = nullptr; + do + { + uint32_t l_byte = 0; + uint8_t l_verifyData = 0x0; + + // Before setting the key reg we need to + // init the verif reg with a random value + uint8_t l_genData[ENC_KEY_SIZE] = {0}; + l_err = nvdimm_getRandom(l_genData); + if (l_err) + { break; } + // Write the verif reg one byte at a time + for (l_byte = 0; l_byte < ENC_KEY_SIZE; l_byte++) + { + // Write the verification byte + l_err = nvdimmWriteReg(i_nvdimm, i_verifyReg, l_genData[l_byte]); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_setKeyReg() huid=0x%X, error writing verif reg=0x%.03X byte=0x%d", get_huid(i_nvdimm), i_verifyReg, l_byte); + break; + } + } - // TPM can only generate up to 34 bytes so gen 1 key at a time - size_t l_genSize = l_attrSizeFw / NUM_KEYS_IN_ATTR; - uint8_t l_genData[l_genSize] = {0}; - for (uint32_t l_key=0; l_key<NUM_KEYS_IN_ATTR; l_key++) + // Delay to allow verif write to complete + nanosleep(0, KEY_WRITE_DELAY_MS*NS_PER_MSEC); + + // Write the reg, one byte at a time + for (l_byte = 0; l_byte < ENC_KEY_SIZE; l_byte++) { - l_err = TRUSTEDBOOT::GetRandom(l_tpmList[0], l_genSize, l_genData); + // Write the key byte + l_err = nvdimmWriteReg(i_nvdimm, i_keyReg, i_keyData[l_byte]); if (l_err) { - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_gen_keys() Failing Trustedboot::GetRandom()"); - errlCommit( l_err, NVDIMM_COMP_ID ); + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_setKeyReg() huid=0x%X, error writing key reg 0x%.03X byte=0x%d", get_huid(i_nvdimm), i_keyReg, l_byte); + break; + } + + // Read the verification byte + l_err = nvdimmReadReg(i_nvdimm, i_verifyReg, l_verifyData); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_setKeyReg() huid=0x%X, error reading verif reg=0x%.03X byte=0x%d", get_huid(i_nvdimm), i_verifyReg, l_byte); + break; + } + + // Verify the key byte + if (l_verifyData != i_keyData[l_byte]) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_setKeyReg() huid=0x%X, key verification failed reg=0x%.03X byte=0x%d set=0x%.02x get=0x%.02x", get_huid(i_nvdimm), i_keyReg, l_byte, i_keyData[l_byte], l_verifyData); + // Write KEY_ABORT_BYTE to abort the key write sequence + l_err = nvdimmWriteReg(i_nvdimm, i_keyReg, KEY_ABORT_BYTE); + if (i_secondAttempt) + { + // Verify check byte failed for the second time + TRACFCOMP(g_trac_nvdimm,ERR_MRK"nvdimm_getTPM() Key verification byte check failed on second attempt."); + /*@ + *@errortype + *@reasoncode NVDIMM_VERIF_BYTE_CHECK_FAILED + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_SET_KEY_REG + *@userdata1 NVDIMM HUID + *@userdata2[0:31] Key Register + *@userdata2[32:63] Verif Register + *@devdesc NVDIMM failed to set encryption register + *@custdesc NVDIMM register error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_SET_KEY_REG, + NVDIMM_VERIF_BYTE_CHECK_FAILED, + get_huid(i_nvdimm), + NVDIMM_SET_USER_DATA_1(i_keyReg,i_verifyReg), + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + + l_err->collectTrace(NVDIMM_COMP_NAME); + l_err->addPartCallout( i_nvdimm, + HWAS::NV_CONTROLLER_PART_TYPE, + HWAS::SRCI_PRIORITY_HIGH); + } + else + { + // Try writing the reg again + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_setKeyReg() huid=0x%X, writing reg=0x%.03X again", get_huid(i_nvdimm), i_keyReg); + l_err = nvdimm_setKeyReg(i_nvdimm, + i_keyData, + i_keyReg, + i_verifyReg, + true); + } + break; } - memcpy( - reinterpret_cast<uint8_t*>(l_attrKeysFw) + (l_key*l_genSize), - l_genData, - l_genSize ); } - // Set the FW attribute - l_sys->setAttr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysFw); + // Delay to allow write to complete + nanosleep(0, KEY_WRITE_DELAY_MS*NS_PER_MSEC); }while(0); - TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_gen_keys()"); + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_setKeyReg(0x%X) reg=0x%X",get_huid(i_nvdimm),i_keyReg); + return l_err; } -/** - * @brief NVDIMM initialization - * - Checks for ready state - * - Gathers timeout values - * - Waits for the ongoing backup to complete - * - Disarms the trigger for draminit - * - * @param[in] i_nvdimm - nvdimm target - * - */ -void nvdimm_init(Target *i_nvdimm) -{ - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_init() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); +bool nvdimm_encrypt_enable(TargetHandleList &i_nvdimmList) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_encrypt_enable()"); errlHndl_t l_err = nullptr; + bool l_success = true; do { - l_err = nvdimmReady(i_nvdimm); + // Get the sys pointer, attribute keys are system level + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); + assert(l_sys, "nvdimm_encrypt_enable() no TopLevelTarget"); - if (l_err) + // Exit if encryption is not enabled via the attribute + if (!l_sys->getAttr<ATTR_NVDIMM_ENCRYPTION_ENABLE>()) { - nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR); - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], controller not ready", - TARGETING::get_huid(i_nvdimm)); - errlCommit(l_err, NVDIMM_COMP_ID); + TRACFCOMP(g_trac_nvdimm,"ATTR_NVDIMM_ENCRYPTION_ENABLE=0"); break; } - // Get the timeout values for the major ops at init - l_err = nvdimmGetTimeoutVal(i_nvdimm); + // Get the FW key attributes + auto l_attrKeysFw = + l_sys->getAttrAsStdArr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(); + + // Cast to key data struct type for easy access to each key + nvdimmKeyData_t* l_keysFw = + reinterpret_cast<nvdimmKeyData_t*>(&l_attrKeysFw); + + // Check for valid key attribute key data + l_err = nvdimm_checkValidAttrKeys(l_keysFw); if (l_err) { - nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR); - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], error retrieving timeout values", - TARGETING::get_huid(i_nvdimm)); - errlCommit(l_err, NVDIMM_COMP_ID); break; } - //Check save progress - uint32_t l_poll = 0; - l_err = nvdimmPollBackupDone(i_nvdimm, l_poll); + // Handle encryption for all nvdimms + for (const auto & l_nvdimm : i_nvdimmList) + { + // Check encryption state in the config/status reg + encryption_config_status_t l_encStatus; + l_encStatus.whole = 0; + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_CONFIG_STATUS, + l_encStatus.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_enable() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } - if (l_err) + // Encryption is enabled and unlocked + if (l_encStatus.encryption_unlocked && + l_encStatus.encryption_enabled) + { + TRACFCOMP(g_trac_nvdimm, "nvdimm_encrypt_enable() nvdimm[%X] enabled and unlocked",get_huid(l_nvdimm)); + continue; + } + + // Need to handle these cases? + if (!(l_encStatus.whole == 0x01)) + { + TRACFCOMP(g_trac_nvdimm, "nvdimm_encrypt_enable() nvdimm[%X] unsupported state 0x%.02X",get_huid(l_nvdimm),l_encStatus.whole); + continue; + } + + // Status = 0x01, enable encryption + // Set the Random String (RS) reg + TRACFCOMP(g_trac_nvdimm,"nvdimm_encrypt_enable() nvdimm[%X] status=0x01 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + l_err = nvdimm_setKeyReg(l_nvdimm, + l_keysFw->rs, + ENCRYPTION_RAMDOM_STRING_SET, + ENCRYPTION_RANDOM_STRING_VERIFY, + false); + if (l_err) + { + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + // Set the Erase Key (EK) Reg + l_err = nvdimm_setKeyReg(l_nvdimm, + l_keysFw->ek, + ENCRYPTION_ERASE_KEY_SET, + ENCRYPTION_ERASE_KEY_VERIFY, + false); + if (l_err) + { + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + // Set the Access Key (AK) Reg + l_err = nvdimm_setKeyReg(l_nvdimm, + l_keysFw->ak, + ENCRYPTION_ACCESS_KEY_SET, + ENCRYPTION_ACCESS_KEY_VERIFY, + false); + if (l_err) + { + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + // Verify encryption is enabled + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_CONFIG_STATUS, + l_encStatus.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_enable() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS after enable",get_huid(l_nvdimm)); + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + if (!(l_encStatus.whole == 0x1F)) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_enable() nvdimm[%X] encryption enable failed, ENCRYPTION_CONFIG_STATUS=0x%.02X, expected=0x1F ",get_huid(l_nvdimm),l_encStatus.whole); + /*@ + *@errortype + *@reasoncode NVDIMM_ENCRYPTION_ENABLE_FAILED + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_ENCRYPT_ENABLE + *@userdata1 NVDIMM HUID + *@userdata2 ENCRYPTION_CONFIG_STATUS + *@devdesc NVDIMM failed to enable encryption + *@custdesc NVDIMM encryption error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_ENCRYPT_ENABLE, + NVDIMM_ENCRYPTION_ENABLE_FAILED, + get_huid(l_nvdimm), + l_encStatus.whole, + 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); + + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + } + else + { + TRACFCOMP(g_trac_nvdimm, "nvdimm_encrypt_enable() nvdimm[%X] encryption is enabled 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + } + } + }while(0); + + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_encrypt_enable()"); + return l_success; +} + + +bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_crypto_erase()"); + errlHndl_t l_err = nullptr; + bool l_success = true; + + do + { + // Get the sys pointer, attribute keys are system level + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); + assert(l_sys, "nvdimm_crypto_erase: no TopLevelTarget"); + + // Exit if encryption is not enabled via the attribute + if (!l_sys->getAttr<ATTR_NVDIMM_ENCRYPTION_ENABLE>()) { - nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOPRSV); - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], error backing up the DRAM!", - TARGETING::get_huid(i_nvdimm)); - errlCommit(l_err, NVDIMM_COMP_ID); + TRACFCOMP(g_trac_nvdimm,"ATTR_NVDIMM_ENCRYPTION_ENABLE=0"); break; } - // Disarm the ddr_resetn here in case it came in armed. When the nvdimm is - // armed the reset_n is masked off from the host, meaning the drams won't - // be able to get reset properly later, causing training to fail. - l_err = nvdimmChangeArmState(i_nvdimm, DISARM_TRIGGER); + // Get the FW key attributes + auto l_attrKeysFw = + l_sys->getAttrAsStdArr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(); + + // Cast to key data struct type for easy access to each key + nvdimmKeyData_t* l_keysFw = + reinterpret_cast<nvdimmKeyData_t*>(&l_attrKeysFw); + // Check for valid key attribute key data + l_err = nvdimm_checkValidAttrKeys(l_keysFw); if (l_err) { - nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOPRSV); - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_init() nvdimm[%X], error disarming the nvdimm!", - TARGETING::get_huid(i_nvdimm)); - errlCommit(l_err, NVDIMM_COMP_ID); break; } + // Handle erase for all nvdimms + for (const auto & l_nvdimm : i_nvdimmList) + { + // Check encryption state in the config/status reg + encryption_config_status_t l_encStatus = {0}; + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_CONFIG_STATUS, + l_encStatus.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); + errlCommit( l_err, NVDIMM_COMP_ID ); + l_success = false; + continue; + } + // Encryption enabled must be set to crypto erase + if (!l_encStatus.encryption_enabled) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] encryption not enabled, will not cypto erase 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + // TODO RTC:210689 Handle function return pass/fail + continue; + } + else + { + TRACFCOMP(g_trac_nvdimm, "nvdimm_crypto_erase() nvdimm[%X] encryption enabled 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + } + + // Set the Erase Key (EK) Reg + l_err = nvdimm_setKeyReg(l_nvdimm, + l_keysFw->ek, + ENCRYPTION_ERASE_KEY_SET, + ENCRYPTION_ERASE_KEY_VERIFY, + false); + if (l_err) + { + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + // Check encryption state in the config/status reg + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_CONFIG_STATUS, + l_encStatus.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + // Erase pending bit should be set + if (!l_encStatus.erase_pending) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] expected erase pending = 1 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + /*@ + *@errortype + *@reasoncode NVDIMM_ENCRYPTION_ERASE_PENDING_FAILED + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_CRYPTO_ERASE + *@userdata1 NVDIMM HUID + *@userdata2 ENCRYPTION_CONFIG_STATUS + *@devdesc NVDIMM failed to set encryption register + *@custdesc NVDIMM register error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_CRYPTO_ERASE, + NVDIMM_ENCRYPTION_ERASE_PENDING_FAILED, + get_huid(l_nvdimm), + l_encStatus.whole, + 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); + + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + else + { + TRACFCOMP(g_trac_nvdimm,"nvdimm_crypto_erase() nvdimm[%X] erase pending 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + } + + // Generate a generic erase key + uint8_t l_genData[ENC_KEY_SIZE] = {0}; + l_err = nvdimm_getRandom(l_genData); + if (l_err) + { + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + // Set the Erase Key (EK) Reg + l_err = nvdimm_setKeyReg(l_nvdimm, + l_genData, + ENCRYPTION_ERASE_KEY_SET, + ENCRYPTION_ERASE_KEY_VERIFY, + false); + if (l_err) + { + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + + // Check encryption state in the config/status reg + l_err = nvdimmReadReg(l_nvdimm, + ENCRYPTION_CONFIG_STATUS, + l_encStatus.whole); + if (l_err) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + // Encryption enabled bit should not be set + if (l_encStatus.encryption_enabled) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] expected encryption enabled = 0 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + /*@ + *@errortype + *@reasoncode NVDIMM_ENCRYPTION_ERASE_FAILED + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_CRYPTO_ERASE + *@userdata1 NVDIMM HUID + *@userdata2 ENCRYPTION_CONFIG_STATUS + *@devdesc NVDIMM failed to set encryption register + *@custdesc NVDIMM register error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_CRYPTO_ERASE, + NVDIMM_ENCRYPTION_ERASE_FAILED, + get_huid(l_nvdimm), + l_encStatus.whole, + 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); + + errlCommit( l_err, NVDIMM_COMP_ID ); + // TODO RTC:210689 Handle status flag + //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + l_success = false; + continue; + } + else + { + TRACFCOMP(g_trac_nvdimm,"nvdimm_crypto_erase() nvdimm[%X] erase complete 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); + } + } }while(0); - TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_init() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_crypto_erase()"); + return l_success; } -#endif + } // end NVDIMM namespace diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H index 4d97a9c66..3caa2c6e3 100644 --- a/src/usr/isteps/nvdimm/nvdimm.H +++ b/src/usr/isteps/nvdimm/nvdimm.H @@ -27,6 +27,7 @@ #define NVDIMM_H__ #include <usr/errl/errlentry.H> +#include <targeting/common/target.H> #include <targeting/common/commontargeting.H> #include <targeting/common/util.H> #include <targeting/common/utilFilter.H> @@ -274,6 +275,18 @@ enum i2cReg : uint16_t TYPED_BLOCK_DATA_BYTE30 = 0x39E, TYPED_BLOCK_DATA_BYTE31 = 0x39F, TYPED_BLOCK_DATA_OFFSET = 0x3E0, + 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, }; // i2cReg macros @@ -292,6 +305,7 @@ enum page : uint8_t TWO = 0x02, THREE = 0x03, FOUR = 0x04, + FIVE = 0x05, }; // Enums for inputs/expected output to/from the i2c registers @@ -330,6 +344,7 @@ enum timeout : uint32_t OPS_POLL_TIME_MS = 5000, NV_READY_POLL_TIME_MS = 1000, PAGE_SWITCH_POLL_TIME_NS = 100, + KEY_WRITE_DELAY_MS = 100, }; // Assign an id to each of the 6 major ops @@ -353,6 +368,26 @@ enum misc HIGH = 1, }; +const size_t NUM_KEYS_IN_ATTR = 3; +const size_t ENC_KEY_SIZE = 32; +const size_t MAX_TPM_SIZE = 34; +const uint8_t KEY_TERMINATE_BYTE = 0x00; +const uint8_t KEY_ABORT_BYTE = 0xFF; +const uint64_t DARN_ERROR_CODE = 0xFFFFFFFFFFFFFFFFull; +const uint32_t MAX_DARN_ERRORS = 10; +const uint32_t MAX_RANDOM_ATTEMPTS = 100; + + +/** + * @brief Encryption key data + */ +struct nvdimmKeyData_t +{ + uint8_t rs[ENC_KEY_SIZE]; // Random String (RS) + uint8_t ek[ENC_KEY_SIZE]; // Erase Key (EK) + uint8_t ak[ENC_KEY_SIZE]; // Access Key (AK) +}; + /** * @brief Wrapper to call deviceOp to read the NV controller via I2C * @@ -434,6 +469,112 @@ errlHndl_t nvdimmPollStatus(TARGETING::Target *i_nvdimm, ops_id i_ops_id, uint32 * the error log. */ errlHndl_t nvdimmSetESPolicy(TARGETING::Target* i_nvdimm); + + +/** + * @brief Helper function to handle conflicting attribute keys + * + * @param[in] i_attrKeysFw - firmware key attribute + * + * @param[in] i_attrKeysAnchor - anchor key attribute + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_handleConflictingKeys( + TARGETING::ATTR_NVDIMM_ENCRYPTION_KEYS_FW_typeStdArr& i_attrKeysFw, + TARGETING::ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_typeStdArr& i_attrKeysAnchor); + + +/** + * @brief Helper function to validate attribute keys + * + * @param[in] i_attrData - pointer to attribute key data + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_checkValidAttrKeys( nvdimmKeyData_t* i_attrData ); + + +/** + * @brief Helper function to write encryption key regs (RS/EK/AK) + * + * @param[in] i_nvdimm - nvdimm target + * + * @param[in] i_keyData - data to write to the key reg + * + * @param[in] i_keyReg - enum register to write key + * + * @param[in] i_verifyReg - enum register to verify key written + * + * @param[in] i_secondAttempt - normally false, true if verif check failed + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_setKeyReg(TARGETING::Target* i_nvdimm, + uint8_t* i_keyData, + uint32_t i_keyReg, + uint32_t i_verifyReg, + bool i_secondAttempt); + + +/** + * @brief Helper function to generate randon number for encryption keys + * Generates ENC_KEY_SIZE bytes of data + * Different implementations for boot vs runtime + * + * @param[out] o_genData - pointer to generated data + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_getRandom(uint8_t* o_genData); + + +/** + * @brief Helper function to make a random number valid for keys + * Keys must not contain 0x00 or 0xFF + * - 0x00 KEY_TERMINATE_BYTE terminates a key < 32 bytes + * - 0xFF KEY_ABORT_BYTE aborts the key reg write process + * This function finds invalid bytes in the first random number + * and replaces with bytes from the second random number + * + * @param[out] o_genData - pointer to final generated data + * + * @param[in] i_xtraData - pointer to extra generated data + * + * @return - false if successful, true if failed + * + */ +bool nvdimm_keyifyRandomNumber(uint8_t* o_genData, uint8_t* i_xtraData); + + +/** + * @brief Helper function to validate a random number + * + * @param[in] i_genData - pointer to generated data + * + * @return - true if valid, false if invalid + * + */ +bool nvdimm_validRandomNumber(uint8_t* i_genData); + +#ifndef __HOSTBOOT_RUNTIME + +/** + * @brief Helper function to get TPM pointer for random number generation + * + * @param[out] - pointer to a functional TPM or nullptr if no TPM found + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_getTPM(TARGETING::Target*& o_tpm); + +#endif + } //End NVDIMM namespace diff --git a/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C b/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C index 267fab07c..75515a761 100644 --- a/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C +++ b/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C @@ -37,6 +37,7 @@ #include <targeting/common/utilFilter.H> #include <usr/runtime/rt_targeting.H> #include <runtime/interface.h> +#include <arch/ppc.H> #include <isteps/nvdimm/nvdimmreasoncodes.H> #include <isteps/nvdimm/nvdimm.H> // implements some of these #include "../nvdimm.H" // for g_trac_nvdimm @@ -358,7 +359,7 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) // the boot. This will notify the user that action is needed // on this module l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024); + l_err->collectTrace(NVDIMM_COMP_NAME); errlCommit( l_err, NVDIMM_COMP_ID ); continue; } @@ -375,7 +376,7 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) // the boot. This will notify the user that action is needed // on this module l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024); + l_err->collectTrace(NVDIMM_COMP_NAME); errlCommit( l_err, NVDIMM_COMP_ID ); o_arm_successful = false; continue; @@ -391,7 +392,7 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) // the boot. This will notify the user that action is needed // on this module l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024); + l_err->collectTrace(NVDIMM_COMP_NAME); errlCommit( l_err, NVDIMM_COMP_ID ); o_arm_successful = false; continue; @@ -405,7 +406,7 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) // the boot. This will notify the user that action is needed // on this module l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024); + l_err->collectTrace(NVDIMM_COMP_NAME); errlCommit( l_err, NVDIMM_COMP_ID ); o_arm_successful = false; continue; @@ -422,7 +423,7 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) // the boot. This will notify the user that action is needed // on this module l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024); + l_err->collectTrace(NVDIMM_COMP_NAME); errlCommit( l_err, NVDIMM_COMP_ID ); o_arm_successful = false; @@ -433,7 +434,7 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmArm() nvdimm[%X], error disarming the nvdimm!", TARGETING::get_huid(l_nvdimm)); l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); - l_err->collectTrace(NVDIMM_COMP_NAME, 1024); + l_err->collectTrace(NVDIMM_COMP_NAME); errlCommit(l_err, NVDIMM_COMP_ID); } @@ -446,6 +447,50 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) return o_arm_successful; } +bool nvdimmDisarm(TARGETING::TargetHandleList &i_nvdimmTargetList) +{ + bool o_disarm_successful = true; + + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmDisarm() %d", + i_nvdimmTargetList.size()); + + errlHndl_t l_err = nullptr; + + for (auto const l_nvdimm : i_nvdimmTargetList) + { + // skip if the nvdimm is in error state + if (NVDIMM::nvdimmInErrorState(l_nvdimm)) + { + // error state means arming not successful + // RTC 210689 Handle return values + o_disarm_successful = false; + continue; + } + + l_err = NVDIMM::nvdimmChangeArmState(l_nvdimm, DISARM_TRIGGER); + // If we run into any error here we will just + // commit the error log and move on. Let the + // system continue to boot and let the user + // salvage the data + if (l_err) + { + NVDIMM::nvdimmSetStatusFlag(l_nvdimm, NVDIMM::NSTD_ERR_NOBKUP); + // Committing the error as we don't want this to interrupt + // the boot. This will notify the user that action is needed + // on this module + l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); + l_err->collectTrace(NVDIMM_COMP_NAME); + errlCommit( l_err, NVDIMM_COMP_ID ); + o_disarm_successful = false; + continue; + } + } + + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmDisarm() returning %d", + o_disarm_successful); + return o_disarm_successful; +} + /** * @brief Check nvdimm error state * @@ -467,4 +512,93 @@ bool nvdimmInErrorState(TARGETING::Target *i_nvdimm) return l_ret; } + +// This could be made a generic utility +errlHndl_t nvdimm_getDarnNumber(size_t i_genSize, uint8_t* o_genData) +{ + assert(i_genSize % sizeof(uint64_t) == 0,"nvdimm_getDarnNumber() bad i_genSize"); + + errlHndl_t l_err = nullptr; + uint64_t* l_darnData = reinterpret_cast<uint64_t*>(o_genData); + + for (uint32_t l_loop = 0; l_loop < (i_genSize / sizeof(uint64_t)); l_loop++) + { + // Darn could return an error code + uint32_t l_darnErrors = 0; + + while (l_darnErrors < MAX_DARN_ERRORS) + { + // Get a 64-bit random number with the darn instruction + l_darnData[l_loop] = getDarn(); + + if ( l_darnData[l_loop] != DARN_ERROR_CODE ) + { + break; + } + else + { + l_darnErrors++; + } + } + + if (l_darnErrors == MAX_DARN_ERRORS) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_getDarnNumber() reached MAX_DARN_ERRORS"); + /*@ + *@errortype + *@reasoncode NVDIMM_ENCRYPTION_MAX_DARN_ERRORS + *@severity ERRORLOG_SEV_PREDICTIVE + *@moduleid NVDIMM_GET_DARN_NUMBER + *@userdata1 MAX_DARN_ERRORS + *@devdesc Error using darn instruction + *@custdesc NVDIMM encryption error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + NVDIMM_GET_DARN_NUMBER, + NVDIMM_ENCRYPTION_MAX_DARN_ERRORS, + MAX_DARN_ERRORS, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + + l_err->collectTrace(NVDIMM_COMP_NAME); + break; + } + } + + return l_err; +} + + +errlHndl_t nvdimm_getRandom(uint8_t* o_genData) +{ + errlHndl_t l_err = nullptr; + uint8_t l_xtraData[ENC_KEY_SIZE] = {0}; + + do + { + // Get a random number with the darn instruction + l_err = nvdimm_getDarnNumber(ENC_KEY_SIZE, o_genData); + if (l_err) + { + break; + } + + // Validate and update the random number + // Retry if more randomness required + do + { + //Get replacement data + l_err = nvdimm_getDarnNumber(ENC_KEY_SIZE, l_xtraData); + if (l_err) + { + break; + } + + }while (nvdimm_keyifyRandomNumber(o_genData, l_xtraData)); + + }while (0); + + return l_err; +} + } // end NVDIMM namespace |