diff options
author | Mike Baiocchi <baiocchi@us.ibm.com> | 2013-09-20 14:47:15 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-10-28 12:21:53 -0500 |
commit | a094332bbe8807c8f24aeb79f34be063845cea10 (patch) | |
tree | 7b05b516287bd27d971ee8404a980bfad311ac2b /src/usr/sbe | |
parent | 7b8d4a482ca2d110f3bf67b7a8e1bed758318420 (diff) | |
download | talos-hostboot-a094332bbe8807c8f24aeb79f34be063845cea10.tar.gz talos-hostboot-a094332bbe8807c8f24aeb79f34be063845cea10.zip |
Initial Support for Updating SBE SEEPROM
This initial commit will be used to create the new SBE
directories and files. It also supports the usr functions
to find and copy SBE PNOR images. NOTE: It will not enable
Updating SBE SEEPROMs in the IPL.
Change-Id: I3f545a134493c7595ce50fd885478bbe606de472
RTC: 47032
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/6311
Tested-by: Jenkins Server
Reviewed-by: ADAM R. MUHLE <armuhle@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/sbe')
-rw-r--r-- | src/usr/sbe/makefile | 42 | ||||
-rw-r--r-- | src/usr/sbe/sbe_update.C | 2311 | ||||
-rw-r--r-- | src/usr/sbe/sbe_update.H | 439 | ||||
-rw-r--r-- | src/usr/sbe/test/makefile | 28 | ||||
-rw-r--r-- | src/usr/sbe/test/sbeupdatetest.H | 777 |
5 files changed, 3597 insertions, 0 deletions
diff --git a/src/usr/sbe/makefile b/src/usr/sbe/makefile new file mode 100644 index 000000000..50de91c2d --- /dev/null +++ b/src/usr/sbe/makefile @@ -0,0 +1,42 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/sbe/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2013 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../.. +MODULE = sbe + +## support for Targeting and fapi +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp + +## pointer to common HWP files +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/include + +## pointer to already consumed procedures. +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/p8_slw_build + +OBJS = sbe_update.o + +SUBDIRS = test.d + +include ${ROOTPATH}/config.mk diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C new file mode 100644 index 000000000..8001c9954 --- /dev/null +++ b/src/usr/sbe/sbe_update.C @@ -0,0 +1,2311 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbe/sbe_update.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <vector> +#include <trace/interface.H> +#include <vpd/mvpdenums.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <errl/errludtarget.H> +#include <targeting/common/predicates/predicatectm.H> +#include <targeting/common/utilFilter.H> +#include <util/align.H> +#include <util/crc32.H> +#include <errno.h> +#include <pnor/pnorif.H> +#include <pnor/ecc.H> +#include <devicefw/driverif.H> +#include <sys/mm.h> +#include <sys/misc.h> +#include <hwas/common/deconfigGard.H> +#include <sbe/sbeif.H> +#include <sbe/sbereasoncodes.H> +#include "sbe_update.H" + +// fapi support +#include <fapi.H> +#include <fapiPlatHwpInvoker.H> +#include <hwpf/plat/fapiPlatTrace.H> + +//Procedures +#include <p8_xip_customize.H> +#include <sbe_xip_image.h> +#include <p8_image_help_base.H> + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +trace_desc_t* g_trac_sbe = NULL; +TRAC_INIT( & g_trac_sbe, SBE_COMP_NAME, KILOBYTE ); + +// ------------------------ +// Macros for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + +using namespace ERRORLOG; +using namespace TARGETING; + +namespace SBE +{ + + enum { + SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE, + RING_BUF1_VADDR = FIXED_SEEPROM_WORK_SPACE + SBE_IMG_VADDR, + RING_BUF2_VADDR = RING_BUF1_VADDR + FIXED_RING_BUF_SIZE, + //NOTE: recycling the same memory space for different + //steps in the process. + SBE_ECC_IMG_VADDR = RING_BUF1_VADDR, + SBE_ECC_IMG_MAX_SIZE = VMM_VADDR_SBE_UPDATE_END - SBE_ECC_IMG_VADDR, + }; + +///////////////////////////////////////////////////////////////////// + errlHndl_t updateProcessorSbeSeeproms() + { + errlHndl_t err = NULL; + errlHndl_t err_cleanup = NULL; + sbeTargetState_t sbeState; + std::vector<sbeTargetState_t> sbeStates_vector; + + bool l_cleanupVmmSpace = false; + bool l_restartNeeded = false; + + TRACUCOMP( g_trac_sbe, + ENTER_MRK"updateProcessorSbeSeeproms()" ); + + do{ + + //Make sure procedure constants keep within expected range. + assert((FIXED_SEEPROM_WORK_SPACE <= VMM_SBE_UPDATE_SIZE/2), + "updateProcessorSbeSeeproms() FIXED_SEEPROM_WORK_SPACE " + "too large"); + assert((FIXED_RING_BUF_SIZE <= VMM_SBE_UPDATE_SIZE/4), + "updateProcessorSbeSeeproms() FIXED_RING_BUF_SIZE too " + "large"); + + err = createSbeImageVmmSpace(); + if (err) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "createSbeImageVmmSpace() Failed. ", + "rc=0x%.4X", err->reasonCode() ); + + break; + } + else + { + // Make sure cleanup gets called + l_cleanupVmmSpace = true; + } + + /*****************************************************************/ + /* Iterate over all the functional processors and do for each: */ + /* 1) Check their SBE State (PNOR, MVPD, SEEPROMs, etc), */ + /* 2) Determine the Necessary Update */ + /* 3) Perform Update Action */ + /*****************************************************************/ + TARGETING::TargetHandleList procList; + TARGETING::getAllChips(procList, + TARGETING::TYPE_PROC, + true); // true: return functional targets + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateProcessorSbeSeeproms() - " + "No functional processors Found!" ); + break; + } + + + for(uint32_t i=0; i<procList.size(); i++) + { + + /*********************************************/ + /* Collect SBE Information for this Target */ + /*********************************************/ + memset(&sbeState, 0, sizeof(sbeState)); + sbeState.target = procList[i]; + + // @todo RTC 47033 check attribute on target to see if it's + // the master processor and set sbeState.target_is_master + + err = getSbeInfoState(sbeState); + + if (err) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "getSbeInfoState() Failed " + "rc=0x%.4X, Target UID=0x%X", + err->reasonCode(), + TARGETING::get_huid(sbeState.target)); + + // Don't break - handle error at the end of the loop + + } + + + /**********************************************/ + /* Determine update actions for this target */ + /**********************************************/ + // Skip if we got an error collecting SBE Info State + if ( err == NULL ) + { + err = getTargetUpdateActions(sbeState); + if (err) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "getTargetUpdateActions() Failed ", + "rc=0x%.4X, Target UID=0x%X", + err->reasonCode(), + TARGETING::get_huid(sbeState.target)); + + // Don't break - handle error at the end of the loop, + } + } + + /**********************************************/ + /* Perform Update Actions For This Target */ + /**********************************************/ + if ((err == NULL) && (sbeState.update_actions & DO_UPDATE)) + { + + err = performUpdateActions(sbeState); + if (err) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "performUpdateActions() Failed ", + "rc=0x%.4X, Target UID=0x%X", + err->reasonCode(), + TARGETING::get_huid(sbeState.target)); + + break; + } + else + { + // Target updated without failure, so set IPL_RESTART + // flag, if necessary + if (sbeState.update_actions & IPL_RESTART) + { + l_restartNeeded = true; + } + } + + } + + + // Push this sbeState onto the vector + sbeStates_vector.push_back(sbeState); + + if ( err ) + { + // Something failed for this target. + // Commit the error here and move on to the next target, + // or if no targets left, will just continue the IPL + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): " + "Committing Error Log rc=0x%.4X for " + "Target UID=0x%X, but continuing procedure", + err->reasonCode(), + TARGETING::get_huid(sbeState.target)); + errlCommit( err, SBE_COMP_ID ); + } + + + + } //end of Target for loop collecting each target's SBE State + + + /**************************************************************/ + /* Perform System Operation */ + /**************************************************************/ + //TODO RTC: 47033 - Restart IPL if SBE Update requires it + // For Now just trace that a restart is needed + if (l_restartNeeded == true) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"updateProcessorSbeSeeproms(): Restart " + "Needed, but not currently supported (%d). " + "Continuing IPL", + l_restartNeeded ); + } + + + }while(0); + + + + // Cleanup VMM Workspace + if ( l_cleanupVmmSpace == true ) + { + err_cleanup = cleanupSbeImageVmmSpace(); + if ( err_cleanup != NULL ) + { + + if ( err != NULL ) + { + // 2 error logs, so commit the cleanup log here + TRACFCOMP( g_trac_sbe, + ERR_MRK"updateProcessorSbeSeeproms(): Previous " + "error (rc=0x%X) before cleanupSbeImageVmmSpace" + "() failed. Committing cleanup error (rc=0x%X) " + "and returning original error", + err->reasonCode(), err_cleanup->reasonCode() ); + + errlCommit( err_cleanup, SBE_COMP_ID ); + } + else + { + // no previous error, so returning cleanup error + TRACFCOMP( g_trac_sbe, + ERR_MRK"updateProcessorSbeSeeproms(): " + "cleanupSbeImageVmmSpace() failed.", + "rc=0x%.4X", err_cleanup->reasonCode() ); + err = err_cleanup; + } + } + } + + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"updateProcessorSbeSeeproms()" ); + + return err; + } + +///////////////////////////////////////////////////////////////////// + errlHndl_t findSBEInPnor(TARGETING::Target* i_target, + void*& o_imgPtr, + size_t& o_imgSize, + sbe_image_version_t* o_version) + { + errlHndl_t err = NULL; + PNOR::SectionInfo_t pnorInfo; + sbeToc_t* sbeToc = NULL; + uint8_t ec = 0; + PNOR::SectionId pnorSectionId = PNOR::INVALID_SECTION; + + void* hdr_Ptr = NULL; + o_imgPtr = NULL; + o_imgSize = 0; + + TRACDCOMP( g_trac_sbe, + ENTER_MRK"findSBEInPnor()" ); + + do{ + + // Get the correct PNOR Section Id + if ( i_target->getAttr<ATTR_TYPE>() == TYPE_PROC ) + { + pnorSectionId = PNOR::SBE_IPL; + } + else if ( i_target->getAttr<ATTR_TYPE>() == TYPE_MEMBUF ) + { + pnorSectionId = PNOR::CENTAUR_SBE; + } + else + { + // Unsopported target type was passed in + TRACFCOMP( g_trac_sbe, ERR_MRK"findSBEInPnor: Unsupported " + "target type was passed in: uid=0x%X, type=0x%X", + TARGETING::get_huid(i_target), + i_target->getAttr<ATTR_TYPE>()); + + /*@ + * @errortype + * @moduleid SBE_FIND_IN_PNOR + * @reasoncode SBE_INVALID_INPUT + * @userdata1 Target Unit Id + * @userdata2 Target Type + * @devdesc Unsupported Target Type passed in + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_FIND_IN_PNOR, + SBE_INVALID_INPUT, + TARGETING::get_huid(i_target), + i_target->getAttr<ATTR_TYPE>()); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + break; + } + + + // Get SBE PNOR section info from PNOR RP + err = PNOR::getSectionInfo( pnorSectionId, + PNOR::CURRENT_SIDE, + pnorInfo ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"findSBEInPnor: Error calling " + "PNOR::getSectionInfo() rc=0x%.4X", + err->reasonCode() ); + break; + } + + TRACUCOMP( g_trac_sbe, + INFO_MRK"findSBEInPnor: UID=0x%X, sectionId=0x%X. " + "pnor vaddr = 0x%.16X", + TARGETING::get_huid(i_target), + pnorSectionId, pnorInfo.vaddr); + + sbeToc = reinterpret_cast<sbeToc_t*>( pnorInfo.vaddr ); + + if (sbeToc->eyeCatch != SBETOC_EYECATCH) + { + //The SBE partition does not have the proper eyecatcher + TRACFCOMP( g_trac_sbe, ERR_MRK"findSBEInPnor: SBE partition " + "does not have the proper eyecatcher: was: 0x%X, " + "should be: 0x%X", + sbeToc->eyeCatch, SBETOC_EYECATCH ); + + /*@ + * @errortype + * @moduleid SBE_FIND_IN_PNOR + * @reasoncode SBE_INVALID_EYECATCHER + * @userdata1 SBE TOC EYE-CATCHER + * @userdata2 Expected EYE-CATCHER + * @devdesc Unsupported EYE-CATCHER found in TOC + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_FIND_IN_PNOR, + SBE_INVALID_EYECATCHER, + sbeToc->eyeCatch, + SBETOC_EYECATCH); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + break; + } + else + { + + //Check the TOC Version + if( SUPPORTED_TOC_VER != sbeToc->tocVersion) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"findSBEInPnor: Unsupported " + "SBE TOC Version in SBE Partition" ); + /*@ + * @errortype + * @moduleid SBE_FIND_IN_PNOR + * @reasoncode SBE_UNSUPPORTED_TOC + * @userdata1[0:31] CHIP EC + * @userdata1[32:63] Expected TOC Version + * @userdata2[0:31] SBE TOC Version + * @userdata2[32:63] SBE TOC EyeCatch + * @devdesc SBE partition contains unsupported version + * of Table of Contents + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_FIND_IN_PNOR, + SBE_UNSUPPORTED_TOC, + TWO_UINT32_TO_UINT64(ec, + SUPPORTED_TOC_VER), + TWO_UINT32_TO_UINT64(sbeToc->tocVersion, + sbeToc->eyeCatch)); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + + // @todo RTC 47033 capture SBE TOC for analysis + + break; + } + + //Walk the TOC and find our current EC + ec = i_target->getAttr<TARGETING::ATTR_EC>(); + for(uint32_t i=0; i<MAX_SBE_ENTRIES; i++) + { + if(static_cast<uint32_t>(ec) == sbeToc->entries[i].ec) + { + + // EC found in TOC + uint64_t offset = pnorInfo.vaddr + + static_cast<uint64_t>(sbeToc->entries[i].offset); + hdr_Ptr = reinterpret_cast<void*>( offset ); + + o_imgSize = sbeToc->entries[i].size; + + TRACUCOMP( g_trac_sbe, INFO_MRK"findSBEInPnor: Found " + "EC Image: ec=0x%.2X offset=0x%.16X, i=%d " + "size=0x%X", + ec, offset, i, o_imgSize ); + break; + } + } + } + + if(NULL == hdr_Ptr) + { + //if we get here, it's an error + TRACFCOMP( g_trac_sbe,ERR_MRK"findSBEInPnor:SBE Image not " + "located, ec=0x%.2X",ec ); + + /*@ + * @errortype + * @moduleid SBE_FIND_IN_PNOR + * @reasoncode SBE_EC_NOT_FOUND + * @userdata1[0:31] CHIP EC + * @userdata1[32:63] PNOR Section ID + * @userdata2[0:31] SBE TOC Version + * @userdata2[32:63] SBE TOC EyeCatch + * @devdesc SBE image for current chip EC was not found + * in PNOR + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_FIND_IN_PNOR, + SBE_EC_NOT_FOUND, + TWO_UINT32_TO_UINT64(ec, + pnorSectionId), + TWO_UINT32_TO_UINT64(sbeToc->tocVersion, + sbeToc->eyeCatch)); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + // @todo RTC 47033 capture SBE TOC for analysis + + break; + } + + // The SBE Image for the corresponding EC was found and includes a + // SBE Header, so advance PNOR pointer 4k to move it past header + // page to the start of the non-customized SBE image + o_imgPtr = reinterpret_cast<void*> + (reinterpret_cast<char*>(hdr_Ptr)+0x1000); + + + if(NULL != o_version) + { + err = readPNORVersion(hdr_Ptr, + *o_version); + if(err) + { + break; + } + } + + }while(0); + + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"findSBEInPnor(): o_imgPtr=%p, o_imgSize=0x%X", + o_imgPtr, o_imgSize ); + + + return err; + } + + + +///////////////////////////////////////////////////////////////////// + errlHndl_t procCustomizeSbeImg(TARGETING::Target* i_target, + void* i_sbePnorPtr, + size_t i_maxImgSize, + void* io_imgPtr, + size_t& o_actImgSize) + { + errlHndl_t err = NULL; + uint32_t coreMask = 0x0000FFFF; + size_t maxCores = P8_MAX_EX_PER_PROC; + uint32_t procIOMask = 0; + + TRACUCOMP( g_trac_sbe, + ENTER_MRK"procCustomizeSbeImg(): uid=0x%X, i_sbePnorPtr= " + "%p, maxS=0x%X, io_imgPtr=%p", + TARGETING::get_huid(i_target), i_sbePnorPtr, + i_maxImgSize, io_imgPtr); + + do{ + + // cast OUR type of target to a FAPI type of target. + const fapi::Target + l_fapiTarg(fapi::TARGET_TYPE_PROC_CHIP, + (const_cast<TARGETING::Target*>(i_target))); + + + // The p8_xip_customize() procedure tries to include as much core + // information as possible, but is limited by SBE Image size + // constraints. + // This loop is designed to remove the number of cores passed into + // p8_xip_customize() until an image can be created successfully. + + while( __builtin_popcount(procIOMask) < + __builtin_popcount(coreMask)) + { + + err = selectBestCores(i_target, + maxCores, + coreMask); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"procCustomizeSbeImg() - " + "selectBestCores() failed rc=0x%X. " + "MaxCores=0x%.8X. HUID=0x%.8X. Aborting Update", + err->reasonCode(), maxCores, + TARGETING::get_huid(i_target)); + break; + } + + procIOMask = coreMask; + + uint32_t tmpImgSize = static_cast<uint32_t>(i_maxImgSize); + + FAPI_INVOKE_HWP( err, + p8_xip_customize, + l_fapiTarg, + i_sbePnorPtr, //image in + io_imgPtr, //image out + tmpImgSize, + 0, //IPL + 0, //HB/IPL + (void*)RING_BUF1_VADDR, + (uint32_t)FIXED_RING_BUF_SIZE, + (void*)RING_BUF2_VADDR, + (uint32_t)FIXED_RING_BUF_SIZE, + procIOMask); + + o_actImgSize = static_cast<size_t>(tmpImgSize); + + maxCores = __builtin_popcount(procIOMask); + + if ( err ) + { + TRACFCOMP( g_trac_sbe, + ERR_MRK"procCustomizeSbeImg(): FAPI_INVOKE_HWP(" + "p8_xip_customize) failed with rc=0x%x04X, " + "MaxCores=0x%.8X. HUID=0x%.8X. coreMask=0x%.8X, " + "procIOMask=0x%.8X.", + err->reasonCode(), maxCores, + TARGETING::get_huid(i_target), + coreMask, procIOMask); + + ERRORLOG::ErrlUserDetailsTarget(i_target, + "Proc Target") + .addToLog(err); + + // @todo RTC 47033 look for specific return code for + // the case where he couldn't fix the cores we asked for + // but could possibly fit a lesser amount + + break; + } + + } + + + if(err) + { + break; + } + }while(0); + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"procCustomizeSbeImg(): io_imgPtr=%p, " + "o_actImgSize=0x%X", io_imgPtr, o_actImgSize ); + + return err; + } + +///////////////////////////////////////////////////////////////////// + errlHndl_t selectBestCores(TARGETING::Target* i_target, + size_t i_maxExs, + uint32_t& o_exMask) + { + TRACUCOMP( g_trac_sbe, + ENTER_MRK"selectBestCores(i_maxCores=0x%.8X)", + i_maxExs); + + errlHndl_t err = NULL; + uint32_t manGuardExs = 0x00000000; + uint32_t exCount = 0; + uint32_t deconfigByEid = 0; + + o_exMask = 0x00000000; + + do{ + // find all EX chiplets of the proc + TARGETING::TargetHandleList l_exTargetList; + TARGETING::getChildChiplets( l_exTargetList, + i_target, + TARGETING::TYPE_EX, + false); // return all + + //Sort through cores + for ( TargetHandleList::const_iterator + l_iterEX = l_exTargetList.begin(); + l_iterEX != l_exTargetList.end(); + ++l_iterEX ) + { + // make a local copy of the EX target + const TARGETING::Target* l_ex_target = *l_iterEX; + + + if( !(l_ex_target-> + getAttr<TARGETING::ATTR_HWAS_STATE>().present) ) + { + // not present, so skip and continue + continue; + } + + + uint8_t chipUnit = l_ex_target-> + getAttr<TARGETING::ATTR_CHIP_UNIT>(); + + if(l_ex_target-> + getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + o_exMask |= (0x00008000 >> chipUnit); + exCount++; + + if(exCount >= i_maxExs) + { + break; + } + } + else + { + //If non-functional due to FCO or Manual gard, + //add it to list of exs to include if + //more are needed + + deconfigByEid = l_ex_target-> + getAttr<TARGETING::ATTR_HWAS_STATE>(). + deconfiguredByEid; + if( + // FCO + (deconfigByEid == + HWAS::DeconfigGard::DECONFIGURED_BY_FIELD_CORE_OVERRIDE) + || // Manual GARD + (deconfigByEid == + HWAS::DeconfigGard::DECONFIGURED_BY_MANUAL_GARD) + ) + { + manGuardExs |= (0x00008000 >> chipUnit); + } + } + } // end ex target loop + + if(exCount >= i_maxExs) + { + //We've found enough, break out of function + break; + } + + //Look for more 'good' exs. + manGuardExs = trimBitMask(manGuardExs, + i_maxExs-exCount); + o_exMask |= manGuardExs; + TRACUCOMP( g_trac_sbe,INFO_MRK"selectBestCores: trimBitMask manGuardExs=0x%.8X", + manGuardExs); + + }while(0); + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"selectBestCores(o_exMask=0x%.8X)", + o_exMask); + + return err; + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t getSetMVPDVersion(TARGETING::Target* i_target, + opType_t i_op, + mvpdSbKeyword_t& io_sb_keyword) + { + errlHndl_t err = NULL; + size_t vpdSize = 0; + + TRACUCOMP( g_trac_sbe, + ENTER_MRK"getSetMVPDVersion(i_op=%d)", i_op ); + + do{ + // Read SB Keyword which contains SBE version and dirty bit + // information + // Note: First read with NULL for o_buffer sets vpdSize to the + // correct length + err = deviceRead( i_target, + NULL, + vpdSize, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::SB ) ); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSetMVPDVersion() - MVPD " + "failure getting SB keywordw size HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + if(vpdSize != MVPD_SB_RECORD_SIZE) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSetMVPDVersion() - MVPD SB " + "keyword wrong length HUID=0x%.8X, length=0x.2X, " + "expected=0x.2x", + TARGETING::get_huid(i_target), vpdSize, + MVPD_SB_RECORD_SIZE); + /*@ + * @errortype + * @moduleid SBE_GETSET_MVPD_VERSION + * @reasoncode SBE_MVPD_LEN_INVALID + * @userdata1 Discovered VPD Size + * @userdata2 Expected VPD Size + * @devdesc SB Keyword in MVPD has invalid size + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_GETSET_MVPD_VERSION, + SBE_MVPD_LEN_INVALID, + TO_UINT64(vpdSize), + TO_UINT64(MVPD_SB_RECORD_SIZE)); + ErrlUserDetailsTarget(i_target + ).addToLog(err); + err->collectTrace(SBE_COMP_NAME, 256); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_MED ); + + break; + } + + if(i_op == MVPDOP_READ) + { + err = deviceRead( i_target, + reinterpret_cast<void*>( &io_sb_keyword ), + vpdSize, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::SB ) ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSetMVPDVersion() - MVPD " + "failure reading SB keyword data HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + TRACDBIN(g_trac_sbe, "MVPD:SB", &io_sb_keyword, vpdSize); + + } + else //write + { + err = deviceWrite( i_target, + reinterpret_cast<void*>( &io_sb_keyword ), + vpdSize, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::SB ) ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSetMVPDVersion() - MVPD " + "failure writing SB keyword data HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + } + + }while(0); + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"getSetMVPDVersion()" ); + + return err; + } + +///////////////////////////////////////////////////////////////////// + errlHndl_t readPNORVersion(void*& i_pnorImgHdrPtr, + sbe_image_version_t& o_version) + { + errlHndl_t err = NULL; + TRACDCOMP( g_trac_sbe, + ENTER_MRK"readPNORVersion()" ); + + do{ + // @todo RTC 34080 - support Secure Boot Header + + //For Non-secure systems, version is prefixed with + //'VERSION\0' in ASCII in the 4k header. The official + //protocol is to scan for VERSION, then grab the value + //that follows. + + char* tmpPtr = static_cast<char*>(i_pnorImgHdrPtr); + + + //Last reasonable offset is (Version size + + //size of eyecatcher) bytes from end of Page. + char* endPtr = tmpPtr +(4*KILOBYTE) - + sizeof(sbe_image_version_t&) - + sizeof(NONSECURE_VER_EYECATCH); + + // Increment pointer sizeof(uint64_t) because eyecatcher + // must be 8-byte alligned + for(; tmpPtr<endPtr; tmpPtr+=sizeof(uint64_t)) + { + if(*(reinterpret_cast<uint64_t*>(tmpPtr)) == + NONSECURE_VER_EYECATCH) + { + //increment 8 more bytes and break out + tmpPtr+=sizeof(uint64_t); + break; + } + } + + if(tmpPtr < endPtr) + { + memcpy(reinterpret_cast<void*>( &o_version ), + tmpPtr, + sizeof(o_version)); + } + else + { + + TRACFCOMP( g_trac_sbe, ERR_MRK"readPNORVersion() - VERSION not found in SBE image in PNOR"); + /*@ + * @errortype + * @moduleid SBE_READ_PNOR_VERSION + * @reasoncode SBE_VERSION_NOT_FOUND + * @userdata1 Not Used + * @userdata2 Not Used + * @devdesc Image Version not found in PNOR + * SBE image. + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_READ_PNOR_VERSION, + SBE_VERSION_NOT_FOUND, + 0, 0); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_SP_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + } + + }while(0); + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"readPNORVersion()" ); + + return err; + } + +///////////////////////////////////////////////////////////////////// + errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target, + sbeSeepromSide_t& o_bootSide) + { + TRACUCOMP( g_trac_sbe, + ENTER_MRK"getSbeBootSeeprom()" ); + + errlHndl_t err = NULL; + uint64_t scomData = 0x0; + + o_bootSide = SBE_SEEPROM0; + + do{ + + size_t op_size = sizeof(scomData); + err = deviceRead( i_target, + &scomData, + op_size, + DEVICE_SCOM_ADDRESS(SBE_VITAL_REG_0x0005001C) ); + if( err ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeBootSeeprom() -Error " + "reading SBE VITAL REG (0x%.8X) from Target :" + "HUID=0x%.8X", + SBE_VITAL_REG_0x0005001C, + TARGETING::get_huid(i_target)); + break; + } + if(scomData & SBE_BOOT_SELECT_MASK) + { + o_bootSide = SBE_SEEPROM1; + } + + }while(0); + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"getSbeBootSeeprom(): o_bootSide=0x%X", o_bootSide ); + + return err; + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t getSbeInfoState(sbeTargetState_t& io_sbeState) + { + + TRACDCOMP( g_trac_sbe, + ENTER_MRK"getSbeInfoState(): HUID=0x%.8X", + TARGETING::get_huid(io_sbeState.target)); + + + errlHndl_t err = NULL; + + do{ + + /************************************************************/ + /* Set Target Properties (target_is_master previously set) */ + /************************************************************/ + io_sbeState.ec = io_sbeState.target->getAttr<TARGETING::ATTR_EC>(); + + + /*******************************************/ + /* Get PNOR SBE Version Information */ + /*******************************************/ + void* sbePnorPtr = NULL; + size_t sbePnorImageSize = 0; + sbe_image_version_t tmp_pnorVersion; + + err = findSBEInPnor(io_sbeState.target, + sbePnorPtr, + sbePnorImageSize, + &tmp_pnorVersion); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - " + "Error getting SBE Version from PNOR"); + break; + } + + // copy tmp_pnorVersion to the main structure + memcpy ( &io_sbeState.pnorVersion, + &tmp_pnorVersion, + sizeof(tmp_pnorVersion)); + + + /*******************************************/ + /* Customize SBE Image from PNOR and */ + /* Calculate CRC of the image */ + /*******************************************/ + size_t sbeImgSize = 0; + err = procCustomizeSbeImg(io_sbeState.target, + sbePnorPtr, //SBE vaddr in PNOR + FIXED_SEEPROM_WORK_SPACE, //max size + reinterpret_cast<void*> + (SBE_IMG_VADDR), //destination + sbeImgSize); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - " + "Error from procCustomizeSbeImg()"); + break; + } + + io_sbeState.customizedImage_size = sbeImgSize; + io_sbeState.customizedImage_crc = + Util::crc32_calc(reinterpret_cast<void*> + (SBE_IMG_VADDR), + sbeImgSize) ; + + TRACUCOMP( g_trac_sbe, "getSbeInfoState() - procCustomizeSbeImg(): " + "maxSize=0x%X, actSize=0x%X, crc=0x%X", + FIXED_SEEPROM_WORK_SPACE, sbeImgSize, + io_sbeState.customizedImage_crc); + + + + /*******************************************/ + /* Get MVPD SBE Version Information */ + /*******************************************/ + err = getSetMVPDVersion(io_sbeState.target, + MVPDOP_READ, + io_sbeState.mvpdSbKeyword); + if(err) + { + //If MVPD is bad, commit the error and move to the next proc + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - " + "Error reading version from MVPD"); + break; + } + + + // Determine Permanent Side from flag in MVPD + if(SEEPROM_0_PERMANENT_VALUE == + (io_sbeState.mvpdSbKeyword.flags & PERMANENT_FLAG_MASK)) + { + io_sbeState.permanent_seeprom_side = SBE_SEEPROM0; + } + else // Side 1 must be permanent + { + io_sbeState.permanent_seeprom_side = SBE_SEEPROM1; + } + + + /*******************************************/ + /* Get SEEPROM A SBE Version Information */ + /*******************************************/ + err = getSeepromSideVersion(io_sbeState.target, + EEPROM::SBE_PRIMARY, + io_sbeState.seeprom_0_ver, + io_sbeState.seeprom_0_ver_ECC_fail); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM A (0x%X)", + EEPROM::SBE_PRIMARY); + break; + } + + TRACDBIN(g_trac_sbe, "getSbeInfoState-spA", + &(io_sbeState.seeprom_0_ver), + sizeof(sbeVersion_t)); + + /*******************************************/ + /* Get SEEPROM B SBE Version Information */ + /*******************************************/ + err = getSeepromSideVersion(io_sbeState.target, + EEPROM::SBE_BACKUP, + io_sbeState.seeprom_1_ver, + io_sbeState.seeprom_1_ver_ECC_fail); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error " + "getting SBE Information from SEEPROM B (0x%X)", + EEPROM::SBE_BACKUP); + break; + } + + + TRACDBIN(g_trac_sbe, "getSbeInfoState-spB", + &(io_sbeState.seeprom_1_ver), + sizeof(sbeVersion_t)); + + /***********************************************/ + /* Determine which SEEPROM System Booted On */ + /***********************************************/ + //Get Current (boot) Side + sbeSeepromSide_t tmp_cur_side = SBE_SEEPROM_INVALID; + err = getSbeBootSeeprom(io_sbeState.target, tmp_cur_side); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error returned from getSbeBootSeeprom()"); + break; + } + io_sbeState.cur_seeprom_side = tmp_cur_side; + if (io_sbeState.cur_seeprom_side == SBE_SEEPROM0) + { + io_sbeState.alt_seeprom_side = SBE_SEEPROM1; + } + else if ( io_sbeState.cur_seeprom_side == SBE_SEEPROM1) + { + io_sbeState.alt_seeprom_side = SBE_SEEPROM0; + } + else + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSbeInfoState() - Error: " + "Unexpected cur_seeprom_side value = 0x%X, ", + io_sbeState.cur_seeprom_side); + + /*@ + * @errortype + * @moduleid SBE_GET_TARGET_INFO_STATE + * @reasoncode SBE_INVALID_SEEPROM_SIDE + * @userdata1 Temporary Current Side + * @userdata2 SBE State Current Side + * @devdesc Invalid Boot SEEPROM Side Found + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_GET_TARGET_INFO_STATE, + SBE_INVALID_SEEPROM_SIDE, + tmp_cur_side, + io_sbeState.cur_seeprom_side); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + + break; + } + + TRACUCOMP( g_trac_sbe,"getSbeInfoState() - cur=0x%X, alt=0x%X", + io_sbeState.cur_seeprom_side, + io_sbeState.alt_seeprom_side); + + }while(0); + + return err; + + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t getSeepromSideVersion(TARGETING::Target* i_target, + EEPROM::eeprom_chip_types_t i_seepromSide, + sbeSeepromVersionInfo_t& o_info, + bool& o_seeprom_ver_ECC_fail) + { + + TRACUCOMP( g_trac_sbe, + ENTER_MRK"getSeepromSideVersion(): HUID=0x%.8X, side:%d", + TARGETING::get_huid(i_target), i_seepromSide); + + errlHndl_t err = NULL; + PNOR::ECC::eccStatus eccStatus = PNOR::ECC::CLEAN; + o_seeprom_ver_ECC_fail = false; + + size_t sbeInfoSize_ECC = (sizeof(sbeSeepromVersionInfo_t)*9)/8; + size_t sbeInfoSize_ECC_aligned = ALIGN_8(sbeInfoSize_ECC); + + // Create data buffer of larger size + // NOTE: EEPROM read will fill in smaller, unaligned size + uint8_t * tmp_data_ECC = static_cast<uint8_t*>( + malloc(sbeInfoSize_ECC_aligned)); + + do{ + + /*******************************************/ + /* Read SBE Version SBE Version Information */ + /*******************************************/ + + // Clear Buffer + memset( tmp_data_ECC, 0, sbeInfoSize_ECC_aligned ); + + //Read SBE Versions + err = deviceRead( i_target, + tmp_data_ECC, + sbeInfoSize_ECC, + DEVICE_EEPROM_ADDRESS( + i_seepromSide, + SBE_VERSION_SEEPROM_ADDRESS)); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getSeepromSideVersion() - Error " + "reading SBE Version from Seeprom 0x%X, HUID=0x%.8X", + i_seepromSide, TARGETING::get_huid(i_target)); + break; + } + + TRACDBIN(g_trac_sbe, + "getSeepromSideVersion()- tmp_data_ECC (not-aligned)", + tmp_data_ECC, + sbeInfoSize_ECC); + + TRACDBIN(g_trac_sbe, + "getSeepromSideVersion()- tmp_data_ECC (aligned)", + tmp_data_ECC, + sbeInfoSize_ECC_aligned); + + + // Clear destination + memset( &o_info, 0, sizeof(o_info) ); + + + // Remove ECC + eccStatus = PNOR::ECC::removeECC( + tmp_data_ECC, + reinterpret_cast<uint8_t*>(&o_info), + sizeof(o_info)); + + TRACUCOMP( g_trac_sbe, "getSeepromSideVersion(): eccStatus=%d, " + "sizeof o_info=%d, sI_ECC=%d, sI_ECC_aligned=%d", + eccStatus, sizeof(o_info), sbeInfoSize_ECC, + sbeInfoSize_ECC_aligned); + + // Handle Uncorrectable ECC - no error log: + // clear data and set o_seeprom_ver_ECC_fail=true + if ( eccStatus == PNOR::ECC::UNCORRECTABLE ) + { + + TRACFCOMP( g_trac_sbe,ERR_MRK"getSeepromSideVersion() - ECC " + "ERROR: eccStatus=%d, side=%d, sizeof o_info=%d, " + "sI_ECC=%d, sI_ECC_aligned=%d", + eccStatus, i_seepromSide, sizeof(o_info), + sbeInfoSize_ECC, sbeInfoSize_ECC_aligned); + + memset( &o_info, 0, sizeof(o_info)); + o_seeprom_ver_ECC_fail = true; + + TRACFCOMP( g_trac_sbe, "getSeepromSideVersion(): clearing out " + "version data (o_info) for side %d and returning " + "o_seeprom_ver_ECC_fail as true (%d)", + i_seepromSide, o_seeprom_ver_ECC_fail); + } + + TRACDBIN(g_trac_sbe, + "getSeepromSideVersion: data (no ECC)", + &o_info, + sizeof(o_info)); + + }while(0); + + // Free allocated memory + free(tmp_data_ECC); + + + TRACUCOMP( g_trac_sbe, + EXIT_MRK"getSeepromSideVersion: o_seeprom_ver_ECC_fail=%d", + o_seeprom_ver_ECC_fail ); + + return err; + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t updateSeepromSide(sbeTargetState_t i_sbeState) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"updateSeepromSide(): HUID=0x%.8X", + TARGETING::get_huid(i_sbeState.target)); + errlHndl_t err = NULL; + int64_t rc = 0; + + int64_t rc_readBack_ECC_memcmp = 0; + PNOR::ECC::eccStatus eccStatus = PNOR::ECC::CLEAN; + + // This struct is always 8-byte aligned + size_t sbeInfoSize = sizeof(sbeSeepromVersionInfo_t); + size_t sbeInfoSize_ECC = (sbeInfoSize*9)/8; + + + // Buffers for reading/writing SBE Version Information + uint8_t * sbeInfo_data = static_cast<uint8_t*>( + malloc(sbeInfoSize)); + + uint8_t * sbeInfo_data_ECC = static_cast<uint8_t*>( + malloc(sbeInfoSize_ECC)); + + uint8_t * sbeInfo_data_readBack = static_cast<uint8_t*>( + malloc(sbeInfoSize)); + + uint8_t * sbeInfo_data_ECC_readBack = static_cast<uint8_t*>( + malloc(sbeInfoSize_ECC)); + + + do{ + + + /*******************************************/ + /* Update SBE Version Information */ + /*******************************************/ + + // The new version has already been created + memcpy(sbeInfo_data, &i_sbeState.new_seeprom_ver, sbeInfoSize); + + // Inject ECC to Data + memset( sbeInfo_data_ECC, 0, sbeInfoSize_ECC); + PNOR::ECC::injectECC(sbeInfo_data, sbeInfoSize, sbeInfo_data_ECC); + + TRACDBIN( g_trac_sbe, "updateSeepromSide: Info", + sbeInfo_data, sbeInfoSize); + TRACDBIN( g_trac_sbe, "updateSeepromSide: Info ECC", + sbeInfo_data_ECC, sbeInfoSize_ECC); + + err = deviceWrite( i_sbeState.target, + sbeInfo_data_ECC, + sbeInfoSize_ECC, + DEVICE_EEPROM_ADDRESS( + i_sbeState.seeprom_side_to_update, + SBE_VERSION_SEEPROM_ADDRESS)); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - Error " + "Writing SBE Version Info: HUID=0x%.8X, side=%d", + TARGETING::get_huid(i_sbeState.target), + i_sbeState.seeprom_side_to_update); + break; + } + + + // In an effort to avoid an infinite loop of updates, if there + // was an ECC error when reading this SBE Version Information + // while collecting data, read back this data to ensure there + // isn't a permanent ECC error on the SEEPROM + if ( i_sbeState.new_readBack_check == true ) + { + + // Read Back Version Information + err = deviceRead( i_sbeState.target, + sbeInfo_data_ECC_readBack, + sbeInfoSize_ECC, + DEVICE_EEPROM_ADDRESS( + i_sbeState.seeprom_side_to_update, + SBE_VERSION_SEEPROM_ADDRESS)); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - Error " + "Reading Back SBE Version Info: HUID=0x%.8X, " + "size=%d", + TARGETING::get_huid(i_sbeState.target), + i_sbeState.seeprom_side_to_update); + break; + } + + // Compare ECC data + rc_readBack_ECC_memcmp = memcmp( sbeInfo_data_ECC, + sbeInfo_data_ECC_readBack, + sbeInfoSize_ECC); + + + // Remove ECC + eccStatus = PNOR::ECC::removeECC( sbeInfo_data_ECC_readBack, + sbeInfo_data_readBack, + sbeInfoSize); + + + TRACUCOMP( g_trac_sbe, "updateSeepromSide(): eccStatus=%d, " + "sizeof sI=%d, sI_ECC=%d, rc_ECC=%d", + eccStatus, sbeInfoSize, sbeInfoSize_ECC, + rc_readBack_ECC_memcmp); + + // Fail if uncorrectable ECC or any data miscompare + if ( ( eccStatus == PNOR::ECC::UNCORRECTABLE ) || + ( rc_readBack_ECC_memcmp != 0 ) + ) + { + + // There is an ECC issue with this SEEPROM + + TRACFCOMP( g_trac_sbe,ERR_MRK"updateSeepromSide() - ECC " + "ERROR or Data Miscimpare On SBE Version Read " + "Back: eccStatus=%d, rc_ECC=%d, " + "sI=%d, sI_ECC=%d, HUID=0x%.8X, side=%d", + eccStatus, rc_readBack_ECC_memcmp, + sbeInfoSize, sbeInfoSize_ECC, + TARGETING::get_huid(i_sbeState.target), + i_sbeState.seeprom_side_to_update); + + + /*@ + * @errortype + * @moduleid SBE_GET_SEEPROM_INFO + * @reasoncode SBE_ECC_FAIL + * @userdata1[0:15] ECC Status + * @userdata1[16:31] SEEPROM Side + * @userdata1[32:47] RC on Data Compare with ECC + * @userdata1[48:63] <unused> + * @userdata2[0:31] Size - No Ecc + * @userdata2[32:63] Size - ECC + * @devdesc ECC or Data Miscompare Fail Reading Back + * SBE Verion Information + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_UPDATE_SEEPROMS, + SBE_ECC_FAIL, + FOUR_UINT16_TO_UINT64( + eccStatus, + i_sbeState.seeprom_side_to_update, + rc_readBack_ECC_memcmp, + 0x0), + TWO_UINT32_TO_UINT64(sbeInfoSize, + sbeInfoSize_ECC)); + + err->collectTrace(SBE_COMP_NAME); + err->addHwCallout( i_sbeState.target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DELAYED_DECONFIG, + HWAS::GARD_Predictive ); + + + ErrlUserDetailsTarget(i_sbeState.target).addToLog(err); + + break; + } + + } + + /*******************************************/ + /* Update SBE with Customized Image */ + /*******************************************/ + // The Customized Image For This Target Still Resides In + // The SBE Update VMM Space: SBE_IMG_VADDR = VMM_VADDR_SBE_UPDATE + + + // Inject ECC + // clear out back half of page block to use as temp space + // for ECC injected SBE Image. + rc = mm_remove_pages(RELEASE, + reinterpret_cast<void*> + (SBE_ECC_IMG_VADDR), + SBE_ECC_IMG_MAX_SIZE); + if( rc ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - Error " + "from mm_remove_pages : rc=%d, HUID=0x%.8X.", + rc, TARGETING::get_huid(i_sbeState.target) ); + /*@ + * @errortype + * @moduleid SBE_UPDATE_SEEPROMS + * @reasoncode SBE_REMOVE_PAGES_FOR_EC + * @userdata1 Requested Address + * @userdata2 rc from mm_remove_pages + * @devdesc updateProcessorSbeSeeproms> mm_remove_pages + * RELEASE failed + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_UPDATE_SEEPROMS, + SBE_REMOVE_PAGES_FOR_EC, + TO_UINT64(SBE_ECC_IMG_VADDR), + TO_UINT64(rc)); + //Target isn't directly related to fail, but could be useful + // to see how far we got before failing. + ErrlUserDetailsTarget(i_sbeState.target + ).addToLog(err); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + break; + } + + + //align size, calculate ECC size + size_t sbeImgSize = ALIGN_8(i_sbeState.customizedImage_size); + size_t sbeEccImgSize = static_cast<size_t>(sbeImgSize*9/8); + + + assert(sbeEccImgSize <= SBE_ECC_IMG_MAX_SIZE, + "updateSeepromSide() SBE Image with ECC too large"); + + TRACUCOMP( g_trac_sbe, INFO_MRK"updateSeepromSide(): " + "SBE_VADDR=0x%.16X, ECC_VADDR=0x%.16X, size=0x%.8X, " + "eccSize=0x%.8X", + SBE_IMG_VADDR, + SBE_ECC_IMG_VADDR, + sbeImgSize, + sbeEccImgSize ); + + PNOR::ECC::injectECC(reinterpret_cast<uint8_t*>(SBE_IMG_VADDR), + sbeImgSize, + reinterpret_cast<uint8_t*> + (SBE_ECC_IMG_VADDR)); + + TRACDBIN(g_trac_sbe,"updateSeepromSide()-start of IMG - no ECC", + reinterpret_cast<void*>(SBE_IMG_VADDR), 0x80); + TRACDBIN(g_trac_sbe,"updateSeepromSide()-start of IMG - ECC", + reinterpret_cast<void*>(SBE_ECC_IMG_VADDR), 0x80); + + + //Write new data to seeprom + TRACFCOMP( g_trac_sbe, INFO_MRK"updateSeepromSide(): Write New " + "SBE Image for Target 0x%X to Seeprom %d", + TARGETING::get_huid(i_sbeState.target), + i_sbeState.seeprom_side_to_update ); + + //Write image to indicated side + err = deviceWrite(i_sbeState.target, + reinterpret_cast<void*> + (SBE_ECC_IMG_VADDR), + sbeEccImgSize, + DEVICE_EEPROM_ADDRESS( + i_sbeState.seeprom_side_to_update, + SBE_IMAGE_SEEPROM_ADDRESS)); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"updateSeepromSide() - Error " + "writing new SBE image to size=%d. HUID=0x%.8X." + "SBE_VADDR=0x%.16X, ECC_VADDR=0x%.16X, size=0x%.8X, " + "eccSize=0x%.8X, EEPROM offset=0x%X", + i_sbeState.seeprom_side_to_update, + TARGETING::get_huid(i_sbeState.target), + SBE_IMG_VADDR, SBE_ECC_IMG_VADDR, sbeImgSize, + sbeEccImgSize, SBE_IMAGE_SEEPROM_ADDRESS); + break; + } + + }while(0); + + // Free allocated memory + free( sbeInfo_data ); + free( sbeInfo_data_ECC); + free( sbeInfo_data_readBack ); + free( sbeInfo_data_ECC_readBack ); + + return err; + + + } + + + +///////////////////////////////////////////////////////////////////// + errlHndl_t getTargetUpdateActions(sbeTargetState_t& io_sbeState) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"getTargetUpdateActions()"); + errlHndl_t err = NULL; + + bool seeprom_0_isDirty = false; + bool seeprom_1_isDirty = false; + bool current_side_isDirty = false; + bool alt_side_isDirty = false; + + + do{ + + + + /**************************************************************/ + /* Compare SEEPROM 0 with PNOR and Customized Image CRC -- */ + /* -- dirty or clean? */ + /**************************************************************/ + if ( + // Check PNOR and SEEPROM 0 Version + (0 != memcmp(&(io_sbeState.pnorVersion), + &(io_sbeState.seeprom_0_ver.image_version), + SBE_IMAGE_VERSION_SIZE)) + || + // Check CRC and SEEPROM 0 CRC + (0 != memcmp(&(io_sbeState.customizedImage_crc), + &(io_sbeState.seeprom_0_ver.data_crc), + SBE_DATA_CRC_SIZE)) + ) + { + seeprom_0_isDirty = true; + } + + + + /**************************************************************/ + /* Compare SEEPROM 1 with PNOR and Customized Image CRC -- */ + /* -- dirty or clean? */ + /**************************************************************/ + if ( + // Check PNOR and SEEPROM 1 Version + (0 != memcmp(&(io_sbeState.pnorVersion), + &(io_sbeState.seeprom_1_ver.image_version), + SBE_IMAGE_VERSION_SIZE)) + || + // Check CRC and SEEPROM 1 CRC + (0 != memcmp(&(io_sbeState.customizedImage_crc), + &(io_sbeState.seeprom_1_ver.data_crc), + SBE_DATA_CRC_SIZE)) + ) + { + seeprom_1_isDirty = true; + } + + + + /**************************************************************/ + /* Determine what side to update */ + /**************************************************************/ + + //If all clean, we are done: + if((!seeprom_0_isDirty) && + (!seeprom_1_isDirty)) + { + break; + } + + //Need to update something + if( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) + { + current_side_isDirty = seeprom_0_isDirty; + alt_side_isDirty = seeprom_1_isDirty; + } + else + { + current_side_isDirty = seeprom_1_isDirty; + alt_side_isDirty = seeprom_0_isDirty; + } + + + // Set system_situation - bits defined in sbe_update.H + uint8_t system_situation = 0x00; + + // Bit 0: current_side is permanent (0) or temp (1) + // -- defaulted to 0 (cur=perm) above + if ( io_sbeState.cur_seeprom_side != + io_sbeState.permanent_seeprom_side ) + { + system_situation |= SITUATION_CUR_IS_TEMP; + } + + // Bit 1: current_side clean (0) or dirty (1) + // -- defaulted to 0 (clean) above + if ( current_side_isDirty ) + { + system_situation |= SITUATION_CUR_IS_DIRTY; + } + + // Bit 2: alt_side is clean (0) or dirty (1) + if ( alt_side_isDirty ) + { + system_situation |= SITUATION_ALT_IS_DIRTY; + } + + + // Call function to update actions + decisionTreeForUpdates(io_sbeState, system_situation); + + TRACUCOMP( g_trac_sbe, "getTargetUpdateActions() - system_situation" + "= 0x%.2X, actions=0x%.8X, Update EEPROM=0x%X", + system_situation, + io_sbeState.update_actions, + io_sbeState.seeprom_side_to_update); + + + /**************************************************************/ + /* Setup new SBE Image Version Info */ + /**************************************************************/ + // Setup new SBE Image Version Info + memset(&(io_sbeState.new_seeprom_ver), + 0x0, + sizeof(sbeSeepromVersionInfo_t)); + + + io_sbeState.new_seeprom_ver.struct_version = + SBE_SEEPROM_STRUCT_VERSION; + + memcpy( &(io_sbeState.new_seeprom_ver.image_version), + &(io_sbeState.pnorVersion), + SBE_IMAGE_VERSION_SIZE); + + memcpy( &(io_sbeState.new_seeprom_ver.data_crc), + &(io_sbeState.customizedImage_crc), + SBE_DATA_CRC_SIZE); + + // If there was an ECC fail on either SEEPROM, do a read-back + // Check when writing this information to the SEEPROM + io_sbeState.new_readBack_check = ( + io_sbeState.seeprom_0_ver_ECC_fail || + io_sbeState.seeprom_1_ver_ECC_fail); + + + TRACDBIN( g_trac_sbe, + "getTargetUpdateActions() - New SBE Version Info", + &(io_sbeState.new_seeprom_ver), + sizeof(sbeSeepromVersionInfo_t)); + + /**************************************************************/ + /* Update MVPD Struct to write back */ + /**************************************************************/ + + // Note: mvpdSbKeyword.flags updated above + memset(&(io_sbeState.mvpdSbKeyword), + 0, + sizeof(sbeSeepromVersionInfo_t)); + + if ( io_sbeState.seeprom_side_to_update == EEPROM::SBE_PRIMARY ) + { + memcpy( &(io_sbeState.mvpdSbKeyword.seeprom_0_data_crc), + &(io_sbeState.customizedImage_crc), + SBE_DATA_CRC_SIZE); + + memcpy( &(io_sbeState.mvpdSbKeyword.seeprom_0_short_version), + &(io_sbeState.pnorVersion), + SBE_MVPD_SHORT_IMAGE_VERSION_SIZE); + } + else // EEPROM::SBE_Backup + { + memcpy( &(io_sbeState.mvpdSbKeyword.seeprom_1_data_crc), + &(io_sbeState.customizedImage_crc), + SBE_DATA_CRC_SIZE); + + memcpy( &(io_sbeState.mvpdSbKeyword.seeprom_1_short_version), + &(io_sbeState.pnorVersion), + SBE_MVPD_SHORT_IMAGE_VERSION_SIZE); + } + + + + + + + }while(0); + + return err; + + + } + +///////////////////////////////////////////////////////////////////// + void decisionTreeForUpdates(sbeTargetState_t& io_sbeState, + uint8_t i_system_situation) + { + + + uint32_t l_actions = CLEAR_ACTIONS; + io_sbeState.update_actions = CLEAR_ACTIONS; + io_sbeState.seeprom_side_to_update = EEPROM::LAST_CHIP_TYPE; + + + do{ + + // To be safe, we're only look at the bits defined in sbe_update.H + i_system_situation &= SITUATION_ALL_BITS_MASK; + + // @todo RTC 47033 set bit 1 in MVPD SB flag byte to + // represent the which SEEPROM the FSP should reboot from + + + switch ( i_system_situation ) + { + case ( SITUATION_CUR_IS_TEMP | + SITUATION_CUR_IS_DIRTY | + SITUATION_ALT_IS_DIRTY ) : + + // 0xE0: cur=temp, cur=dirty, alt=dirty + // Treat like 0xC0 + // not sure why we booted off of temp + + case ( SITUATION_CUR_IS_TEMP | + SITUATION_CUR_IS_DIRTY | + SITUATION_ALT_IS_CLEAN ) : + + + // 0xC0: cur=temp, cur=dirty, alt=clean + // Bad path: we shouldn't be booting to dirty side + // Update Alt and re-IPL to it + // Update MVPD flag: make cur=perm (because we know it + // works a bit) + + l_actions |= IPL_RESTART; + l_actions |= DO_UPDATE; + + // Set Update side to alt + io_sbeState.seeprom_side_to_update = + ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; + + // Update MVPD flag make cur=perm + ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ? + // clear bit 0 + io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK + : //set bit 0 + io_sbeState.mvpdSbKeyword.flags |= PERMANENT_FLAG_MASK; + + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=temp/dirty. Update alt. Re-IPL. " + "Update MVPD flag. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + + break; + + case ( SITUATION_CUR_IS_TEMP | + SITUATION_CUR_IS_CLEAN | + SITUATION_ALT_IS_DIRTY ) : + + // 0xA0: cur=temp, cur=clean, alt=dirty + // Common 2nd step of Code Update path + // Update Alt and Continue IPL + // Update MVPD flag: make cur=perm + + l_actions |= DO_UPDATE; + + // Set Update side to alt + io_sbeState.seeprom_side_to_update = + ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; + + + // MVPD flag Update + // Update MVPD flag make cur=perm + ( io_sbeState.cur_seeprom_side == SBE_SEEPROM0 ) ? + // clear bit 0 + io_sbeState.mvpdSbKeyword.flags &= ~PERMANENT_FLAG_MASK + : //set bit 0 + io_sbeState.mvpdSbKeyword.flags |= PERMANENT_FLAG_MASK; + + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=temp/clean, alt=dirty. " + "Update alt. Continue IPL. Update MVPD flag." + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + + case ( SITUATION_CUR_IS_TEMP | + SITUATION_CUR_IS_CLEAN | + SITUATION_ALT_IS_CLEAN ) : + + // 0x80: cur=temp, cur=clean, alt=clean + // Should've broke earlier -- both sides are clean, + // but handle just in case + // Not sure why cur=temp, but do nothing + + l_actions = CLEAR_ACTIONS; + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "Both sides clean-no updates. cur was temp. " + "Continue IPL. (d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + + case ( SITUATION_CUR_IS_PERM | + SITUATION_CUR_IS_DIRTY | + SITUATION_ALT_IS_DIRTY ) : + + // 0x60: cur=perm, cur=dirty, alt=dirty + // Common situation: likely first step of code update + // Update alt and re-ipl + l_actions |= IPL_RESTART; + l_actions |= DO_UPDATE; + + // Set Update side to alt + io_sbeState.seeprom_side_to_update = + ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=perm/dirty, alt=dirty. Update alt. re-IPL. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + + case ( SITUATION_CUR_IS_PERM | + SITUATION_CUR_IS_DIRTY | + SITUATION_ALT_IS_CLEAN ) : + + // 0x40: cur=perm, cur=dirty, alt=clean + // @todo RTC 40733 - Ask FSP if we just asked for re-IPL + // for now just continue IPL + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=perm/dirty, alt=clean. Continue IPL. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + break; + + + case ( SITUATION_CUR_IS_PERM | + SITUATION_CUR_IS_CLEAN | + SITUATION_ALT_IS_DIRTY ) : + + // 0x20: cur=perm, cur=clean, alt=dirty + // Not sure why alt is dirty, but update alt and + // continue IPL + + l_actions |= DO_UPDATE; + + // Set Update side to alt + io_sbeState.seeprom_side_to_update = + ( io_sbeState.alt_seeprom_side == SBE_SEEPROM0 ) + ? EEPROM::SBE_PRIMARY : EEPROM::SBE_BACKUP ; + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "cur=perm/clean, alt=dirty. " + "Update alt. Continue IPL. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + + case ( SITUATION_CUR_IS_PERM | + SITUATION_CUR_IS_CLEAN | + SITUATION_ALT_IS_CLEAN ) : + + // 0x0: cur=perm, cur=clean, alt=clean + // Should've broke earlier -- both sides are clean, + // but handle just in case + l_actions = CLEAR_ACTIONS; + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "Both sides clean-no updates. cur was temp. " + "Continue IPL. (d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + + default: + + TRACFCOMP( g_trac_sbe, INFO_MRK"decisionTreeForUpdates() - " + "Unsupported Scenario. Just Continue IPL. " + "(d_t=0x%.2X, act=0x%.8X)", + i_system_situation, l_actions); + + break; + } + + + // Set actions + io_sbeState.update_actions = static_cast<sbeUpdateActions_t> + (l_actions); + + TRACUCOMP( g_trac_sbe, "decisionTreeForUpdates() - i_system_situation= " + "0x%.2X, actions=0x%.8X, Update EEPROM=0x%X, doU=%d, " + "reIpl=%d", + i_system_situation, + io_sbeState.update_actions, + io_sbeState.seeprom_side_to_update, + io_sbeState.update_actions && DO_UPDATE, + io_sbeState.update_actions && IPL_RESTART); + + }while(0); + + return; + + + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t performUpdateActions(sbeTargetState_t& io_sbeState) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"performUpdateActions()"); + errlHndl_t err = NULL; + + do{ + + + /**************************************************************/ + /* Update Actions: */ + /* 1) Update SEEPROM */ + /* 2) Update MVPD */ + /**************************************************************/ + + /**************************************************************/ + /* 1) Update SEEPROM */ + /**************************************************************/ + err = updateSeepromSide(io_sbeState); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"performUpdateActions() - " + "updateProcessorSbeSeeproms() failed. HUID=0x%.8X.", + TARGETING::get_huid(io_sbeState.target)); + continue; + } + + /**************************************************************/ + /* 2) Update MVPD */ + /**************************************************************/ + //Update MVPD anytime we do any sort of SBE Update. + err = getSetMVPDVersion(io_sbeState.target, + MVPDOP_WRITE, + io_sbeState.mvpdSbKeyword); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"performUpdateActions() - " + "Error Updating MVPD with new SBE Image Info " + "HUID=0x%.8X, rc=0x%.4x", + TARGETING::get_huid(io_sbeState.target), + err->reasonCode()); + break; + } + + + + }while(0); + + return err; + + + } + +///////////////////////////////////////////////////////////////////// + // @todo RTC 47033 - Likely to remove this function because creating a + // CRC from the customized image seems more efficient. + errlHndl_t getDataCrc(TARGETING::Target* i_target, + uint32_t& o_data_crc) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"getDataCrc"); + + errlHndl_t err = NULL; + size_t data_size = 0; + uint8_t* data_ptr = NULL; + uint8_t index = 0; + + size_t mvpd_pdG_size = 0; + uint8_t* mvpd_pdG_data_ptr = NULL; + size_t mvpd_pdR_size = 0; + uint8_t* mvpd_pdR_data_ptr = NULL; + + o_data_crc = 0x0; + + do{ + + + /*******************************************/ + /* Get #G Ring Data from MVPD */ + /*******************************************/ + // Note: First read with NULL for o_buffer sets vpdSize to the + // correct length + err = deviceRead( i_target, + NULL, + mvpd_pdG_size, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::pdG ) ); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getDataCrc() - MVPD failure getting pdG keyword size HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + // Create buffer to capture the data + mvpd_pdG_data_ptr = static_cast<uint8_t*>(malloc(mvpd_pdG_size)); + + err = deviceRead( i_target, + mvpd_pdG_data_ptr, + mvpd_pdG_size, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::pdG ) ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getDataCrc() - MVPD failure read pdG data HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + + /*******************************************/ + /* Get #R Ring Data from MVPD */ + /*******************************************/ + // Note: First read with NULL for o_buffer sets vpdSize to the + // correct length + err = deviceRead( i_target, + NULL, + mvpd_pdR_size, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::pdR ) ); + + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getDataCrc() - MVPD failure getting pdR keyword size HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + // Create buffer to capture the data + mvpd_pdR_data_ptr = static_cast<uint8_t*>(malloc(mvpd_pdR_size)); + + err = deviceRead( i_target, + mvpd_pdR_data_ptr, + mvpd_pdR_size, + DEVICE_MVPD_ADDRESS( MVPD::CP00, + MVPD::pdR ) ); + if(err) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getDataCrc() - MVPD failure read pdG data HUID=0x%.8X", + TARGETING::get_huid(i_target)); + break; + } + + + /**********************************************/ + /* Concatenate the Data and compute the CRC */ + /**********************************************/ + // Add up all the sizes and create a buffer + data_size = mvpd_pdG_size + mvpd_pdR_size; + data_ptr = static_cast<uint8_t*>(malloc(data_size)); + + + memcpy( data_ptr, mvpd_pdG_data_ptr, mvpd_pdG_size); + index = mvpd_pdG_size; + + memcpy( &(data_ptr[index]), mvpd_pdR_data_ptr, mvpd_pdR_size); + + o_data_crc = Util::crc32_calc(data_ptr, data_size); + + + }while(0); + + // Free allocated memory + free(mvpd_pdG_data_ptr); + free(mvpd_pdR_data_ptr); + + + TRACUCOMP( g_trac_sbe, EXIT_MRK"getDataCrc: o_data_crc= 0x%.4x, " + "pdG_size=%d, pdR_size=%d", + o_data_crc, mvpd_pdG_size, mvpd_pdR_size); + + return err; + + } + + + +///////////////////////////////////////////////////////////////////// + uint32_t trimBitMask(uint32_t i_mask, + size_t i_maxBits) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"trimBitMask(i_mask=0x%.8X, i_maxBits=0x%.8X)", + i_mask, i_maxBits); + uint32_t retMask = i_mask; + + + while(__builtin_popcount(retMask) > static_cast<int32_t>(i_maxBits)) + { + retMask ^= 0x1 << static_cast<uint32_t>(__builtin_ctz(retMask)); + } + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"trimBitMask(): retMask=0x%.8X", + retMask); + + return retMask; + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t createSbeImageVmmSpace(void) + { + + TRACDCOMP( g_trac_sbe, + ENTER_MRK"createSbeImageVmmSpace"); + + int64_t rc = 0; + errlHndl_t err = NULL; + + do{ + + //Make sure procedure constants keep within expected range. + assert((FIXED_SEEPROM_WORK_SPACE <= VMM_SBE_UPDATE_SIZE/2), + "createSbeImageVmmSpace() FIXED_SEEPROM_WORK_SPACE too large"); + assert((FIXED_RING_BUF_SIZE <= VMM_SBE_UPDATE_SIZE/4), + "createSbeImageVmmSpace() FIXED_RING_BUF_SIZE too large"); + + + // Create a memory block to serve as XIP Customize scratch space + // NOTE: using mm_alloc_block since this code is running before we + // have mainstore and we must have contiguous blocks of memory for + // the customize procedure to use. + rc = mm_alloc_block( NULL, + reinterpret_cast<void*> + (VMM_VADDR_SBE_UPDATE), + VMM_SBE_UPDATE_SIZE); + + if( rc ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"createSbeImageVmmSpace() - " + "Error from mm_alloc_block : rc=%d", rc ); + /*@ + * @errortype + * @moduleid SBE_CREATE_TEST_SPACE + * @reasoncode SBE_ALLOC_BLOCK_FAIL + * @userdata1 Requested Address + * @userdata2 rc from mm_alloc_block + * @devdesc updateProcessorSbeSeeproms> Error + * from mm_alloc_block + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_CREATE_TEST_SPACE, + SBE_ALLOC_BLOCK_FAIL, + TO_UINT64(VMM_VADDR_SBE_UPDATE), + TO_UINT64(rc)); + + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + + break; + } + + rc = mm_set_permission(reinterpret_cast<void*> + (VMM_VADDR_SBE_UPDATE), + VMM_SBE_UPDATE_SIZE, + WRITABLE | ALLOCATE_FROM_ZERO ); + if( rc ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"createSbeImageVmmSpace() - Error from mm_set_permission : rc=%d", rc ); + /*@ + * @errortype + * @moduleid SBE_CREATE_TEST_SPACE + * @reasoncode SBE_SET_PERMISSION_FAIL + * @userdata1 Requested Address + * @userdata2 rc from mm_set_permission + * @devdesc updateProcessorSbeSeeproms> Error from + * mm_set_permission + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_CREATE_TEST_SPACE, + SBE_SET_PERMISSION_FAIL, + TO_UINT64(VMM_VADDR_SBE_UPDATE), + TO_UINT64(rc)); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + break; + } + + }while(0); + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"createSbeImageVmmSpace() - rc =0x%X", rc); + + return err; + + } + + +///////////////////////////////////////////////////////////////////// + errlHndl_t cleanupSbeImageVmmSpace(void) + { + TRACDCOMP( g_trac_sbe, + ENTER_MRK"cleanupSbeImageVmmSpace"); + + errlHndl_t err = NULL; + int64_t rc = 0; + + do{ + + //release all pages in page block to ensure we + //start with clean state + rc = mm_remove_pages(RELEASE, + reinterpret_cast<void*> + (VMM_VADDR_SBE_UPDATE), + VMM_SBE_UPDATE_SIZE); + if( rc ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"cleanupSbeImageVmmSpace() - " + "Error from mm_remove_pages : rc=%d", rc ); + /*@ + * @errortype + * @moduleid SBE_CLEANUP_TEST_SPACE + * @reasoncode SBE_REMOVE_PAGES_FAIL + * @userdata1 Requested Address + * @userdata2 rc from mm_remove_pages + * @devdesc updateProcessorSbeSeeproms> mm_remove_pages + * RELEASE failed + */ + err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, + SBE_CLEANUP_TEST_SPACE, + SBE_REMOVE_PAGES_FAIL, + TO_UINT64(VMM_VADDR_SBE_UPDATE), + TO_UINT64(rc)); + err->collectTrace(SBE_COMP_NAME); + err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH ); + } + + }while(0); + + + TRACDCOMP( g_trac_sbe, + EXIT_MRK"cleanupSbeImageVmmSpace() - rc =0x%X", rc); + + return err; + + } + + +} //end SBE Namespace diff --git a/src/usr/sbe/sbe_update.H b/src/usr/sbe/sbe_update.H new file mode 100644 index 000000000..bb161dfd0 --- /dev/null +++ b/src/usr/sbe/sbe_update.H @@ -0,0 +1,439 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbe/sbe_update.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SBE_SBE_UPDATE_H +#define __SBE_SBE_UPDATE_H + + +#include <stdint.h> +#include <builtins.h> +#include <errl/errlentry.H> +#include <pnor/pnorif.H> +#include <vmmconst.h> +#include <targeting/common/targetservice.H> +#include <i2c/eepromif.H> + +namespace SBE +{ + /******************************************/ + /* Constants */ + /******************************************/ + // Size of CRC used for version checking + const size_t SBE_DATA_CRC_SIZE = 4; // 4 bytes (32 bits) + + // Using only first 20 bytes of 64-byte sbe_image_version + const size_t SBE_MVPD_SHORT_IMAGE_VERSION_SIZE = 20; + + // Version of Struct stored in SEEPROM + const uint32_t SBE_SEEPROM_STRUCT_VERSION = 0x00000001; + + // Used for locations of SBE_Version and SBE Image on a SEEPROM + const uint64_t SBE_IMAGE_SEEPROM_ADDRESS = 0x400; // 1KB + const uint64_t SBE_VERSION_SEEPROM_ADDRESS = 0x300; // 1KB - 256B + + //Used to read SBE Boot Side from processor + const uint64_t SBE_VITAL_REG_0x0005001C = 0x005001C; + const uint64_t SBE_BOOT_SELECT_MASK = 0x0080000000000000; + + // PNOR SBE and SBEC Partition constants + const uint32_t MAX_SBE_ENTRIES = 9; + const uint32_t SBETOC_EYECATCH = 0x53424500; //'SBE\0' + const uint64_t NONSECURE_VER_EYECATCH = 0x56455253494F4E00; //'VERSION\0' + const uint32_t SUPPORTED_TOC_VER = 0x00000001; + + // MVPD SB Keyword contants + const size_t MVPD_SB_RECORD_SIZE = 49; + const uint8_t PERMANENT_FLAG_MASK = 0x80; + // PERMANENT FLAG = 0 -> indicates 0 is permanent. + const uint8_t SEEPROM_0_PERMANENT_VALUE = 0x00; + const uint8_t SEEPROM_1_PERMANENT_VALUE = 0x80; + // @todo RTC 47033 - add support for bit 1 (0x40): temp boot side + + + // Situation constants -- bits numbered from left to right + const uint8_t SITUATION_ALL_BITS_MASK = 0xE0; + // Bit 0: current side is permanent (=0) or temp (=1) + const uint8_t SITUATION_CUR_IS_PERM = 0x00; + const uint8_t SITUATION_CUR_IS_TEMP = 0x80; + + // Bit 1: current_side clean (=0) or dirty (=1) + const uint8_t SITUATION_CUR_IS_CLEAN = 0x00; + const uint8_t SITUATION_CUR_IS_DIRTY = 0x40; + + // Bit 2: alt side clean (=0) or dirty (=1) + const uint8_t SITUATION_ALT_IS_CLEAN = 0x00; + const uint8_t SITUATION_ALT_IS_DIRTY = 0x20; + + + /******************************************/ + /* Enums */ + /******************************************/ + // Used for MVPD function + enum opType_t + { + MVPDOP_UNKNOWN, // Invalid + MVPDOP_READ, // Read version data from MVPD + MVPDOP_WRITE, // Write version data to MVPD + }; + + // Used to keep track of perm/temp, and cur/alt + enum sbeSeepromSide_t + { + SBE_SEEPROM0, // corresponds to EEPROM::SBE_PRIMARY + SBE_SEEPROM1, // corresponts to EEPROM::SBE_BACKUP + SBE_SEEPROM_INVALID, + }; + + // Actions can be combined + enum sbeUpdateActions_t + { + CLEAR_ACTIONS = 0x00000000, + DO_UPDATE = 0x00000001, + IPL_RESTART = 0x00000002, + CALLOUT_SBE_CODE = 0x00000004, + UNSUPPORTED_SITUATION = 0x00000008, + }; + + + /******************************************/ + /* Structs */ + /******************************************/ + + /** + * @brief Struct containing version information stored on SBE SEEPROMs + * + * NOTE: For ECC purposes, this must be 8-byte aligned, + * so pad data if necessary + * struct_version 1: size = 4+64+4 = 72 (aligned) + */ + struct sbeSeepromVersionInfo_t + { + uint32_t struct_version; + uint8_t image_version[SBE_IMAGE_VERSION_SIZE]; + uint8_t data_crc[SBE_DATA_CRC_SIZE]; + } PACKED; + + + /** + * @brief Struct of individual SBE entry in SBE and SBEC + * Table of Contents in PNOR partitions + */ + struct sbeTocEntry_t + { + uint32_t ec; // Chip EC, right aligned + uint32_t offset; // Offset within partition, in bytes + uint32_t size; // Size of image, in bytes + } PACKED; + + /** + * @brief Layout of Table of Contents at beginning of SBE and + * SBEC Partitions in PNOR + */ + struct sbeToc_t + { + uint32_t eyeCatch; // Expected to contain 'SBE\0' + uint32_t tocVersion; // Version of SBE TOC + sbeTocEntry_t entries[MAX_SBE_ENTRIES]; // Image entries + } PACKED; + + /** + * @brief Layout of SB keyword in MVPD + */ + struct mvpdSbKeyword_t + { + uint8_t flags; // 1 byte for various flags + + uint8_t seeprom_0_data_crc[SBE_DATA_CRC_SIZE]; + uint8_t seeprom_0_short_version[SBE_MVPD_SHORT_IMAGE_VERSION_SIZE]; + + uint8_t seeprom_1_data_crc[SBE_DATA_CRC_SIZE]; + uint8_t seeprom_1_short_version[SBE_MVPD_SHORT_IMAGE_VERSION_SIZE]; + } PACKED; + + + /** + * @brief Contains the SBE state for a given target + */ + struct sbeTargetState_t + { + + // Target Information + TARGETING::Target* target; + bool target_is_master; + uint8_t ec; + + // Current Target SBE State Information + sbe_image_version_t pnorVersion; + mvpdSbKeyword_t mvpdSbKeyword; + + sbeSeepromVersionInfo_t seeprom_0_ver; + sbeSeepromVersionInfo_t seeprom_1_ver; + + bool seeprom_0_ver_ECC_fail; + bool seeprom_1_ver_ECC_fail; + + sbeSeepromSide_t cur_seeprom_side; // aka 'booted' side + sbeSeepromSide_t alt_seeprom_side; + sbeSeepromSide_t permanent_seeprom_side; + + // Customized Image Information for this Target + size_t customizedImage_size; + uint32_t customizedImage_crc; + + // Update Fields and New Fields to be Written to the Target + sbeUpdateActions_t update_actions; + EEPROM::eeprom_chip_types_t seeprom_side_to_update; + + sbeSeepromVersionInfo_t new_seeprom_ver; + bool new_readBack_check; + + }; + + + + /******************************************/ + /* Functions -- High Level Functions */ + /******************************************/ + + /** + * @brief Collects SBE Information for a specifc target + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getSbeInfoState(sbeTargetState_t& io_sbeState); + + /** + * @brief Analyze and Determine Update Actions for a specific target + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getTargetUpdateActions(sbeTargetState_t& io_sbeState); + + /** + * @brief Performs the Update Actions for a specific target + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t performUpdateActions(sbeTargetState_t& io_sbeState); + + + /******************************************/ + /* Functions -- System Access */ + /******************************************/ + + /** + * @brief Read or Write SB Keyword in MVPD + * + * @param[in] i_target Target processor + * + * @param[in] i_op Indicates read or write + * + * @param[io/out] io_sb_keyword Pointer to MVPD SBE Keyword struct + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getSetMVPDVersion(TARGETING::Target* i_target, + opType_t i_op, + mvpdSbKeyword_t& io_sb_keyword); + + + /** + * @brief Read SBE Version from PNOR + * + * @param[in] i_pnorImgHdrPtr Pointer to Image Header in PNOR + * + * @param[out] o_version Pointer to SBE Version struct + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t readPNORVersion(void*& i_pnorImgHdrPtr, + sbe_image_version_t& o_version); + + + /** + * @brief Customize SBE Image for current Processor + * + * @param[in] i_target Target processor to customize + * + * @param[in] i_sbePnorPtr Pointer to SBE Image in PNOR + * Expected that this pointer was found with + * findSBEInPnor() function and is past any + * image header + * + * @param[in] i_maxImgSize Maximum size of customized image + * + * @param[out] io_imgPtr Pointer to SBE image in memory + * Memory from this pointer through + * i_maxImgSize is expected to be pre-alloacted + * + * @param[out] o_actImgSize Actual size of the customized image + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t procCustomizeSbeImg(TARGETING::Target* i_target, + void* i_sbePnorPtr, + size_t i_maxImgSize, + void* io_imgPtr, + size_t& o_actImgSize); + + /** + @brief Collect data for CRC, Concatenate the data, then compute the CRC + * + * @param[in] i_target Target processor + * + * @param[out] o_data_crc CRC computed from concatenated collected data + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getDataCrc(TARGETING::Target* i_target, + uint32_t& o_data_crc); + + + /** + * @brief Determines which Seeprom was used to boot the SBE + * + * @param[in] i_target Target processor to customize + * + * @param[out] o_bootSide The Seeprom the SBE booted from + * + * @return errlHndl_t Error log handle on failure. + */ + + errlHndl_t getSbeBootSeeprom(TARGETING::Target* i_target, + sbeSeepromSide_t& o_bootSide); + + + /** + * @brief Collects Version information from a specific SEEPROM + * + * @param[in] i_target Target processor to customize + * + * @param[in] i_seepromSide The SEEPROM on the target that to collect + * the information from + * + * @param[out] o_info Struct containing the SBE Version Information + * + * @param[out] o_seeprom_ver_ECC_fail Reports if there was an ECC erorr on + * the collected information + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t getSeepromSideVersion(TARGETING::Target* i_target, + EEPROM::eeprom_chip_types_t i_seepromSide, + sbeSeepromVersionInfo_t& o_info, + bool& o_seeprom_ver_ECC_fail); + + /** + * @brief Updates a specific SEEPROM + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * and the information to be used for updating + * the SBE State of the target + */ + errlHndl_t updateSeepromSide(sbeTargetState_t i_sbeState); + + + + /******************************************/ + /* Functions -- Helper Functions */ + /******************************************/ + + /** + * @brief Determines the Update Actions for a specific target situation + * + * @param[io/out] io_sbeState Struct containing SBE State of the target + * and is updated based on the situation + * + * @param[in] i_system_situation SBE Situation of the target that requires + * analysis to determine Update Actions + * + * @return void + */ + void decisionTreeForUpdates(sbeTargetState_t& io_sbeState, + uint8_t i_system_situation); + + /** + * @brief Creates the memory space needed for SBE Image Customization + * by allocating and setting permissions on VMM_VADDR_SBE_UPDATE + * area defined in vmmconst.H + * + * @param[in] void + * + * @return void + */ + errlHndl_t createSbeImageVmmSpace(void); + + /** + * @brief Cleans up memory space needed for SBE Image Customization + * + * @param[in] void + * + * @return void + */ + errlHndl_t cleanupSbeImageVmmSpace(void); + + /** + * @brief Select best cores to include in SBE Image. + * The output is used to indicate to p8_xip_customize which cores + * should be included in the SBE image. + * + * @param[in] i_target Target processor to use for core selection + * + * @param[in] i_maxCores Maximum number of cores to select for inclusion + * in the SBE Image + * + * @param[out] o_coreMask Core Mask for the target that does not exceed + * the maximum number of cores + * NOTE: bits 16:31 = EX0:EX15 + * This value is used as input into + * p8_xip_customize.C + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t selectBestCores(TARGETING::Target* i_target, + size_t i_maxCores, + uint32_t& o_coreMask); + + + /** + * @brief Reduces bits set in a bit mask until there is a + * a maximum number of bits set + * + * @param[in] i_mask Starting mask to be reduced + * + * @param[in] i_maxBits Maximum number of bits that the + * returned Bit Mask can contain + * + * @return uint32_t Bit Mask + */ + uint32_t trimBitMask(uint32_t i_mask, + size_t i_maxBits); + + +} //end namespace SBE +#endif diff --git a/src/usr/sbe/test/makefile b/src/usr/sbe/test/makefile new file mode 100644 index 000000000..4190b0625 --- /dev/null +++ b/src/usr/sbe/test/makefile @@ -0,0 +1,28 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/sbe/test/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2013 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../../.. + +MODULE = testsbe +TESTS = *.H + +include ${ROOTPATH}/config.mk diff --git a/src/usr/sbe/test/sbeupdatetest.H b/src/usr/sbe/test/sbeupdatetest.H new file mode 100644 index 000000000..e92dc6d4c --- /dev/null +++ b/src/usr/sbe/test/sbeupdatetest.H @@ -0,0 +1,777 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbe/test/sbeupdatetest.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SBEUPDATETEST_H +#define __SBEUPDATETEST_H +/** + * @file sbeupdatetest.H + * + * @brief Test cases for SBE Update code + */ +#include <sys/time.h> + +#include <cxxtest/TestSuite.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <devicefw/driverif.H> +#include <vfs/vfs.H> +#include <targeting/common/utilFilter.H> +#include <sbe/sbeif.H> +#include "../sbe_update.H" + + +extern trace_desc_t* g_trac_sbe; + +// Macros for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + +const char SBE_BUILD_WINK_NAME[30] = "libbuild_winkle_images.so"; +const char SBE_LIBRARY_NAME[16] = "libsbe.so"; + + +using namespace SBE; + + +void getTargetList( TARGETING::TYPE i_targetType, + TARGETING::TargetHandleList & o_targetList, + bool i_functional ) // if true: return functional targets +{ + + + TARGETING::getAllChips(o_targetList, + i_targetType, + i_functional); + + if ( o_targetList.size() == 0 ) + { + TRACFCOMP( g_trac_sbe, + INFO_MRK"getTargetList() - Found Zero (%d) Targets of " + "type 0x%X", + o_targetList.size(), i_targetType ); + } + + TRACDCOMP( g_trac_sbe, + "getTargetList() - found %d Targets of type 0x%X", + o_targetList.size(), i_targetType ); + + return; +} + +TARGETING::Target* getFunctionalTarget(TARGETING::TYPE i_targetType) +{ + TARGETING::Target * theTarget = NULL; + TRACDCOMP( g_trac_sbe, + "getFunctionalTarget() - Finding Target of Type 0x%0x", + i_targetType ); + + do { + // Get the Processor targets + TARGETING::TargetHandleList targetList; + getTargetList( i_targetType, targetList, true ); + + if( ( 0 == targetList.size() ) || + ( NULL == targetList[0] ) ) + { + TRACFCOMP( g_trac_sbe, ERR_MRK"getFunctionalTarget() - Couldn't " + "find functional Target of Type 0x%0x (list.size=%d)", + i_targetType, targetList.size()); + continue; // continue because have no valid targets + } + + // List is of functional targets, so just return the first one + theTarget = targetList[0]; + + }while(0); + + TRACDCOMP( g_trac_sbe, + "getFunctionalTarget() - Returning Target 0x%0x of Type 0x%0x", + TARGETING::get_huid(theTarget), i_targetType ); + + return theTarget; + +} + + +errlHndl_t loadSbeModule(bool& o_loaded) +{ + errlHndl_t err = NULL; + o_loaded = false; + + if(!VFS::module_is_loaded(SBE_LIBRARY_NAME)) + { + err = VFS::module_load(SBE_LIBRARY_NAME); + if(err) + { + // Don't use g_trac_sbe - libsbe might not be loaded + TS_FAIL("loadSbeModule() - %s load failed", SBE_LIBRARY_NAME ); + + } + else + { + o_loaded = true; + } + } + + // This module is needed for certain HW procedure (like p8_xip_customize()) + if(!VFS::module_is_loaded(SBE_BUILD_WINK_NAME)) + { + err = VFS::module_load(SBE_BUILD_WINK_NAME); + if(err) + { + // Don't use g_trac_sbe - libsbe might not be loaded + TS_FAIL("loadSbeModule() - %s load failed", SBE_BUILD_WINK_NAME); + } + else + { + o_loaded = true; + } + } + + return err; +} + +errlHndl_t unloadSbeModule() +{ + errlHndl_t err = NULL; + + err = VFS::module_unload(SBE_LIBRARY_NAME); + if(err) + { + // Don't use g_trac_sbe - libsbe might be unloaded + TS_FAIL("unloadSbeModule() - %s unload failed", SBE_LIBRARY_NAME ); + + // No break or return - still try and unload other module + } + + err = VFS::module_unload(SBE_BUILD_WINK_NAME); + if(err) + { + // Don't use g_trac_sbe - libsbe might be unloaded + TS_FAIL("unloadSbeModule() - %s unload failed", SBE_BUILD_WINK_NAME); + } + + return err; +} + + +class SBEUpdateTest: public CxxTest::TestSuite +{ + public: + + /** + * @brief This function will test __trimCoreMask + */ + void testTrimBitMask( void ) + { + + uint64_t fails = 0x0; + uint64_t total = 0x0; + + do{ + + TRACFCOMP( g_trac_sbe, + ENTER_MRK"testTrimBitMask()" ); + + struct + { + uint32_t inMask; + uint32_t maxBits; + uint32_t outMask; + } testData[] = + { + {0xFFFFFFFF, 10, 0xFFC00000}, + {0xFFFFFFFF, 32, 0xFFFFFFFF}, + {0x0000FF00, 4, 0x0000F000}, + {0x0000FF00, 8, 0x0000FF00}, + {0x0000FF50, 16, 0x0000FF50}, + {0x000000FF, 5, 0x000000F8}, + {0x000000FF, 8, 0x000000FF}, + }; + const uint32_t NUM_TESTS = sizeof(testData)/sizeof(testData[0]); + + uint32_t retMask = 0; + + for(uint32_t i=0; i < NUM_TESTS; i++) + { + retMask = trimBitMask(testData[i].inMask, + testData[i].maxBits); + total++; + if(retMask != testData[i].outMask) + { + fails++; + TRACFCOMP( g_trac_sbe, ERR_MRK"testTrimBitMask() - i=%d, " + "retMask=0x%.8X, expMask=0x%.8X", + i, retMask, testData[i].outMask); + TS_FAIL("testTrimBitMask() - Return data did not match " + "expected data."); + } + } + + }while(0); + + TRACFCOMP( g_trac_sbe, + EXIT_MRK"testTrimBitMask - %d/%d fails", + fails, total ); + } + + /** + * @brief This function will test SBE Update's ability + * to find SBE images in PNOR + */ + + void testFindSbeInPnor ( void ) + { + errlHndl_t err = NULL; + uint64_t fails = 0x0; + uint64_t total = 0x0; + + TARGETING::Target* theTarget = NULL; + void* sbeImgPtr = NULL; + size_t sbeImgSize = 0; + sbe_image_version_t version; + + do{ + + TRACFCOMP( g_trac_sbe, + ENTER_MRK"testFindSbeInPnor()" ); + + /****************************************************/ + /* Find a valid Processor */ + /****************************************************/ + theTarget = getFunctionalTarget(TARGETING::TYPE_PROC); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testReadSbeFromPnor() - No Functional Proc Targets found!"); + break; + } + + total++; + err = findSBEInPnor(theTarget, + sbeImgPtr, + sbeImgSize, + &version); + + if(err || (sbeImgPtr == NULL) || (sbeImgSize == 0) ) + { + fails++; + TRACFCOMP( g_trac_sbe, ERR_MRK"testFindSbeInPnor() - failure " + "finding Proc SBE image for uid=0x%X, ec=0x%.2X" + "sbeImgPtr=%p, sbeImgSize=0x%x", + TARGETING::get_huid(theTarget), + theTarget->getAttr<TARGETING::ATTR_EC>(), + sbeImgPtr, sbeImgSize ); + TS_FAIL("testFindSbeInPnor() -failure finding SBE image!"); + errlCommit( err, + SBE_COMP_ID ); + + } + TRACDBIN(g_trac_sbe, "testFindSbeInPnor()-Proc PNOR Version", &version, sizeof(version)); + TRACDBIN(g_trac_sbe, "testFindSbeInPnor()-Proc PNOR Image", sbeImgPtr, 0x80); + + + /****************************************************/ + /* Find a valid MemBuf */ + /****************************************************/ + theTarget = getFunctionalTarget(TARGETING::TYPE_MEMBUF); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testReadSbeFromPnor() - No Functional MemBuf Targets found!"); + break; + } + + total++; + err = findSBEInPnor(theTarget, + sbeImgPtr, + sbeImgSize, + &version); + + if(err || (sbeImgPtr == NULL) || (sbeImgSize == 0) ) + { + fails++; + TRACFCOMP( g_trac_sbe, ERR_MRK"testFindSbeInPnor() - failure " + "finding MemBuf SBE image for uid=0x%X, ec=0x%.2X, " + "sbeImgPtr=%p, sbeImgSize=0x%x", + TARGETING::get_huid(theTarget), + theTarget->getAttr<TARGETING::ATTR_EC>(), + sbeImgPtr, sbeImgSize ); + TS_FAIL("testFindSbeInPnor() -failure finding SBE image!"); + errlCommit( err, + SBE_COMP_ID ); + + } + TRACDBIN(g_trac_sbe, "testFindSbeInPnor()-MEMBUF PNOR Version", &version, sizeof(version)); + TRACDBIN(g_trac_sbe, "testFindSbeInPnor()-MEMBUF PNOR Image", sbeImgPtr, 0x80); + + + /****************************************************/ + /* Verify invalid target Type is not found */ + /****************************************************/ + // test with system target -- safe that this target is configured + TARGETING::TargetService & tS = TARGETING::targetService(); + tS.getTopLevelTarget( theTarget ); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testFindSbeInPnor() - System target Not Found!"); + break; + } + + total++; + err = findSBEInPnor(theTarget, + sbeImgPtr, + sbeImgSize); + + if(err) + { + TRACFCOMP( g_trac_sbe, "testFindSbeInPnor() - Did not " + "find system-target SBE image as expected: " + "uid=0x%X, err=0x%X", + TARGETING::get_huid(theTarget), + err->reasonCode() ); + delete err; + err = NULL; + } + else + { + fails++; + TRACFCOMP( g_trac_sbe, ERR_MRK"testFindSbeInPnor() - Fail " + " expected when searching for invalid target " + "(Xbus): uid=0x%X, ec=0x%.2X", + TARGETING::get_huid(theTarget), + theTarget->getAttr<TARGETING::ATTR_EC>() ); + + TS_FAIL("testFindSbeInPnor() - Fail expected when searching for invalid EC level!"); + errlCommit( err, + SBE_COMP_ID ); + } + + TRACFCOMP( g_trac_sbe, + EXIT_MRK"testFindSbeInPnor - %d/%d fails", + fails, total ); + + }while(0); + + } + + + /** + * @brief This function will run through the functions used to collect + * SBE information on a single target, determine if that target + * needs to be updated, and perform the update. + */ + void testSbeUpdateTarget ( void ) + { + + errlHndl_t err = NULL; + errlHndl_t err_cleanup = NULL; + + uint64_t fails = 0x0; + uint64_t total = 0x0; + sbeTargetState_t sbeState; + + do{ + + /****************************************************/ + /* Get Functional Target and Load SBE Module */ + /****************************************************/ + TARGETING::Target * theTarget = + getFunctionalTarget(TARGETING::TYPE_PROC); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testSbeUpdateTarget() - No Functional Targets found!"); + break; + } + + TRACFCOMP( g_trac_sbe, + ENTER_MRK"testSbeUpdateTarget()" ); + + uint8_t local_ec = theTarget->getAttr<TARGETING::ATTR_EC>(); + + err = createSbeImageVmmSpace(); + if(theTarget == NULL) + { + total++; + fails++; + TS_FAIL("testSbeUpdateTarget() - Call to createSbeImageVmmSpace() failed"); + break; + } + + + /****************************************************/ + /* Get SBE Info State */ + /****************************************************/ + // Clear struct + memset(&sbeState, 0, sizeof(sbeState)); + + // Must set struct's target field + sbeState.target = theTarget; + + // set bad ec just for comparison to local_ec later + sbeState.ec = 0xFF; + + + total++; + err = getSbeInfoState(sbeState); + if(err) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - call getSbeInfoState() failed."); + break; + } + + + /****************************************************/ + /* Compare/Display SBE Version Information */ + /****************************************************/ + + // Quick EC check + if (local_ec != sbeState.ec) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - Bad ec check: local=0x%X, other=0x%X", local_ec, sbeState); + break; + } + + // Display sbeState + TRACUCOMP( g_trac_sbe, + "testSbeUpdateTarget() Info For Target 0x%X ec=0x%X " + "cur=0x%X alt=0x%X, ECC_fail 0/1=%d/%d, isMaster=%d " + "Custom Image Size=0x%X, CRC=0x%X", + TARGETING::get_huid(sbeState.target), sbeState.ec, + sbeState.cur_seeprom_side, sbeState.alt_seeprom_side, + sbeState.seeprom_0_ver_ECC_fail, + sbeState.seeprom_1_ver_ECC_fail, + sbeState.target_is_master, + sbeState.customizedImage_size, + sbeState.customizedImage_crc); + + TRACDBIN( g_trac_sbe, "testSbeUpdateTarget()-pnorVersion", + &sbeState.pnorVersion, sizeof(sbe_image_version_t)); + TRACDBIN( g_trac_sbe, "testSbeUpdateTarget()-mvpdSbKeyword", + &sbeState.mvpdSbKeyword, sizeof(mvpdSbeVersion_t)); + TRACDBIN( g_trac_sbe, "testSbeUpdateTarget()-seeprom_0_ver", + &sbeState.seeprom_0_ver, + sizeof(sbeSeepromVersionInfo_t)); + TRACDBIN( g_trac_sbe, "testSbeUpdateTarget()-seeprom_1_ver", + &sbeState.seeprom_1_ver, + sizeof(sbeSeepromVersionInfo_t)); + + + /****************************************************/ + /* CRC Calculation */ + /****************************************************/ + uint32_t new_data_crc = 0; + total++; + + err = getDataCrc(theTarget, new_data_crc); + if(err) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - getDataCrc() failed"); + break; + } + + TRACUCOMP( g_trac_sbe, "testSbeUpdateTarget(): getDataCrc(): data_crc=0x%.4x", + new_data_crc); + + /****************************************************/ + /* Get Target Update Actions */ + /****************************************************/ + + total++; + err = getTargetUpdateActions(sbeState); + if(err) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - getTargetUpdateActions() failed"); + break; + } + + + /****************************************************/ + /* Update SBE Backup */ + /****************************************************/ + // force backup to SEEPROM 1 just in case + if ( !(sbeState.update_actions & DO_UPDATE ) ) + { + sbeState.seeprom_side_to_update = EEPROM::SBE_BACKUP; + } + total++; + + err = performUpdateActions(sbeState); + if(err) + { + fails++; + TS_FAIL("testSbeUpdateTarget() - performUpdateActions() failed."); + break; + } + + + }while(0); + + err_cleanup = cleanupSbeImageVmmSpace(); + if(err_cleanup) + { + total++; + fails++; + TS_FAIL("testSbeUpdateTarget() -Call to cleanupSbeImageVmmSpace() failed."); + errlCommit( err_cleanup, SBE_COMP_ID ); + + } + + TRACFCOMP( g_trac_sbe, + EXIT_MRK"testSbeUpdateTarget() - %d/%d fails", + fails, total ); + } + + + + /** + * @brief This function will call decisionTreeForUpdates() and make + sure the correct update action is returned for a specific + situation. + */ + void testSbeDecisionTree ( void ) + { + + uint64_t fails = 0x0; + uint64_t total = 0x0; + + sbeTargetState_t sbeState; + + struct + { + // Inputs + uint8_t i_situation; + sbeSeepromSide_t i_cur; // current_seeprom_side + uint8_t i_flags; // mvpdSbKeyword.flags + + // Expected Output + sbeUpdateActions_t o_update_actions; + EEPROM::eeprom_chip_types_t o_seeprom; + uint8_t o_flags; // mvpdSbKeyword.flags + + } testData[] = + { + + // case 0xE0: cur=temp, cur=dirty, alt=dirty + // Arbitrarily set cur side to 0 (therefore perm set to 1) + // - update alt=1 + // - make cur=perm + // - re-IPL + { 0xE0, SBE_SEEPROM0, 0x80, + static_cast<sbeUpdateActions_t>(DO_UPDATE|IPL_RESTART), + EEPROM::SBE_BACKUP, 0x00 }, + + + // case 0xC0: cur=temp, cur=dirty, alt=dirty + // Arbitrarily set cur side to 1 (therefore perm set to 0) + // - update alt=0 + // - make cur=perm + // - re-IPL + { 0xC0, SBE_SEEPROM1, 0x00, + static_cast<sbeUpdateActions_t>(DO_UPDATE|IPL_RESTART), + EEPROM::SBE_PRIMARY, 0x80 }, + + // case 0xA0: cur=temp, cur=clean, alt=dirty + // Arbitarily Set cur side to 1 (therefore perm set to 0) + // - update alt=0 + // - make cur=perm + // - Continue IPL + { 0xA0, SBE_SEEPROM1, 0x00, + static_cast<sbeUpdateActions_t>(DO_UPDATE), + EEPROM::SBE_PRIMARY, 0x80 }, + + // case 0x80: cur=temp, cur=clean, alt=clean + // Arbitrarily set cur side to 1 (therefore perm set to 0) + // - No updates + // - Continue IPL + { 0x80, SBE_SEEPROM1, 0x00, + static_cast<sbeUpdateActions_t>(CLEAR_ACTIONS), + EEPROM::LAST_CHIP_TYPE, 0x00 }, + + // case 0x60: cur=perm, cur=dirty, alt=dirty + // Arbitrarily set cur side to 0 (therefore perm set to 0) + // - update alt=1 + // - re-IPL + { 0x60, SBE_SEEPROM0, 0x00, + static_cast<sbeUpdateActions_t>(DO_UPDATE|IPL_RESTART), + EEPROM::SBE_BACKUP, 0x00 }, + + // case 0x40: cur=temp, cur=dirty, alt=clean + // @todo RTC 47033 - Ask FSP if we just re-IPLed, but just + // continue IPL now + // Arbitrarily set cur side to 1 (therefore perm set to 1) + // No Updates + // Continue IPL + { 0x40, SBE_SEEPROM1, 0x80, + static_cast<sbeUpdateActions_t>(CLEAR_ACTIONS), + EEPROM::LAST_CHIP_TYPE, 0x80 }, + + // case 0x20: cur=perm, cur=clean, alt=dirty + // Arbitrarily set cur side to 0 (therefore perm set to 0) + // - update alt=1 + // - Continue IPL + { 0x20, SBE_SEEPROM0, 0x00, + static_cast<sbeUpdateActions_t>(DO_UPDATE), + EEPROM::SBE_BACKUP, 0x00 }, + + // case 0x00: cur=perm, cur=clean, alt=clean + // Arbitrarily set cur side to 0 (therefore perm set to 0) + // - No Updates + // - Continue IPL + // NOTE: this will test that right-most-bit is ignored: + // so techincally case 0x01, which should be = case 0x00 + { 0x01, SBE_SEEPROM0, 0x00, + static_cast<sbeUpdateActions_t>(CLEAR_ACTIONS), + EEPROM::LAST_CHIP_TYPE, 0x00 }, + + }; + + const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]); + + + do{ + + TRACFCOMP( g_trac_sbe, + ENTER_MRK"testSbeDecisionTree()" ); + + + // Loop through each situation + for( uint32_t i = 0; i < NUM_CMDS; i++ ) + { + + sbeState.update_actions = CLEAR_ACTIONS; + + /****************************************************/ + /* Set Input Values */ + /****************************************************/ + sbeState.cur_seeprom_side = testData[i].i_cur; + + sbeState.alt_seeprom_side = + ( ( testData[i].i_cur == SBE_SEEPROM0 ) + ? SBE_SEEPROM1 : SBE_SEEPROM0 ); + + sbeState.mvpdSbKeyword.flags = testData[i].i_flags; + + + /****************************************************/ + /* Get Target Update Actions */ + /****************************************************/ + total++; + SBE::decisionTreeForUpdates(sbeState, + testData[i].i_situation); + + + /****************************************************/ + /* Check Output Values */ + /****************************************************/ + if (( testData[i].o_update_actions != sbeState.update_actions ) + || + ( testData[i].o_seeprom != sbeState.seeprom_side_to_update ) + || + ( testData[i].o_flags != sbeState.mvpdSbKeyword.flags ) + ) + { + fails++; + + TRACFCOMP( g_trac_sbe, ERR_MRK"testSbeDecisionTree() - " + "Fail! Unexpected results for situation=0x%.2X (i=%d): " + "Inputs: cur=%d, flags=0x%.2X", + testData[i].i_situation, i, + testData[i].i_cur, testData[i].i_flags); + + TRACFCOMP( g_trac_sbe, ERR_MRK"testSbeDecisionTree() - " + "Expected/Returned: update_actions=0x%.4X/0x%.4x, " + "update seeprom=%d/%d, flags=0x%.2X/0x%.2X", + testData[i].o_update_actions, sbeState.update_actions, + testData[i].o_seeprom, sbeState.seeprom_side_to_update, + testData[i].o_flags, sbeState.mvpdSbKeyword.flags); + + TS_FAIL("testSbeDecisionTree() - Fail! Unexpected results for pass %d, situation=0x%.2X", i, testData[i].i_situation); + + // Don't break - complete the remaining tests + } + + } // end of for-loop + + }while(0); + + TRACFCOMP( g_trac_sbe, EXIT_MRK + EXIT_MRK"testSbeDecisionTree() - %d/%d fails", + fails, total ); + } + + + /** + * @brief Constructor + */ + SBEUpdateTest() : CxxTest::TestSuite() + { + errlHndl_t err = NULL; + uint64_t fails = 0x0; + uint64_t total = 0x0; + bool sbe_loaded = false; + + err = loadSbeModule(sbe_loaded); + if(err) + { + total++; + fails++; + TS_FAIL("SBEUpdateTest() - Constuctor: failed to load modules"); + errlCommit( err, SBE_COMP_ID ); + } + + }; + + + /** + * @brief Destructor + */ + ~SBEUpdateTest() + { + errlHndl_t err = NULL; + uint64_t fails = 0x0; + uint64_t total = 0x0; + + err = unloadSbeModule(); + if(err) + { + total++; + fails++; + TS_FAIL("~SBEUpdateTest() - Destuctor: failed to load modules"); + errlCommit( err, SBE_COMP_ID ); + } + + }; + +}; + +#endif |