summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Bofferding <bofferdn@us.ibm.com>2018-03-19 23:26:08 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-05-08 09:44:28 -0400
commit2fe71f4ddc13e3c730fbb7e1fcfe0d319eddc333 (patch)
tree6717b134419978a4b0836382364f98f620d1630c
parent3c2b4bf2adc3e076d7dc9e2876b64b813a799260 (diff)
downloadtalos-hostboot-2fe71f4ddc13e3c730fbb7e1fcfe0d319eddc333.tar.gz
talos-hostboot-2fe71f4ddc13e3c730fbb7e1fcfe0d319eddc333.zip
Secure Boot: Implement Centaur SCOM cache
This change implements a Centaur SCOM cache for sensitive SCOM registers. The cache is initialized and enabled before the first Centaur SCOM, and disabled just prior to locking down the Centaur configuration. Once the Centaur has been locked down, the real register values are compared to the cache entries, and the Centaur is deconfigured (not garded) on any mismatch in assumptions. RTC: 187288 Change-Id: I7b13bfd7eb6b427aba115d6944958bf55e171008 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/57532 Reviewed-by: ILYA SMIRNOV <ismirno@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rw-r--r--src/include/usr/scom/centaurScomCache.H391
-rw-r--r--src/include/usr/scom/scomreasoncodes.H16
-rwxr-xr-xsrc/usr/errl/plugins/errluserdetails.H52
-rw-r--r--src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C15
-rw-r--r--src/usr/isteps/istep14/call_proc_exit_cache_contained.C24
-rw-r--r--src/usr/isteps/istep14/call_proc_setup_bars.C15
-rw-r--r--src/usr/scom/centaurScomCache.C878
-rw-r--r--src/usr/scom/errlud_cache.C81
-rw-r--r--src/usr/scom/errlud_cache.H98
-rwxr-xr-xsrc/usr/scom/genCentaurScomCacheRegDefs.pl399
-rw-r--r--src/usr/scom/makefile36
-rw-r--r--src/usr/scom/plugins/errludP_cache.H135
-rw-r--r--src/usr/scom/plugins/scomUdParserFactory.H8
-rw-r--r--src/usr/scom/scom.C66
-rwxr-xr-xsrc/usr/targeting/common/xmltohb/attribute_types_hb.xml13
-rw-r--r--src/usr/targeting/common/xmltohb/target_types_hb.xml1
-rwxr-xr-xsrc/usr/targeting/common/xmltohb/xmltohb.pl4
17 files changed, 2221 insertions, 11 deletions
diff --git a/src/include/usr/scom/centaurScomCache.H b/src/include/usr/scom/centaurScomCache.H
new file mode 100644
index 000000000..013976384
--- /dev/null
+++ b/src/include/usr/scom/centaurScomCache.H
@@ -0,0 +1,391 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/scom/centaurScomCache.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2018 */
+/* [+] 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 */
+
+#ifndef __CENTAURSCOMCACHE_H
+#define __CENTAURSCOMCACHE_H
+
+/**
+ * @file src/include/usr/scom/centaurScomCache.H
+ *
+ * @brief Interface for the Secure Boot Centaur SCOM cache
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+
+extern trace_desc_t* g_trac_scom;
+
+// These defines allow standard logging of error information in traces
+#define TRACE_ERR_FMT "Error info: PLID=0x%08X, EID=0x%08X, Reason=0x%04X. "
+#define TRACE_ERR_ARGS(pError) \
+ ERRL_GETPLID_SAFE(pError), ERRL_GETEID_SAFE(pError), ERRL_GETRC_SAFE(pError)
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+/**
+ * @brief Structure which provides Centaur SCOM cache register definitions
+ */
+struct ScomRegDef
+{
+ // Address of the SCOM register
+ // Must not be 0
+ uint64_t addr;
+
+ // NOTE: only one of isWandReg or isWorReg can be set in a given record at a
+ // time
+
+ // Indicates whether a write to this register bitwise ANDs the requested
+ // write value into a different base register. 0b1=yes, 0b0=no
+ uint8_t isWandReg : 1;
+
+ // Indicates whether a write to this register bitwise ORs the requested
+ // write value into a different base register. 0b1=yes, 0b0=no
+ uint8_t isWorReg : 1;
+
+ // If isWandReg or isWorReg is 0b1, indicates the base register to perform
+ // the WAND or WOR operation on (which must not be 0).
+ // N/A (set to 0) otherwise
+ uint64_t baseAddr;
+
+ // If isWandReg or isWorReg is 0b1, indicates a different index into the
+ // register definition vector where the base address register is located.
+ // Otherwise, indicates this record's position in the register definition
+ // vector. This index allows base register record and per-Centaur register
+ // lookup with O(1) algorithmic complexity.
+ // Must be -1 prior to init, 0..size-1 afterwards
+ ssize_t baseIndex;
+
+ // The expected hardware initialization value
+ // Default = 0
+ // N/A (set to 0) if isWandReg or isWorReg bit set to 0b1
+ uint64_t expectedHwInitValue;
+
+ // A mask indicating which bits of the register to consider when
+ // comparing values read from hardware vs. the cache. If a bit
+ // is set, the bits at the same position should be compared.
+ // Default = all bits 0b1 = compare whole register.
+ // Must not be 0 when neither isWandReg nor isWorReg bit is set.
+ // N/A (set to 0) if isWandReg or isWorReg bit set to 0b1
+ uint64_t mask;
+
+ /**
+ * @brief Returns whether this register has an associated base register
+ *
+ * @retval bool Boolean indicating whether register has an associated base
+ * register that gets changed on write operations
+ * @return true Register has a base register
+ * @return false Register does not have a base register
+ */
+ bool hasBaseAddr() const
+ {
+ return (isWandReg || isWorReg);
+ }
+
+ /**
+ * @brief Enum giving defaults for various record fields
+ */
+ enum DEFAULTS
+ {
+ DEFAULT_IS_WAND_REG=0b0, ///< Not a WAND register
+ DEFAULT_IS_WOR_REG=0b0, ///< Not a WOR register
+ DEFAULT_BASE_ADDR=0x0ULL, ///< No associated base register
+ DEFAULT_BASE_INDEX=-1, ///< Lookup index not populated
+ DEFAULT_EXPECTED_HW_INIT_VALUE=0x0ULL, ///< Expected HW init value of 0
+ DEFAULT_MASK=0xFFFFFFFFFFFFFFFFULL, ///< Compare whole registers
+ };
+
+ /**
+ * @brief Constructor to build a SCOM register definition record
+ *
+ * @param[in] i_addr Register address
+ * @param[in] i_isWandReg Whether register has a base register it bitwise
+ * ANDs into
+ * @param[in] i_isWorReg Whether register has a base register it bitwise
+ * ANDs into
+ * @param[in] i_baseAddr If isWandReg or isWorReg set, the associated base
+ * register
+ * @param[in] i_baseIndex If isWandReg or isWorReg set, the index of the
+ * associated base register in the SCOM register definition vector.
+ * Otherwise, the index of this record in the SCOM register definition
+ * vector. If DEFAULT_BASE_INDEX, the value must be changed before
+ * caching is enabled.
+ * @param[in] i_expectedHwInitValue The expected hardware initialization
+ * value for the register
+ * @param[in] i_mask A mask indicating which bits to analyze when a
+ * register's cache value is compared to the value read from hardware.
+ *
+ * @note: See ScomRegDef field documentation above for additional
+ * restrictions.
+ */
+ ScomRegDef(
+ uint64_t i_addr,
+ int i_isWandReg=DEFAULT_IS_WAND_REG,
+ int i_isWorReg=DEFAULT_IS_WOR_REG,
+ uint64_t i_baseAddr=DEFAULT_BASE_ADDR,
+ ssize_t i_baseIndex=DEFAULT_BASE_INDEX,
+ uint64_t i_expectedHwInitValue=DEFAULT_EXPECTED_HW_INIT_VALUE,
+ uint64_t i_mask=DEFAULT_MASK)
+ : addr(i_addr),
+ isWandReg(i_isWandReg),
+ isWorReg(i_isWorReg),
+ baseAddr(i_baseAddr),
+ baseIndex(i_baseIndex),
+ expectedHwInitValue(i_expectedHwInitValue),
+ mask(i_mask)
+ {
+ }
+};
+
+// Alias for the SCOM register definition vector type
+typedef std::vector<ScomRegDef> ScomRegDefs;
+
+/**
+ * @brief Class which coordinates tracking read and write access to any Centaur
+ * SCOM register deemed to be security sensitive
+ */
+class ScomCache
+{
+ public:
+
+ /**
+ * @brief Initializes all Centaurs' SCOM register cache
+ *
+ * @par Detailed Description:
+ * Builds a SCOM register cache seeded with expected hardware
+ * initialization values for each security sensitive register, and
+ * clones it to every Centaur
+ */
+ void init() const;
+
+ /**
+ * @brief Globally enables caching of read/write SCOM requests for every
+ * functional Centaur
+ */
+ void enableCache();
+
+ /**
+ * @brief Globally disables caching of read/write SCOM requests for every
+ * functional Centaur
+ */
+ void disableCache();
+
+ /**
+ * @brief Returns whether Centaur SCOM register caching is enabled for
+ * all functional Centaurs
+ *
+ * @retval boolean Indicating whether Centaur SCOM register cache is
+ * enabled for all functional Centuars or not
+ */
+ bool cacheEnabled() const;
+
+ /**
+ * @brief Delete all Centaurs' SCOM register cache
+ */
+ void destroy() const;
+
+ /**
+ * @brief If caching enabled and register is sensitive, writes the
+ * requested value to the given Membuf's cache
+ *
+ * @param[in] i_Membuf Membuf target to write. If the request happens
+ * -not- to be a Centaur or caching is disabled, it's a no-op. Returns
+ * error if target is nullptr.
+ * @param[in] i_addr Register address
+ * @param[in] i_value Register value
+ *
+ * @return errlHndl_t Error log handle
+ * @retval nullptr Operation was successful
+ * @retval !nullptr Operation failed with valid error log
+ */
+ errlHndl_t write(
+ TARGETING::Target* i_pMembuf,
+ uint64_t i_addr,
+ uint64_t i_value) const;
+
+ /**
+ * @brief If caching enabled and register is sensitive, reads the
+ * requested register from the given Membuf's cache. If the
+ * register was returned, the call indicates a cache hit, else a miss
+ *
+ * @param[in] i_pMembuf Membuf target to read. If the request happens
+ * -not- to be a Centaur, or caching is disabled, it's a no-op.
+ * Returns error if target is nullptr.
+ * @param[in] i_addr SCOM register address to read
+ * @param[out] o_cacheHit Whether the cache held the requested register
+ * value
+ * @param[out] o_value Register value that was read; only valid if
+ * o_cacheHit is true
+ *
+ * @return errlHndl_t Error log handle
+ * @retval nullptr Operation was successful
+ * @retval !nullptr Operation failed with valid error log; all outputs
+ * invalid
+ */
+ errlHndl_t read(
+ TARGETING::Target* i_pMembuf,
+ uint64_t i_addr,
+ bool& o_cacheHit,
+ uint64_t& o_value) const;
+
+ /**
+ * @brief Verifies, node-wide, that every security sensitive Centaur SCOM
+ * register's cached value matches (as directed by the compare mask)
+ * the value actually read from the hardware.
+ *
+ * @return errlHndl_t Error log handle
+ * @retval nullptr Operation was successful
+ * @retval !nullptr Operation failed with valid error log
+ */
+ errlHndl_t verify() const;
+
+ /**
+ * @brief Dumps, node-wide, the cached values of every security sensitive
+ * Centaur SCOM register to the trace
+ */
+ void dump() const;
+
+ /**
+ * @brief Returns the Centaur SCOM cache singleton
+ *
+ * @retval ScomCache& Reference to the Centaur SCOM cache singleton
+ */
+ static ScomCache& getInstance();
+
+ /**
+ * Delete Copy Constructor
+ */
+ ScomCache(const ScomCache&) = delete;
+
+ /**
+ * Delete Copy Assignment
+ */
+ ScomCache& operator= (const ScomCache&) = delete;
+
+ /**
+ * Delete Move Constructor
+ */
+ ScomCache (ScomCache&&) = delete;
+
+ /**
+ * Delete Move Assignment
+ */
+ ScomCache& operator = (ScomCache&&) = delete;
+
+ protected:
+
+ /**
+ * @brief Centaur SCOM cache constructor
+ */
+ ScomCache();
+
+ /**
+ * @brief Centaur SCOM cache destructor
+ */
+ ~ScomCache();
+
+ private: // APIs
+
+ /**
+ * @brief Helper function to retrieve a Centaur's SCOM cache
+ *
+ * @param[in] i_pCentaur Centaur target. Must not be nullptr and must be a
+ * Centaur, but this is not strictly enforced.
+ * @retval std::vector<uint64_t>* Pointer to the SCOM cache
+ */
+ std::vector<uint64_t>* _getCachePtr(
+ TARGETING::Target* i_pCentaur) const
+ {
+ return reinterpret_cast<std::vector<uint64_t>*>(
+ i_pCentaur->getAttr<TARGETING::ATTR_CENTAUR_REGISTER_CACHE_PTR>());
+ }
+
+ /**
+ * @brief Helper function to store a Centaur's SCOM cache
+ *
+ * @param[in] i_pCentaur Centaur target. Must not be nullptr and must be a
+ * Centaur, but this is not strictly enforced.
+ * @param[in] i_pCache Pointer to the SCOM cache
+ */
+ void _setCachePtr(
+ TARGETING::Target* i_pCentaur,
+ const std::vector<uint64_t>* i_pCache) const
+ {
+ i_pCentaur->setAttr<TARGETING::ATTR_CENTAUR_REGISTER_CACHE_PTR>(
+ reinterpret_cast<uint64_t>(
+ const_cast<std::vector<uint64_t>*>(i_pCache)));
+ }
+
+ /**
+ * @brief Generated function to initialize the SCOM register definitions
+ *
+ * @return ScomRegDefs* Pointer to the SCOM register definitions. Memory
+ * transfer occurs and caller responsible for deleting the vector later.
+ *
+ * @note: Generated source @ obj/genfiles/centaurScomCacheRegDefs.C
+ */
+ ScomRegDefs* _initScomRegDefs() const;
+
+ /**
+ * @brief Checks for duplicate SCOM register definition records (any with
+ * duplicate addresses) and asserts if that condition is found
+ */
+ void _enforceScomRegDefUniqueness() const;
+
+ /**
+ * @brief Ensures the SCOM register definition records are formatted
+ * properly. Asserts on any violation.
+ */
+ void _validateScomRegDefs() const;
+
+ /**
+ * @brief Performs a performance fixup that allows register lookup for an
+ * individual Centaur that runs in O(log n) algoritmic complexity
+ */
+ void _optimizeScomRegDefs();
+
+ private: // Instance vars
+
+ ///< Pointer to vector of SCOM register definitions
+ ScomRegDefs* iv_pScomRegDefs;
+
+ ///< Whether the node-wide Centaur SCOM cache is active
+ bool iv_cacheEnabled;
+};
+
+} // end CENTAUR_SECURITY namespace
+
+} // end SECUREBOOT namespace
+
+#endif
+
diff --git a/src/include/usr/scom/scomreasoncodes.H b/src/include/usr/scom/scomreasoncodes.H
index c4db021c8..4f6c73187 100644
--- a/src/include/usr/scom/scomreasoncodes.H
+++ b/src/include/usr/scom/scomreasoncodes.H
@@ -42,6 +42,9 @@ namespace SCOM
SCOM_TRANSLATE_CENTAUR = 0x08,
SCOM_RT_SEND_SCOM_TO_HYP = 0x09,
SCOM_OP_SANITY_CHECK = 0x0A,
+ SCOM_VERIFY_CENTAUR_CACHE = 0x0B,
+ SCOM_WRITE_CENTAUR_CACHE = 0x0C,
+ SCOM_READ_CENTAUR_CACHE = 0x0D,
};
enum scomReasonCode
@@ -69,11 +72,22 @@ namespace SCOM
SCOM_RUNTIME_HYP_ERR = SCOM_COMP_ID | 0x15,
SCOM_INVALID_DATA_BUFFER = SCOM_COMP_ID | 0x16,
SCOM_INVALID_OP_TYPE = SCOM_COMP_ID | 0x17,
+ SCOM_BAD_CACHE_VERIFY_SEQ = SCOM_COMP_ID | 0x18,
+ SCOM_CACHE_VERIFY_FAILURE = SCOM_COMP_ID | 0x19,
+ SCOM_SENSITIVE_REG_READ_FAIL = SCOM_COMP_ID | 0x1A,
+ SCOM_BAD_TARGET = SCOM_COMP_ID | 0x1B,
+ SCOM_CACHE_SEQ_ERROR = SCOM_COMP_ID | 0x1C,
};
enum UserDetailsTypes
{
- SCOM_UDT_PIB = 0x1
+ SCOM_UDT_PIB = 0x01,
+ SCOM_UDT_CENTAUR_CACHE_MISMATCH = 0x02,
+ };
+
+ enum UserDetailsVersions
+ {
+ SCOM_UDT_VERSION_1 = 0x01,
};
};
diff --git a/src/usr/errl/plugins/errluserdetails.H b/src/usr/errl/plugins/errluserdetails.H
index 8cc3421b2..917dcf266 100755
--- a/src/usr/errl/plugins/errluserdetails.H
+++ b/src/usr/errl/plugins/errluserdetails.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2018 */
+/* [+] 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. */
@@ -37,6 +39,54 @@ namespace ERRORLOG
{
/**
+ * @brief Returns the uint64_t at the pointed to location in host byte order
+ *
+ * @param[in] i_pUint64 Pointer to a uint64_t in network byte order
+ *
+ * @return uint64_t The uint64_t at the pointed to location in host byte order
+ */
+inline uint64_t NTH_UINT64(const void* i_pUint64)
+{
+ return (ntohll(*(reinterpret_cast<const uint64_t*>(i_pUint64))));
+}
+
+/**
+ * @brief Returns the uint32_t at the pointed to location in host byte order
+ *
+ * @param[in] i_pUint32 Pointer to a uint32_t in network byte order
+ *
+ * @return uint32_t The uint32_t at the pointed to location in host byte order
+ */
+inline uint32_t NTH_UINT32(const void* i_pUint32)
+{
+ return (ntohl(*(reinterpret_cast<const uint32_t*>(i_pUint32))));
+}
+
+/**
+ * @brief Returns the uint16_t at the pointed to location in host byte order
+ *
+ * @param[in] i_pUint16 Pointer to a uint16_t in network byte order
+ *
+ * @return uint16_t The uint16_t at the pointed to location in host byte order
+ */
+inline uint16_t NTH_UINT16(const void* i_pUint16)
+{
+ return (ntohs(*(reinterpret_cast<const uint16_t*>(i_pUint16))));
+}
+
+/**
+ * @brief Returns the uint8_t at the pointed to location in host byte order
+ *
+ * @param[in] i_pUint8 Pointer to a uint8_t in network byte order
+ *
+ * @return uint8_t The uint8_t at the pointed to location in host byte order
+ */
+inline uint8_t NTH_UINT8(const void* i_pUint8)
+{
+ return (*(reinterpret_cast<const uint8_t*>(i_pUint8)));
+}
+
+/**
*
* @class ErrlUserDetailsParser
*
diff --git a/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C b/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C
index 6aba97bc5..f0828b072 100644
--- a/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C
+++ b/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C
@@ -102,6 +102,11 @@
#include "../../secureboot/common/errlud_secure.H"
#include <sbe/sbe_update.H>
+#ifdef CONFIG_SECUREBOOT
+#include <secureboot/service.H>
+#include <scom/centaurScomCache.H>
+#endif
+
// end includes for post sbe secureboot steps
const uint64_t MS_TO_WAIT_FIRST = 2500; //(2.5 s)
@@ -817,6 +822,16 @@ void* call_proc_cen_ref_clk_enable(void *io_pArgs )
validateSecuritySettings();
+#ifdef CONFIG_SECUREBOOT
+ if(SECUREBOOT::enabled())
+ {
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache& centaurCache =
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance();
+ centaurCache.init();
+ centaurCache.enableCache();
+ }
+#endif
+
TARGETING::TargetHandleList functionalProcChipList;
getAllChips(functionalProcChipList, TYPE_PROC, true);
diff --git a/src/usr/isteps/istep14/call_proc_exit_cache_contained.C b/src/usr/isteps/istep14/call_proc_exit_cache_contained.C
index f018c452b..46ed22845 100644
--- a/src/usr/isteps/istep14/call_proc_exit_cache_contained.C
+++ b/src/usr/isteps/istep14/call_proc_exit_cache_contained.C
@@ -51,6 +51,11 @@
#include <util/misc.H>
#include <hwas/common/hwas.H>
+#ifdef CONFIG_SECUREBOOT
+#include <secureboot/service.H>
+#include <scom/centaurScomCache.H>
+#endif
+
using namespace ISTEP;
using namespace ISTEP_ERROR;
using namespace ERRORLOG;
@@ -69,6 +74,24 @@ void* call_proc_exit_cache_contained (void *io_pArgs)
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
"call_proc_exit_cache_contained entry" );
+ errlHndl_t l_errl = nullptr;
+
+#ifdef CONFIG_SECUREBOOT
+ if(SECUREBOOT::enabled())
+ {
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache& centaurCache =
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance();
+
+ l_errl = centaurCache.verify();
+ if(l_errl)
+ {
+ l_stepError.addErrorDetails(l_errl);
+ errlCommit(l_errl, HWPF_COMP_ID );
+ }
+
+ centaurCache.destroy();
+ }
+#endif
// @@@@@ CUSTOM BLOCK: @@@@@
// figure out what targets we need
@@ -87,7 +110,6 @@ void* call_proc_exit_cache_contained (void *io_pArgs)
//Check that minimum hardware requirement is meet.
//If not, log error and do not proceed
bool l_bootable;
- errlHndl_t l_errl = nullptr;
l_errl = HWAS::checkMinimumHardware(l_sys, &l_bootable);
if (!l_bootable && !l_errl)
{
diff --git a/src/usr/isteps/istep14/call_proc_setup_bars.C b/src/usr/isteps/istep14/call_proc_setup_bars.C
index e42ba9a07..08d1708d3 100644
--- a/src/usr/isteps/istep14/call_proc_setup_bars.C
+++ b/src/usr/isteps/istep14/call_proc_setup_bars.C
@@ -22,6 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+#include <config.h>
#include <errl/errlentry.H>
#include <isteps/hwpisteperror.H>
#include <initservice/isteps_trace.H>
@@ -48,6 +49,10 @@
#include <attribute_ids.H>
+#ifdef CONFIG_SECUREBOOT
+#include <scom/centaurScomCache.H>
+#endif
+
using namespace ISTEP_ERROR;
using namespace ERRORLOG;
@@ -188,6 +193,7 @@ void* call_proc_setup_bars (void *io_pArgs)
} // end if !l_errl
+#ifdef CONFIG_SECUREBOOT
// Assuming no errors, secure any Centaurs
if ( l_stepError.isNull() )
{
@@ -247,7 +253,16 @@ void* call_proc_setup_bars (void *io_pArgs)
}
}
}
+
+ if(SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().
+ cacheEnabled())
+ {
+ SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().
+ disableCache();
+ }
+
}
+#endif
if ( l_errl )
{
diff --git a/src/usr/scom/centaurScomCache.C b/src/usr/scom/centaurScomCache.C
new file mode 100644
index 000000000..99ccc73fd
--- /dev/null
+++ b/src/usr/scom/centaurScomCache.C
@@ -0,0 +1,878 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/scom/centaurScomCache.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2018 */
+/* [+] 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 */
+
+/**
+ * @file src/usr/scom/centaurScomCache.C
+ *
+ * @brief Implementation for Centaur SCOM register cache
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+#include <assert.h>
+#include <devicefw/driverif.H>
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <errl/errludtarget.H>
+#include <targeting/common/utilFilter.H>
+#include <scom/scomreasoncodes.H>
+
+#include <scom/centaurScomCache.H>
+#include "scom.H"
+#include "errlud_cache.H"
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+const bool ADD_HI_PRI_HB_SW_CALLOUT=true;
+const bool NO_HB_SW_CALLOUT=false;
+
+ScomCache::ScomCache()
+ : iv_pScomRegDefs(_initScomRegDefs()),
+ iv_cacheEnabled(false)
+{
+ // Sort SCOM register defintion records by register address so that we
+ // can look up a given register using std::lower_bound in O(log n)
+ // algorithmic complexity and then jump to same index within local
+ // Centaur SCOM cache to find the current value, yielding overall
+ // algorithmic complexity of O(log n) for lookup of any given Centaur's
+ // cached SCOM register
+ std::sort(
+ iv_pScomRegDefs->begin(),
+ iv_pScomRegDefs->end(),
+ [](const ScomRegDef& i_lhs,const ScomRegDef &i_rhs)
+ {
+ return (i_lhs.addr<i_rhs.addr);
+ });
+
+ _enforceScomRegDefUniqueness();
+
+ _validateScomRegDefs();
+
+ _optimizeScomRegDefs();
+}
+
+ScomCache::~ScomCache()
+{
+ delete iv_pScomRegDefs;
+ iv_pScomRegDefs=nullptr;
+}
+
+void ScomCache::_enforceScomRegDefUniqueness() const
+{
+ // Assumes the register definitions are already sorted
+ auto scomRegDefDupStartItr =
+ std::unique(iv_pScomRegDefs->begin(), iv_pScomRegDefs->end(),
+ [](const ScomRegDef& i_lhs, const ScomRegDef& i_rhs)
+ {
+ return (i_lhs.addr==i_rhs.addr);
+ }
+ );
+
+ auto scomRegDefDupItr = scomRegDefDupStartItr;
+ while(scomRegDefDupItr != iv_pScomRegDefs->end())
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "Found duplicate SCOM register definition for address 0x%016llX",
+ scomRegDefDupItr->addr);
+ ++scomRegDefDupItr;
+ }
+
+ assert(scomRegDefDupStartItr == iv_pScomRegDefs->end(),
+ "BUG! Duplicate Centaur SCOM register "
+ "definitions found");
+}
+
+void ScomCache::_validateScomRegDefs() const
+{
+ for(const auto& scomRegDef : *iv_pScomRegDefs)
+ {
+ assert(scomRegDef.addr != 0,"BUG! Centaur SCOM register definition "
+ "address is 0");
+
+ // Index fixup should happen later; starts out as DEFAULT_BASE_INDEX
+ assert(scomRegDef.baseIndex == ScomRegDef::DEFAULT_BASE_INDEX,
+ "Centaur SCOM register "
+ "definition has non DEFAULT_BASE_INDEX baseIndex for "
+ "register address 0x%016llX.",
+ scomRegDef.addr);
+
+ if(scomRegDef.hasBaseAddr())
+ {
+ assert(!(scomRegDef.isWandReg && scomRegDef.isWorReg),
+ "BUG! Centaur SCOM register definition should only have "
+ "one of isWandReg or isWorReg set. Actual isWandReg = %d, "
+ "isWorReg = %d for "
+ "register address 0x%016llX.",
+ scomRegDef.isWandReg,scomRegDef.isWorReg,scomRegDef.addr);
+ assert(scomRegDef.baseAddr != ScomRegDef::DEFAULT_BASE_ADDR,
+ "BUG! Centaur SCOM register "
+ "definition should have a base register, but it is "
+ "DEFAULT_BASE_ADDR "
+ "for register address 0x%016llX.",scomRegDef.addr);
+ assert( scomRegDef.expectedHwInitValue
+ == ScomRegDef::DEFAULT_EXPECTED_HW_INIT_VALUE,
+ "BUG! Centaur SCOM "
+ "register definition having base address should have an "
+ "expected HW init value of DEFAULT_EXPECTED_HW_INIT_VALUE but "
+ "it is 0x%016llX for address 0x%016llX.",
+ scomRegDef.expectedHwInitValue,scomRegDef.addr);
+ assert(!scomRegDef.mask,
+ "BUG! Centaur SCOM register "
+ "definition having base address should have a mask of "
+ "all 0b0's, but it is 0x%016llX for address 0x%016llX.",
+ scomRegDef.mask,scomRegDef.addr);
+ }
+ else
+ {
+ assert(!scomRegDef.baseAddr, "BUG! Centaur SCOM register "
+ "definition should not have a base register, but it's "
+ "0x%016llX for address 0x%016llX.",
+ scomRegDef.baseAddr,scomRegDef.addr);
+ assert(scomRegDef.mask, "BUG! Centaur SCOM register "
+ "definition should have a mask of !0 "
+ "but it is 0 for address 0x%016llX.",
+ scomRegDef.addr);
+ }
+ }
+}
+
+void ScomCache::_optimizeScomRegDefs()
+{
+ for(auto scomRegDefItr=iv_pScomRegDefs->begin();
+ scomRegDefItr != iv_pScomRegDefs->end();
+ ++scomRegDefItr)
+ {
+ if(scomRegDefItr->hasBaseAddr())
+ {
+ ScomRegDef regToFind(scomRegDefItr->baseAddr);
+ auto scomBaseRegDefItr=std::lower_bound(
+ iv_pScomRegDefs->begin(),
+ iv_pScomRegDefs->end(),
+ regToFind,
+ [](const ScomRegDef& i_lhs, const ScomRegDef& i_rhs)
+ {
+ return (i_lhs.addr<i_rhs.addr);
+ }
+ );
+ assert( (scomBaseRegDefItr!=iv_pScomRegDefs->end())
+ && (scomBaseRegDefItr->addr==scomRegDefItr->baseAddr),
+ "BUG! Could not find base register 0x%016llX for register "
+ "0x%016llX.",scomRegDefItr->baseAddr,scomRegDefItr->addr);
+ scomRegDefItr->baseIndex=scomBaseRegDefItr-iv_pScomRegDefs->begin();
+ }
+ else
+ {
+ scomRegDefItr->baseIndex=scomRegDefItr-iv_pScomRegDefs->begin();
+ }
+ }
+}
+
+void ScomCache::init() const
+{
+ destroy();
+
+ std::vector<uint64_t> registerCache(iv_pScomRegDefs->size(),0);
+ auto registerCacheItr = registerCache.begin();
+ for (const auto& scomRegDef : *iv_pScomRegDefs)
+ {
+ if(!scomRegDef.hasBaseAddr())
+ {
+ (*registerCacheItr) = scomRegDef.expectedHwInitValue;
+ }
+ ++registerCacheItr;
+ }
+
+ // Find functional Centaurs
+ TARGETING::TargetHandleList centaurTargets;
+ (void)getAllChips(centaurTargets, TARGETING::TYPE_MEMBUF);
+
+ for(auto& pCentaur : centaurTargets)
+ {
+ if( pCentaur->getAttr<TARGETING::ATTR_MODEL>()
+ != TARGETING::MODEL_CENTAUR)
+ {
+ continue;
+ }
+
+ const std::vector<uint64_t>* pCache
+ =_getCachePtr(pCentaur);
+ assert(pCache==nullptr,"BUG! Centaur cache detected prior to init");
+
+ // Clone the initialized cache into each Centaur target and transfer
+ // memory ownership
+ pCache = new std::vector<uint64_t>(registerCache);
+ _setCachePtr(pCentaur,pCache);
+ pCache=nullptr;
+ }
+}
+
+void ScomCache::destroy() const
+{
+ // Grab all blueprint Centaurs in case a Centaur got deconfigured after
+ // Hostboot configured its cache
+ TARGETING::TargetHandleList centaurTargets;
+ (void)getAllChips(centaurTargets, TARGETING::TYPE_MEMBUF, false);
+
+ for(auto& pCentaur : centaurTargets)
+ {
+ if( pCentaur->getAttr<TARGETING::ATTR_MODEL>()
+ != TARGETING::MODEL_CENTAUR)
+ {
+ continue;
+ }
+
+ std::vector<uint64_t>* pCache = _getCachePtr(pCentaur);
+ if(pCache)
+ {
+ delete pCache;
+ pCache = nullptr;
+ _setCachePtr(pCentaur,pCache);
+ }
+ }
+}
+
+errlHndl_t ScomCache::write(
+ TARGETING::Target* const i_pMembuf,
+ const uint64_t i_addr,
+ const uint64_t i_value) const
+{
+ TRACDCOMP(g_trac_scom,INFO_MRK
+ "ScomCache::write: register 0x%016llX, value 0x%016llX, HUID 0x%08X",
+ i_addr,i_value,TARGETING::get_huid(i_pMembuf));
+
+ errlHndl_t pError=nullptr;
+
+ do {
+
+ if(i_pMembuf==nullptr)
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "BUG! API usage error! Caller passed a nullptr target");
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_WRITE_CENTAUR_CACHE
+ * @reasoncode SCOM::SCOM_BAD_TARGET
+ * @devdesc Caller passed a nullptr target when attempting to
+ * write the SCOM cache
+ * @custdesc Secure Boot failure
+ */
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM::SCOM_WRITE_CENTAUR_CACHE,
+ SCOM::SCOM_BAD_TARGET,
+ 0,
+ 0,
+ ADD_HI_PRI_HB_SW_CALLOUT);
+
+ break;
+ }
+
+ if( cacheEnabled()
+ && ( i_pMembuf->getAttr<TARGETING::ATTR_MODEL>()
+ == TARGETING::MODEL_CENTAUR) )
+ {
+ // This is logically still the input
+ TARGETING::Target* const i_pCentaur = i_pMembuf;
+
+ std::vector<uint64_t>* const pCache = _getCachePtr(i_pCentaur);
+ if(pCache==nullptr)
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "BUG! Sequence error! Cache for Centaur with HUID "
+ "0x%08X is not properly initialized",
+ TARGETING::get_huid(i_pCentaur));
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_WRITE_CENTAUR_CACHE
+ * @reasoncode SCOM::SCOM_CACHE_SEQ_ERROR
+ * @userdata1 HUID of Centaur whose cache was not initialized
+ * @devdesc Caller attempted to write a Centaur cache that
+ * is not initialized.
+ * @custdesc Secure Boot failure
+ */
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM::SCOM_WRITE_CENTAUR_CACHE,
+ SCOM::SCOM_CACHE_SEQ_ERROR,
+ TARGETING::get_huid(i_pCentaur),
+ 0,
+ ADD_HI_PRI_HB_SW_CALLOUT);
+
+ break;
+ }
+
+ ssize_t index=ScomRegDef::DEFAULT_BASE_INDEX;
+ ScomRegDef regToFind(i_addr);
+ auto scomRegDefItr=std::lower_bound(
+ iv_pScomRegDefs->begin(),
+ iv_pScomRegDefs->end(),
+ regToFind,
+ [](const ScomRegDef& i_lhs, const ScomRegDef& i_rhs)
+ {
+ return (i_lhs.addr<i_rhs.addr);
+ } );
+ if( (scomRegDefItr!=iv_pScomRegDefs->end())
+ && (scomRegDefItr->addr==i_addr))
+ {
+ index=scomRegDefItr->baseIndex;
+
+ if(scomRegDefItr->isWandReg)
+ {
+ (*pCache)[index] &= i_value;
+ }
+ else if(scomRegDefItr->isWorReg)
+ {
+ (*pCache)[index] |= i_value;
+ }
+ else
+ {
+ (*pCache)[index] = i_value;
+ }
+ }
+ // else ...
+ // Not a cacheable register = noop
+ }
+
+ } while(0);
+
+ if(pError)
+ {
+ // Collect interesting traces
+ pError->collectTrace(SCOM_COMP_NAME);
+ pError->collectTrace(SECURE_COMP_NAME);
+ }
+
+ return pError;
+}
+
+errlHndl_t ScomCache::read(
+ TARGETING::Target* i_pMembuf,
+ const uint64_t i_addr,
+ bool& o_cacheHit,
+ uint64_t& o_value) const
+{
+ TRACDCOMP(g_trac_scom,INFO_MRK
+ "ScomCache::read: register 0x%016llX, HUID 0x%08X",
+ i_addr,TARGETING::get_huid(i_pMembuf));
+
+ errlHndl_t pError=nullptr;
+ auto cacheHit = false;
+
+ do {
+
+ if(i_pMembuf==nullptr)
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "BUG! API usage error! Caller passed a nullptr target");
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_READ_CENTAUR_CACHE
+ * @reasoncode SCOM::SCOM_BAD_TARGET
+ * @devdesc Caller passed a nullptr target when attempting to
+ * read the SCOM cache
+ * @custdesc Secure Boot failure
+ */
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM::SCOM_READ_CENTAUR_CACHE,
+ SCOM::SCOM_BAD_TARGET,
+ 0,
+ 0,
+ ADD_HI_PRI_HB_SW_CALLOUT);
+
+ break;
+ }
+
+ if( cacheEnabled()
+ && ( i_pMembuf->getAttr<TARGETING::ATTR_MODEL>()
+ == TARGETING::MODEL_CENTAUR) )
+ {
+ // This is logically still the input
+ TARGETING::Target* const i_pCentaur = i_pMembuf;
+
+ std::vector<uint64_t>* const pCache = _getCachePtr(i_pCentaur);
+ if(pCache==nullptr)
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "BUG! Sequence error! Cache for Centaur with HUID "
+ "0x%08X is not properly initialized",
+ TARGETING::get_huid(i_pCentaur));
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_READ_CENTAUR_CACHE
+ * @reasoncode SCOM::SCOM_CACHE_SEQ_ERROR
+ * @userdata1 HUID of Centaur whose cache was not initialized
+ * @devdesc Caller attempted to read a Centaur cache that
+ * is not initialized.
+ * @custdesc Secure Boot failure
+ */
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM::SCOM_READ_CENTAUR_CACHE,
+ SCOM::SCOM_CACHE_SEQ_ERROR,
+ TARGETING::get_huid(i_pCentaur),
+ 0,
+ ADD_HI_PRI_HB_SW_CALLOUT);
+
+ break;
+ }
+
+ ScomRegDef regToFind(i_addr);
+ auto scomRegDefItr=std::lower_bound(
+ iv_pScomRegDefs->begin(),
+ iv_pScomRegDefs->end(),
+ regToFind,
+ [](const ScomRegDef& i_lhs, const ScomRegDef& i_rhs)
+ {
+ return (i_lhs.addr<i_rhs.addr);
+ } );
+ if( (scomRegDefItr!=iv_pScomRegDefs->end())
+ && (scomRegDefItr->addr==i_addr) )
+ {
+ if(!scomRegDefItr->hasBaseAddr())
+ {
+ o_value = (*pCache)[scomRegDefItr->baseIndex];
+ cacheHit = true;
+ }
+ // else ...
+ // Attempt to read WAND/WOR register is not allowed;
+ // Force a cache miss and let SCOM code handle
+ // getting an error on the HW read
+ }
+ // else ...
+ // No cache entry for this address
+ }
+ // else ...
+ // Cache not applicable
+
+ } while(0);
+
+ o_cacheHit=cacheHit;
+ if(!o_cacheHit)
+ {
+ o_value=0;
+ }
+
+ if(pError)
+ {
+ // Collect interesting traces
+ pError->collectTrace(SCOM_COMP_NAME);
+ pError->collectTrace(SECURE_COMP_NAME);
+ }
+
+ return pError;
+}
+
+errlHndl_t ScomCache::verify() const
+{
+ errlHndl_t pError=nullptr;
+
+ do {
+
+ if(cacheEnabled())
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "BUG! Sequence error! Cannot verify cache when it's enabled");
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_VERIFY_CENTAUR_CACHE
+ * @reasoncode SCOM::SCOM_BAD_CACHE_VERIFY_SEQ
+ * @devdesc Centaurs' SCOM cache cannot be verified when caching
+ * is enabled
+ * @custdesc Secure Boot failure
+ */
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM::SCOM_VERIFY_CENTAUR_CACHE,
+ SCOM::SCOM_BAD_CACHE_VERIFY_SEQ,
+ 0,
+ 0,
+ ADD_HI_PRI_HB_SW_CALLOUT);
+
+ break;
+ }
+
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ "Verifying Centaur SCOM caches against hardware");
+
+ TARGETING::TargetHandleList centaurTargets;
+ (void)getAllChips(centaurTargets, TARGETING::TYPE_MEMBUF);
+
+ for(auto& pCentaur : centaurTargets)
+ {
+ if( pCentaur->getAttr<TARGETING::ATTR_MODEL>()
+ != TARGETING::MODEL_CENTAUR)
+ {
+ continue;
+ }
+
+ std::vector<uint64_t>* const pCache = _getCachePtr(pCentaur);
+ if(pCache==nullptr)
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "BUG! Sequence error! Cache for Centaur with HUID "
+ "0x%08X is not properly initialized",
+ TARGETING::get_huid(pCentaur));
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_VERIFY_CENTAUR_CACHE
+ * @reasoncode SCOM::SCOM_CACHE_SEQ_ERROR
+ * @userdata1 HUID of Centaur whose cache was not initialized
+ * @devdesc Caller attempted to read a Centaur cache that
+ * is not initialized.
+ * @custdesc Secure Boot failure
+ */
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM::SCOM_VERIFY_CENTAUR_CACHE,
+ SCOM::SCOM_CACHE_SEQ_ERROR,
+ TARGETING::get_huid(pCentaur),
+ 0,
+ ADD_HI_PRI_HB_SW_CALLOUT);
+
+ break;
+ }
+
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ "Verifying Centaur SCOM cache for HUID=0x%08X",
+ TARGETING::get_huid(pCentaur));
+
+ size_t index=0;
+ for(const auto& scomRegDef : *iv_pScomRegDefs)
+ {
+ if(!scomRegDef.hasBaseAddr())
+ {
+ uint64_t actualValue = 0;
+ const size_t expSize = sizeof(actualValue);
+ auto reqSize = expSize;
+ pError = deviceRead(pCentaur,
+ &actualValue,
+ reqSize,
+ DEVICE_SCOM_ADDRESS(
+ scomRegDef.addr));
+ if(pError)
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "ScomCache::verify: SCOM deviceRead call failed for "
+ "Target HUID 0x%08X and address 0x%016llX. "
+ TRACE_ERR_FMT,
+ TARGETING::get_huid(pCentaur),
+ scomRegDef.addr,
+ TRACE_ERR_ARGS(pError));
+
+ // save the PLID from the error before committing
+ const auto plid = pError->plid();
+ ERRORLOG::errlCommit(pError, SCOM_COMP_ID);
+
+ /*@
+ * @errortype
+ * @reasoncode SCOM::SCOM_SENSITIVE_REG_READ_FAIL
+ * @moduleid SCOM::SCOM_VERIFY_CENTAUR_CACHE
+ * @userdata1 HUID of offending Centaur
+ * @userdata2 SCOM address
+ * @devdesc Failed attempting to read current value of
+ * sensitive Centaur SCOM register after locking down
+ * the Centaur. The Centaur will be deconfigured in
+ * order to maintain system security.
+ * @custdesc Secure Boot failure
+ */
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM::SCOM_VERIFY_CENTAUR_CACHE,
+ SCOM::SCOM_SENSITIVE_REG_READ_FAIL,
+ TARGETING::get_huid(pCentaur),
+ scomRegDef.addr,
+ NO_HB_SW_CALLOUT);
+
+ // Link to the original PLID
+ pError->plid(plid);
+
+ // Most likely a hardware problem
+ pError->addHwCallout(
+ pCentaur,
+ HWAS::SRCI_PRIORITY_HIGH,
+ HWAS::DELAYED_DECONFIG,
+ HWAS::GARD_NULL);
+
+ // Next most likely a software issue
+ pError->addProcedureCallout(
+ HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_MED);
+
+ break;
+ }
+ else
+ {
+ assert(reqSize==expSize,"ScomCache::verify: SCOM "
+ "deviceRead didn't return expected data size "
+ "of %d (it was %d)",
+ expSize,reqSize);
+ const auto expectedValue = (*pCache)[index];
+ if( (expectedValue & scomRegDef.mask)
+ != (actualValue & scomRegDef.mask) )
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "For Centaur with HUID of 0x%08X, found "
+ "discrepancy between expected and actual "
+ "security sensitive SCOM register values.",
+ TARGETING::get_huid(pCentaur));
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ " Register: 0x%016llX, "
+ "Expected value (masked): 0x%016llX, "
+ "Actual value (masked): 0x%016llX, ",
+ scomRegDef.addr,
+ expectedValue & scomRegDef.mask,
+ actualValue & scomRegDef.mask);
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ " Unmasked cache value: 0x%016llX, "
+ "Unmasked register value: 0x%016llX, "
+ "Mask: 0x%016llX.",
+ expectedValue,
+ actualValue,
+ scomRegDef.mask);
+
+ /*@
+ * @errortype
+ * @reasoncode SCOM::SCOM_CACHE_VERIFY_FAILURE
+ * @moduleid SCOM::SCOM_VERIFY_CENTAUR_CACHE
+ * @userdata1 HUID of Centaur being verified
+ * @userdata2 SCOM address registering the mismatch
+ * @devdesc Secure Boot detected an unexpected
+ * discrepancy between the expected and actual
+ * values of a security sensitive Centaur SCOM
+ * register after locking down the Centaur. The
+ * Centaur will be deconfigured in order to
+ * maintain system security.
+ * @custdesc Secure Boot failure
+ */
+
+ // Most likely a software bug
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM::SCOM_VERIFY_CENTAUR_CACHE,
+ SCOM::SCOM_CACHE_VERIFY_FAILURE,
+ TARGETING::get_huid(pCentaur),
+ scomRegDef.addr,
+ ADD_HI_PRI_HB_SW_CALLOUT);
+
+ UdCentaurCacheMismatch ffdc(
+ scomRegDef.addr,
+ expectedValue,
+ actualValue,
+ scomRegDef.mask);
+ ffdc.addToLog(pError);
+
+ // Next most likely a hardware issue
+ pError->addHwCallout(
+ pCentaur,
+ HWAS::SRCI_PRIORITY_MED,
+ HWAS::DELAYED_DECONFIG,
+ HWAS::GARD_NULL);
+
+ break;
+ }
+ }
+ }
+ // else ...
+ // Not a meaningful register to cache verify, no-op it
+
+ ++index;
+ }
+
+ if(pError)
+ {
+ // Log the target information
+ ERRORLOG::ErrlUserDetailsTarget(pCentaur).
+ addToLog(pError);
+
+ // Collect interesting traces
+ pError->collectTrace(SCOM_COMP_NAME);
+ pError->collectTrace(SECURE_COMP_NAME);
+
+ // Commit it
+ ERRORLOG::errlCommit(pError,SCOM_COMP_ID);
+ }
+ }
+
+ } while(0);
+
+ if(pError)
+ {
+ // Collect interesting traces
+ pError->collectTrace(SCOM_COMP_NAME);
+ pError->collectTrace(SECURE_COMP_NAME);
+ }
+
+ return pError;
+}
+
+void ScomCache::dump(void) const
+{
+ errlHndl_t pError=nullptr;
+
+ do {
+
+ if(cacheEnabled())
+ {
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ "**WARNING** Centaur SCOM cache dump HW reads being pulled "
+ "from cache instead of actual hardware");
+ }
+
+ TARGETING::TargetHandleList centaurTargets;
+ (void)getAllChips(centaurTargets, TARGETING::TYPE_MEMBUF);
+
+ for(auto& pCentaur : centaurTargets)
+ {
+ if( pCentaur->getAttr<TARGETING::ATTR_MODEL>()
+ != TARGETING::MODEL_CENTAUR)
+ {
+ continue;
+ }
+
+ std::vector<uint64_t>* const pCache = _getCachePtr(pCentaur);
+ if(pCache)
+ {
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ "Dumping Centaur cache for: HUID=0x%08X",
+ TARGETING::get_huid(pCentaur));
+
+ size_t index=0;
+ for(const auto& scomRegDef : *iv_pScomRegDefs)
+ {
+ if(!scomRegDef.hasBaseAddr())
+ {
+ uint64_t actualValue = 0;
+ const size_t expSize = sizeof(actualValue);
+ auto reqSize = expSize;
+ pError = deviceRead(pCentaur,
+ &actualValue,
+ reqSize,
+ DEVICE_SCOM_ADDRESS(
+ scomRegDef.addr));
+ if(pError)
+ {
+ TRACFCOMP(g_trac_scom,ERR_MRK
+ "ScomCache::dump: SCOM deviceRead call failed for "
+ "Target HUID 0x%08X and address 0x%016llX. "
+ TRACE_ERR_FMT "Ignoring and continuing on.",
+ TARGETING::get_huid(pCentaur),
+ scomRegDef.addr,
+ TRACE_ERR_ARGS(pError));
+
+ pError->collectTrace(SCOM_COMP_NAME);
+ pError->collectTrace(SECURE_COMP_NAME);
+
+ errlCommit(pError,SCOM_COMP_ID);
+ }
+ else
+ {
+ assert(reqSize==expSize,"ScomCache::verify: SCOM "
+ "deviceRead didn't return expected data size "
+ "of %d (it was %d)",
+ expSize,reqSize);
+ const auto expectedValue = (*pCache)[index];
+ const auto expectedValueMasked =
+ expectedValue & scomRegDef.mask;
+ const auto actualValueMasked =
+ actualValue & scomRegDef.mask;
+
+ // Split trace for readability
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ "Register: 0x%016llX, "
+ "Expected value (masked): 0x%016llX, "
+ "Actual value (masked): 0x%016llX%s, ",
+ scomRegDef.addr,
+ expectedValueMasked,
+ actualValueMasked,
+ ( expectedValueMasked
+ == actualValueMasked) ? "" : " (MISMATCH!)");
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ " Unmasked cache value: 0x%016llX, "
+ "Unmasked register value: 0x%016llX, "
+ "Mask: 0x%016llX.",
+ expectedValue,
+ actualValue,
+ scomRegDef.mask);
+ }
+ }
+ // else ...
+ // Not a meaningful register to dump
+
+ ++index;
+ }
+ }
+ else // No cache entry for this Centaur
+ {
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ "Warning: No cache for Centaur with HUID of 0x%08X.",
+ TARGETING::get_huid(pCentaur));
+ }
+ }
+
+ } while(0);
+}
+
+bool ScomCache::cacheEnabled() const
+{
+ return iv_cacheEnabled;
+}
+
+void ScomCache::enableCache()
+{
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ "Enabling Centaur SCOM cache");
+ iv_cacheEnabled=true;
+}
+
+void ScomCache::disableCache()
+{
+ TRACFCOMP(g_trac_scom,INFO_MRK
+ "Disabling Centaur SCOM cache");
+ iv_cacheEnabled=false;
+}
+
+ScomCache& ScomCache::getInstance()
+{
+ return Singleton<ScomCache>::instance();
+}
+
+} // end CENTAUR_SECURITY namespace
+
+} // end SECUREBOOT namespace
+
diff --git a/src/usr/scom/errlud_cache.C b/src/usr/scom/errlud_cache.C
new file mode 100644
index 000000000..014b77846
--- /dev/null
+++ b/src/usr/scom/errlud_cache.C
@@ -0,0 +1,81 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/scom/errlud_cache.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2018 */
+/* [+] 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 */
+
+/**
+ * @file errlud_cache.C
+ *
+ * @brief Implementation of classes to log Centaur SCOM register cache
+ * mismatch FFDC
+ */
+
+#include <scom/scomreasoncodes.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <util/utilmem.H>
+#include "errlud_cache.H"
+
+SECUREBOOT::CENTAUR_SECURITY::UdCentaurCacheMismatch::UdCentaurCacheMismatch(
+ const uint64_t i_registerAddr,
+ const uint64_t i_unmaskedExpectedValue,
+ const uint64_t i_unmaskedActualValue,
+ const uint64_t i_mask)
+{
+ // Set up Ud instance variables
+ iv_CompId = SCOM_COMP_ID;
+ iv_Version = SCOM::SCOM_UDT_VERSION_1;
+ iv_SubSection = SCOM::SCOM_UDT_CENTAUR_CACHE_MISMATCH;
+
+ const auto maskedExpectedValue=i_unmaskedExpectedValue&i_mask;
+ const auto maskedActualValue =i_unmaskedActualValue&i_mask;
+
+ //***** Version SCOM_UDT_VERSION_1 Memory Layout *****
+ // 8 bytes : Centaur SCOM address with the cache miscompare
+ // 8 bytes : Expected value from cache (unmasked)
+ // 8 bytes : Actual value read from hardware (unmasked)
+ // 8 bytes : Mask of bits to compare for the two values
+ // 8 bytes : Expected value from cache (masked)
+ // 8 bytes : Actual value read from hardware (masked)
+
+ UtilMem memBuf;
+ memBuf << i_registerAddr
+ << i_unmaskedExpectedValue
+ << i_unmaskedActualValue
+ << i_mask
+ << maskedExpectedValue
+ << maskedActualValue;
+
+ auto pError = memBuf.getLastError();
+ if(pError)
+ {
+ errlCommit(pError,SCOM_COMP_ID);
+ }
+ else
+ {
+ uint8_t* const pBuf =
+ reallocUsrBuf(memBuf.size());
+ memcpy(pBuf, memBuf.base(), memBuf.size());
+ }
+}
+
diff --git a/src/usr/scom/errlud_cache.H b/src/usr/scom/errlud_cache.H
new file mode 100644
index 000000000..b7c2c7bf0
--- /dev/null
+++ b/src/usr/scom/errlud_cache.H
@@ -0,0 +1,98 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/scom/errlud_cache.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,2018 */
+/* [+] 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 */
+
+#ifndef ERRLUD_CACHE_H
+#define ERRLUD_CACHE_H
+
+/**
+ * @file errlud_cache.H
+ *
+ * Defines the classes that log Centaur SCOM register cache failures
+ */
+
+#include <errl/errluserdetails.H>
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+/**
+ * @class UdCentaurCacheMismatch
+ *
+ * @brief Adds Centaur SCOM register cache mismatch FFDC to an error
+ * log
+ */
+class UdCentaurCacheMismatch : public ERRORLOG::ErrlUserDetails
+{
+ public:
+
+ /**
+ * @brief Constructor
+ * @param[in] i_registerAddr Register that registered a cache mismatch
+ * @param[in] i_unmaskedExpectedValue Value read from the cache
+ * @param[in] i_unmaskedActualValue Value read from the hardware
+ * @param[in] i_mask Mask of bits to compare between the two values
+ */
+ UdCentaurCacheMismatch(
+ uint64_t i_registerAddr,
+ uint64_t i_unmaskedExpectedValue,
+ uint64_t i_unmaskedActualValue,
+ uint64_t i_mask);
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~UdCentaurCacheMismatch()
+ {
+ }
+
+ /**
+ * Delete Copy Constructor
+ */
+ UdCentaurCacheMismatch(const UdCentaurCacheMismatch&) = delete;
+
+ /**
+ * Delete Copy Assignment
+ */
+ UdCentaurCacheMismatch& operator= (const UdCentaurCacheMismatch&) = delete;
+
+ /**
+ * Delete Move Constructor
+ */
+ UdCentaurCacheMismatch (UdCentaurCacheMismatch&&) = delete;
+
+ /**
+ * Delete Move Assignment
+ */
+ UdCentaurCacheMismatch& operator = (UdCentaurCacheMismatch&&) = delete;
+};
+
+} // End CENTAUR_SECURITY namespace
+
+} // End SECUREBOOT namespace
+
+#endif
diff --git a/src/usr/scom/genCentaurScomCacheRegDefs.pl b/src/usr/scom/genCentaurScomCacheRegDefs.pl
new file mode 100755
index 000000000..8e8574d42
--- /dev/null
+++ b/src/usr/scom/genCentaurScomCacheRegDefs.pl
@@ -0,0 +1,399 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/scom/genCentaurScomCacheRegDefs.pl $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2012,2018
+# [+] 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
+
+use strict;
+
+################################################################################
+# Imported packages
+################################################################################
+
+use Carp;
+use Getopt::Long;
+use Pod::Usage;
+
+################################################################################
+# Initialize some globals
+################################################################################
+
+use constant OUT_FILE_BASE=>"centaurScomCacheRegDefs";
+use constant OUT_C_FILE=>OUT_FILE_BASE.".C";
+
+################################################################################
+# Process command line parameters, issue help text if needed.
+################################################################################
+
+my $cfgCsvFile ="Centaur_Register_List.csv";
+my $cfgOutputDir = ".";
+my $cfgHelp=0;
+my $cfgMan=0;
+my $cfgVerbose=0;
+
+GetOptions("csv:s" => \$cfgCsvFile,
+ "output-dir:s" => \$cfgOutputDir,
+ "help" => \$cfgHelp,
+ "man" => \$cfgMan,
+ "verbose" => \$cfgVerbose ) || pod2usage(-verbose => 0);
+
+pod2usage(-verbose => 1) if $cfgHelp;
+pod2usage(-verbose => 2) if $cfgMan;
+
+# Remove extraneous '/' from end of path names; use temporary version of $/ for
+# the chomp
+{
+ local $/ = '/';
+ chomp($cfgOutputDir);
+ $cfgOutputDir .= "/";
+}
+
+if($cfgVerbose)
+{
+ print STDOUT "CSV file = $cfgCsvFile\n";
+ print STDOUT "Output dir = $cfgOutputDir\n";
+ print STDOUT "Output file name = " . OUT_C_FILE . "\n";
+}
+
+################################################################################
+# Main logic
+################################################################################
+
+open(CSV_FILE,"<$cfgCsvFile")
+ or croak("Failed to open CSV file of $cfgCsvFile.");
+my $csvFile = *CSV_FILE;
+
+my $outSrcFile="$cfgOutputDir".OUT_C_FILE;
+open(OUT_SRC_FILE,">$outSrcFile")
+ or croak("Failed to open output source file of "
+ . "$outSrcFile");
+my $sourceFile = *OUT_SRC_FILE;
+
+writeScomRegDefSourceHeader($sourceFile);
+writeScomRegDefSourceContent($csvFile,$sourceFile);
+writeScomRegDefSourceFooter($sourceFile);
+
+close CSV_FILE or croak("Failed to close CSV file of $cfgCsvFile");
+
+close OUT_SRC_FILE or
+ croak("Failed to close output source file of $outSrcFile");
+
+################################################################################
+# @brief: Strips off leading and trailing whitespace from an input line
+# and returns it
+# @param[in] $line Line of input file
+# @return Line without leading and trailing whitespace
+################################################################################
+
+sub stripLeadingAndTrailingWhitespace {
+ my($line) = @_;
+
+ $line =~ s/^\s+|\s+$//g;
+
+ return $line;
+}
+
+################################################################################
+# @brief: Verifies an input line ends with a comma
+# @param[in] $line Line of input file
+################################################################################
+
+sub verifyEndsWithComma
+{
+ my $line = shift;
+
+ if ($line !~ m/,$/)
+ {
+ croak "BUG! CSV file doesn't end with comma\n\t$line";
+ }
+}
+
+################################################################################
+# @brief: Verifies an input line has no starting comma
+# @param[in] $line Line of input file
+################################################################################
+
+sub verifyNoStartingComma
+{
+ my $line = shift;
+
+ if ($line =~ m/^,/)
+ {
+ croak "BUG! CSV file should not start with comma\n\t$line";
+ }
+}
+
+################################################################################
+# @brief: Returns whether number is a hex number without leading 0x
+# @param[in] $number Number to verify
+# @retval 0 if not a 0x-less hex number
+# @retval 1 if a 0x-less hex number
+################################################################################
+
+sub isValidNumber
+{
+ my $number=shift;
+ my $valid=0;
+
+ my $maxLength = 16;
+
+ if ($number =~ m/^[0-9a-fA-F]{1,$maxLength}$/)
+ {
+ $valid=1;
+ }
+
+ return $valid;
+}
+
+################################################################################
+# @brief: Scrubs required register address and returns a sanitized copy
+# @param[in] $addr The register address
+# @param[in] $line Line of the input file to display on error conditions
+# @return A normalized register address
+################################################################################
+
+sub normalizeRequiredAddr
+{
+ my $addr=shift;
+ my $line=shift;
+
+ if(!defined $addr
+ || $addr eq "")
+ {
+ croak "BUG! CSV file record had undefined register "
+ . "address [$addr]\n\t$line";
+ }
+
+ if(!isValidNumber($addr))
+ {
+ croak "BUG! CSV file record has invalid address [$addr]\n\t$line";
+ }
+
+ $addr="0x".$addr."ULL";
+ return $addr;
+}
+
+################################################################################
+# @brief: Scrubs optional input value and returns a sanitized copy
+# @param[in] $value The property value read from the input file
+# @param[in] $default The default value to use if file did not specify
+# @param[in] $name Name of the property to display on error conditions
+# @param[in] $line Line of the input file to display on error conditions
+# @return A normalized value
+################################################################################
+
+sub normalizeOptionalValue
+{
+ my $value=shift;
+ my $default=shift;
+ my $name=shift;
+ my $line=shift;
+
+ if(!defined $value
+ || $value eq "")
+ {
+ $value=$default;
+ }
+
+ if(!isValidNumber($value))
+ {
+ croak "BUG! CSV file record has invalid optional $name "
+ . "value [$value]\n"
+ . "\tOffending line: $line";
+ }
+
+ $value="0x".$value."ULL";
+ return $value;
+}
+
+################################################################################
+# @brief: Writes the leading mostly non-dynamic content for the output source
+# file
+# @param[in] $outFile Name of the output source file (no path components)
+################################################################################
+
+sub writeScomRegDefSourceHeader {
+ my($outFile) = @_;
+
+print $outFile <<VERBATIM;
+
+/**
+VERBATIM
+print $outFile " * \@file ".OUT_C_FILE."\n";
+print $outFile <<VERBATIM;
+ *
+ * \@brief Automatically generated source code to initialize the Centaur
+ * SCOM cache register definition vector
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+#include <scom/centaurScomCache.H>
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+ScomRegDefs* ScomCache::_initScomRegDefs() const
+{
+ ScomRegDefs* pScomRegDefs = new ScomRegDefs{
+VERBATIM
+}
+
+################################################################################
+# @brief: Writes the dynamic register definition content to the output file
+#
+# @param[in] $csvFile Input CSV file's handle to read from
+# @param[in] $outFile Output file's handle to write to
+################################################################################
+
+sub writeScomRegDefSourceContent {
+ my($csvFile,$outFile) = @_;
+
+ while( <$csvFile> )
+ {
+ my $line=stripLeadingAndTrailingWhitespace($_);
+
+ #Ignore comments
+ if ($line =~ m/^#/)
+ {
+ next;
+ }
+
+ verifyEndsWithComma($line);
+
+ verifyNoStartingComma($line);
+
+ my ($addr,$wandAddr,$worAddr,$init,$mask) = split(/,/,$line);
+
+ $addr = normalizeRequiredAddr($addr,$line);
+
+ $wandAddr = normalizeOptionalValue($wandAddr,"0","wand address",$line);
+
+ $worAddr = normalizeOptionalValue($worAddr,"0","wor address",$line);
+
+ $init = normalizeOptionalValue($init,"0","init",$line);
+
+ my $defaultMask = "FFFFFFFFFFFFFFFF";
+
+ $mask = normalizeOptionalValue(
+ $mask,$defaultMask,"mask",$line);
+
+ # Output columns are:
+ # Address,WAND?,WOR?,base address,base index,init,mask
+
+ if($wandAddr ne "0x0ULL")
+ {
+ print $outFile " "
+ . "{$wandAddr,0b1,0b0,$addr,-1,0x0ULL,0x0ULL},\n";
+
+ }
+
+ if($worAddr ne "0x0ULL")
+ {
+ print $outFile " "
+ . "{$worAddr,0b0,0b1,$addr,-1,0x0ULL,0x0ULL},\n";
+
+ }
+
+ print $outFile " "
+ . "{$addr,0b0,0b0,0x0ULL,-1,$init,$mask},\n";
+ }
+}
+
+################################################################################
+# @brief: Writes the trailing non-dynamic content to the output source
+# file
+# @param[in] $outFile Output file handle to write to
+################################################################################
+
+sub writeScomRegDefSourceFooter {
+ my($outFile) = @_;
+
+print $outFile <<VERBATIM;
+ };
+
+ return pScomRegDefs;
+}
+
+} // End CENTAUR_SECURITY namespace
+
+} // End SECUREBOOT namespace
+
+
+VERBATIM
+}
+
+################################################################################
+# Man page
+################################################################################
+
+1;
+
+__END__
+
+=head1 NAME
+
+genCentaurScomCacheRegDefs.pl
+
+=head1 SYNOPSIS
+
+genCentaurScomCacheRegDefs.pl --csv=FILE --output-dir=DIR
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--csv>
+
+Absolute path and file name of CSV file containing register definitions
+
+=item B<--output-dir>
+
+Output dir to write the generated source file
+
+=item B<--verbose>
+
+Prints out some internal workings
+
+=item B<--help>
+
+Print a brief help message and exits
+
+=item B<--man>
+
+Prints the manual page and exits
+
+=back
+
+=head1 DESCRIPTION
+
+B<getCentaurScomCacheRegDefs.pl> will generate a source file, which should be
+compiled into Hostboot, that seeds the Secure Boot Centaur SCOM cache sensitive
+register definitions
+
+=cut
diff --git a/src/usr/scom/makefile b/src/usr/scom/makefile
index 8ca16f829..461ad44e6 100644
--- a/src/usr/scom/makefile
+++ b/src/usr/scom/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2011,2017
+# Contributors Listed Below - COPYRIGHT 2011,2018
# [+] International Business Machines Corp.
#
#
@@ -28,8 +28,38 @@ MODULE = scom
#include common ojects between hostboot and runtime hostboot
include scom.mk
-#include unique object modules - currently none
-# OBJS +=
+# Configure virtual paths
+GENDIR = ${ROOTPATH}/obj/genfiles
+VPATH += ${ROOTPATH}/src/import/chips/p9/security/
+VPATH += ${GENDIR}
+
+# Defines for targets/prereqs
+CENTAUR_SCOM_REG_DEF_SCRIPT=genCentaurScomCacheRegDefs.pl
+CENTAUR_SCOM_REG_DEF_BASE=centaurScomCacheRegDefs
+CENTAUR_SCOM_REG_DEF_OBJ=${CENTAUR_SCOM_REG_DEF_BASE}.o
+CENTAUR_SCOM_REG_DEF_SRC=${CENTAUR_SCOM_REG_DEF_BASE}.C
+CENTAUR_SCOM_REG_DEF_CSV=Centaur_Register_List.csv
+
+#include unique object modules
+OBJS += $(if $(CONFIG_SECUREBOOT),centaurScomCache.o,)
+OBJS += $(if $(CONFIG_SECUREBOOT),${CENTAUR_SCOM_REG_DEF_OBJ},)
+OBJS += $(if $(CONFIG_SECUREBOOT),errlud_cache.o,)
+
+# Build rules
+all: GENPASS
+
+GENPASS: ${GENDIR}/${CENTAUR_SCOM_REG_DEF_SRC}
+
+# Bring the Centaur SCOM cache register definition initialization source file
+# up to date by executing the generation script (first dependency), passing
+# it the input .csv file (second dependency) and passing it the output dir
+# (the directory part of the rule target .. namely obj/genfiles)
+${GENDIR}/${CENTAUR_SCOM_REG_DEF_SRC}: \
+ ${CENTAUR_SCOM_REG_DEF_SCRIPT} \
+ ${CENTAUR_SCOM_REG_DEF_CSV}
+ ./$< \
+ --csv=$(word 2,$^) \
+ --output-dir=$(@D)
SUBDIRS += test.d
SUBDIRS += runtime.d
diff --git a/src/usr/scom/plugins/errludP_cache.H b/src/usr/scom/plugins/errludP_cache.H
new file mode 100644
index 000000000..15f5ce747
--- /dev/null
+++ b/src/usr/scom/plugins/errludP_cache.H
@@ -0,0 +1,135 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/scom/plugins/errludP_cache.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* [+] 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 */
+
+#ifndef ERRLUDP_CACHE_H
+#define ERRLUDP_CACHE_H
+
+/**
+* @file errludP_cache.H
+*
+* Defines the ErrlUserDetailsParser classes that parse Centaur SCOM register
+* cache mismatch FFDC
+*/
+
+#include "errluserdetails.H"
+
+namespace SECUREBOOT
+{
+
+namespace CENTAUR_SECURITY
+{
+
+ /**
+ * @class UdParserCentaurCacheMismatch
+ *
+ * @brief Parses UdParserCentaurCacheMismatch user details sections
+ */
+ class UdParserCentaurCacheMismatch : public ERRORLOG::ErrlUserDetailsParser
+ {
+
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ UdParserCentaurCacheMismatch()
+ {
+ }
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~UdParserCentaurCacheMismatch()
+ {
+ }
+
+ /**
+ * @brief Parses user detail data from an error log
+ *
+ * @param[in] i_version Version of the data
+ * @param[in] i_parse ErrlUsrParser object for outputting information
+ * @param[in] i_pBuffer Pointer to buffer containing detail data
+ * @param[in] i_buflen Length of the buffer
+ */
+ virtual void parse(
+ errlver_t i_version,
+ ErrlUsrParser& i_parser,
+ void * i_pBuffer,
+ const uint32_t i_buflen) const
+ {
+ if(i_version < SCOM_UDT_VERSION_1)
+ {
+ i_parser.PrintHeading("SCOM cache FFDC: Unknown version");
+ }
+ else
+ {
+ i_parser.PrintHeading("SCOM cache FFDC");
+
+ const char* fieldName[] =
+ {
+ "Register address",
+ "Unmasked expected value",
+ "Unmasked actual value",
+ "Mask",
+ "Masked expected value",
+ "Masked actual value",
+ };
+
+ const uint64_t* pField =
+ reinterpret_cast<const uint64_t *>(i_pBuffer);
+ for(size_t i=0;
+ i<sizeof(fieldName)/sizeof(fieldName[0]);
+ ++i)
+ {
+ if(i_buflen >= (i+1)*sizeof(*pField) )
+ {
+ i_parser.PrintNumberUint64(
+ fieldName[i],"0x%016llX",
+ ERRORLOG::NTH_UINT64(pField+i));
+ }
+ }
+ }
+ }
+
+ private:
+
+ // Parser isn't compiled with c++11 in all environments, and
+ // therefore "delete" of unused interfaces (like below) is not
+ // supported, nor are functions with move semantics
+
+ // Disable compiler provided default functions
+ UdParserCentaurCacheMismatch(
+ const UdParserCentaurCacheMismatch&);
+
+ UdParserCentaurCacheMismatch & operator=(
+ const UdParserCentaurCacheMismatch&);
+ };
+
+}
+
+}
+
+#endif
+
diff --git a/src/usr/scom/plugins/scomUdParserFactory.H b/src/usr/scom/plugins/scomUdParserFactory.H
index 2763e0f32..adc291882 100644
--- a/src/usr/scom/plugins/scomUdParserFactory.H
+++ b/src/usr/scom/plugins/scomUdParserFactory.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* Contributors Listed Below - COPYRIGHT 2016,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -27,6 +27,7 @@
#include "errludparserfactory.H"
#include "errludP_scom.H"
+#include "errludP_cache.H"
namespace SCOM
{
@@ -37,7 +38,10 @@ namespace SCOM
UserDetailsParserFactory()
{
registerParser<SCOM::UdParserPib>
- (SCOM_UDT_PIB);
+ (SCOM_UDT_PIB);
+ registerParser<
+ ::SECUREBOOT::CENTAUR_SECURITY::UdParserCentaurCacheMismatch>
+ (SCOM_UDT_CENTAUR_CACHE_MISMATCH);
}
diff --git a/src/usr/scom/scom.C b/src/usr/scom/scom.C
index ef9bdf8e6..2dcf4a3c0 100644
--- a/src/usr/scom/scom.C
+++ b/src/usr/scom/scom.C
@@ -50,6 +50,14 @@
#include <targeting/common/utilFilter.H>
#include <targeting/namedtarget.H>
+#include <config.h>
+
+#ifndef __HOSTBOOT_RUNTIME
+#ifdef CONFIG_SECUREBOOT
+#include <secureboot/service.H>
+#include <scom/centaurScomCache.H>
+#endif
+#endif
// Trace definition
trace_desc_t* g_trac_scom = NULL;
@@ -161,7 +169,6 @@ errlHndl_t scomMemBufPerformOp(DeviceFW::OperationType i_opType,
{
errlHndl_t l_err = NULL;
-
uint64_t l_scomAddr = va_arg(i_args,uint64_t);
l_err = checkIndirectAndDoScom(i_opType,
@@ -219,6 +226,39 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
errlHndl_t l_err = NULL;
do {
+
+#ifndef __HOSTBOOT_RUNTIME
+#ifdef CONFIG_SECUREBOOT
+ if( (i_opType == DeviceFW::READ)
+ && (i_target != TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ && SECUREBOOT::enabled()
+ && SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().cacheEnabled()
+ && (i_target->getAttr<TARGETING::ATTR_TYPE>()==TARGETING::TYPE_MEMBUF))
+ {
+ bool skipScom=true;
+ uint64_t cacheData=0;
+ l_err=SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().
+ read(i_target,i_addr,skipScom,cacheData);
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_scom, ERR_MRK
+ "checkIndirectAndDoScom: failed in call to ScomCache::read() "
+ "for HUID = 0x%08X, address = 0x%016llX",
+ TARGETING::get_huid(i_target),
+ i_addr);
+ break;
+ }
+
+ if(skipScom)
+ {
+ *reinterpret_cast<uint64_t*>(io_buffer) = cacheData;
+ io_buflen=sizeof(cacheData);
+ break;
+ }
+ }
+#endif
+#endif
+
// Do we need to do the indirect logic or not?
bool l_runIndirectLogic = true;
@@ -329,6 +369,30 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
} while(0);
+#ifndef __HOSTBOOT_RUNTIME
+#ifdef CONFIG_SECUREBOOT
+ if( !l_err
+ && (i_opType == DeviceFW::WRITE)
+ && (i_target!=TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ && SECUREBOOT::enabled()
+ && SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().cacheEnabled()
+ && (i_target->getAttr<TARGETING::ATTR_TYPE>()==TARGETING::TYPE_MEMBUF) )
+ {
+ l_err = SECUREBOOT::CENTAUR_SECURITY::ScomCache::getInstance().
+ write(i_target,i_addr,
+ *reinterpret_cast<uint64_t*>(io_buffer));
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_scom, ERR_MRK
+ "checkIndirectAndDoScom: failed in call to ScomCache::write() "
+ "for HUID = 0x%08X, address = 0x%016llX",
+ TARGETING::get_huid(i_target),
+ i_addr);
+ }
+ }
+#endif
+#endif
+
return l_err;
}
diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
index 972c2f01e..e1cebe965 100755
--- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
@@ -1128,4 +1128,17 @@
<writeable/>
</attribute>
+<attribute>
+ <id>CENTAUR_REGISTER_CACHE_PTR</id>
+ <description>
+ Pointer to Secure Boot Centaur SCOM register cache
+ </description>
+ <simpleType>
+ <uint64_t></uint64_t>
+ </simpleType>
+ <persistency>volatile-zeroed</persistency>
+ <readable/>
+ <writeable/>
+</attribute>
+
</attributes>
diff --git a/src/usr/targeting/common/xmltohb/target_types_hb.xml b/src/usr/targeting/common/xmltohb/target_types_hb.xml
index 5f43f0a7a..46c145c75 100644
--- a/src/usr/targeting/common/xmltohb/target_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/target_types_hb.xml
@@ -186,6 +186,7 @@
<attribute>
<id>HBRT_HYP_ID</id>
</attribute>
+ <attribute><id>CENTAUR_REGISTER_CACHE_PTR</id></attribute>
</targetTypeExtension>
<targetTypeExtension>
diff --git a/src/usr/targeting/common/xmltohb/xmltohb.pl b/src/usr/targeting/common/xmltohb/xmltohb.pl
index 8d8ac765b..78b28e227 100755
--- a/src/usr/targeting/common/xmltohb/xmltohb.pl
+++ b/src/usr/targeting/common/xmltohb/xmltohb.pl
@@ -4366,8 +4366,8 @@ sub getAttributeIdEnumeration {
# attribute_types_hb.xml or attributes_types_fsp.
else
{
- croak("Error: AttributeId $attribute->{id} "
- . "defined multiple times");
+ croak("Error: AttributeId $attribute->{id} "
+ . "defined multiple times");
}
}
else
OpenPOWER on IntegriCloud