diff --git a/src/include/usr/runtime/runtime.H b/src/include/usr/runtime/runtime.H index bdbcf20a8f9..04c7274095b 100644 --- a/src/include/usr/runtime/runtime.H +++ b/src/include/usr/runtime/runtime.H @@ -137,7 +137,8 @@ enum SectionId SPIRA_L, //< Legacy SPIRA NACA, //< NACA HBRT, //< Hostboot Runtime - HBRT_DATA, //< Hostboot Runtime Data + HBRT_DATA, //< Hostboot Runtime Data + PCRD, //< Processor Chip Related Data IPMI_DATA, //< IPMI Sensor Mapping Data NODE_TPM_RELATED, //< Node TPM Related Data RESERVED_MEM, //< Hostboot's Reserved Mainstore Memory @@ -164,6 +165,19 @@ errlHndl_t get_host_data_section( SectionId i_section, size_t& o_dataSize ); const size_t DATA_SIZE_UNKNOWN = 0xFFFFFFFFFFFFFFFF; +/** + * @brief Get the number of instances in a given section. + * + * @param[in] i_section The section for which the instance count is desired + * + * @param[out] o_count The number of instances in this section + * + * @return errlHndl_t Returns nullptr on success. Returns an error if the + * section id used is invalid or has no concept of instances. Also, can + * return an error if the n-tuple is either corrupt or unavailable. + */ +errlHndl_t get_instance_count( RUNTIME::SectionId i_section, uint64_t& o_count); + /** * @brief Store the actual count of a section in local memory. * diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H index f287a5d9793..6570e78fe59 100644 --- a/src/include/usr/runtime/runtime_reasoncodes.H +++ b/src/include/usr/runtime/runtime_reasoncodes.H @@ -43,6 +43,7 @@ namespace RUNTIME MOD_HDATSERVICE_FINDSPIRA = 0x09, /** hdatservice.C */ MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL = 0x0A, /**< hdatservice.C */ MOD_HDATSERVICE_MAPREGION = 0x0B, /**< hdatservice.C */ + MOD_HDATSERVICE_GETINSTANCECOUNT = 0x0C, /**< hdatservice.C */ // customize_attrs_for_payload.C MOD_CUST_COMP_NON_PHYP_RT_TARGET = 0x12, @@ -52,43 +53,49 @@ namespace RUNTIME MOD_PM_RT_HCODE_UPDATE = 0x16, /**< rt_pm.C */ MOD_MAP_PHYS_ADDR = 0x17, /**< populate_hbruntime.C */ MOD_UNMAP_VIRT_ADDR = 0x18, /**< populate_hbruntime.C */ + MOD_POPULATE_TPMINFOBYNODE = 0x19, /**< populate_hbruntime.C */ }; enum RuntimeReasonCode { - RC_DO_NOT_USE_THIS = RUNTIME_COMP_ID | 0x00, - RC_ATTR_GET_FAIL = RUNTIME_COMP_ID | 0x01, - RC_BAD_HDAT_HEADER = RUNTIME_COMP_ID | 0x02, - RC_BAD_HDAT_TUPLE = RUNTIME_COMP_ID | 0x03, - RC_INVALID_STANDALONE = RUNTIME_COMP_ID | 0x04, - RC_CANNOT_MAP_MEMORY = RUNTIME_COMP_ID | 0x05, - //RC_XXX = RUNTIME_COMP_ID | 0x06, - RC_CANNOT_MAP_MEMORY2 = RUNTIME_COMP_ID | 0x07, - RC_INVALID_PAYLOAD_KIND = RUNTIME_COMP_ID | 0x08, - RC_NO_HSVC_NODE_DATA_FOUND = RUNTIME_COMP_ID | 0x09, - RC_BAD_NACA = RUNTIME_COMP_ID | 0x0A, - RC_INVALID_ADDRESS = RUNTIME_COMP_ID | 0x0B, - RC_INVALID_SECTION = RUNTIME_COMP_ID | 0x0C, - RC_CANNOT_MAP_MEMORY3 = RUNTIME_COMP_ID | 0x0D, - RC_TCE_INVALID_SIZE = RUNTIME_COMP_ID | 0x0E, - RC_TCE_ADDR_NOT_ALIGNED = RUNTIME_COMP_ID | 0x0F, - RC_TCE_INIT_NOT_RUN = RUNTIME_COMP_ID | 0x10, - RC_TCE_DEV_MAP_FAIL = RUNTIME_COMP_ID | 0x11, - RC_TCE_DEV_UNMAP_FAIL = RUNTIME_COMP_ID | 0x12, - RC_TCE_NO_ACTIVE_PSI = RUNTIME_COMP_ID | 0x13, + RC_DO_NOT_USE_THIS = RUNTIME_COMP_ID | 0x00, + RC_ATTR_GET_FAIL = RUNTIME_COMP_ID | 0x01, + RC_BAD_HDAT_HEADER = RUNTIME_COMP_ID | 0x02, + RC_BAD_HDAT_TUPLE = RUNTIME_COMP_ID | 0x03, + RC_INVALID_STANDALONE = RUNTIME_COMP_ID | 0x04, + RC_CANNOT_MAP_MEMORY = RUNTIME_COMP_ID | 0x05, + //RC_XXX = RUNTIME_COMP_ID | 0x06, + RC_CANNOT_MAP_MEMORY2 = RUNTIME_COMP_ID | 0x07, + RC_INVALID_PAYLOAD_KIND = RUNTIME_COMP_ID | 0x08, + RC_NO_HSVC_NODE_DATA_FOUND = RUNTIME_COMP_ID | 0x09, + RC_BAD_NACA = RUNTIME_COMP_ID | 0x0A, + RC_INVALID_ADDRESS = RUNTIME_COMP_ID | 0x0B, + RC_INVALID_SECTION = RUNTIME_COMP_ID | 0x0C, + RC_CANNOT_MAP_MEMORY3 = RUNTIME_COMP_ID | 0x0D, + RC_TCE_INVALID_SIZE = RUNTIME_COMP_ID | 0x0E, + RC_TCE_ADDR_NOT_ALIGNED = RUNTIME_COMP_ID | 0x0F, + RC_TCE_INIT_NOT_RUN = RUNTIME_COMP_ID | 0x10, + RC_TCE_DEV_MAP_FAIL = RUNTIME_COMP_ID | 0x11, + RC_TCE_DEV_UNMAP_FAIL = RUNTIME_COMP_ID | 0x12, + RC_TCE_NO_ACTIVE_PSI = RUNTIME_COMP_ID | 0x13, RC_TCE_NOT_ENOUGH_FREE_ENTRIES = RUNTIME_COMP_ID | 0x14, - RC_TCE_ENTRY_NOT_CONTIGUOUS = RUNTIME_COMP_ID | 0x15, - RC_NO_SPIRA = RUNTIME_COMP_ID | 0x16, - RC_CANNOT_MAP_HDAT = RUNTIME_COMP_ID | 0x17, - RC_NOT_ENOUGH_SPACE = RUNTIME_COMP_ID | 0x18, - RT_UNIT_TARGET_NOT_FOUND = RUNTIME_COMP_ID | 0x19, - RT_TARGET_TYPE_NOT_SUPPORTED = RUNTIME_COMP_ID | 0x1A, - RT_NO_PROC_TARGET = RUNTIME_COMP_ID | 0x1B, - RC_UNMAP_FAIL = RUNTIME_COMP_ID | 0x1C, - RC_PM_RT_UNKNOWN_MODE = RUNTIME_COMP_ID | 0x1D, - RC_PM_RT_INTERFACE_ERR = RUNTIME_COMP_ID | 0x1E, - RC_PM_RT_HCODE_UPDATE_ERR = RUNTIME_COMP_ID | 0x1F, - RC_INVALID_RHB_INSTANCE = RUNTIME_COMP_ID | 0x20, + RC_TCE_ENTRY_NOT_CONTIGUOUS = RUNTIME_COMP_ID | 0x15, + RC_NO_SPIRA = RUNTIME_COMP_ID | 0x16, + RC_CANNOT_MAP_HDAT = RUNTIME_COMP_ID | 0x17, + RC_NOT_ENOUGH_SPACE = RUNTIME_COMP_ID | 0x18, + RT_UNIT_TARGET_NOT_FOUND = RUNTIME_COMP_ID | 0x19, + RT_TARGET_TYPE_NOT_SUPPORTED = RUNTIME_COMP_ID | 0x1A, + RT_NO_PROC_TARGET = RUNTIME_COMP_ID | 0x1B, + RC_UNMAP_FAIL = RUNTIME_COMP_ID | 0x1C, + RC_PM_RT_UNKNOWN_MODE = RUNTIME_COMP_ID | 0x1D, + RC_PM_RT_INTERFACE_ERR = RUNTIME_COMP_ID | 0x1E, + RC_PM_RT_HCODE_UPDATE_ERR = RUNTIME_COMP_ID | 0x1F, + RC_INVALID_RHB_INSTANCE = RUNTIME_COMP_ID | 0x20, + RC_DUPLICATE_I2C_LINK_IDS = RUNTIME_COMP_ID | 0x21, + RC_I2C_DEVICE_NOT_IN_MRW = RUNTIME_COMP_ID | 0x22, + RC_INSTANCES_UNSUPPORTED = RUNTIME_COMP_ID | 0x23, + RC_I2C_DEVICE_DUPLICATE_IN_MRW = RUNTIME_COMP_ID | 0x24, + RC_EXTRA_I2C_DEVICE_IN_MRW = RUNTIME_COMP_ID | 0x25, }; enum UserDetailsTypes diff --git a/src/usr/hdat/hdatcommonutil.C b/src/usr/hdat/hdatcommonutil.C index 09d377d96c8..4e40119ddec 100644 --- a/src/usr/hdat/hdatcommonutil.C +++ b/src/usr/hdat/hdatcommonutil.C @@ -86,7 +86,7 @@ uint32_t hdatTpmDataCalcMaxSize() l_size += sizeof(hdatTpmData_t); // account for the size of the TPM Info array header - l_size += sizeof(hdatSbTpmInfo_t); + l_size += sizeof(hdatHDIFDataArray_t); // account for each element of the TPM Info array l_size += ((sizeof(hdatSbTpmInstInfo_t) + diff --git a/src/usr/hdat/hdatpcrd.C b/src/usr/hdat/hdatpcrd.C index 8b46f156cab..cd5b75ac15a 100644 --- a/src/usr/hdat/hdatpcrd.C +++ b/src/usr/hdat/hdatpcrd.C @@ -76,9 +76,6 @@ const HdatKeywordInfo l_mvpdKeywords[] = }; -//Max number of I2c devices for any given proc -#define HDAT_PCRD_MAX_I2C_DEV 64 - /******************************************************************************* * hdatSetPcrdHdrs * diff --git a/src/usr/hdat/hdatpcrd.H b/src/usr/hdat/hdatpcrd.H index 647c8779a13..421c7c5873e 100644 --- a/src/usr/hdat/hdatpcrd.H +++ b/src/usr/hdat/hdatpcrd.H @@ -56,6 +56,9 @@ namespace HDAT const uint16_t HDAT_PCRD_VERSION = 0x20; const char HDAT_PCRD_STRUCT_NAME[7] = "SPPCRD"; +//Max number of I2c devices for any given proc +#define HDAT_PCRD_MAX_I2C_DEV 64 + /** @enum hdatDataPtrs * Enumeration which defines the data sections of the PCRD */ diff --git a/src/usr/hdat/hdattpmdata.H b/src/usr/hdat/hdattpmdata.H index 369e30f286d..b9ee44552af 100644 --- a/src/usr/hdat/hdattpmdata.H +++ b/src/usr/hdat/hdattpmdata.H @@ -60,6 +60,7 @@ enum { TpmDataPtrCnt = 1, TpmDataChildStrCnt = 0, TpmDataChildStrOffset = 0, + TpmDataMinRqrdPcrdVersion = 0x1 }; /** @@ -82,18 +83,6 @@ struct hdatTpmData_t uint8_t hdatReserved1[16]; // Padding for alignment and growth/compatibility } __attribute__ ((packed)); - -/** - * @brief Structure definition for Secureboot TPM Info Array - */ -struct hdatSbTpmInfo_t -{ - uint32_t hdatSbTpmArrayOffset; - uint32_t hdatSbTpmArrayNumEntries; - uint32_t hdatSbTpmArrayEntrySize; -} __attribute__ ((packed)); - - /** * @brief Structure definition for Secureboot TPM Instance Info */ diff --git a/src/usr/runtime/hdatservice.C b/src/usr/runtime/hdatservice.C index cc289f5fa0f..f556be18085 100644 --- a/src/usr/runtime/hdatservice.C +++ b/src/usr/runtime/hdatservice.C @@ -868,6 +868,38 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section, o_dataSize = record_size; o_dataAddr = base_addr + i_instance * o_dataSize; } + else if( RUNTIME::PCRD == i_section ) + { + hdat5Tuple_t* tuple = nullptr; + if( iv_spiraS ) + { + tuple = &(iv_spiraS->hdatDataArea[SPIRAS_PCRD]); + } + else if( unlikely(iv_spiraL != nullptr) ) + { + tuple = &(iv_spiraL->hdatDataArea[SPIRAL_PCRD]); + } + TRACUCOMP( g_trac_runtime, "PCRD_DATA tuple=%p", tuple ); + + errhdl = check_tuple( i_section, tuple ); + if( errhdl ) + { + break; + } + + uint64_t base_addr = 0; + errhdl = getSpiraTupleVA(tuple, base_addr); + if( errhdl ) + { + break; + } + + TRACUCOMP( g_trac_runtime, "pcrd_data=%p", base_addr ); + + record_size = tuple->hdatAllocSize; + o_dataSize = record_size; + o_dataAddr = base_addr + i_instance * o_dataSize; + } // MS DUMP Source Table - MDST else if( RUNTIME::MS_DUMP_SRC_TBL == i_section ) { @@ -1425,6 +1457,91 @@ void hdatService::rediscoverHDAT( void ) iv_mem_regions.clear(); } +/* + * @brief Get the number of instances in an HDAT section + */ +errlHndl_t hdatService::getInstanceCount(RUNTIME::SectionId i_section, + uint64_t& o_count) +{ + errlHndl_t errhdl = nullptr; + hdat5Tuple_t* tuple = nullptr; + + do + { + hdatSpiraSDataAreas l_spiraS = SPIRAS_INVALID; + hdatSpiraLegacyDataAreas l_spiraL = SPIRAL_INVALID; + hdatSpiraHDataAreas l_spiraH = SPIRAH_INVALID; + + switch(i_section) + { + case RUNTIME::NODE_TPM_RELATED: + l_spiraS = SPIRAS_TPM_DATA; + l_spiraL = SPIRAL_TPM_DATA; + break; + case RUNTIME::PCRD: + l_spiraS = SPIRAS_PCRD; + l_spiraL = SPIRAL_PCRD; + break; + case RUNTIME::MS_DUMP_SRC_TBL: + l_spiraH = SPIRAH_MS_DUMP_SRC_TBL; + l_spiraL = SPIRAL_MS_DUMP_SRC_TBL; + break; + case RUNTIME::MS_DUMP_DST_TBL: + l_spiraH = SPIRAH_MS_DUMP_DST_TBL; + l_spiraL = SPIRAL_MS_DUMP_DST_TBL; + break; + case RUNTIME::MS_DUMP_RESULTS_TBL: + l_spiraH = SPIRAH_MS_DUMP_RSLT_TBL; + l_spiraL = SPIRAL_MS_DUMP_RSLT_TBL; + break; + default: + TRACFCOMP( g_trac_runtime, + "getInstanceCount> section %d has no concept of instances", + i_section ); + /*@ + * @errortype + * @moduleid RUNTIME::MOD_HDATSERVICE_GETINSTANCECOUNT + * @reasoncode RUNTIME::RC_INSTANCES_UNSUPPORTED + * @userdata1 Section Id + * @userdata2 + * @devdesc Unsupported section requested + * @custdesc Unexpected boot firmware error. + */ + errhdl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_HDATSERVICE_GETINSTANCECOUNT, + RUNTIME::RC_INSTANCES_UNSUPPORTED, + i_section, + 0, + true /*Add HB Software Callout*/); + errhdl->collectTrace(RUNTIME_COMP_NAME,KILOBYTE); + break; + } + + if( iv_spiraS ) + { + tuple = &(iv_spiraS->hdatDataArea[l_spiraS]); + } + else if( iv_spiraH ) + { + tuple = &(iv_spiraH->hdatDataArea[l_spiraH]); + } + else if( unlikely(iv_spiraL != nullptr) ) + { + tuple = &(iv_spiraL->hdatDataArea[l_spiraL]); + } + errhdl = check_tuple( i_section, tuple ); + if( errhdl ) + { + break; + } + o_count = tuple->hdatActualCnt; + + } while (0); + + return errhdl; +} + /******************** Public Methods ********************/ @@ -1477,6 +1594,12 @@ void rediscover_hdat( void ) Singleton::instance().rediscoverHDAT(); } +errlHndl_t get_instance_count( RUNTIME::SectionId i_section, uint64_t& o_count ) +{ + return Singleton::instance(). + getInstanceCount(i_section, o_count); +} + }; /******************** diff --git a/src/usr/runtime/hdatservice.H b/src/usr/runtime/hdatservice.H index a8de9402deb..a421459ac3c 100644 --- a/src/usr/runtime/hdatservice.H +++ b/src/usr/runtime/hdatservice.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -97,6 +97,12 @@ namespace RUNTIME uint64_t& o_dataAddr, size_t& o_dataSize ); + /** + * @brief See documentation for get_instance_count in runtime.H + */ + errlHndl_t getInstanceCount( RUNTIME::SectionId i_section, + uint64_t& o_count); + /** * @brief Update the actual count of section. Only supported for * memory dump results table @@ -267,7 +273,7 @@ namespace RUNTIME public: /** - * @brief Store the actual count of a section. + * @brief Store the actual count of a section. * * @param[in] i_section Chunk of data to update * @param[in] i_count Actual count for MDRT entries diff --git a/src/usr/runtime/hdatstructs.H b/src/usr/runtime/hdatstructs.H index b686d7f8c99..f601053a32d 100644 --- a/src/usr/runtime/hdatstructs.H +++ b/src/usr/runtime/hdatstructs.H @@ -74,6 +74,7 @@ struct hdatNaca_t */ enum hdatSpiraLegacyDataAreas { + SPIRAL_INVALID = -1, SPIRAL_FIRST = 0, SPIRAL_SP_SUBSYS = 0, // service processor subsystem SPIRAL_IPL_PARMS = 1, // IPL parameters @@ -111,6 +112,7 @@ enum hdatSpiraLegacyDataAreas */ enum hdatSpiraHDataAreas { + SPIRAH_INVALID = -1, SPIRAH_FIRST = 0, SPIRAH_HOST_DATA_AREAS = 0, // Reserved memory for FSP-filled data SPIRAH_PROC_INIT = 1, // phyp-supplied processor init data @@ -127,6 +129,7 @@ enum hdatSpiraHDataAreas */ enum hdatSpiraSDataAreas { + SPIRAS_INVALID = -1, SPIRAS_FIRST = 0, SPIRAS_SP_SUBSYS = 0, // service processor subsystem SPIRAS_IPL_PARMS = 1, // IPL parameters diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C index 59e322b53ae..4be72cce3e0 100644 --- a/src/usr/runtime/populate_hbruntime.C +++ b/src/usr/runtime/populate_hbruntime.C @@ -57,6 +57,7 @@ #include #include #include "../hdat/hdattpmdata.H" +#include "../hdat/hdatpcrd.H" #include "../secureboot/trusted/tpmLogMgr.H" #include "../secureboot/trusted/trustedboot.H" #include @@ -1289,7 +1290,7 @@ errlHndl_t populate_TpmInfoByNode() // populated using the following start offset auto l_sbTpmInfoStart = l_currOffset; - auto const l_hdatSbTpmInfo = reinterpret_cast + auto const l_hdatSbTpmInfo = reinterpret_cast (l_baseAddr + l_currOffset); TARGETING::TargetHandleList tpmList; @@ -1302,9 +1303,10 @@ errlHndl_t populate_TpmInfoByNode() auto const l_numTpms = tpmList.size(); // fill in the values for the Secure Boot TPM Info Array Header - l_hdatSbTpmInfo->hdatSbTpmArrayOffset = sizeof(*l_hdatSbTpmInfo); - l_hdatSbTpmInfo->hdatSbTpmArrayNumEntries = l_numTpms; - l_hdatSbTpmInfo->hdatSbTpmArrayEntrySize = sizeof(HDAT::hdatSbTpmInstInfo_t); + l_hdatSbTpmInfo->hdatOffset = sizeof(*l_hdatSbTpmInfo); + l_hdatSbTpmInfo->hdatArrayCnt = l_numTpms; + l_hdatSbTpmInfo->hdatAllocSize = sizeof(HDAT::hdatSbTpmInstInfo_t); + l_hdatSbTpmInfo->hdatActSize = l_hdatSbTpmInfo->hdatAllocSize; // advance current offset to after the Secure Boot TPM info array header l_currOffset += sizeof(*l_hdatSbTpmInfo); @@ -1328,7 +1330,8 @@ errlHndl_t populate_TpmInfoByNode() assert(itr != l_procList.end(), "Bug! TPM must have a processor."); auto l_proc = *itr; - l_tpmInstInfo->hdatChipId = l_proc->getAttr(); + l_tpmInstInfo->hdatChipId = l_proc->getAttr< + TARGETING::ATTR_ORDINAL_ID>(); l_tpmInstInfo->hdatDbobId = l_node->getAttr< TARGETING::ATTR_ORDINAL_ID>(); @@ -1421,13 +1424,308 @@ errlHndl_t populate_TpmInfoByNode() // the following will be used to calculate the second part of pointer pair auto l_physInterStart = l_currOffset; - // set up the physical interaction mechanism info header - // @TODO RTC 170638: Calculate the real IDs - l_physInter->i2cLinkIdWindowOpen = HDAT::I2C_LINK_ID::NOT_APPLICABLE; + // start with an empty list of link IDs + std::vector l_linkIds; + + // obtain a list of i2c targets + std::vector l_i2cTargetList; + for (auto pProc : l_procList) + { + I2C::getDeviceInfo(pProc, l_i2cTargetList); + } + auto i2cDevItr = l_i2cTargetList.begin(); + while(i2cDevItr != l_i2cTargetList.end()) + { + switch((*i2cDevItr).devicePurpose) + { + case TARGETING::HDAT_I2C_DEVICE_PURPOSE_WINDOW_OPEN: + case TARGETING::HDAT_I2C_DEVICE_PURPOSE_PHYSICAL_PRESENCE: + // keep devices with these two purposes + ++i2cDevItr; + break; + default: + // remove devices with any other purpose + i2cDevItr = l_i2cTargetList.erase(i2cDevItr); + break; + } + } + + uint64_t l_numInstances = 0; + + l_elog = RUNTIME::get_instance_count(RUNTIME::PCRD, l_numInstances); + if (l_elog) + { + TRACFCOMP( g_trac_runtime, ERR_MRK "populate_TpmInfoByNode: get_instance_count() failed for PCRD HDAT section"); + break; + } + + uint64_t l_pcrdAddr = 0; + uint64_t l_pcrdSizeMax = 0; + + // Initialize i2cLinkIds to NA before attempting populate l_physInter->i2cLinkIdPhysicalPresence = HDAT::I2C_LINK_ID::NOT_APPLICABLE; + l_physInter->i2cLinkIdWindowOpen = HDAT::I2C_LINK_ID::NOT_APPLICABLE; + + for (uint64_t l_pcrdInstance = 0; + l_pcrdInstance < l_numInstances; + ++l_pcrdInstance) + { + + l_elog = RUNTIME::get_host_data_section(RUNTIME::PCRD, + l_pcrdInstance, + l_pcrdAddr, + l_pcrdSizeMax); + if(l_elog) + { + TRACFCOMP( g_trac_runtime, ERR_MRK "populate_TpmInfoByNode: get_host_data_section() failed for PCRD HDAT section, instance %d", l_pcrdInstance); + break; + } + + // Get a pointer to the PCRD header + auto l_pcrd = reinterpret_cast(l_pcrdAddr); + + // Check the version of the PCRD section header + assert(l_pcrd->hdatHdr.hdatVersion >= HDAT::TpmDataMinRqrdPcrdVersion, + "Bad PCRD section version 0x%X - must be 0x1 or greater", + l_pcrd->hdatHdr.hdatVersion); + + // Get offset for the i2c array header + auto i2cAryOff = + l_pcrd->hdatPcrdIntData[HDAT::HDAT_PCRD_DA_HOST_I2C].hdatOffset; + + // Convert i2c array header offset to a pointer to the i2c array header + const auto l_hostI2cPcrdHdrPtr = + reinterpret_cast(l_pcrdAddr + i2cAryOff); + + // make sure the array count is within reasonable limits + assert(l_hostI2cPcrdHdrPtr->hdatArrayCnt <= HDAT_PCRD_MAX_I2C_DEV, + "HDAT PCRD reported more than the max number of i2c devices! Count:%d", + l_hostI2cPcrdHdrPtr->hdatArrayCnt); + + // Get the pointer to the first element in the i2c array + // This is the address of the header plus the offset given in the header + auto l_i2cDevStart = + reinterpret_cast(l_hostI2cPcrdHdrPtr) + + l_hostI2cPcrdHdrPtr->hdatOffset; + + // Calculate the stop pointer + auto l_i2cDevStop = l_i2cDevStart + (l_hostI2cPcrdHdrPtr->hdatArrayCnt * + l_hostI2cPcrdHdrPtr->hdatAllocSize); + + // for each link ID in the PCRD + for (auto l_cur = l_i2cDevStart; + l_cur != l_i2cDevStop; + l_cur += l_hostI2cPcrdHdrPtr->hdatAllocSize ) + { + // reinterpret the byte pointer as a struct pointer + auto l_i2cDev = reinterpret_cast(l_cur); + + // if we've seen it already + auto it = std::find(l_linkIds.begin(), + l_linkIds.end(), + l_i2cDev->hdatI2cLinkId); + if (it != l_linkIds.end()) + { + const auto l_linkId = *it; + TRACFCOMP(g_trac_runtime, + "populate_TpmInfoByNode: A duplicate link Id was found. %d", + l_linkId); + +#if 0 + // TODO RTC 173541 - Renable when HB + FIPS have the uniqueness + // change. + + // terminate the boot due to an integrity violation + /*@ + * @errortype + * @reasoncode RUNTIME::RC_DUPLICATE_I2C_LINK_IDS + * @moduleid RUNTIME::MOD_POPULATE_TPMINFOBYNODE + * @severity ERRL_SEV_UNRECOVERABLE + * @userdata1 I2C Link ID + * @devdesc Found duplicate I2C link IDs in PCRD section + * of HDAT. System security cannot be guaranteed. + * @custdesc Platform security problem detected + */ + auto err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_POPULATE_TPMINFOBYNODE, + RUNTIME::RC_DUPLICATE_I2C_LINK_IDS, + l_linkId, + 0, + true); + + SECUREBOOT::handleSecurebootFailure(err); + + assert(true,"Bug! handleSecurebootFailure shouldn't return!"); +#endif + + } + else + { + // add it to a known list to make sure we don't see it again + l_linkIds.push_back(l_i2cDev->hdatI2cLinkId); + } + // use this pointer to avoid having to repeat the switch statement + // later + HDAT::i2cLinkId_t* l_pLinkId = nullptr; + + switch(l_i2cDev->hdatI2cSlaveDevPurp) + { + case TARGETING::HDAT_I2C_DEVICE_PURPOSE_WINDOW_OPEN: + + l_pLinkId = &l_physInter->i2cLinkIdWindowOpen; + break; + + case TARGETING::HDAT_I2C_DEVICE_PURPOSE_PHYSICAL_PRESENCE: + + l_pLinkId = &l_physInter->i2cLinkIdPhysicalPresence; + break; + + default: + // Physical Presence Info not supported for this I2c device + // purpose. This device will not be referred to by the Node TPM + // Related Info Section, but we still ensure uniqueness of all + // link IDs in the I2c device list from the PCRD. + continue; + } + + // now make sure we have a match in the mrw + auto itr = std::find_if(l_i2cTargetList.begin(), + l_i2cTargetList.end(), + + [&l_i2cDev,&l_pcrd](const I2C::DeviceInfo_t & i_i2cDevMrw) + { + return + i_i2cDevMrw.masterChip->getAttr< + TARGETING::ATTR_ORDINAL_ID>() == + l_pcrd->hdatChipData.hdatPcrdProcChipId && + l_i2cDev->hdatI2cEngine == i_i2cDevMrw.engine && + l_i2cDev->hdatI2cMasterPort == i_i2cDevMrw.masterPort && + l_i2cDev->hdatI2cBusSpeed == i_i2cDevMrw.busFreqKhz && + l_i2cDev->hdatI2cSlaveDevType == i_i2cDevMrw.deviceType && + l_i2cDev->hdatI2cSlaveDevAddr == i_i2cDevMrw.addr && + l_i2cDev->hdatI2cSlavePort == i_i2cDevMrw.slavePort && + l_i2cDev->hdatI2cSlaveDevPurp == i_i2cDevMrw.devicePurpose; + }); + + if (itr == l_i2cTargetList.end()) + { + // couldn't find it, physical presense will not be available + TRACFCOMP(g_trac_runtime, + "populate_TpmInfoByNode: I2c device in the PCRD with link ID %d does not have a match in the MRW", + l_i2cDev->hdatI2cLinkId); + /*@ + * @errortype + * @reasoncode RUNTIME::RC_I2C_DEVICE_NOT_IN_MRW + * @moduleid RUNTIME::MOD_POPULATE_TPMINFOBYNODE + * @severity ERRL_SEV_INFORMATIONAL + * @userdata1 I2C Link ID + * @devdesc An I2C device in the PCRD does not have a match + * in the MRW. Physical presence detection + * will not be available. + * @custdesc Platform security problem detected + */ + auto err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + RUNTIME::MOD_POPULATE_TPMINFOBYNODE, + RUNTIME::RC_I2C_DEVICE_NOT_IN_MRW, + l_i2cDev->hdatI2cLinkId, + 0, + true); + ERRORLOG::errlCommit(err, RUNTIME_COMP_ID); + } + else + { + if (*l_pLinkId != HDAT::I2C_LINK_ID::NOT_APPLICABLE) + { + // found a duplicate link id match indicating that there + // was an error in the model + TRACFCOMP(g_trac_runtime, + "populate_TpmInfoByNode: I2c device in the PCRD with link ID %d has a duplicate match in the MRW", + l_i2cDev->hdatI2cLinkId); + /*@ + * @errortype + * @reasoncode RUNTIME::RC_I2C_DEVICE_DUPLICATE_IN_MRW + * @moduleid RUNTIME::MOD_POPULATE_TPMINFOBYNODE + * @severity ERRL_SEV_INFORMATIONAL + * @userdata1 I2C Link ID + * @devdesc An I2C device in the PCRD has a duplicate + * match in the MRW. Physical presence + * detection will still be available. + * @custdesc Platform security problem detected + */ + auto err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + RUNTIME::MOD_POPULATE_TPMINFOBYNODE, + RUNTIME::RC_I2C_DEVICE_DUPLICATE_IN_MRW, + l_i2cDev->hdatI2cLinkId, + 0, + true); + ERRORLOG::errlCommit(err, RUNTIME_COMP_ID); + } + else // found a match + { + *l_pLinkId = l_i2cDev->hdatI2cLinkId; + l_i2cTargetList.erase(itr); + } + } + + } // for each link ID in the current PCRD instance + + } // for each instance + + if (!l_i2cTargetList.empty()) + { + for (auto i2cDev : l_i2cTargetList) + { + TRACFCOMP(g_trac_runtime, + "populate_TpmInfoByNode: I2c device in the MRW was not found in the PCRD having engine: 0x%X masterport: 0x%X devicetype: 0x%X address: 0x%X slaveport: 0x%X devicepurpose: 0x%X master HUID: %X", + i2cDev.engine, + i2cDev.masterPort, + i2cDev.deviceType, + i2cDev.addr, + i2cDev.slavePort, + i2cDev.devicePurpose, + TARGETING::get_huid(i2cDev.masterChip)); + /*@ + * @errortype + * @reasoncode RUNTIME::RC_EXTRA_I2C_DEVICE_IN_MRW + * @moduleid RUNTIME::MOD_POPULATE_TPMINFOBYNODE + * @severity ERRL_SEV_UNRECOVERABLE + * @userdata1 [0:7] I2C engine + * @userdata1 [8:15] I2C masterPort + * @userdata1 [16:23] I2C slave deviceType + * @userdata1 [24:31] I2C slave address + * @userdata1 [32:39] I2C slave port + * @userdata1 [40:47] I2C device purpose + * @userdata1 [48:63] Bus speed in KHz + * @userdata2 master chip HUID + * @devdesc An I2C device in the MRW has no match + * in the PCRD. + * @custdesc Platform security problem detected + */ + auto err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_POPULATE_TPMINFOBYNODE, + RUNTIME::RC_EXTRA_I2C_DEVICE_IN_MRW, + TWO_UINT32_TO_UINT64( + FOUR_UINT8_TO_UINT32(i2cDevItr->engine, + i2cDevItr->masterPort, + i2cDevItr->deviceType, + i2cDevItr->addr), + TWO_UINT16_TO_UINT32( + TWO_UINT8_TO_UINT16(i2cDevItr->slavePort, + i2cDevItr->devicePurpose), + i2cDevItr->busFreqKhz) + ), + TARGETING::get_huid(i2cDevItr->masterChip), + true); + ERRORLOG::errlCommit(err, RUNTIME_COMP_ID); + } + } - // advance the current offset to account for the physical interaction - // mechanism info struct + // advance the current offset to account for the physical + // interaction mechanism info struct l_currOffset =+ sizeof(*l_physInter); // populate the second part of the pointer pair from earlier diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 27fc6b6164d..6a79205da7f 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -33882,6 +33882,14 @@ Measured in GB NVLINK B + + WINDOW_OPEN + 0xD + + + PHYSICAL_PRESENCE + 0xE + UNKNOWN FF