summaryrefslogtreecommitdiffstats
path: root/src/usr/isteps/expupd/ocmbFwImage.C
diff options
context:
space:
mode:
authorGlenn Miles <milesg@ibm.com>2019-04-24 19:09:15 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2019-05-07 09:35:39 -0500
commitf1b76d406973cffd6276fcbf05a036a0ef31b150 (patch)
tree939bd1a6fd2be0b3539e87a5272d7e6f1c2c901d /src/usr/isteps/expupd/ocmbFwImage.C
parentee2270e80fc2d925dc1a93f987035bb8fba15cff (diff)
downloadtalos-hostboot-f1b76d406973cffd6276fcbf05a036a0ef31b150.tar.gz
talos-hostboot-f1b76d406973cffd6276fcbf05a036a0ef31b150.zip
Load and validate OCMB FW image in istep 12.13
Adds function for loading and validating the OCMB firmware image. RTC: 193924 Change-Id: I398d80940710f46cf7e0b66ed663116e574e54b9 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/76624 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: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/isteps/expupd/ocmbFwImage.C')
-rw-r--r--src/usr/isteps/expupd/ocmbFwImage.C391
1 files changed, 391 insertions, 0 deletions
diff --git a/src/usr/isteps/expupd/ocmbFwImage.C b/src/usr/isteps/expupd/ocmbFwImage.C
new file mode 100644
index 000000000..dee2affdd
--- /dev/null
+++ b/src/usr/isteps/expupd/ocmbFwImage.C
@@ -0,0 +1,391 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/isteps/expupd/ocmbFwImage.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "ocmbFwImage.H"
+#include <expupd/ocmbFwImage_const.H>
+#include <expupd/expupd_reasoncodes.H>
+#include "expupd_trace.H"
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <hbotcompid.H>
+#include <algorithm>
+
+#define EXPUPD_8BYTE_ALIGNED(_SIZE) (!(_SIZE & 0x7))
+
+namespace expupd
+{
+
+/**
+ * @brief Validates a tagged data triplet
+ * @param[in] i_tripletPtr starting address of a tagged data triplet
+ * @param[in] i_endDataPtr ending address of the OCMB firmware header
+ * @param[out] o_imageInfo Structure will hold pointer to SHA512 hash (if found)
+ * @param[out] o_numBytes total number of bytes used by this tagged data triplet
+ * @return errlHndl_t indicating success or failure
+ *
+ */
+errlHndl_t parseTaggedDataTriplet(const uint8_t* i_tripletPtr,
+ const uint8_t* i_endDataPtr,
+ rawImageInfo_t& o_imageInfo,
+ uint32_t& o_numBytes)
+{
+ errlHndl_t l_err = nullptr;
+
+ // Determine start of the data for the tagged data triplet
+ const uint8_t* l_dataStartPtr = i_tripletPtr + sizeof(taggedTriplet_t);
+ const taggedTriplet_t* l_ttPtr =
+ reinterpret_cast<const taggedTriplet_t*>(i_tripletPtr);
+
+ // Assume failure and set number of bytes consumed to 0
+ o_numBytes = 0;
+
+ do
+ {
+ // Check that we have enough room for the triplet
+ if((l_dataStartPtr > i_endDataPtr) ||
+ ((l_dataStartPtr + l_ttPtr->dataSize) > i_endDataPtr) ||
+ !EXPUPD_8BYTE_ALIGNED(l_ttPtr->dataSize))
+ {
+ int64_t l_reqdSize = sizeof(taggedTriplet_t);
+ l_reqdSize += (l_dataStartPtr > i_endDataPtr)? 0: l_ttPtr->dataSize;
+
+ int64_t l_allocSize =
+ reinterpret_cast<int64_t>(i_endDataPtr - i_tripletPtr);
+
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "parseTaggedDataTriplet: Triplet does not fit or is"
+ " misaligned. bytesReqd[%d] bytesAllocated[%d]",
+ l_reqdSize,
+ l_allocSize);
+
+ /* @errorlog
+ * @errortype ERRL_SEV_PREDICTIVE
+ * @moduleid EXPUPD::MOD_PARSE_TAGGED_DATA_TRIPLET
+ * @reasoncode EXPUPD::INVALID_DATA_TRIPLET_SIZE
+ * @userdata1 allocated size
+ * @userdata2 required size
+ * @devdesc Tagged data triplet size is too big or misaligned
+ * @custdesc Error occurred during system boot.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ EXPUPD::MOD_PARSE_TAGGED_DATA_TRIPLET,
+ EXPUPD::INVALID_DATA_TRIPLET_SIZE,
+ l_allocSize,
+ l_reqdSize,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Check for the SHA512 tag
+ if(l_ttPtr->tagId == TAG_SHA512)
+ {
+ // Check that hash data is complete
+ if(l_ttPtr->dataSize != HEADER_SHA512_SIZE)
+ {
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "parseTaggedDataTriplet: Invalid hash triplet size."
+ " expected[%u] actual[%u]",
+ HEADER_SHA512_SIZE,
+ l_ttPtr->dataSize);
+
+ /* @errorlog
+ * @errortype ERRL_SEV_PREDICTIVE
+ * @moduleid EXPUPD::MOD_PARSE_TAGGED_DATA_TRIPLET
+ * @reasoncode EXPUPD::INVALID_HASH_TRIPLET_SIZE
+ * @userdata1 Expected Size
+ * @userdata2 Actual Size
+ * @devdesc Incorrect hash size in OCMB image header
+ * @custdesc Error occurred during system boot.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ EXPUPD::MOD_PARSE_TAGGED_DATA_TRIPLET,
+ EXPUPD::INVALID_HASH_TRIPLET_SIZE,
+ HEADER_SHA512_SIZE,
+ l_ttPtr->dataSize,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Save off pointer to hash for later.
+ o_imageInfo.imageSHA512HashPtr = l_dataStartPtr;
+ }
+ else if(l_ttPtr->tagId == TAG_KEY_VALUE_PAIRS)
+ {
+ //trace up to MAX_BIN_TRACE bytes of the data in case it is useful
+ TRACFBIN(g_trac_expupd, "OCMB FW IMAGE KEY/VALUE DATA",
+ l_dataStartPtr,
+ std::min(l_ttPtr->dataSize, MAX_BIN_TRACE));
+ }
+ else
+ {
+ //unsupported tag id.
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "parseTaggedDataTriplet: Invalid tag id[%u].",
+ l_ttPtr->tagId);
+
+ /* @errorlog
+ * @errortype ERRL_SEV_PREDICTIVE
+ * @moduleid EXPUPD::MOD_PARSE_TAGGED_DATA_TRIPLET
+ * @reasoncode EXPUPD::INVALID_TAG_ID
+ * @userdata1 tag id
+ * @userdata2 <unused>
+ * @devdesc Invalid tag id found in OCMB image header
+ * @custdesc Error occurred during system boot.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ EXPUPD::MOD_PARSE_TAGGED_DATA_TRIPLET,
+ EXPUPD::INVALID_TAG_ID,
+ l_ttPtr->tagId,
+ 0,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ //Parsing was successful. Set bytes consumed.
+ o_numBytes = sizeof(taggedTriplet_t) + l_ttPtr->dataSize;
+ }while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Validates OCMB firmware header of packaged image
+ *
+ * @param[in] i_imageStart Start address of packaged image
+ * @param[in] i_imageSize Size of packaged image
+ * @param[out] o_imageInfo Information pertaining to image after
+ * being stripped of OCMB firmware header
+ * @return errlHndl_t indicating success or failure
+ *
+ */
+errlHndl_t ocmbFwValidateImage(const uint64_t i_imageStart,
+ const uint64_t i_imageSize,
+ rawImageInfo_t& o_imageInfo)
+{
+ const uint8_t* l_imageStartPtr =
+ reinterpret_cast<const uint8_t*>(i_imageStart);
+ errlHndl_t l_err = nullptr;
+
+ TRACFCOMP(g_trac_expupd,
+ ENTER_MRK "ocmbFwValidateImage(): startAddr[0x%016x] size[%u]",
+ i_imageStart, i_imageSize);
+
+ //clear out o_imageInfo
+ memset(&o_imageInfo, 0, sizeof(o_imageInfo));
+
+ do
+ {
+ const uint64_t l_minHeaderSize =
+ sizeof(ocmbFwHeader_t) +
+ sizeof(taggedTriplet_t) + HEADER_SHA512_SIZE;
+
+ const uint64_t l_maxHeaderSize =
+ std::min(static_cast<const uint64_t>(HEADER_MAX_SIZE),
+ i_imageSize);
+
+ // Check input parameters
+ if((!l_imageStartPtr) || (i_imageSize < l_minHeaderSize))
+ {
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "ocmbFwValidateImage: Invalid image address[%p] or"
+ " size[%u]",
+ l_imageStartPtr, i_imageSize);
+
+ /* @errorlog
+ * @errortype ERRL_SEV_PREDICTIVE
+ * @moduleid EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE
+ * @reasoncode EXPUPD::INVALID_PARMS
+ * @userdata1 i_imageStart
+ * @userdata2 i_imageSize
+ * @devdesc Invalid size or address for OCMB Flash Image
+ * @custdesc Error occurred during system boot.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE,
+ EXPUPD::INVALID_PARMS,
+ i_imageStart,
+ i_imageSize,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ const ocmbFwHeader_t* l_header =
+ reinterpret_cast<const ocmbFwHeader_t*>(l_imageStartPtr);
+
+ // Check eye catcher value
+ if(l_header->eyeCatcher != EYE_CATCHER_VALUE)
+ {
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "ocmbFwValidateImage: Invalid eye catcher value: "
+ "expected[0x%016llx] actual[0x%016llx]",
+ EYE_CATCHER_VALUE, l_header->eyeCatcher);
+ /* @errorlog
+ * @errortype ERRL_SEV_PREDICTIVE
+ * @moduleid EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE
+ * @reasoncode EXPUPD::INVALID_EYE_CATCHER
+ * @userdata1 Expected Value
+ * @userdata2 Actual Value
+ * @devdesc Invalid eye catcher value for OCMB Flash Image
+ * @custdesc Error occurred during system boot.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE,
+ EXPUPD::INVALID_EYE_CATCHER,
+ EYE_CATCHER_VALUE,
+ l_header->eyeCatcher,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Check header version
+ if((l_header->majorVersion != HEADER_VERSION_MAJOR) ||
+ (l_header->minorVersion != HEADER_VERSION_MINOR))
+ {
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "ocmbFwValidateImage: Unsupported header version: %u.%u",
+ l_header->majorVersion, l_header->minorVersion);
+ /* @errorlog
+ * @errortype ERRL_SEV_PREDICTIVE
+ * @moduleid EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE
+ * @reasoncode EXPUPD::INVALID_HEADER_VERSION
+ * @userdata1 majorVersion
+ * @userdata2 minorVersion
+ * @devdesc Invalid header version for OCMB Flash Image
+ * @custdesc Error occurred during system boot.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE,
+ EXPUPD::INVALID_HEADER_VERSION,
+ l_header->majorVersion,
+ l_header->minorVersion,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ //Check that header size is within min/max range and 8byte aligned
+ if((l_header->headerSize < l_minHeaderSize) ||
+ (l_header->headerSize > l_maxHeaderSize) ||
+ !EXPUPD_8BYTE_ALIGNED(l_header->headerSize))
+ {
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "ocmbFwValidateImage: Unsupported header size: %u bytes",
+ l_header->headerSize);
+ /* @errorlog
+ * @errortype ERRL_SEV_PREDICTIVE
+ * @moduleid EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE
+ * @reasoncode EXPUPD::INVALID_HEADER_SIZE
+ * @userdata1 header size
+ * @userdata2 maximum allowed size
+ * @devdesc Invalid header size for OCMB Flash Image
+ * @custdesc Error occurred during system boot.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE,
+ EXPUPD::INVALID_HEADER_SIZE,
+ l_header->headerSize,
+ l_maxHeaderSize,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Trace header information.
+ TRACFCOMP(g_trac_expupd, "OCMB HEADER: Version[%u.%u] size[%u]"
+ " triplets[%u]",
+ l_header->majorVersion,
+ l_header->minorVersion,
+ l_header->headerSize,
+ l_header->numTriplets);
+
+ // Parse all tagged triplet data
+ const uint8_t* l_curTripletPtr = l_imageStartPtr + sizeof(*l_header);
+ const uint8_t* l_endDataPtr = l_imageStartPtr + l_header->headerSize;
+ for(uint32_t l_curTriplet = 0;
+ l_curTriplet < l_header->numTriplets;
+ l_curTriplet++)
+ {
+ uint32_t l_numBytes = 0;
+
+ // This will set o_imageInfo.imageSHA512Ptr if
+ // SHA512 hash is found
+ l_err = parseTaggedDataTriplet(l_curTripletPtr,
+ l_endDataPtr,
+ o_imageInfo,
+ l_numBytes);
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "ocmbFwValidateImage: Failed parsing tagged data"
+ " triplet %u of %u",
+ l_curTriplet + 1, l_header->numTriplets);
+ break;
+ }
+
+ // Advance to next triplet
+ l_curTripletPtr += l_numBytes;
+ }
+ if(l_err)
+ {
+ break;
+ }
+
+ // Check if we found a SHA512 hash in the header
+ if(!o_imageInfo.imageSHA512HashPtr)
+ {
+ TRACFCOMP(g_trac_expupd, ERR_MRK
+ "ocmbFwValidateImage: No SHA512 Hash found in header!");
+ /* @errorlog
+ * @errortype ERRL_SEV_PREDICTIVE
+ * @moduleid EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE
+ * @reasoncode EXPUPD::MISSING_SHA512_HASH
+ * @userdata1 <unused>
+ * @userdata2 <unused>
+ * @devdesc Missing SHA512 hash in OCMB Flash Image
+ * @custdesc Error occurred during system boot.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ EXPUPD::MOD_OCMB_FW_VALIDATE_IMAGE,
+ EXPUPD::MISSING_SHA512_HASH,
+ 0, 0,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ //** Header is valid if we made it this far **
+
+ // Trace the SHA512 hash
+ TRACFBIN(g_trac_expupd, "OCMB FW IMAGE SHA512 HASH",
+ o_imageInfo.imageSHA512HashPtr, HEADER_SHA512_SIZE);
+
+ // Set the image start address and size and we are done here.
+ o_imageInfo.imagePtr = l_imageStartPtr + l_header->headerSize;
+ o_imageInfo.imageSize = i_imageSize - l_header->headerSize;
+
+ }while(0);
+
+ TRACFCOMP(g_trac_expupd, EXIT_MRK "ocmbFwValidateImage()");
+ return l_err;
+}
+
+} //namespace expupd
+
OpenPOWER on IntegriCloud