summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Miles <milesg@ibm.com>2019-04-30 09:22:44 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2019-05-09 16:17:31 -0500
commitc0b91d3b52a6139f7e56a6e3896018cdeac26dae (patch)
treeb577c70c06d52254ea64d0dc51a8f73123f5f662
parentbbbd68a140c9b34ccded9273d91e6b5bc97d0f28 (diff)
downloadtalos-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.C209
-rw-r--r--src/usr/isteps/expupd/expupd.mk1
-rw-r--r--src/usr/isteps/istep12/call_cen_set_inband_addr.C13
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
OpenPOWER on IntegriCloud