diff options
-rw-r--r-- | src/include/usr/errl/errlmanager.H | 65 | ||||
-rw-r--r-- | src/usr/errl/errlentry.C | 89 | ||||
-rw-r--r-- | src/usr/errl/errlmanager.C | 138 | ||||
-rw-r--r-- | src/usr/pnor/pnorrp.C | 7 |
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 } |