summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/errl/errlmanager.H65
-rw-r--r--src/usr/errl/errlentry.C89
-rw-r--r--src/usr/errl/errlmanager.C138
-rw-r--r--src/usr/pnor/pnorrp.C7
4 files changed, 214 insertions, 85 deletions
diff --git a/src/include/usr/errl/errlmanager.H b/src/include/usr/errl/errlmanager.H
index f7407d8c4..5bd2aa196 100644
--- a/src/include/usr/errl/errlmanager.H
+++ b/src/include/usr/errl/errlmanager.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2018 */
+/* Contributors Listed Below - COPYRIGHT 2011,2019 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -82,6 +82,32 @@ void errlCommit(errlHndl_t& io_err, compId_t i_committerComp );
uint8_t getHiddenLogsEnable();
/**
+ * @brief Returns the cached VERSION partition, if any. Makes a call to
+ * ErrlManager::getCachedVersionPartition
+ * @return uint8_t* The pointer to the binary contents of the VERSION
+ * partition; nullptr will be returned if VERSION hasn't been
+ * cached yet of if there was an error during caching
+ */
+const uint8_t* getCachedVersionPartition();
+
+/**
+ * @brief Returns the size of the cached VERSION partition. Makes a call
+ * to ErrlManager::getCachedVersionPartitionSize
+ * @return size_t The size of the cached VERSION partition. A 0 will be
+ * returned if VERSION hasn't been cached yet or if there was an
+ * error during caching
+ */
+size_t getCachedVersionPartitionSize();
+
+/*
+ * @brief Call to ErrlManager to cache the VERSION PNOR partition into an
+ * internal buffer.
+ *
+ * @return errlHndl_t nullptr on success; non-nullptr on error.
+ */
+errlHndl_t cacheVersionPartition();
+
+/**
* @brief Global enums used by static errlResourceReady function
*/
enum errlManagerNeeds
@@ -209,6 +235,34 @@ public:
*/
static bool errlCommittedThisBoot();
+ /**
+ * @brief Returns the cached VERSION partition, if any
+ * @return uint8_t* The pointer to the binary contents of the VERSION
+ * partition
+ */
+ const uint8_t* getCachedVersionPartition() const;
+
+ /**
+ * @brief Returns the size of the cached VERSION partition
+ * @return size_t The size of the cached VERSION partition
+ */
+ size_t getCachedVersionPartitionSize() const;
+
+ /**
+ * @brief Cache the VERSION PNOR partition into a member buffer. The
+ * buffer is dynamically allocated here to hold the contents of the
+ * partition. If any error occurs during the execution, the buffer
+ * is deleted and the error is returned. This function is not
+ * supposed to be called within ErrlManager message handler, since
+ * the function itself makes synchronous calls to various message
+ * handlers. Note that once the partition is cached, the cache is
+ * never purged to make sure all possible error logs receive the
+ * VERSION field. No-op on FSP systems.
+ *
+ * @return errlHndl_t nullptr on success; non-nullptr on error.
+ */
+ errlHndl_t cacheVersionPartition();
+
/**
* @brief Value to determine what logs are to be skipped. Mirrors
@@ -634,6 +688,15 @@ private:
bool allowCallHomeEselsToBmc(void);
#endif
+ const uint8_t* iv_versionPartitionCache; // The bin contents of the VERSION
+ // partition; once cached, the
+ // constents are never removed
+
+ size_t iv_versionPartitionCacheSize; // The size of the VERSION partition
+
+ bool iv_isVersionPartitionCached; // Whether the caching of the VERSION
+ // partition has been attempted
+
};
diff --git a/src/usr/errl/errlentry.C b/src/usr/errl/errlentry.C
index 06f9d92a3..9baeb67a0 100644
--- a/src/usr/errl/errlentry.C
+++ b/src/usr/errl/errlentry.C
@@ -657,99 +657,24 @@ void ErrlEntry::addVersionInfo()
if ( !INITSERVICE::spBaseServicesEnabled()
&& PNOR::isSectionAvailable(PNOR::VERSION))
{
-
-// Setting variables only used in config secureboot
-#ifdef CONFIG_SECUREBOOT
- bool l_secureSectionLoaded = false;
- errlHndl_t l_errl_loadSecureSection = nullptr;
-#endif
-
- errlHndl_t l_errl = nullptr;
-
do
{
-
-#ifdef CONFIG_SECUREBOOT
- l_errl_loadSecureSection = PNOR::loadSecureSection(PNOR::VERSION);
- if (l_errl_loadSecureSection)
- {
- TRACFCOMP( g_trac_errl,
- "addVersionInfo: Failed to load secure VERSION");
- // Since an error occurred while attempting to add version info
- // to another error log there is nothing that can be done with
- // this error since attempting to commit it will lead to an
- // infinite loop of committing the error and then recalling this
- // function. If this error occurred then the VERSION partition
- // is not added and the error log commit continues.
- delete l_errl_loadSecureSection;
- l_errl_loadSecureSection = nullptr;
- break;
- }
- else
- {
- l_secureSectionLoaded = true;
- }
-#endif
-
- // Get PNOR Version
- PNOR::SectionInfo_t l_pnorVersionInfo;
- l_errl = getSectionInfo(PNOR::VERSION, l_pnorVersionInfo);
-
- if (l_errl)
- {
- TRACFCOMP( g_trac_errl,
- "addVersionInfo: Failed to getSectionInfo");
- // Since an error occurred while attempting to add version info
- // to another error log there is nothing that can be done with
- // this error since attempting to commit it will lead to an
- // infinite loop of committing the error and then recalling this
- // function. If this error occurred then the VERSION partition
- // is not added and the error log commit continues.
- delete l_errl;
- l_errl = nullptr;
- break;
- }
-
const uint8_t* l_versionData =
- reinterpret_cast<uint8_t*>(l_pnorVersionInfo.vaddr);
+ ERRORLOG::getCachedVersionPartition();
+ size_t l_versionSize =
+ ERRORLOG::getCachedVersionPartitionSize();
- size_t l_numberOfBytes = 0;
-
- // Determine the size of the version data. The max size is the given
- // size in the SectionInfo but can be less.
- while ((static_cast<char>(l_versionData[l_numberOfBytes]) != '\0')
- && l_numberOfBytes < l_pnorVersionInfo.size)
+ if(!l_versionData || !l_versionSize)
{
- ++l_numberOfBytes;
+ break;
}
- char l_pVersionString[l_numberOfBytes + 1]={0};
+ char l_pVersionString[l_versionSize + 1]={0};
- memcpy(l_pVersionString, l_versionData, l_numberOfBytes);
+ memcpy(l_pVersionString, l_versionData, l_versionSize);
ErrlUserDetailsString(l_pVersionString).addToLog(this);
} while(0);
-
-#ifdef CONFIG_SECUREBOOT
- if (l_secureSectionLoaded)
- {
- l_errl_loadSecureSection = PNOR::unloadSecureSection(PNOR::VERSION);
- if(l_errl_loadSecureSection)
- {
- TRACFCOMP( g_trac_errl,
- "addVersionInfo: Failed to unload secure VERSION");
- // Since an error occurred while attempting to add version info
- // to another error log there is nothing that can be done with
- // this error since attempting to commit it will lead to an
- // infinite loop of committing the error and then recalling this
- // function. If this error occurred then the VERSION partition
- // is not added and the error log commit continues.
- delete l_errl_loadSecureSection;
- l_errl_loadSecureSection = nullptr;
- }
- }
-#endif
-
}
// End of IPL only block
diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C
index c32c2b2b7..97310383f 100644
--- a/src/usr/errl/errlmanager.C
+++ b/src/usr/errl/errlmanager.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2018 */
+/* Contributors Listed Below - COPYRIGHT 2011,2019 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -55,10 +55,14 @@
#include <hwas/common/deconfigGard.H>
#include <kernel/terminate.H>
#include <debugpointers.H>
+#include <sys/sync.h>
namespace ERRORLOG
{
+// Used in VERSION partition caching
+mutex_t g_errlMutex = MUTEX_INITIALIZER;
+
extern trace_desc_t* g_trac_errl;
#ifdef STORE_ERRL_IN_L3
@@ -103,6 +107,20 @@ bool compareEidToPlid(const uint32_t i_plid,
return (i_pair.first->eid() == i_plid);
}
+const uint8_t* getCachedVersionPartition()
+{
+ return Singleton<ErrlManager>::instance().getCachedVersionPartition();
+}
+
+size_t getCachedVersionPartitionSize()
+{
+ return Singleton<ErrlManager>::instance().getCachedVersionPartitionSize();
+}
+
+errlHndl_t cacheVersionPartition()
+{
+ return Singleton<ErrlManager>::instance().cacheVersionPartition();
+}
class AtLoadFunctions
{
@@ -129,7 +147,9 @@ ErrlManager::ErrlManager() :
iv_isMboxEnabled(false), // assume mbox isn't ready yet..
iv_isIpmiEnabled(false), // assume ipmi isn't ready yet..
iv_nonInfoCommitted(false),
- iv_isErrlDisplayEnabled(false)
+ iv_isErrlDisplayEnabled(false),
+ iv_versionPartitionCache(nullptr),
+ iv_versionPartitionCacheSize(0)
{
TRACFCOMP( g_trac_errl, ENTER_MRK "ErrlManager::ErrlManager constructor" );
@@ -1031,4 +1051,118 @@ bool ErrlManager::_updateErrlListIter(ErrlListItr_t & io_it)
return l_removed;
}
+const uint8_t* ErrlManager::getCachedVersionPartition() const
+{
+ mutex_lock(&g_errlMutex);
+ const uint8_t* l_versionPtr = iv_versionPartitionCache;
+ mutex_unlock(&g_errlMutex);
+ return l_versionPtr;
+}
+
+size_t ErrlManager::getCachedVersionPartitionSize() const
+{
+ mutex_lock(&g_errlMutex);
+ size_t l_versionSize = iv_versionPartitionCacheSize;
+ mutex_unlock(&g_errlMutex);
+ return l_versionSize;
+}
+
+errlHndl_t ErrlManager::cacheVersionPartition()
+{
+ errlHndl_t l_errl = nullptr;
+ bool l_versionPartitionLoaded = false;
+
+ do {
+
+ if(iv_isVersionPartitionCached ||
+ !PNOR::isSectionAvailable(PNOR::VERSION))
+ {
+ // No need to try to cache more than once or if
+ // there is no VERSION partition
+ break;
+ }
+
+#ifdef CONFIG_SECUREBOOT
+ l_errl = PNOR::loadSecureSection(PNOR::VERSION);
+ if(l_errl)
+ {
+ TRACFCOMP(g_trac_errl, ERR_MRK"ErrlManager::cacheVersionPartition() - could not load VERSION partition");
+ break;
+ }
+
+ l_versionPartitionLoaded = true;
+#endif
+
+ PNOR::SectionInfo_t l_pnorVersionSectionInfo;
+ l_errl = getSectionInfo(PNOR::VERSION, l_pnorVersionSectionInfo);
+ if(l_errl)
+ {
+ TRACFCOMP(g_trac_errl, ERR_MRK"ErrlManager::cacheVersionPartition() - could not get VERSION section info");
+ break;
+ }
+
+ // Since multiple errls may be at different stages of commit at the same
+ // time, lock the mutex to prevent atomicity issues
+ mutex_lock(&g_errlMutex);
+
+ iv_versionPartitionCacheSize = 0;
+
+ const char* l_versionSectionPtr =
+ reinterpret_cast<char*>(l_pnorVersionSectionInfo.vaddr);
+
+ // The actual size of the text in the VERSION partition is likely to be less
+ // than the declared size. Calculate the actual size here.
+ while((l_versionSectionPtr[iv_versionPartitionCacheSize] != '\0') &&
+ (iv_versionPartitionCacheSize < l_pnorVersionSectionInfo.size))
+ {
+ ++iv_versionPartitionCacheSize;
+ }
+ iv_versionPartitionCache = new uint8_t[iv_versionPartitionCacheSize];
+
+ memcpy(const_cast<uint8_t*>(iv_versionPartitionCache),
+ reinterpret_cast<uint8_t*>(l_pnorVersionSectionInfo.vaddr),
+ iv_versionPartitionCacheSize);
+
+ mutex_unlock(&g_errlMutex);
+
+ } while(0);
+
+ if(l_versionPartitionLoaded)
+ {
+#ifdef CONFIG_SECUREBOOT
+ errlHndl_t l_unloadSecErr = PNOR::unloadSecureSection(PNOR::VERSION);
+ if(l_unloadSecErr)
+ {
+ TRACFCOMP(g_trac_errl, ERR_MRK"ErrlManager::cacheVersionPartition() - could not unload VERSION partition");
+ if(l_errl)
+ {
+ l_unloadSecErr->plid(l_errl->plid());
+ errlCommit(l_unloadSecErr, ERRL_COMP_ID);
+ }
+ else
+ {
+ l_errl = l_unloadSecErr;
+ l_unloadSecErr = nullptr;
+ }
+ }
+#endif
+ }
+
+ if(l_errl)
+ {
+ if(iv_versionPartitionCache)
+ {
+ delete[] iv_versionPartitionCache;
+ iv_versionPartitionCache = nullptr;
+ }
+ iv_versionPartitionCacheSize = 0;
+ }
+
+ // Set the cache attrmpted flag regardless of whether we actually
+ // were able to cache the partition
+ iv_isVersionPartitionCached = true;
+
+ return l_errl;
+}
+
} // End namespace
diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C
index cb70eb94c..2c531e63e 100644
--- a/src/usr/pnor/pnorrp.C
+++ b/src/usr/pnor/pnorrp.C
@@ -214,6 +214,13 @@ void PnorRP::init( errlHndl_t &io_rtaskRetErrl )
#ifdef CONFIG_SECUREBOOT
// Extend the base image to the TPM, regardless of how it was obtained
l_errl = TRUSTEDBOOT::extendBaseImage();
+
+ // Cache the VERSION partition data for future use by the errl commit
+ // code.
+ if(!l_errl)
+ {
+ l_errl = ERRORLOG::cacheVersionPartition();
+ }
#endif
#endif
}
OpenPOWER on IntegriCloud