diff options
author | Jaymes Wilks <mjwilks@us.ibm.com> | 2017-02-24 15:08:57 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-04-10 13:48:29 -0400 |
commit | 5bdb1f8ec34124c68db869dbb46b27e5a5fc24b5 (patch) | |
tree | 84ccf175a63ea0c362d2221cc12b59669ec0a51f /src | |
parent | d85536ac35dd97a666b7b8de090f255b1a33c7d8 (diff) | |
download | talos-hostboot-5bdb1f8ec34124c68db869dbb46b27e5a5fc24b5.tar.gz talos-hostboot-5bdb1f8ec34124c68db869dbb46b27e5a5fc24b5.zip |
Populate HDAT TPM Info
Populate TPM Info during the secureboot runtime routine.
Change-Id: I02b960c175d51dc9b5941e15a529bd1587747444
RTC:166834
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/37187
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Stephen M. Cprek <smcprek@us.ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/isteps/istep20list.H | 3 | ||||
-rw-r--r-- | src/include/usr/runtime/runtime.H | 22 | ||||
-rw-r--r-- | src/usr/hdat/hdatcommonutil.C | 109 | ||||
-rwxr-xr-x | src/usr/hdat/hdathdif.C | 6 | ||||
-rw-r--r-- | src/usr/hdat/hdattpmdata.C | 60 | ||||
-rw-r--r-- | src/usr/hdat/hdattpmdata.H | 42 | ||||
-rw-r--r-- | src/usr/hdat/hdatutil.C | 6 | ||||
-rw-r--r-- | src/usr/isteps/istep21/call_host_runtime_setup.C | 11 | ||||
-rw-r--r-- | src/usr/runtime/hdatservice.C | 28 | ||||
-rw-r--r-- | src/usr/runtime/hdatstructs.H | 8 | ||||
-rw-r--r-- | src/usr/runtime/makefile | 5 | ||||
-rw-r--r-- | src/usr/runtime/populate_hbruntime.C | 330 |
12 files changed, 523 insertions, 107 deletions
diff --git a/src/include/usr/isteps/istep20list.H b/src/include/usr/isteps/istep20list.H index 4de197e13..a12f9bdea 100644 --- a/src/include/usr/isteps/istep20list.H +++ b/src/include/usr/isteps/istep20list.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2016 */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -91,6 +91,7 @@ const DepModInfo g_istep20Dependancies = { { DEP_LIB(libistep20.so), DEP_LIB(libxz.so), + DEP_LIB(libruntime.so), NULL } }; diff --git a/src/include/usr/runtime/runtime.H b/src/include/usr/runtime/runtime.H index 0ece1744a..7086ef55b 100644 --- a/src/include/usr/runtime/runtime.H +++ b/src/include/usr/runtime/runtime.H @@ -75,11 +75,29 @@ errlHndl_t populate_hbRuntimeData( void ); * values acquired via the secureboot module from a verified source, and * so, henceforth are available to the host at runtime. * - * @return errlHndl_t NULL on Success + * @return errlHndl_t nullptr on Success else pointer to error log */ errlHndl_t populate_hbSecurebootData( void ); /** + * @brief Populate TPM Info in mainstore + * + * @description Populates the Secure Boot TPM Instance Info section of HDAT + * with trusted information acquired via secure methods, and overwrites + * any untrusted information that was already there. + * + * @return errlHndl_t nullptr on Success else pointer to error log + */ +errlHndl_t populate_hbTpmInfo( void ); + +/** + * @brief Fills in Tpm Info in HDAT for current node + * + * @return errlHndl_t nullptr on success else pointer to error log + */ +errlHndl_t populate_TpmInfoByNode(); + +/** * @brief Fills in HBRT for given NODE * * @param[in] iNodeId : Node number from 0 to 7 ..etc... @@ -127,6 +145,8 @@ enum SectionId NACA, //< NACA HBRT, //< Hostboot Runtime HBRT_DATA, //< Hostboot Runtime Data + IPMI_DATA, //< IPMI Sensor Mapping Data + NODE_TPM_RELATED, //< Node TPM Related Data RESERVED_MEM, //< Hostboot's Reserved Mainstore Memory LAST_SECTION = RESERVED_MEM //< Placeholder for arrays }; diff --git a/src/usr/hdat/hdatcommonutil.C b/src/usr/hdat/hdatcommonutil.C new file mode 100644 index 000000000..350b5b727 --- /dev/null +++ b/src/usr/hdat/hdatcommonutil.C @@ -0,0 +1,109 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hdat/hdatcommonutil.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include <ctype.h> +#include "hdattpmdata.H" +#include <util/align.H> +#include <algorithm> + +#include <targeting/common/util.H> +#include <targeting/common/target.H> +#include <targeting/common/targetservice.H> + +namespace HDAT +{ +trace_desc_t *g_trac_hdat = nullptr; +TRAC_INIT(&g_trac_hdat,HDAT_COMP_NAME,4096); + +/** @brief Structure id for an HDIF structure*/ +const uint16_t HDAT_HDIF_STRUCT_ID = 0xD1F0; + +/** @brief Align value for HDAT instances */ +const uint8_t HDAT_HDIF_ALIGN = 128; + +const char g_hdatTpmDataEyeCatch[] = "TPMREL"; + +uint16_t hdatCalcMaxTpmsPerNode() +{ + size_t l_maxTpms = 0; + + // calculate max # of TPMs per node + + // look for class ENC type NODE and class chip TPM to find TPMs + TARGETING::TargetHandleList l_nodeEncList; + + getEncResources(l_nodeEncList, TARGETING::TYPE_NODE, + TARGETING::UTIL_FILTER_ALL); + + // loop thru the nodes and check number of TPMs + std::for_each(l_nodeEncList.begin(), l_nodeEncList.end(), + [&l_maxTpms](const TARGETING::Target* const i_pNode) + { + // for this Node, get a list of tpms + TARGETING::TargetHandleList l_tpmChipList; + + getChildAffinityTargets ( l_tpmChipList, i_pNode, + TARGETING::CLASS_CHIP, TARGETING::TYPE_TPM, false ); + + l_maxTpms = std::max(l_maxTpms, l_tpmChipList.size()); + } ); + return l_maxTpms; +} + +uint32_t hdatTpmDataCalcMaxSize() +{ + uint32_t l_size = 0; + + // TODO RTC 167290 - In order to support multiple nodes, this calculation + // needs to be #nodes * [ the entire 18.x set of structures ] and the + // initialization needs to be done on each instance. The reported size + // (in variable o_size) needs to be the size of a single instance and the + // reported count (via o_count) needs to be the number of nodes. For now, + // we assume one node. + + // account for the size of the TPM data header + l_size += sizeof(hdatTpmData_t); + + // account for the size of the TPM Info array header + l_size += sizeof(hdatSbTpmInfo_t); + + // account for each element of the TPM Info array + l_size += ((sizeof(hdatSbTpmInstInfo_t) + + TPM_SRTM_EVENT_LOG_MAX + + TPM_DRTM_EVENT_LOG_MAX) + * hdatCalcMaxTpmsPerNode()); + + // account for User physical interaction mechanism info struct + // and Host I2C device information pointers + l_size += (sizeof(hdatPhysInterMechInfo_t) + sizeof(hdatI2cDevInfoPtrs_t) * + NUM_I2C_PHYS_PRESENCE_DEVICES); + + // Align size value to match actual allocated size, because we also want to + // zero the padded part, and thus simplify multinode support going forward. + l_size = ALIGN_X(l_size, HDAT_HDIF_ALIGN); + + return l_size; +} + +} diff --git a/src/usr/hdat/hdathdif.C b/src/usr/hdat/hdathdif.C index 7ce7d1bfb..329a1bd37 100755 --- a/src/usr/hdat/hdathdif.C +++ b/src/usr/hdat/hdathdif.C @@ -58,9 +58,6 @@ const int32_t HDAT_FAILURE = -1; /** @brief No children for a data structure*/ const uint32_t HDAT_NO_CHILD = 0; -/** @brief Structure id for an HDIF structure*/ -const uint16_t HDAT_HDIF_STRUCT_ID = 0xD1F0; - /** @brief FFDC Version to classify data in error log */ const uint8_t HDAT_VERSION1 = 1; @@ -72,9 +69,6 @@ const uint8_t HDAT_NACA_FFDC_SUBSEC2 = 3; const uint32_t HDAT_REAL_ADDRESS_MASK = 0x80000000; const uint64_t HDAT_REAL_ADDRESS_MASK64 = 0x8000000000000000ull; -/** @brief Align value for HDAT instances */ -const uint8_t HDAT_HDIF_ALIGN = 128; - /** @brief See the prologue in hdathdif.H */ diff --git a/src/usr/hdat/hdattpmdata.C b/src/usr/hdat/hdattpmdata.C index 8b13fe4e8..dddfc6c67 100644 --- a/src/usr/hdat/hdattpmdata.C +++ b/src/usr/hdat/hdattpmdata.C @@ -46,8 +46,6 @@ namespace HDAT extern trace_desc_t *g_trac_hdat; -const uint8_t g_hdatTpmDataEyeCatch[] = {'T', 'P', 'M', 'R', 'E', 'L'}; - HdatTpmData::HdatTpmData(errlHndl_t &o_errlHndl, const HDAT::hdatMsAddr_t &i_msAddr): iv_msAddr(i_msAddr), @@ -147,36 +145,9 @@ errlHndl_t HdatTpmData::hdatLoadTpmData(uint32_t &o_size, uint32_t &o_count) { errlHndl_t l_errl = nullptr; - o_size = 0; o_count = 0; - // TODO RTC 167290 - In order to support multiple nodes, this calculation - // needs to be #nodes * [ the entire 18.x set of structures ] and the - // initialization needs to be done on each instance. The reported size - // (in variable o_size) needs to be the size of a single instance and the - // reported count (via o_count) needs to be the number of nodes. For now, - // we assume one node. - - // account for the size of the TPM data header - o_size += sizeof(hdatTpmData_t); - - // account for the size of the TPM Info array header - o_size += sizeof(hdatSbTpmInfo_t); - - // account for each element of the TPM Info array - o_size += ((sizeof(hdatSbTpmInstInfo_t) + - TPM_SRTM_EVENT_LOG_MAX + - TPM_DRTM_EVENT_LOG_MAX) - * hdatCalcMaxTpmsPerNode()); - - // account for User physical interaction mechanism info struct - // and Host I2C device information pointers - o_size += (sizeof(hdatPhysInterMechInfo_t) + sizeof(hdatI2cDevInfoPtrs_t) * - NUM_I2C_PHYS_PRESENCE_DEVICES); - - // Align size value to match actual allocated size, because we also want to - // zero the padded part, and thus simplify multinode support going forward. - o_size = ALIGN_X(o_size, HDAT_HDIF_ALIGN); + o_size = hdatTpmDataCalcMaxSize(); // zero all of it memset(iv_hdatTpmData,0,o_size); @@ -191,7 +162,7 @@ errlHndl_t HdatTpmData::hdatLoadTpmData(uint32_t &o_size, uint32_t &o_count) // add the eyecatcher memcpy(iv_hdatTpmData->hdatHdr.hdatStructName, g_hdatTpmDataEyeCatch, - sizeof(g_hdatTpmDataEyeCatch)); + strlen(g_hdatTpmDataEyeCatch)); // account for this one instance of Node TPM Related Data ++o_count; @@ -199,31 +170,4 @@ errlHndl_t HdatTpmData::hdatLoadTpmData(uint32_t &o_size, uint32_t &o_count) return l_errl; } -uint16_t hdatCalcMaxTpmsPerNode() -{ - size_t l_maxTpms = 0; - - // calculate max # of TPMs per node - - // look for class ENC type NODE and class chip TPM to find TPMs - TARGETING::TargetHandleList l_nodeEncList; - - getEncResources(l_nodeEncList, TARGETING::TYPE_NODE, - TARGETING::UTIL_FILTER_ALL); - - // loop thru the nodes and check number of TPMs - std::for_each(l_nodeEncList.begin(), l_nodeEncList.end(), - [&l_maxTpms](const TARGETING::Target* const i_pNode) - { - // for this Node, get a list of tpms - TARGETING::TargetHandleList l_tpmChipList; - - getChildAffinityTargets ( l_tpmChipList, i_pNode, - TARGETING::CLASS_CHIP, TARGETING::TYPE_TPM, false ); - - l_maxTpms = std::max(l_maxTpms, l_tpmChipList.size()); - } ); - return l_maxTpms; -} - } diff --git a/src/usr/hdat/hdattpmdata.H b/src/usr/hdat/hdattpmdata.H index d17172366..ec7ccb3e5 100644 --- a/src/usr/hdat/hdattpmdata.H +++ b/src/usr/hdat/hdattpmdata.H @@ -50,6 +50,28 @@ namespace HDAT { /** + * @brief Enumeration definition for known defaults to TPM data fields + */ +enum { + TpmDataInstance = 0, + TpmDataVersion = 0x10, + TpmDataHdrSize = 0x20, + TpmDataPtrOffset = 0x20, + TpmDataPtrCnt = 1, + TpmDataChildStrCnt = 0, + TpmDataChildStrOffset = 0, +}; + +/** + * @brief Enumeration definition for the TPM states of existence + */ +enum TpmState { + TpmPresentAndFunctional = 0x1, + TpmPresentNonFunctional = 0x2, + TpmNonPresent = 0x3, +}; + +/** * @brief Structure definition for HDAT Tpm Node Data Header */ struct hdatTpmData_t @@ -68,7 +90,7 @@ struct hdatSbTpmInfo_t { uint32_t hdatSbTpmArrayOffset; uint32_t hdatSbTpmArrayNumEntries; - uint32_t hdatSbTpmArraySize; + uint32_t hdatSbTpmArrayEntrySize; } __attribute__ ((packed)); @@ -91,9 +113,8 @@ struct hdatSbTpmInstInfo_t uint32_t hdatTpmDrtmEventLogEntrySize; } __attribute__ ((packed)); - /** - * @brief Structure definition for HDAT physical interaction mechanism info + * @brief Structure definition for HDAT physical interaction mechanism info */ struct hdatPhysInterMechInfo_t { @@ -102,9 +123,8 @@ struct hdatPhysInterMechInfo_t uint32_t hdatSizeOfI2cDevInfoPtrs; } __attribute__ ((packed)); - /** - * @brief Structure definition for HDAT Host I2c Device Information pointers + * @brief Structure definition for HDAT Host I2C Device Info pointers */ struct hdatI2cDevInfoPtrs_t { @@ -113,6 +133,7 @@ struct hdatI2cDevInfoPtrs_t uint32_t hdatHostI2cLinkId; } __attribute__ ((packed)); +extern const char g_hdatTpmDataEyeCatch[]; /** Begin Class Description * @@ -226,5 +247,16 @@ class HdatTpmData */ uint16_t hdatCalcMaxTpmsPerNode(); +/** + * @brief Calculate the maximum size of the HDAT TPM data section + * + * @pre None + * + * @post None + * + * @retval uint32_t Maximum size of the HDAT TPM data section + */ +uint32_t hdatTpmDataCalcMaxSize(); + } #endif // HDATTPMDATA_H diff --git a/src/usr/hdat/hdatutil.C b/src/usr/hdat/hdatutil.C index 456584316..3e8ef607e 100644 --- a/src/usr/hdat/hdatutil.C +++ b/src/usr/hdat/hdatutil.C @@ -34,11 +34,9 @@ using namespace TARGETING; namespace HDAT { -trace_desc_t *g_trac_hdat = NULL; -TRAC_INIT(&g_trac_hdat,HDAT_COMP_NAME,4096); +extern trace_desc_t *g_trac_hdat; - -/******************************************************************************* +/*****************************************************************************n * hdatBldErrLog *******************************************************************************/ void hdatBldErrLog(errlHndl_t & io_err, diff --git a/src/usr/isteps/istep21/call_host_runtime_setup.C b/src/usr/isteps/istep21/call_host_runtime_setup.C index d3c8602e8..801f08a11 100644 --- a/src/usr/isteps/istep21/call_host_runtime_setup.C +++ b/src/usr/isteps/istep21/call_host_runtime_setup.C @@ -144,7 +144,16 @@ void* call_host_runtime_setup (void *io_pArgs) if ( l_err ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "Failed hbSecurebotData setup" ); + "Failed hbSecurebootData setup" ); + break; + } + + // API call to populate the TPM Info fields + l_err = RUNTIME::populate_hbTpmInfo(); + if ( l_err ) + { + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + "Failed hbTpmInfo setup" ); break; } diff --git a/src/usr/runtime/hdatservice.C b/src/usr/runtime/hdatservice.C index 32b266788..ab306c381 100644 --- a/src/usr/runtime/hdatservice.C +++ b/src/usr/runtime/hdatservice.C @@ -819,6 +819,34 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section, o_dataAddr = internal_data_ptrs[0].hdatOffset + base_addr; o_dataSize = internal_data_ptrs[0].hdatSize; } + else if( RUNTIME::NODE_TPM_RELATED == i_section ) + { + // Find the right tuple and verify it makes sense + hdat5Tuple_t* tuple = nullptr; + if( iv_spiraS ) + { + tuple = &(iv_spiraS->hdatDataArea[SPIRAS_TPM_DATA]); + } + else if( unlikely(iv_spiraL != nullptr) ) + { + tuple = &(iv_spiraL->hdatDataArea[SPIRAL_TPM_DATA]); + } + TRACUCOMP( g_trac_runtime, "NODE_TPM_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, "tpm_data=%p", base_addr ); + + // set the base address and size for the section + 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 ) { diff --git a/src/usr/runtime/hdatstructs.H b/src/usr/runtime/hdatstructs.H index 8fbea2eee..887ecf7fc 100644 --- a/src/usr/runtime/hdatstructs.H +++ b/src/usr/runtime/hdatstructs.H @@ -100,7 +100,9 @@ enum hdatSpiraLegacyDataAreas SPIRAL_PCRD = 22, // PCRD (Chip related data area) SPIRAL_HSVC_DATA = 23, // Host Services Data SPIRAL_HBRT_DATA = 24, // Hostboot Runtime Data - SPIRAL_LAST = 24 + SPIRAL_IPMI_DATA = 25, // IPMI Data + SPIRAL_TPM_DATA = 26, // TPM Node Related Data + SPIRAL_LAST = 26 }; /** @enum hdatSpiraHDataAreas @@ -141,7 +143,9 @@ enum hdatSpiraSDataAreas SPIRAS_PCRD = 13, // PCRD (Chip related data area) SPIRAS_HSVC_DATA = 14, // Host Services Data SPIRAS_HBRT_DATA = 15, // Hostboot Runtime Data - SPIRAS_LAST = 15 + SPIRAS_IPMI_DATA = 16, // IPMI Data + SPIRAS_TPM_DATA = 17, // Node TPM Related Data + SPIRAS_LAST = 17 }; diff --git a/src/usr/runtime/makefile b/src/usr/runtime/makefile index 14838e18d..d0e0abd93 100644 --- a/src/usr/runtime/makefile +++ b/src/usr/runtime/makefile @@ -32,6 +32,8 @@ ROOTPATH = ../../.. MODULE = runtime +VPATH += ${ROOTPATH}/src/usr/hdat + #@TODO RTC:132750 #OBJS += populate_attributes.o OBJS += populate_hbruntime.o @@ -39,7 +41,10 @@ OBJS += hdatservice.o OBJS += fakepayload.o OBJS += errlud_hdat.o OBJS += customize_attrs_for_payload.o +OBJS += hdatcommonutil.o SUBDIRS += test.d +EXTRAINCDIR += ${ROOTPATH}/src/usr/hdat + include ${ROOTPATH}/config.mk diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C index 89456969d..0be167fdf 100644 --- a/src/usr/runtime/populate_hbruntime.C +++ b/src/usr/runtime/populate_hbruntime.C @@ -38,6 +38,7 @@ #include <targeting/common/targetservice.H> #include <targeting/common/utilFilter.H> #include <targeting/common/entitypath.H> +#include <targeting/common/commontargeting.H> #include <runtime/runtime_reasoncodes.H> #include <runtime/runtime.H> #include "hdatstructs.H" @@ -54,6 +55,8 @@ #include <secureboot/trustedbootif.H> #include <secureboot/service.H> #include <config.h> +#include "../hdat/hdattpmdata.H" +#include "../secureboot/trusted/tpmLogMgr.H" namespace RUNTIME @@ -64,6 +67,8 @@ mutex_t g_rhbMutex = MUTEX_INITIALIZER; // used for populating the TPM required bit in HDAT const uint16_t TPM_REQUIRED_BIT = 0x8000; //leftmost bit of uint16_t set to 1 +const uint8_t BITS_PER_BYTE = 8; + trace_desc_t *g_trac_runtime = nullptr; TRAC_INIT(&g_trac_runtime, RUNTIME_COMP_NAME, KILOBYTE); @@ -810,57 +815,324 @@ errlHndl_t populate_hbSecurebootData ( void ) // populate TPM config bits in hdat bool tpmRequired = false; - #ifdef CONFIG_TRUSTEDBOOT + #ifdef CONFIG_TPMDD tpmRequired = TRUSTEDBOOT::isTpmRequired(); #endif l_sysParmsPtr->hdatTpmConfBits = tpmRequired? TPM_REQUIRED_BIT: 0; - // find max # of TPMs per drawer and populate hdat with it + // get max # of TPMs per drawer and populate hdat with it + auto l_maxTpms = HDAT::hdatTpmDataCalcMaxSize(); + + l_sysParmsPtr->hdatTpmDrawer = l_maxTpms; + TRACFCOMP(g_trac_runtime,"Max TPMs = 0x%04X", l_maxTpms); + + // populate hw key hash in hdat + #ifdef CONFIG_SECUREBOOT + auto hash = l_sysParmsPtr->hdatHwKeyHashValue; + SECUREBOOT::getHwKeyHash(hash); + #else + memset(l_sysParmsPtr->hdatHwKeyHashValue,0, + sizeof(l_sysParmsPtr->hdatHwKeyHashValue)); + #endif + + } while(0); + + return (l_elog); +} // end populate_hbRuntime + +errlHndl_t populate_TpmInfoByNode() +{ + errlHndl_t l_elog = nullptr; + + do { + + uint64_t l_baseAddr = 0; + uint64_t l_dataSizeMax = 0; + const uint64_t l_instance = 0; // pass 0 since there is only one record + + // TODO RTC 167290 - We will need to pass the appropriate instance value + // when we implement multinode support + + l_elog = RUNTIME::get_host_data_section(RUNTIME::NODE_TPM_RELATED, + l_instance, + l_baseAddr, + l_dataSizeMax); + if(l_elog) + { + TRACFCOMP( g_trac_runtime, ERR_MRK "populate_TpmInfoByNode: " + "get_host_data_section() failed for Node TPM-related Data section"); + break; + } + + // obtain the node target, used later to populate fields + TARGETING::Target* mproc = nullptr; + l_elog = TARGETING::targetService().queryMasterProcChipTargetHandle(mproc); + if(l_elog) + { + TRACFCOMP( g_trac_runtime, ERR_MRK "populate_TpmInfoByNode: " + "could not obtain the master processor from targeting"); + break; + } + auto targetType = TARGETING::TYPE_NODE; + const TARGETING::Target* l_node = getParent(mproc, targetType); + assert(l_node != nullptr, "Bug! getParent on master proc returned null."); + + // this will additively keep track of the next available offset + // as we fill the section + uint32_t l_currOffset = 0; + + auto const l_hdatTpmData + = reinterpret_cast<HDAT::hdatTpmData_t*>(l_baseAddr); + + // make sure we have enough room + auto const l_tpmDataCalculatedMax = HDAT::hdatTpmDataCalcMaxSize(); + assert(l_dataSizeMax >= l_tpmDataCalculatedMax, + "Bug! The TPM data hdat section doesn't have enough space"); + + // check that hdat structure format and eye catch were filled out + assert(l_hdatTpmData->hdatHdr.hdatStructId == HDAT::HDAT_HDIF_STRUCT_ID, + "Bug! The TPM data hdat struct format value doesn't match"); + + auto l_eyeCatchLen = strlen(HDAT::g_hdatTpmDataEyeCatch); + assert(memcmp(l_hdatTpmData->hdatHdr.hdatStructName, + HDAT::g_hdatTpmDataEyeCatch, + l_eyeCatchLen)==0, + "Bug! The TPM data hdat struct name eye catcher doesn't match"); + + l_hdatTpmData->hdatHdr.hdatInstance = HDAT::TpmDataInstance; + l_hdatTpmData->hdatHdr.hdatVersion = HDAT::TpmDataVersion; + l_hdatTpmData->hdatHdr.hdatHdrSize = HDAT::TpmDataHdrSize; + l_hdatTpmData->hdatHdr.hdatDataPtrOffset = HDAT::TpmDataPtrOffset; + l_hdatTpmData->hdatHdr.hdatDataPtrCnt = HDAT::TpmDataPtrCnt; + l_hdatTpmData->hdatHdr.hdatChildStrCnt = HDAT::TpmDataChildStrCnt; + l_hdatTpmData->hdatHdr.hdatChildStrOffset = HDAT::TpmDataChildStrOffset; + + TRACFCOMP(g_trac_runtime,"populate_TpmInfoByNode: " + "HDAT TPM Data successfully read. Struct Format:0x%X", + l_hdatTpmData->hdatHdr.hdatStructId); + TRACFBIN(g_trac_runtime, "populate_TpmINfoByNode - EyeCatch: ", + l_hdatTpmData->hdatHdr.hdatStructName, l_eyeCatchLen); + + // go past the end of the first struct to get to the next one + l_currOffset += sizeof(*l_hdatTpmData); + + // populate first part of pointer pair for secure boot TPM info + l_hdatTpmData->hdatSbTpmInfo.hdatOffset = l_currOffset; + + // the second part of the pointer pair for secure boot TPM info will be + // populated using the following start offset + auto l_sbTpmInfoStart = l_currOffset; + + auto const l_hdatSbTpmInfo = reinterpret_cast<HDAT::hdatSbTpmInfo_t*> + (l_baseAddr + l_currOffset); + + std::list<TRUSTEDBOOT::TpmTarget> l_tpmList; + #ifdef CONFIG_TPMDD + TRUSTEDBOOT::getTPMs(l_tpmList); + #endif + + TARGETING::TargetHandleList l_procList; + + getAllChips(l_procList,TARGETING::TYPE_PROC,false); - // look for class ENC type NODE and class chip TPM to find TPMs - TARGETING::TargetHandleList l_nodeEncList; + auto const l_numTpms = l_tpmList.size(); - getEncResources(l_nodeEncList, TYPE_NODE, UTIL_FILTER_ALL); + // 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); - uint16_t l_maxTpms = 0; + // advance current offset to after the Secure Boot TPM info array header + l_currOffset += sizeof(*l_hdatSbTpmInfo); - // loop thru the nodes and check number of TPMs - for (TargetHandleList::const_iterator - l_node_iter = l_nodeEncList.begin(); - l_node_iter != l_nodeEncList.end(); - ++l_node_iter) + // fill in the values for each Secure Boot TPM Instance Info in the array + for (auto itpm : l_tpmList) { - // for this Node, get a list of tpms - TARGETING::TargetHandleList l_tpmChipList; + auto l_tpmInstInfo = reinterpret_cast<HDAT::hdatSbTpmInstInfo_t*> + (l_baseAddr + l_currOffset); + auto l_tpmInfo = itpm.tpmTarget->getAttr<TARGETING::ATTR_TPM_INFO>(); + + TARGETING::PredicateAttrVal<TARGETING::ATTR_PHYS_PATH> + hasSameI2cMaster(l_tpmInfo.i2cMasterPath); + + auto itr = std::find_if(l_procList.begin(),l_procList.end(), + [&hasSameI2cMaster](const TARGETING::TargetHandle_t & t) + { + return hasSameI2cMaster(t); + }); - getChildAffinityTargets ( l_tpmChipList, *l_node_iter, - TARGETING::CLASS_CHIP, TYPE_TPM, false ); + assert(itr != l_procList.end(), "Bug! TPM must have a processor."); + auto l_proc = *itr; - size_t l_numTpms = l_tpmChipList.size(); + l_tpmInstInfo->hdatChipId = l_proc->getAttr<TARGETING::ATTR_CHIP_ID>(); - if (l_numTpms > l_maxTpms) + l_tpmInstInfo->hdatDbobId = l_node->getAttr< + TARGETING::ATTR_ORDINAL_ID>(); + + l_tpmInstInfo->hdatLocality1Addr = l_tpmInfo.devAddrLocality1; + l_tpmInstInfo->hdatLocality2Addr = l_tpmInfo.devAddrLocality2; + l_tpmInstInfo->hdatLocality3Addr = l_tpmInfo.devAddrLocality3; + l_tpmInstInfo->hdatLocality4Addr = l_tpmInfo.devAddrLocality4; + + uint8_t functional = !itpm.failed; + // TODO RTC 168781 Replace above with something like below + // itpm.tpmTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional; + + uint8_t present = itpm.available; + // TODO RTC 168781 Replace above with something like below + // itpm.tpmTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().present; + + if (functional && present) { - l_maxTpms = static_cast<uint16_t>(l_numTpms); + // present and functional + l_tpmInstInfo->hdatFunctionalStatus = HDAT::TpmPresentAndFunctional; } + else if (present) + { + // present and not functional + l_tpmInstInfo->hdatFunctionalStatus = HDAT::TpmPresentNonFunctional; + } + else + { + // not present + l_tpmInstInfo->hdatFunctionalStatus = HDAT::TpmNonPresent; + } + + // advance the current offset to account for this tpm instance info + l_currOffset += sizeof(*l_tpmInstInfo); + + // use the current offset for the beginning of the SRTM event log + l_tpmInstInfo->hdatTpmSrtmEventLogOffset = sizeof(*l_tpmInstInfo); + + #ifdef CONFIG_TPMDD + // copy the contents of the SRTM event log into HDAT picking the + // min of log size and log max (to make sure log size never goes + // over the max + memcpy(reinterpret_cast<void*>(l_baseAddr + l_currOffset), + TpmLogMgr_getLogStartPtr(itpm.logMgr), + itpm.logMgr->logSize < TPM_SRTM_EVENT_LOG_MAX ? + itpm.logMgr->logSize : TPM_SRTM_EVENT_LOG_MAX); + + // set the size value for the data that was copied + l_tpmInstInfo->hdatTpmSrtmEventLogEntrySize = itpm.logMgr->logSize; + #else + l_tpmInstInfo->hdatTpmSrtmEventLogEntrySize = 0; + #endif + + // advance the current offset to account for the SRTM event log + l_currOffset += TPM_SRTM_EVENT_LOG_MAX; + + // set the DRTM offset to zero as it is not yet supported + l_tpmInstInfo->hdatTpmDrtmEventLogOffset = 0; + + // set the DRTM event log size to zero as it is not yet supported + l_tpmInstInfo->hdatTpmDrtmEventLogEntrySize = 0; + + // Note: We don't advance the current offset, because the size of the + // DRTM event log is zero } - l_sysParmsPtr->hdatTpmDrawer = l_maxTpms; - TRACFCOMP(g_trac_runtime,"Max TPMs = 0x%04X", l_maxTpms); + // populate second part of pointer pair for secure boot TPM info + l_hdatTpmData->hdatSbTpmInfo.hdatSize = l_currOffset - l_sbTpmInfoStart; - // populate hw key hash in hdat - #ifdef CONFIG_SECUREBOOT - auto hash = l_sysParmsPtr->hdatHwKeyHashValue; - SECUREBOOT::getHwKeyHash(hash); - #else - memset(l_sysParmsPtr->hdatHwKeyHashValue,0, - sizeof(l_sysParmsPtr->hdatHwKeyHashValue)); - #endif + // the current offset now corresponds to the physical interaction mechanism + // info array header + auto l_physInter = reinterpret_cast<HDAT::hdatPhysInterMechInfo_t*> + (l_baseAddr + l_currOffset); + + // populate the first part of pointer pair from earlier to point here + l_hdatTpmData->hdatPhysInter.hdatOffset = l_currOffset; + + // 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 + l_physInter->hdatOffsetI2cDevInfoPtrs = sizeof(*l_physInter); + l_physInter->hdatNumEntries = 0; + l_physInter->hdatSizeOfI2cDevInfoPtrs = sizeof(HDAT::hdatI2cDevInfoPtrs_t); + + // 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 + l_hdatTpmData->hdatPhysInter.hdatSize = l_currOffset - l_physInterStart; + + // set the total structure length to the current offset + l_hdatTpmData->hdatHdr.hdatSize = l_currOffset; + + } while (0); + + return (l_elog); +} + +errlHndl_t populate_hbTpmInfo() +{ + errlHndl_t l_elog = nullptr; + + do { + // TODO RTC 171851 Remove FSP restriction when FSP code provides + // Node TPM Related Data + + // Skip populating HDAT TPM Node Related Data on FSP systems + if (INITSERVICE::spBaseServicesEnabled()) + { + break; + } + + TRACFCOMP(g_trac_runtime, "Running populate_hbTpmInfo"); + + TARGETING::Target* sys = nullptr; + TARGETING::targetService().getTopLevelTarget( sys ); + assert(sys != nullptr, + "populate_hbTpmInfo: Bug! Could not obtain top level target"); + + // This attribute is only set on a multi-node system. + // We will use it below to detect a multi-node scenario + auto hb_images = sys->getAttr<TARGETING::ATTR_HB_EXISTING_IMAGE>(); + + // if single node system + if (!hb_images) + { + l_elog = populate_TpmInfoByNode(); + if(l_elog != nullptr) + { + TRACFCOMP( g_trac_runtime, "populate_hbTpmInfo: " + "populate_RtDataByNode failed" ); + } + break; + } + + // start the 1 in the mask at leftmost position + decltype(hb_images) l_mask = 0x1 << (sizeof(hb_images)*BITS_PER_BYTE-1); + + // start at node 0 + uint32_t l_node = 0; + + // while the one in the mask hasn't shifted out + while (l_mask) + { + // if this node is present + if(l_mask & hb_images) + { + TRACFCOMP( g_trac_runtime, "populate_hbTpmInfo: " + "MsgToNode %d for HBRT TPM Info", + l_node ); + // @TODO RTC 167290 + // Need to send message to the current node + // When node receives a message it should call + // populate_TpmInfoByNode() + } + l_mask >>= 1; // shift to the right for the next node + l_node++; // go to the next node + } } while(0); return (l_elog); -} // end populate_hbRuntiome +} // end populate_hbTpmInfo + errlHndl_t populate_hbRuntimeData( void ) |