/** * @brief Entry point for initialization service to initialize the targeting * code * * @param[in] io_pError * Error log handle; returns NULL on success, !NULL otherwise * * @note: Link register is configured to automatically invoke task_end() when * this routine returns */ static void initTargeting(errlHndl_t& io_pError) { #define TARG_FN "initTargeting(errlHndl_t& io_pError)" TARG_ENTER(); AttrRP::init(io_pError); if (io_pError == NULL) { TargetService& l_targetService = targetService(); (void)l_targetService.init(); initializeAttributes(l_targetService); checkProcessorTargeting(l_targetService); // Print out top-level model value from loaded targeting values. // @TODO RTC:88056 Make the model printed more meaniful Target* l_pTopLevel = NULL; l_targetService.getTopLevelTarget(l_pTopLevel); ATTR_MODEL_type l_model = MODEL_NA; if (l_pTopLevel->tryGetAttr<ATTR_MODEL>(l_model)) { TARG_INF("Initialized targeting for model: %s", l_pTopLevel->getAttrAsString<ATTR_MODEL>()); } // call ErrlManager function - tell him that TARG is ready! ERRORLOG::ErrlManager::errlResourceReady(ERRORLOG::TARG); } TARG_EXIT(); #undef TARG_FN }
ATTR_SYNC_RC AttributeSync::updateSectionData() const { TARG_INF( ENTER_MRK "AttributeSync::updateSectionData - " "section type %u total pages %d", iv_section_to_sync, iv_total_pages ); if (!SECUREBOOT::allowAttrOverrides()) { TARG_INF("AttributeSync::updateSectionData(): skipping since " "attribute overrides are not allowed and we don't " "trust the FSP, but still returning ATTR_SYNC_SUCCESS"); return ATTR_SYNC_SUCCESS; } ATTR_SYNC_RC l_rc = ATTR_SYNC_SUCCESS; // call the targeting function here to get context. TargetService& l_targetService = targetService(); // write the section data info into the iv_pages structure if ( false == l_targetService.writeSectionData( iv_pages ) ) { l_rc = ATTR_SYNC_FAILURE; } TARG_INF( EXIT_MRK "AttributeSync::updateSectionData"); return l_rc; }
TargetHandle_t TargetServiceImpl::getMcs( TargetHandle_t i_proc, uint64_t i_pos) { PredicateCTM classTypeMatch(CLASS_UNIT, TYPE_MCS); PredicateIsFunctional functionalMatch; PredicatePostfixExpr pred; class ChipUnitMatch : public PredicateBase { uint8_t iv_pos; public: bool operator()(const Target * i_target) const { uint8_t pos; bool match = false; if(i_target->tryGetAttr<ATTR_CHIP_UNIT>(pos)) { match = iv_pos == pos; } return match; } explicit ChipUnitMatch(uint8_t i_pos) : iv_pos(i_pos) {} } chipUnitMatch(i_pos); pred.push(&classTypeMatch).push( &functionalMatch).And(); pred.push(&chipUnitMatch).And(); TargetHandleList list; TargetHandle_t mcs = NULL; targetService().getAssociated( list, i_proc, TARGETING::TargetService::CHILD_BY_AFFINITY, TARGETING::TargetService::ALL, &pred); if(list.size() == 1) { mcs = list[0]; } return mcs; }
static bool operate() { bool rc = false; Target* sys = NULL; targetService().getTopLevelTarget(sys); uint8_t vpo_mode = 0; if (unlikely(sys && sys->tryGetAttr<ATTR_IS_SIMULATION>(vpo_mode) && (1 == vpo_mode))) { rc = true; } return rc; }
void AttributeSync::getSectionData() { // make sure we have a clean slate iv_total_pages = 0; iv_current_page = 0; iv_pages.clear(); // call the targeting function here to get context. TargetService& l_targetService = targetService(); // read the section data info into the iv_pages structure l_targetService.readSectionData( iv_pages, iv_section_to_sync ); iv_total_pages = iv_pages.size(); TRACDCOMP(g_trac_targeting, "total pages %d", iv_total_pages ); }
void AttributeSync::getSectionData() { // make sure we have a clean slate iv_total_pages = 0; iv_current_page = 0; iv_pages.clear(); // call the targeting function here to get context. TargetService& l_targetService = targetService(); // read the section data info into the iv_pages structure l_targetService.readSectionData( iv_pages, iv_section_to_sync ); iv_total_pages = iv_pages.size(); TARG_INF("AttributeSync::getDataSection() - total pages %d, section type 0x%x", iv_total_pages, iv_section_to_sync ); }
ATTR_SYNC_RC AttributeSync::updateSectionData() const { TARG_INF( ENTER_MRK "AttributeSync::updateSectionData - " "section type %u total pages %d", iv_section_to_sync, iv_total_pages ); ATTR_SYNC_RC l_rc = ATTR_SYNC_SUCCESS; // call the targeting function here to get context. TargetService& l_targetService = targetService(); // write the section data info into the iv_pages structure if ( false == l_targetService.writeSectionData( iv_pages ) ) { l_rc = ATTR_SYNC_FAILURE; } TARG_INF( EXIT_MRK "AttributeSync::updateSectionData"); return l_rc; }
TargetHandle_t TargetServiceImpl::getMcs( TargetHandle_t i_membuf) { TargetHandle_t mcs = NULL; TargetHandleList list; PredicateCTM pred(CLASS_UNIT, TYPE_MCS); targetService().getAssociated( list, i_membuf, TARGETING::TargetService::PARENT_BY_AFFINITY, TARGETING::TargetService::IMMEDIATE, &pred); if(list.size() == 1) { mcs = list[0]; } return mcs; }
TargetHandle_t TargetServiceImpl::getProc( TargetHandle_t i_membuf) { TargetHandle_t proc = NULL; TargetHandleList list; PredicateCTM pred(CLASS_CHIP, TYPE_PROC); targetService().getAssociated( list, i_membuf, TARGETING::TargetService::PARENT_BY_AFFINITY, TARGETING::TargetService::ALL, &pred); if(list.size() == 1) { proc = list[0]; } return proc; }
/** * @brief Checks if we are loading a PHYP payload */ bool is_phyp_load( ATTR_PAYLOAD_KIND_type* o_type ) { Target* sys = NULL; targetService().getTopLevelTarget( sys ); assert(sys != NULL); // get the current payload kind TARGETING::PAYLOAD_KIND payload_kind = sys->getAttr<ATTR_PAYLOAD_KIND>(); if( o_type ) { *o_type = payload_kind; } //If in AVP mode default to false bool is_phyp = false; if(!is_avp_load()) { is_phyp = (PAYLOAD_KIND_PHYP == payload_kind); } return is_phyp; }
void* call_host_load_payload (void *io_pArgs) { errlHndl_t l_err = NULL; TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ENTER_MRK"call_host_start_payload entry" ); do { // Get Target Service, and the system target. TargetService& tS = targetService(); TARGETING::Target* sys = NULL; (void) tS.getTopLevelTarget( sys ); if( NULL == sys ) { // Error getting system target to get payload related values. We // will create an error to be passed back. This will cause the // istep to fail. TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"call_load_payload: System Target was NULL!" ); /*@ * @errortype * @reasoncode RC_TARGET_NULL * @severity ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM * @moduleid MOD_LOAD_PAYLOAD * @userdata1 <UNUSED> * @userdata2 <UNUSED> * @devdesc System target was NULL! * @custdesc A problem occurred during the IPL * of the system. */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, MOD_LOAD_PAYLOAD, RC_TARGET_NULL, 0x0, 0x0 ); break; } if(INITSERVICE::spBaseServicesEnabled()) { //this function is a NOOP on FSP system break; } // Get Payload base/entry from attributes uint64_t payloadBase = sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>(); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,INFO_MRK "call_load_payload: Payload Base: 0x%08x MB, Base:0x%08x", payloadBase, (payloadBase * MEGABYTE) ); payloadBase = payloadBase * MEGABYTE; // Load payload data in PHYP mode or in Sapphire mode if(is_sapphire_load() || is_phyp_load()) { l_err = load_pnor_section( PNOR::PAYLOAD, payloadBase ); if ( l_err ) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "call_load_payload: error loading pnor section"); break; } } }while(0); return l_err; }
errlHndl_t discoverTargets() { HWAS_INF("discoverTargets entry"); errlHndl_t errl = NULL; // loop through all the targets and set HWAS_STATE to a known default for (TargetIterator target = targetService().begin(); target != targetService().end(); ++target) { HwasState hwasState = target->getAttr<ATTR_HWAS_STATE>(); hwasState.deconfiguredByEid = 0; hwasState.poweredOn = false; hwasState.present = false; hwasState.functional = false; hwasState.dumpfunctional = false; target->setAttr<ATTR_HWAS_STATE>(hwasState); } // Assumptions and actions: // CLASS_SYS (exactly 1) - mark as present // CLASS_ENC, TYPE_PROC, TYPE_MEMBUF, TYPE_DIMM // (ALL require hardware query) - call platPresenceDetect // \->children: CLASS_* (NONE require hardware query) - mark as present do { // find CLASS_SYS (the top level target) Target* pSys; targetService().getTopLevelTarget(pSys); HWAS_ASSERT(pSys, "HWAS discoverTargets: no CLASS_SYS TopLevelTarget found"); // mark this as present enableHwasState(pSys, true, true, 0); HWAS_DBG("pSys %.8X - marked present", pSys->getAttr<ATTR_HUID>()); // find list of all we need to call platPresenceDetect against PredicateCTM predEnc(CLASS_ENC); PredicateCTM predChip(CLASS_CHIP); PredicateCTM predDimm(CLASS_LOGICAL_CARD, TYPE_DIMM); PredicatePostfixExpr checkExpr; checkExpr.push(&predChip).push(&predDimm).Or().push(&predEnc).Or(); TargetHandleList pCheckPres; targetService().getAssociated( pCheckPres, pSys, TargetService::CHILD, TargetService::ALL, &checkExpr ); // pass this list to the hwas platform-specific api where // pCheckPres will be modified to only have present targets HWAS_DBG("pCheckPres size: %d", pCheckPres.size()); errl = platPresenceDetect(pCheckPres); HWAS_DBG("pCheckPres size: %d", pCheckPres.size()); if (errl != NULL) { break; // break out of the do/while so that we can return } // for each, read their ID/EC level. if that works, // mark them and their descendants as present // read the partialGood vector to determine if any are not functional // and read and store values from the PR keyword // list of procs and data that we'll need to look at the PR keyword procRestrict_t l_procEntry; std::vector <procRestrict_t> l_procPRList; // sort the list by ATTR_HUID to ensure that we // start at the same place each time std::sort(pCheckPres.begin(), pCheckPres.end(), compareTargetHuid); for (TargetHandleList::const_iterator pTarget_it = pCheckPres.begin(); pTarget_it != pCheckPres.end(); ++pTarget_it ) { TargetHandle_t pTarget = *pTarget_it; // if CLASS_ENC is still in this list, mark as present if (pTarget->getAttr<ATTR_CLASS>() == CLASS_ENC) { enableHwasState(pTarget, true, true, 0); HWAS_DBG("pTarget %.8X - CLASS_ENC marked present", pTarget->getAttr<ATTR_HUID>()); // on to the next target continue; } bool chipPresent = true; bool chipFunctional = true; uint32_t errlEid = 0; uint16_t pgData[VPD_CP00_PG_DATA_LENGTH / sizeof(uint16_t)]; bzero(pgData, sizeof(pgData)); if (pTarget->getAttr<ATTR_CLASS>() == CLASS_CHIP) { // read Chip ID/EC data from these physical chips errl = platReadIDEC(pTarget); if (errl) { // read of ID/EC failed even tho we THOUGHT we were present. HWAS_INF("pTarget %.8X - read IDEC failed (eid 0x%X) - bad", errl->eid(), pTarget->getAttr<ATTR_HUID>()); // chip NOT present and NOT functional, so that FSP doesn't // include this for HB to process chipPresent = false; chipFunctional = false; errlEid = errl->eid(); // commit the error but keep going errlCommit(errl, HWAS_COMP_ID); // errl is now NULL } else if (pTarget->getAttr<ATTR_TYPE>() == TYPE_PROC) { // read partialGood vector from these as well. errl = platReadPartialGood(pTarget, pgData); if (errl) { // read of PG failed even tho we were present.. HWAS_INF("pTarget %.8X - read PG failed (eid 0x%X)- bad", errl->eid(), pTarget->getAttr<ATTR_HUID>()); chipFunctional = false; errlEid = errl->eid(); // commit the error but keep going errlCommit(errl, HWAS_COMP_ID); // errl is now NULL } else // look at the 'nest' logic to override the functionality // of this proc if (pgData[VPD_CP00_PG_PIB_INDEX] != VPD_CP00_PG_PIB_GOOD) { HWAS_INF("pTarget %.8X - PIB pgPdata[%d]: expected 0x%04X - bad", pTarget->getAttr<ATTR_HUID>(), VPD_CP00_PG_PIB_INDEX, VPD_CP00_PG_PIB_GOOD); chipFunctional = false; } else if (pgData[VPD_CP00_PG_PERVASIVE_INDEX] != VPD_CP00_PG_PERVASIVE_GOOD) { HWAS_INF("pTarget %.8X - Pervasive pgPdata[%d]: expected 0x%04X - bad", pTarget->getAttr<ATTR_HUID>(), VPD_CP00_PG_PERVASIVE_INDEX, VPD_CP00_PG_PERVASIVE_GOOD); chipFunctional = false; } else if ((pgData[VPD_CP00_PG_POWERBUS_INDEX] & VPD_CP00_PG_POWERBUS_BASE) != VPD_CP00_PG_POWERBUS_BASE) { HWAS_INF("pTarget %.8X - PowerBus pgPdata[%d]: expected 0x%04X - bad", pTarget->getAttr<ATTR_HUID>(), VPD_CP00_PG_POWERBUS_INDEX, VPD_CP00_PG_POWERBUS_BASE); chipFunctional = false; } else { // read the PR keywords that we need, so that if // we have errors, we can handle them as approprite. uint8_t prData[VPD_VINI_PR_DATA_LENGTH/sizeof(uint8_t)]; bzero(prData, sizeof(prData)); errl = platReadPR(pTarget, prData); if (errl != NULL) { // read of PR keyword failed HWAS_INF("pTarget %.8X - read PR failed - bad", pTarget->getAttr<ATTR_HUID>()); chipFunctional = false; errlEid = errl->eid(); // commit the error but keep going errlCommit(errl, HWAS_COMP_ID); // errl is now NULL } else { // save info so that we can // process the PR keyword after this loop HWAS_INF("pTarget %.8X - pushing to procPRlist; FRU_ID %d", pTarget->getAttr<ATTR_HUID>(), pTarget->getAttr<ATTR_FRU_ID>()); l_procEntry.target = pTarget; l_procEntry.group = pTarget->getAttr<ATTR_FRU_ID>(); l_procEntry.procs = (prData[7] & VPD_VINI_PR_B7_MASK) + 1; l_procEntry.maxEXs = l_procEntry.procs * (prData[2] & VPD_VINI_PR_B2_MASK) >> VPD_VINI_PR_B2_SHIFT; l_procPRList.push_back(l_procEntry); if (l_procEntry.maxEXs == 0) { // this is PROBABLY bad PR, so YELL... HWAS_ERR("pTarget %.8X - PR VPD says 0 CORES", pTarget->getAttr<ATTR_HUID>()); } } } } // TYPE_PROC } // CLASS_CHIP HWAS_DBG("pTarget %.8X - detected present, %sfunctional", pTarget->getAttr<ATTR_HUID>(), chipFunctional ? "" : "NOT "); // now need to mark all of this target's // physical descendants as present and functional as appropriate TargetHandleList pDescList; targetService().getAssociated( pDescList, pTarget, TargetService::CHILD, TargetService::ALL); for (TargetHandleList::const_iterator pDesc_it = pDescList.begin(); pDesc_it != pDescList.end(); ++pDesc_it) { TargetHandle_t pDesc = *pDesc_it; // by default, the descendant's functionality is 'inherited' bool descFunctional = chipFunctional; if (chipFunctional) { // if the chip is functional, the look through the // partialGood vector to see if its chiplets // are functional if ((pDesc->getAttr<ATTR_TYPE>() == TYPE_XBUS) && (pgData[VPD_CP00_PG_XBUS_INDEX] != VPD_CP00_PG_XBUS_GOOD)) { HWAS_INF("pDesc %.8X - XBUS pgPdata[%d]: expected 0x%04X - bad", pDesc->getAttr<ATTR_HUID>(), VPD_CP00_PG_XBUS_INDEX, VPD_CP00_PG_XBUS_GOOD); descFunctional = false; } else if ((pDesc->getAttr<ATTR_TYPE>() == TYPE_ABUS) && (pgData[VPD_CP00_PG_ABUS_INDEX] != VPD_CP00_PG_ABUS_GOOD)) { HWAS_INF("pDesc %.8X - ABUS pgPdata[%d]: expected 0x%04X - bad", pDesc->getAttr<ATTR_HUID>(), VPD_CP00_PG_ABUS_INDEX, VPD_CP00_PG_ABUS_GOOD); descFunctional = false; } else if ((pDesc->getAttr<ATTR_TYPE>() == TYPE_PCI) && (pgData[VPD_CP00_PG_PCIE_INDEX] != VPD_CP00_PG_PCIE_GOOD)) { HWAS_INF("pDesc %.8X - PCIe pgPdata[%d]: expected 0x%04X - bad", pDesc->getAttr<ATTR_HUID>(), VPD_CP00_PG_PCIE_INDEX, VPD_CP00_PG_PCIE_GOOD); descFunctional = false; } else if ((pDesc->getAttr<ATTR_TYPE>() == TYPE_EX) || (pDesc->getAttr<ATTR_TYPE>() == TYPE_CORE) ) { ATTR_CHIP_UNIT_type indexEX = pDesc->getAttr<ATTR_CHIP_UNIT>(); if (pgData[VPD_CP00_PG_EX0_INDEX + indexEX] != VPD_CP00_PG_EX0_GOOD) { HWAS_INF("pDesc %.8X - CORE/EX%d pgPdata[%d]: expected 0x%04X - bad", pDesc->getAttr<ATTR_HUID>(), indexEX, VPD_CP00_PG_EX0_INDEX + indexEX, VPD_CP00_PG_EX0_GOOD); descFunctional = false; } } else if (pDesc->getAttr<ATTR_TYPE>() == TYPE_MCS) { ATTR_CHIP_UNIT_type indexMCS = pDesc->getAttr<ATTR_CHIP_UNIT>(); // check: MCS 0..3 in MCL, MCS 4..7 in MCR if (((indexMCS >=0) && (indexMCS <=3)) && ((pgData[VPD_CP00_PG_POWERBUS_INDEX] & VPD_CP00_PG_POWERBUS_MCL) == 0)) { HWAS_INF("pDesc %.8X - MCS%d pgPdata[%d]: MCL expected 0x%04X - bad", pDesc->getAttr<ATTR_HUID>(), indexMCS, VPD_CP00_PG_POWERBUS_INDEX, VPD_CP00_PG_POWERBUS_MCL); descFunctional = false; } else if (((indexMCS >=4) && (indexMCS <=7)) && ((pgData[VPD_CP00_PG_POWERBUS_INDEX] & VPD_CP00_PG_POWERBUS_MCR) == 0)) { HWAS_INF("pDesc %.8X - MCS%d pgPdata[%d]: MCR expected 0x%04X - bad", pDesc->getAttr<ATTR_HUID>(), indexMCS, VPD_CP00_PG_POWERBUS_INDEX, VPD_CP00_PG_POWERBUS_MCR); descFunctional = false; } } } // chipFunctional // for sub-parts, if it's not functional, it's not present. enableHwasState(pDesc, descFunctional, descFunctional, errlEid); HWAS_DBG("pDesc %.8X - marked %spresent, %sfunctional", pDesc->getAttr<ATTR_HUID>(), descFunctional ? "" : "NOT ", descFunctional ? "" : "NOT "); } // set HWAS state to show CHIP is present, functional per above enableHwasState(pTarget, chipPresent, chipFunctional, errlEid); } // for pTarget_it
/** * @brief Check flash image SHA512 hash value of each explorer chip * and update the flash if it does not match the SHA512 hash * of the image in PNOR. * * @param[out] o_stepError Error handle for logging istep failures * */ void updateAll(IStepError& o_stepError) { bool l_imageLoaded = false; errlHndl_t l_err = nullptr; bool l_rebootRequired = false; // Get a list of OCMB chips TARGETING::TargetHandleList l_ocmbTargetList; getAllChips(l_ocmbTargetList, TYPE_OCMB_CHIP); TRACFCOMP(g_trac_expupd, ENTER_MRK "updateAll: %d ocmb chips found", l_ocmbTargetList.size()); do { // If no OCMB chips exist, we're done. if(l_ocmbTargetList.size() == 0) { break; } // Read explorer fw image from pnor PNOR::SectionInfo_t l_pnorSectionInfo; rawImageInfo_t l_imageInfo; #ifdef CONFIG_SECUREBOOT l_err = PNOR::loadSecureSection(PNOR::OCMBFW); if(l_err) { TRACFCOMP(g_trac_expupd, ERR_MRK "updateAll: Failed to load OCMBFW section" " from PNOR!"); l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error that occurred o_stepError.addErrorDetails( l_err ); // Commit Error errlCommit( l_err, EXPUPD_COMP_ID ); break; } #endif //CONFIG_SECUREBOOT l_imageLoaded = true; // get address and size of packaged image l_err = PNOR::getSectionInfo(PNOR::OCMBFW, l_pnorSectionInfo); if(l_err) { TRACFCOMP(g_trac_expupd, ERR_MRK "updateAll: Failure in getSectionInfo()"); l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error that occurred o_stepError.addErrorDetails( l_err ); // Commit Error errlCommit( l_err, EXPUPD_COMP_ID ); break; } // Verify the header and retrieve address, size and // SHA512 hash of unpackaged image l_err = ocmbFwValidateImage( l_pnorSectionInfo.vaddr, l_pnorSectionInfo.secureProtectedPayloadSize, l_imageInfo); if(l_err) { TRACFCOMP(g_trac_expupd, ERR_MRK "updateAll: Failure in expupdValidateImage"); l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error that occurred o_stepError.addErrorDetails( l_err ); // Commit Error errlCommit( l_err, EXPUPD_COMP_ID ); break; } // For each explorer chip, compare flash hash with PNOR hash and // create a list of explorer chips with differing hash values. TARGETING::TargetHandleList l_flashUpdateList; for(const auto & l_ocmbTarget : l_ocmbTargetList) { sha512regs_t l_regs; //skip all gemini ocmb chips (not updateable) if(l_ocmbTarget->getAttr<TARGETING::ATTR_CHIP_ID>() == POWER_CHIPID::GEMINI_16) { TRACFCOMP(g_trac_expupd, "updateAll: skipping update of gemini OCMB 0x%08x", TARGETING::get_huid(l_ocmbTarget)); continue; } //retrieve the SHA512 hash for the currently flashed image. l_err = getFlashedHash(l_ocmbTarget, l_regs); if(l_err) { TRACFCOMP(g_trac_expupd, ERR_MRK "updateAll: Failure in getFlashedHash(huid = 0x%08x)", TARGETING::get_huid(l_ocmbTarget)); l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error // that occurred o_stepError.addErrorDetails(l_err); errlCommit(l_err, EXPUPD_COMP_ID); //Don't stop on error, go to next target. continue; } // Trace the hash and image ID values TRACFCOMP(g_trac_expupd, "updateAll: OCMB 0x%08x image ID=0x%08x", TARGETING::get_huid(l_ocmbTarget), l_regs.imageId); TRACFBIN(g_trac_expupd, "SHA512 HASH FROM EXPLORER", l_regs.sha512Hash, HEADER_SHA512_SIZE); //Compare hashes. If different, add to list for update. if(memcmp(l_regs.sha512Hash, l_imageInfo.imageSHA512HashPtr, HEADER_SHA512_SIZE)) { TRACFCOMP(g_trac_expupd, "updateAll: SHA512 hash mismatch on ocmb[0x%08x]", TARGETING::get_huid(l_ocmbTarget)); //add target to our list of targets needing an update l_flashUpdateList.push_back(l_ocmbTarget); } else { TRACFCOMP(g_trac_expupd, "updateAll: SHA512 hash for ocmb[0x%08x]" " matches SHA512 hash of PNOR image.", TARGETING::get_huid(l_ocmbTarget)); } } TRACFCOMP(g_trac_expupd, "updateAll: updating flash for %d OCMB chips", l_flashUpdateList.size()); // update each explorer in the list of chips needing updates for(const auto & l_ocmb : l_flashUpdateList) { TRACFCOMP(g_trac_expupd, "updateAll: updating OCMB 0x%08x", TARGETING::get_huid(l_ocmb)); fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>l_fapi2Target(l_ocmb); // reset watchdog for each ocmb as this function can be very slow INITSERVICE::sendProgressCode(); // Invoke procedure FAPI_INVOKE_HWP(l_err, exp_fw_update, l_fapi2Target, l_imageInfo.imagePtr, l_imageInfo.imageSize); if (l_err) { TRACFCOMP(g_trac_expupd, "Error from exp_fw_update for OCMB 0x%08x", TARGETING::get_huid(l_ocmb)); l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error // that occurred o_stepError.addErrorDetails( l_err ); errlCommit(l_err, EXPUPD_COMP_ID); // Don't stop on error, go to next target. continue; } else { TRACFCOMP(g_trac_expupd, "updateAll: successfully updated OCMB 0x%08x", TARGETING::get_huid(l_ocmb)); // Request reboot for new firmware to be used l_rebootRequired = true; } } }while(0); // unload explorer fw image if(l_imageLoaded) { #ifdef CONFIG_SECUREBOOT l_err = PNOR::unloadSecureSection(PNOR::OCMBFW); if(l_err) { TRACFCOMP(g_trac_expupd, ERR_MRK "updateAll: Failed to unload OCMBFW"); l_err->collectTrace(EXPUPD_COMP_NAME); // Create IStep error log and cross reference to error that occurred o_stepError.addErrorDetails( l_err ); // Commit Error errlCommit( l_err, EXPUPD_COMP_ID ); } #endif //CONFIG_SECUREBOOT } // force reboot if any updates were successful if(l_rebootRequired) { TRACFCOMP(g_trac_expupd, "updateAll: OCMB chip(s) was updated. Requesting reboot..."); Target* l_pTopLevel = nullptr; targetService().getTopLevelTarget( l_pTopLevel ); assert(l_pTopLevel, "expupd::updateAll: no TopLevelTarget"); auto l_reconfigAttr = l_pTopLevel->getAttr<TARGETING::ATTR_RECONFIGURE_LOOP>(); l_reconfigAttr |= RECONFIGURE_LOOP_OCMB_FW_UPDATE; l_pTopLevel->setAttr<TARGETING::ATTR_RECONFIGURE_LOOP>(l_reconfigAttr); } else { TRACFCOMP(g_trac_expupd, "updateAll: No OCMB chips were updated"); } TRACFCOMP(g_trac_expupd, EXIT_MRK"updateAll()"); }
errlHndl_t runStep(const TargetHandleList & i_targetList) { MDIA_FAST("memory diagnostics entry with %d target(s)", i_targetList.size()); // memory diagnostics ipl step entry point errlHndl_t err = 0; Globals globals; TargetHandle_t top = 0; targetService().getTopLevelTarget(top); if(top) { globals.mfgPolicy = top->getAttr<ATTR_MNFG_FLAGS>(); uint8_t maxMemPatterns = top->getAttr<ATTR_RUN_MAX_MEM_PATTERNS>(); // This registry / attr is the same as the // exhaustive mnfg one if(maxMemPatterns) { globals.mfgPolicy |= MNFG_FLAG_ENABLE_EXHAUSTIVE_PATTERN_TEST; } globals.simicsRunning = Util::isSimicsRunning(); globals.disableScrubs = top->getAttr<ATTR_DISABLE_SCRUB_AFTER_PATTERN_TEST>(); } // get the workflow for each target mba passed in. // associate each workflow with the target handle. WorkFlowAssocMap list; TargetHandleList::const_iterator tit; DiagMode mode; for(tit = i_targetList.begin(); tit != i_targetList.end(); ++tit) { err = getMbaDiagnosticMode(globals, *tit, mode); if(err) { break; } err = getMbaWorkFlow(mode, list[*tit], globals); if(err) { break; } } if(!err) { // set global data Singleton<StateMachine>::instance().setGlobals(globals); // TODO...run the workflow through the state machine err = Singleton<StateMachine>::instance().run(list); } // ensure threads and pools are shutdown when finished doStepCleanup(globals); return err; }
/** * @brief Starts OCCs on all Processors in the node * This is intended to be used for AVP testing. * * @param[out] o_failedOccTarget: Pointer to the target failing * loadnStartAllOccs * @param[in] i_useSRAM: bool - use SRAM for OCC image, ie during IPL * true if during IPL, false if at end of IPL (default) * @return errlHndl_t Error log if OCC load failed */ errlHndl_t loadnStartAllOccs(TARGETING::Target *& o_failedOccTarget, bool i_useSRAM) { errlHndl_t l_errl = NULL; void* homerVirtAddrBase = NULL; uint64_t homerPhysAddrBase = VMM_HOMER_REGION_START_ADDR; bool winkle_loaded = false; TRACUCOMP( g_fapiTd, ENTER_MRK"loadnStartAllOccs(%d)", i_useSRAM); do { #ifndef __HOSTBOOT_RUNTIME //OCC requires the build_winkle_images library if ( !VFS::module_is_loaded( "libbuild_winkle_images.so" ) ) { l_errl = VFS::module_load( "libbuild_winkle_images.so" ); if ( l_errl ) { // load module returned with errl set TRACFCOMP( g_fapiTd,ERR_MRK"loadnStartAllOccs: Could not load build_winkle module" ); // break from do loop if error occured break; } winkle_loaded = true; } assert(VMM_HOMER_REGION_SIZE <= THIRTYTWO_GB, "loadnStartAllOccs: Unsupported HOMER Region size"); if (!i_useSRAM) { //If running Sapphire need to place this at the top of memory if(TARGETING::is_sapphire_load()) { homerPhysAddrBase = TARGETING::get_top_mem_addr(); assert (homerPhysAddrBase != 0, "loadnStartAllOccs: Top of memory was 0!"); homerPhysAddrBase -= VMM_ALL_HOMER_OCC_MEMORY_SIZE; } TRACFCOMP( g_fapiTd, "HOMER is at %.16X", homerPhysAddrBase ); //Map entire homer region into virtual memory homerVirtAddrBase = mm_block_map(reinterpret_cast<void*>(homerPhysAddrBase), VMM_HOMER_REGION_SIZE); TRACFCOMP( g_fapiTd, "HOMER virtaddrbase %.16X", homerVirtAddrBase ); } else { // malloc space big enough for all of OCC homerVirtAddrBase = (void *)malloc(1 * MEGABYTE); homerPhysAddrBase = mm_virt_to_phys(homerVirtAddrBase); } #endif if (i_useSRAM) { // OCC is going into L3 and SRAM so only need 1 prime and load // into the Master Proc TargetService & tS = targetService(); Target * sysTarget = NULL; tS.getTopLevelTarget( sysTarget ); assert( sysTarget != NULL ); Target* masterproc = NULL; tS.masterProcChipTargetHandle( masterproc ); /******* SETUP AND LOAD **************/ l_errl = primeAndLoadOcc (masterproc, homerVirtAddrBase, homerPhysAddrBase, i_useSRAM); if(l_errl) { o_failedOccTarget = masterproc; TRACFCOMP( g_fapiImpTd, ERR_MRK "loadnStartAllOccs:primeAndLoadOcc failed"); free(homerVirtAddrBase); break; } /********* START OCC *************/ l_errl = HBOCC::startOCC (masterproc, NULL, o_failedOccTarget); // it either started or errored; either way, free the memory free(homerVirtAddrBase); if (l_errl) { TRACFCOMP( g_fapiImpTd, ERR_MRK"loadnStartAllOccs: startOCC failed"); break; } } else { TargetHandleList procChips; getAllChips(procChips, TYPE_PROC, true); if(procChips.size() == 0) { TRACFCOMP( g_fapiTd,INFO_MRK"loadnStartAllOccs: No processors found" ); //We'll never get this far in the IPL without any processors, // so just exit. break; } TRACUCOMP( g_fapiTd, INFO_MRK"loadnStartAllOccs: %d procs found", procChips.size()); TargetHandleList::iterator itr1 = procChips.begin(); //The OCC Procedures require processors within a DCM be //setup together. So, first checking if any proc has //DCM installed attribute set. If not, we can iterate //over the list in any order. //If DCM installed is set, we work under the assumption //that each nodeID is a DCM. So sort the list by NodeID //then call OCC Procedures on NodeID pairs. if(0 == (*itr1)->getAttr<ATTR_PROC_DCM_INSTALLED>()) { TRACUCOMP( g_fapiTd, INFO_MRK"loadnStartAllOccs: non-dcm path entered"); for (TargetHandleList::iterator itr = procChips.begin(); itr != procChips.end(); ++itr) { /******* SETUP AND LOAD **************/ l_errl = primeAndLoadOcc (*itr, homerVirtAddrBase, homerPhysAddrBase, i_useSRAM); if(l_errl) { o_failedOccTarget = *itr; TRACFCOMP( g_fapiImpTd, ERR_MRK "loadnStartAllOccs:primeAndLoadOcc failed"); break; } /********* START OCC *************/ l_errl = HBOCC::startOCC (*itr, NULL, o_failedOccTarget); if (l_errl) { TRACFCOMP( g_fapiImpTd, ERR_MRK"loadnStartAllOccs: startOCC failed"); break; } } if (l_errl) { break; } } else { TRACUCOMP( g_fapiTd, INFO_MRK"loadnStartAllOccs: Following DCM Path"); std::sort(procChips.begin(), procChips.end(), orderByNodeAndPosition); TRACUCOMP( g_fapiTd, INFO_MRK"loadnStartAllOccs: procChips list sorted"); for (TargetHandleList::iterator itr = procChips.begin(); itr != procChips.end(); ++itr) { TRACUCOMP( g_fapiImpTd, INFO_MRK"loadnStartAllOccs: Insepcting first target" ); Target* targ0 = *itr; Target* targ1 = NULL; TRACUCOMP( g_fapiImpTd, INFO_MRK "loadnStartAllOccs: Cur target nodeID=%d", targ0->getAttr<ATTR_FABRIC_NODE_ID>()); //if the next target in the list is in the same node // they are on the same DCM, so bump itr forward // and update targ1 pointer if((itr+1) != procChips.end()) { TRACUCOMP( g_fapiImpTd, INFO_MRK "loadnStartAllOccs: n+1 target nodeID=%d", ((*(itr+1))->getAttr<ATTR_FABRIC_NODE_ID>()) ); if((targ0->getAttr<ATTR_FABRIC_NODE_ID>()) == ((*(itr+1))->getAttr<ATTR_FABRIC_NODE_ID>())) { itr++; targ1 = *itr; } } /********** Setup and load targ0 ***********/ l_errl = primeAndLoadOcc (targ0, homerVirtAddrBase, homerPhysAddrBase, i_useSRAM); if(l_errl) { o_failedOccTarget = targ0; TRACFCOMP( g_fapiImpTd, ERR_MRK "loadnStartAllOccs: " "primeAndLoadOcc failed on targ0"); break; } /*********** Setup and load targ1 **********/ l_errl = primeAndLoadOcc (targ1, homerVirtAddrBase, homerPhysAddrBase, i_useSRAM); if(l_errl) { o_failedOccTarget = targ1; TRACFCOMP( g_fapiImpTd, ERR_MRK "loadnStartAllOccs: " "primeAndLoadOcc failed on targ1"); break; } /*********** Start OCC *******************/ l_errl = HBOCC::startOCC (targ0, targ1, o_failedOccTarget); if (l_errl) { TRACFCOMP( g_fapiImpTd, ERR_MRK "loadnStartAllOccs: start failed"); break; } } if (l_errl) { break; } } } } while(0); errlHndl_t l_tmpErrl = NULL; //Unless HTMGT is in use, there are no further accesses to HOMER memory //required during the IPL #ifndef CONFIG_HTMGT if(homerVirtAddrBase) { int rc = 0; rc = mm_block_unmap(homerVirtAddrBase); if (rc != 0) { /*@ * @errortype * @moduleid fapi::MOD_OCC_LOAD_START_ALL_OCCS * @reasoncode fapi::RC_MM_UNMAP_ERR * @userdata1 Return Code * @userdata2 Unmap address * @devdesc mm_block_unmap() returns error * @custdesc A problem occurred during the IPL * of the system. */ l_tmpErrl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_OCC_LOAD_START_ALL_OCCS, fapi::RC_MM_UNMAP_ERR, rc, reinterpret_cast<uint64_t> (homerVirtAddrBase)); if(l_tmpErrl) { if(l_errl) { errlCommit( l_tmpErrl, HWPF_COMP_ID ); } else { l_errl = l_tmpErrl; } } } } #endif //make sure we always unload the module if (winkle_loaded) { l_tmpErrl = VFS::module_unload( "libbuild_winkle_images.so" ); if ( l_tmpErrl ) { TRACFCOMP ( g_fapiTd,ERR_MRK "loadnStartAllOccs: Error unloading build_winkle module" ); if(l_errl) { errlCommit( l_tmpErrl, HWPF_COMP_ID ); } else { l_errl = l_tmpErrl; } } } TRACUCOMP( g_fapiTd, EXIT_MRK"loadnStartAllOccs" ); return l_errl; }