diff options
author | Glenn Miles <milesg@ibm.com> | 2019-04-30 09:22:44 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2019-05-09 16:17:31 -0500 |
commit | c0b91d3b52a6139f7e56a6e3896018cdeac26dae (patch) | |
tree | b577c70c06d52254ea64d0dc51a8f73123f5f662 | |
parent | bbbd68a140c9b34ccded9273d91e6b5bc97d0f28 (diff) | |
download | talos-hostboot-c0b91d3b52a6139f7e56a6e3896018cdeac26dae.tar.gz talos-hostboot-c0b91d3b52a6139f7e56a6e3896018cdeac26dae.zip |
High level support for updating explorer firmware
Includes the following.
-Reading SHA512 hash from each explorer chip.
-Comparing SHA512 hash to PNOR image SHA512 hash.
-Calling exp_fw_update procedure on each explorer with
hash value that does not match PNOR hash value.
-Don't do update if MPIPL
-Request reboot if any OCMB chips were updated
RTC: 193924
Change-Id: I797e12415a5dd8013dafb20a9f22dac770995b30
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/76724
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Matt Derksen <mderkse1@us.ibm.com>
Reviewed-by: Ilya Smirnov <ismirno@us.ibm.com>
Reviewed-by: Matthew Raybuck <matthew.raybuck@ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rw-r--r-- | src/usr/isteps/expupd/expupd.C | 209 | ||||
-rw-r--r-- | src/usr/isteps/expupd/expupd.mk | 1 | ||||
-rw-r--r-- | src/usr/isteps/istep12/call_cen_set_inband_addr.C | 13 |
3 files changed, 208 insertions, 15 deletions
diff --git a/src/usr/isteps/expupd/expupd.C b/src/usr/isteps/expupd/expupd.C index 743d77f38..74231b5a5 100644 --- a/src/usr/isteps/expupd/expupd.C +++ b/src/usr/isteps/expupd/expupd.C @@ -33,9 +33,13 @@ #include <isteps/hwpistepud.H> #include <fapi2.H> #include <fapi2/plat_hwp_invoker.H> +#include <fapi2/hw_access.H> +#include <chipids.H> #include <trace/interface.H> #include <hbotcompid.H> #include "ocmbFwImage.H" +#include <exp_fw_update.H> +#include <initservice/istepdispatcherif.H> using namespace ISTEP_ERROR; using namespace ERRORLOG; @@ -49,12 +53,65 @@ trace_desc_t* g_trac_expupd = nullptr; TRAC_INIT(&g_trac_expupd, EXPUPD_COMP_NAME, 2*KILOBYTE); /** + * @brief Structure for retrieving the explorer SHA512 hash value + * + */ +typedef union sha512regs +{ + struct + { + uint32_t imageId; + uint8_t sha512Hash[HEADER_SHA512_SIZE]; + }; + uint8_t unformatted[sizeof(uint32_t) + HEADER_SHA512_SIZE]; +}sha512regs_t; + +/** * @brief Retrieve the SHA512 hash for the currently flashed explorer * firmware image. + * + * @param[in] i_target Target of the OCMB chip to retrieve the SHA512 hash + * @param[out] o_regs Structure for storing the retrieved SHA512 hash + * + * @return NULL on success. Non-null on failure. */ -errlHndl_t expupdGetFlashedHash() +errlHndl_t getFlashedHash(TargetHandle_t i_target, sha512regs_t& o_regs) { - return nullptr; + fapi2::buffer<uint64_t> l_scomBuffer; + uint8_t* l_scomPtr = reinterpret_cast<uint8_t*>(l_scomBuffer.pointer()); + fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>l_fapi2Target(i_target); + errlHndl_t l_err = nullptr; + + //Start addres of hash register (a.k.a. RAM1 register) + const uint32_t HASH_REG_ADDR = 0x00002200; + + // loop until we've filled the sha512regs_t struct + for(uint32_t l_bytesCopied = 0; l_bytesCopied < sizeof(sha512regs_t); + l_bytesCopied += sizeof(uint32_t)) + { + // Use getScom, this knows internally whether to use i2c or inband + FAPI_INVOKE_HWP(l_err, getScom, + l_fapi2Target, + HASH_REG_ADDR + l_bytesCopied, + l_scomBuffer); + if(l_err) + { + TRACFCOMP(g_trac_expupd, ERR_MRK + "getFlashedHash: Failed reading SHA512 hash from" + " ocmb[0x%08x]. bytesCopied[%u]", + TARGETING::get_huid(i_target), l_bytesCopied); + + break; + } + + // copy scom buffer into the unformatted uint8_t array. + // Even though the scom buffer is 8 bytes, only 4 bytes are read and + // copied into the least significant 4 bytes. + memcpy(&o_regs.unformatted[l_bytesCopied], l_scomPtr + sizeof(uint32_t), + sizeof(uint32_t)); + } + + return l_err; } /** @@ -62,13 +119,16 @@ errlHndl_t expupdGetFlashedHash() * and update the flash if it does not match the SHA512 hash * of the image in PNOR. * + * @param[out] o_stepError Error handle for logging istep failures + * */ -void updateAll(IStepError& i_StepError) +void updateAll(IStepError& o_stepError) { bool l_imageLoaded = false; errlHndl_t l_err = nullptr; + bool l_rebootRequired = false; - // Get a list of explorer chips + // Get a list of OCMB chips TARGETING::TargetHandleList l_ocmbTargetList; getAllChips(l_ocmbTargetList, TYPE_OCMB_CHIP); @@ -78,7 +138,7 @@ void updateAll(IStepError& i_StepError) do { - // If no explorer chips exist, we're done. + // If no OCMB chips exist, we're done. if(l_ocmbTargetList.size() == 0) { break; @@ -99,7 +159,7 @@ void updateAll(IStepError& i_StepError) l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error that occurred - i_StepError.addErrorDetails( l_err ); + o_stepError.addErrorDetails( l_err ); // Commit Error errlCommit( l_err, EXPUPD_COMP_ID ); @@ -120,7 +180,7 @@ void updateAll(IStepError& i_StepError) l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error that occurred - i_StepError.addErrorDetails( l_err ); + o_stepError.addErrorDetails( l_err ); // Commit Error errlCommit( l_err, EXPUPD_COMP_ID ); @@ -129,9 +189,10 @@ void updateAll(IStepError& i_StepError) // Verify the header and retrieve address, size and // SHA512 hash of unpackaged image - l_err = ocmbFwValidateImage(l_pnorSectionInfo.vaddr, - l_pnorSectionInfo.size, - l_imageInfo); + l_err = ocmbFwValidateImage( + l_pnorSectionInfo.vaddr, + l_pnorSectionInfo.secureProtectedPayloadSize, + l_imageInfo); if(l_err) { TRACFCOMP(g_trac_expupd, ERR_MRK @@ -140,7 +201,7 @@ void updateAll(IStepError& i_StepError) l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error that occurred - i_StepError.addErrorDetails( l_err ); + o_stepError.addErrorDetails( l_err ); // Commit Error errlCommit( l_err, EXPUPD_COMP_ID ); @@ -148,9 +209,113 @@ void updateAll(IStepError& i_StepError) } // For each explorer chip, compare flash hash with PNOR hash and - // create a list of explorer chips with differing hash values + // create a list of explorer chips with differing hash values. + TARGETING::TargetHandleList l_flashUpdateList; + for(const auto & l_ocmbTarget : l_ocmbTargetList) + { + sha512regs_t l_regs; + + //skip all gemini ocmb chips (not updateable) + if(l_ocmbTarget->getAttr<TARGETING::ATTR_CHIP_ID>() == + POWER_CHIPID::GEMINI_16) + { + TRACFCOMP(g_trac_expupd, + "updateAll: skipping update of gemini OCMB 0x%08x", + TARGETING::get_huid(l_ocmbTarget)); + continue; + } + + //retrieve the SHA512 hash for the currently flashed image. + l_err = getFlashedHash(l_ocmbTarget, l_regs); + if(l_err) + { + TRACFCOMP(g_trac_expupd, ERR_MRK + "updateAll: Failure in getFlashedHash(huid = 0x%08x)", + TARGETING::get_huid(l_ocmbTarget)); + + l_err->collectTrace(EXPUPD_COMP_NAME); + + // Create IStep error log and cross reference to error + // that occurred + o_stepError.addErrorDetails(l_err); + + errlCommit(l_err, EXPUPD_COMP_ID); + + //Don't stop on error, go to next target. + continue; + } + + // Trace the hash and image ID values + TRACFCOMP(g_trac_expupd, + "updateAll: OCMB 0x%08x image ID=0x%08x", + TARGETING::get_huid(l_ocmbTarget), l_regs.imageId); + TRACFBIN(g_trac_expupd, "SHA512 HASH FROM EXPLORER", + l_regs.sha512Hash, HEADER_SHA512_SIZE); + + //Compare hashes. If different, add to list for update. + if(memcmp(l_regs.sha512Hash, l_imageInfo.imageSHA512HashPtr, + HEADER_SHA512_SIZE)) + { + TRACFCOMP(g_trac_expupd, + "updateAll: SHA512 hash mismatch on ocmb[0x%08x]", + TARGETING::get_huid(l_ocmbTarget)); + + //add target to our list of targets needing an update + l_flashUpdateList.push_back(l_ocmbTarget); + } + else + { + TRACFCOMP(g_trac_expupd, + "updateAll: SHA512 hash for ocmb[0x%08x]" + " matches SHA512 hash of PNOR image.", + TARGETING::get_huid(l_ocmbTarget)); + } + } - // If list not empty update each explorer in the list + TRACFCOMP(g_trac_expupd, + "updateAll: updating flash for %d OCMB chips", + l_flashUpdateList.size()); + + // update each explorer in the list of chips needing updates + for(const auto & l_ocmb : l_flashUpdateList) + { + TRACFCOMP(g_trac_expupd, "updateAll: updating OCMB 0x%08x", + TARGETING::get_huid(l_ocmb)); + fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>l_fapi2Target(l_ocmb); + + // reset watchdog for each ocmb as this function can be very slow + INITSERVICE::sendProgressCode(); + + // Invoke procedure + FAPI_INVOKE_HWP(l_err, exp_fw_update, l_fapi2Target, + l_imageInfo.imagePtr, l_imageInfo.imageSize); + if (l_err) + { + TRACFCOMP(g_trac_expupd, + "Error from exp_fw_update for OCMB 0x%08x", + TARGETING::get_huid(l_ocmb)); + + l_err->collectTrace(EXPUPD_COMP_NAME); + + // Create IStep error log and cross reference to error + // that occurred + o_stepError.addErrorDetails( l_err ); + + errlCommit(l_err, EXPUPD_COMP_ID); + + // Don't stop on error, go to next target. + continue; + } + else + { + TRACFCOMP(g_trac_expupd, + "updateAll: successfully updated OCMB 0x%08x", + TARGETING::get_huid(l_ocmb)); + + // Request reboot for new firmware to be used + l_rebootRequired = true; + } + } }while(0); // unload explorer fw image @@ -166,7 +331,7 @@ void updateAll(IStepError& i_StepError) l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error that occurred - i_StepError.addErrorDetails( l_err ); + o_stepError.addErrorDetails( l_err ); // Commit Error errlCommit( l_err, EXPUPD_COMP_ID ); @@ -175,6 +340,22 @@ void updateAll(IStepError& i_StepError) } // force reboot if any updates were successful + if(l_rebootRequired) + { + TRACFCOMP(g_trac_expupd, + "updateAll: OCMB chip(s) was updated. Requesting reboot..."); + Target* l_pTopLevel = nullptr; + targetService().getTopLevelTarget( l_pTopLevel ); + assert(l_pTopLevel, "expupd::updateAll: no TopLevelTarget"); + auto l_reconfigAttr = + l_pTopLevel->getAttr<TARGETING::ATTR_RECONFIGURE_LOOP>(); + l_reconfigAttr |= RECONFIGURE_LOOP_OCMB_FW_UPDATE; + l_pTopLevel->setAttr<TARGETING::ATTR_RECONFIGURE_LOOP>(l_reconfigAttr); + } + else + { + TRACFCOMP(g_trac_expupd, "updateAll: No OCMB chips were updated"); + } TRACFCOMP(g_trac_expupd, EXIT_MRK"updateAll()"); diff --git a/src/usr/isteps/expupd/expupd.mk b/src/usr/isteps/expupd/expupd.mk index 595161b08..b7b769e7a 100644 --- a/src/usr/isteps/expupd/expupd.mk +++ b/src/usr/isteps/expupd/expupd.mk @@ -29,6 +29,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/import/chips/common/utils/imageProcs EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/procedures/hwp/ffdc/ EXTRAINCDIR += ${ROOTPATH}/src/import/hwpf/fapi2/include EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2 +EXTRAINCDIR += ${ROOTPATH}/src/import/chips/common/utils OBJS += expupd.o OBJS += ocmbFwImage.o diff --git a/src/usr/isteps/istep12/call_cen_set_inband_addr.C b/src/usr/isteps/istep12/call_cen_set_inband_addr.C index 439dccaf6..d26bcbd83 100644 --- a/src/usr/isteps/istep12/call_cen_set_inband_addr.C +++ b/src/usr/isteps/istep12/call_cen_set_inband_addr.C @@ -220,7 +220,18 @@ void* call_cen_set_inband_addr (void *io_pArgs) // Check if any explorer chips require a firmware update and update them // (skipped on MPIPL) - expupd::updateAll(l_StepError); + Target* l_pTopLevel = nullptr; + targetService().getTopLevelTarget( l_pTopLevel ); + assert(l_pTopLevel, "call_cen_set_inband_addr: no TopLevelTarget"); + if (l_pTopLevel->getAttr<TARGETING::ATTR_IS_MPIPL_HB>()) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "skipping expupdUpdateAll due to MPIPL"); + } + else + { + expupd::updateAll(l_StepError); + } #endif // CONFIG_AXONE |