diff options
author | Monte Copeland <copelanm@us.ibm.com> | 2011-10-24 09:30:49 -0500 |
---|---|---|
committer | Monte K. Copeland <copelanm@us.ibm.com> | 2011-10-31 11:07:10 -0500 |
commit | 723239d5a14fe82713a2aa57fef3130534b15a41 (patch) | |
tree | b6d19b1d1d66ec9ea4acd19c0dfdb47bcf86babd | |
parent | f2794eed87ca9c35140c601dfcbb5baf299d834b (diff) | |
download | talos-hostboot-723239d5a14fe82713a2aa57fef3130534b15a41.tar.gz talos-hostboot-723239d5a14fe82713a2aa57fef3130534b15a41.zip |
Error log changes for Sprint 6
Change-Id: I44ad678cfae8cd84e5370391dc7e20d74f59c9ca
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/449
Tested-by: Jenkins Server
Reviewed-by: Mark W. Wenning <wenning@us.ibm.com>
Reviewed-by: Monte K. Copeland <copelanm@us.ibm.com>
30 files changed, 2823 insertions, 966 deletions
diff --git a/img/.gitignore b/img/.gitignore index 476897d14..d026df6f9 100644 --- a/img/.gitignore +++ b/img/.gitignore @@ -10,3 +10,4 @@ .*.lnkout hbotStringFile *.toc +errlparser diff --git a/src/build/simics/hb-simdebug.py b/src/build/simics/hb-simdebug.py index fbc223705..06b5e4ccd 100755 --- a/src/build/simics/hb-simdebug.py +++ b/src/build/simics/hb-simdebug.py @@ -446,7 +446,7 @@ def istepHB( str_arg1, inList): #------------------------------------------------------------------------------ # Function to dump error logs #------------------------------------------------------------------------------ -def errlHB(symsFile, errlParser, flag, logid): +def errlHB(symsFile, errlParser, flag, logid, stringFile): # "constants" L3_SIZE = 0x800000 @@ -461,9 +461,9 @@ def errlHB(symsFile, errlParser, flag, logid): #print result if logid == "all": - string = "./%s %s %s %s| tee Errorlogs"%(errlParser,dumpFile,symsFile,flag) + string = "./%s %s %s %s -t %s| tee Errorlogs"%(errlParser,dumpFile,symsFile,flag,stringFile) else: - string = "./%s %s %s %s %s| tee Errorlogs"%(errlParser,dumpFile,symsFile,flag,logid) + string = "./%s %s %s %s %s -t %s| tee Errorlogs"%(errlParser,dumpFile,symsFile,flag,logid,stringFile) #print string os.system(string) os.system("rm hbdump.out") @@ -656,7 +656,7 @@ def hb_errl(logid, logidStr, flg_list, flg_detail): print "syms=%s" % str(syms) print "errlParser=%s" % str(errlParser) #print "logid=%s" % str(id) - errlHB(syms, errlParser, flag, id) + errlHB(syms, errlParser, flag, id, default_stringFile) return None new_command("hb-errl", diff --git a/src/build/tools/cpfiles.pl b/src/build/tools/cpfiles.pl index 79c794335..5ee77afe3 100755 --- a/src/build/tools/cpfiles.pl +++ b/src/build/tools/cpfiles.pl @@ -58,7 +58,7 @@ sub printUsage; my @files = ("src/build/tools/hb-parsedump.pl", "src/build/simics/hb-simdebug.py", "src/build/simics/post_model_hook.simics", - "src/usr/errl/parser/bin/errlparser", + "img/errlparser", "img/hbotStringFile", "img/hbicore.syms", "img/hbicore_test.syms", diff --git a/src/include/usr/errl/errlentry.H b/src/include/usr/errl/errlentry.H index 5e5205fb8..51a0df843 100644 --- a/src/include/usr/errl/errlentry.H +++ b/src/include/usr/errl/errlentry.H @@ -38,6 +38,11 @@ #include <stdint.h> #include <vector> #include <errl/errltypes.H> +#include <errl/errlsctn.H> +#include <errl/errlprvt.H> +#include <errl/errluh.H> +#include <errl/errlsrc.H> +#include <errl/errlud.H> #include <hbotcompid.H> namespace ERRORLOG @@ -47,8 +52,15 @@ namespace ERRORLOG // Forward class declarations /*****************************************************************************/ class ErrlManager; -class ErrlSctn; -class ErrlFFDC; + + + + +// In Sprint 6, the return from errl->addFFDC changed from +// ErrlFFDC* to ErrlUD*. This typedef is for compatibility in +// case anybody previously stored the return from errl->addFFDC() as +// ErrlFFDC *. +typedef ErrlUD ErrlFFDC; /** * @brief Host Boot Error log entry class. @@ -63,6 +75,8 @@ class ErrlEntry friend class ErrlManager; + + public: /** * @brief ErrlEntry constructor. Builds an error log with info @@ -123,6 +137,7 @@ public: */ errlSeverity_t sev() const; + /** * @brief Set the log's severity * The severity of a log determines how severe the @@ -175,6 +190,19 @@ public: /** + * @brief Get the unique platform log identifier (PLID) of the error log. + * In legacy FSP, you could have one platform log ID such that a + * of entry IDs (EIDs) related to a single PLID. So far in Hostboot, + * PLID == EID. As such, there is no setter in the ErrlEntry interface + * for EID. When flattened as PEL for export, EID will be set to PLID. + * + * @return The platform log ID of the error log. + */ + uint32_t plid() const; + + + + /** * @brief Get the event type of the error log. * See errl/errltypes.H * @return errlEventType_t @@ -247,6 +275,8 @@ public: */ void setTermState(const errlTermState_t i_termState); + + /** * @brief Allows the caller to add a chunk of data in a log * @@ -263,79 +293,92 @@ public: * @return Pointer to FFDC section if successfully added. * NULL if fails */ - ErrlFFDC* addFFDC(const compId_t i_compId, - const void * i_dataPtr, - const uint32_t i_ffdcLen, - const uint8_t i_ffdcVer = 0, - const uint8_t i_ffdcSubSect = 0); + ErrlUD * addFFDC(const compId_t i_compId, + const void * i_dataPtr, + const uint32_t i_ffdcLen, + const uint8_t i_ffdcVer = 0, + const uint8_t i_ffdcSubSect = 0); /** * @brief Append more data to an FFDC section. * - * @param[in] i_ffdcSctnPtr Pointer to FFDC section to add data to. - * This pointer is returned when addFFDC + * @param[in] i_pErrlUD Pointer to the user-define section + * to add data to. This pointer is + * returned when addFFDC * function is called earlier. * @param[in] i_dataPtr Points to data block to be added * @param[in] i_dataLen Length of data in bytes * * @return void */ - void appendToFFDC(ErrlFFDC* i_ffdcSctnPtr, - const void *i_dataPtr, - const uint32_t i_dataLen); + void appendToFFDC( ErrlUD * i_pErrlUD, + const void *i_dataPtr, + const uint32_t i_dataLen); - - - /** - * @brief Compute the flattened size of an error log. - * - * @return size in bytes of the flattened data. - */ - uint64_t flattenedSize(); - - /** - * @brief Flatten the data to caller's buffer. + * @brief Collect component trace + * The given component's trace is collected (if possible) + * and added to the log's data sections. The amount of data + * added is the smallest of the log's available space (up to + * 1024 bytes of trace) or the given input max. * - * @param[in,out] io_buffer Points to data block to be filled - * @param[in] i_cbBuffer Count of bytes in buffer supplied + * @param[in] i_Name Component Name + * @param[in] i_Max Upper limit of trace to capture. * - * @return Count of bytes copied to caller's - * buffer or else zero if it does not fit. + * @return A Boolean indication of success. False likely means + * the component name input is not found. */ - uint64_t flatten( void * io_buffer, const uint64_t i_cbBuffer ); + bool collectTrace(const char i_name[], + const uint32_t i_max = 0); -private: +private: /** - * @brief Disabled copy constructor and assignment operator - */ - ErrlEntry(const ErrlEntry& i_right); - ErrlEntry& operator=(const ErrlEntry& i_right); + * @brief The ErrlManager will call here to ask the + * ErrlEntry to assign the time of commit, and to assign + * the commiter's comp ID. + * The ErrlManager is the primary user of this call. + * + */ + void commit( compId_t i_commiterComp ); /** - * @brief Set the log's id - * This function is called by the ErrlManager to - * set this log's ID to a unique input number. - * This is to be called by ErrlManager only. + * @brief Compute the flattened size of an error log. It is typical + * to call this function for the size of buffer required, then + * allocate a buffer, then call flatten(). + * The ErrlManager is the primary user of this call. * - * There is no call to get the log id because it - * would just be zero until the log is committed. + * @return Size in bytes of the flattened data. + */ + uint64_t flattenedSize(); + + + /** + * @brief Flatten the data to caller's buffer. The resulting flat + * data will be in PEL (platform event log) format. + * The ErrlManager is the primary user of this call. * - * @param[in] i_val Log ID as assigned by ErrlManager + * @param[in,out] o_buffer Points to data block to be filled + * @param[in] i_cbBuffer Count of bytes in buffer supplied * - * @return void + * @return Count of bytes copied to caller's + * buffer or else zero if it does not fit. */ - void setLogId(const uint32_t i_val); + uint64_t flatten( void * o_buffer, const uint64_t i_cbBuffer ); + /** + * @brief Disabled copy constructor and assignment operator + */ + ErrlEntry(const ErrlEntry& i_right); + ErrlEntry& operator=(const ErrlEntry& i_right); @@ -375,21 +418,6 @@ private: const callOutPriority_t i_priority); /** - * @brief Collect component trace - * The given component's trace is collected ( if possible ) - * and added to the log's data sections. The amount of data - * added is the smallest of the log's available space (up to - * 1024 bytes of trace) or the given input max. - * - * @param[in] i_Name Component Name - * @param[in] i_Max Upper limit of trace to capture. - * - * @return None - */ - void CollectTrace(const char i_Name[], - const uint32_t i_Max = 0); - - /** * @brief Adds a software section to the log which is * mostly used as a stack call indicator * @@ -417,127 +445,101 @@ private: private: // Data Members - uint16_t iv_reasonCode; // Comp ID and reason code, 2 nibbles ea - errlSeverity_t iv_sev; // Log severity - errlEventType_t iv_eventType; // Event type - epubSubSystem_t iv_subSys; // Sub system - srcType_t iv_srcType; // SRC type - errlTermState_t iv_termState; // Terminate state - uint8_t iv_modId; // Module ID - uint64_t iv_user1; // Optional user data 1 - uint64_t iv_user2; // Optional user data 2 - uint64_t iv_CreationTime; // Time of instantiation - uint32_t iv_logId; // This log's unique ID - std::vector<ErrlSctn*> iv_SectionVector; // list of user sections + ErrlPrvt iv_Private; // private header object + ErrlUH iv_User; // user header object + ErrlSrc iv_Src; // primary SRC section + std::vector<ErrlUD*> iv_SectionVector; // list of user defined sections + + // TODO need to interpret term state and terminate accordingly. + // TODO termstate is presently not being flattend into PEL + errlTermState_t iv_termState; }; + + + + //----------------------------------------------------------------------- // In-line functions //----------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// -inline errlSeverity_t ErrlEntry::sev() const -{ - return iv_sev; -} - -inline void ErrlEntry::setSev(const errlSeverity_t i_sev) -{ - iv_sev = i_sev; - return; -} - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -inline uint16_t ErrlEntry::reasonCode() const +inline uint32_t ErrlEntry::plid() const { - return iv_reasonCode; + return iv_Private.iv_plid; } -inline void ErrlEntry::setReasonCode( const uint16_t i_reasonCode ) -{ - iv_reasonCode = i_reasonCode; - return; -} //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// inline uint8_t ErrlEntry::moduleId() const { - return iv_modId; + return iv_Src.iv_modId; } +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// inline void ErrlEntry::setModuleId( const uint8_t i_moduleId ) { - iv_modId = i_moduleId; + iv_Src.iv_modId = i_moduleId; return; } + + //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// -inline errlEventType_t ErrlEntry::eventType() const +inline errlTermState_t ErrlEntry::termState() const { - return iv_eventType; + return iv_termState; } -inline void ErrlEntry::setEventType(const errlEventType_t i_eventType) +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline void ErrlEntry::setTermState(const errlTermState_t i_termState) { - iv_eventType = i_eventType; + iv_termState = i_termState; return; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// -inline epubSubSystem_t ErrlEntry::subSys() const +inline void ErrlEntry::setReasonCode( const uint16_t i_reasonCode ) { - return iv_subSys; + iv_Src.iv_reasonCode = i_reasonCode; + return; } -inline void ErrlEntry::setSubSys(const epubSubSystem_t i_subSys) +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline uint16_t ErrlEntry::reasonCode() const { - iv_subSys = i_subSys; - return; + return iv_Src.iv_reasonCode; } - //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// inline srcType_t ErrlEntry::srcType() const { - return iv_srcType; + return iv_Src.iv_srcType; } +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// inline void ErrlEntry::setSrcType(const srcType_t i_srcType) { - iv_srcType = i_srcType; + iv_Src.iv_srcType = i_srcType; return; } -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -inline errlTermState_t ErrlEntry::termState() const -{ - return iv_termState; -} -inline void ErrlEntry::setTermState(const errlTermState_t i_termState) -{ - iv_termState = i_termState; - return; -} -//////////////////////////////////////////////////////////////////////////// -// Called by errlmanager at log commit time. -inline void ErrlEntry::setLogId(const uint32_t i_val) -{ - iv_logId = i_val; -} } // End namespace diff --git a/src/include/usr/errl/errlmanager.H b/src/include/usr/errl/errlmanager.H index 4f1275eef..d6d5c5a05 100644 --- a/src/include/usr/errl/errlmanager.H +++ b/src/include/usr/errl/errlmanager.H @@ -39,6 +39,10 @@ #include <sys/sync.h> #include <vector> #include <kernel/timemgr.H> +#include <hbotcompid.H> + + + namespace ERRORLOG { @@ -59,11 +63,14 @@ namespace ERRORLOG * linker issue in HostBoot (linker can't find singleton outside of * a module). * - * @param[in,out] io_err Error log handle to be committed + * @param[in,out] io_err Error log handle to be committed + * @param[in] i_comitterComp Component committing the error log * * @return None */ -void errlCommit(errlHndl_t& io_err); + +// TODO Work item 4104 to make comitter comp required, no default. +void errlCommit(errlHndl_t& io_err, compId_t i_committerComp = 0 ); /*****************************************************************************/ // Forward class declarations @@ -100,7 +107,7 @@ public: * * @return None */ - void commitErrLog(errlHndl_t& io_err); + void commitErrLog(errlHndl_t& io_err, compId_t i_committerComp ); /** * @brief Returns a unique error log ID @@ -139,10 +146,10 @@ private: ErrlManager(const ErrlManager& i_right); ErrlManager& operator=(const ErrlManager& i_right); + /** - * @brief - * Current log ID: increment this when assigning log ID to a new errlog - * as it is being committed. + * @brief Current log ID. As new error logs are created, + * this value will be used to assign the new error log its ID. */ uint32_t iv_currLogId; diff --git a/src/include/usr/errl/errlprvt.H b/src/include/usr/errl/errlprvt.H new file mode 100644 index 000000000..d8086b50b --- /dev/null +++ b/src/include/usr/errl/errlprvt.H @@ -0,0 +1,145 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/errl/errlprvt.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef ERRLPRVT_H +#define ERRLPRVT_H + +/** + * @file errlprvt.H + * + * @brief A class for the private header 'PH' section of an error log. + * Manages the data destined for the PEL PH section. + * +*/ + +#include <errl/errlsctnhdr.H> + + +namespace ERRORLOG +{ + +class ErrlPrvt +{ + + // ErrlEntry may access private elements of this class. Data items that + // you would expect to be part of ErrlEntry are actually instance data + // in this class. + friend class ErrlEntry; + + +private: + + enum constants + { + SLEN = 40, // section length w/o sizeof(ErrlSctnHdr) + SST = 0, // section type + VER = 1 // section version + // CSS_VER = 8 // TODO unused, relates to iv_cssver[] + }; + + /** + * @brief Constructor will initialize as much data in the private + * header as it can, including asking the ErrlManager for the error + * log ID. Also sets the time of creation. + * + * @param[in] i_CreatorCompId Creator of this error log. + */ + ErrlPrvt( compId_t i_CreatorCompId ); + + + /** + * @brief Destructor + */ + ~ErrlPrvt(); + + + /** + * @brief Disable copy constructor and assignment operator. + */ + ErrlPrvt(const ErrlPrvt& i_right); + ErrlPrvt& operator=(const ErrlPrvt& i_right); + + + /** + * @brief Calculates the flattened size of this. + * + * @return Count of bytes needed to flatten this. + */ + uint64_t flatSize() const; + + + /** + * @brief Flatten this to the output buffer given. + * + * @param[out] o_pBuffer Pointer to memory buffer where data will go. + * @param[in] i_cbBuffer Count of bytes in memory buffer. + * Call flatSize() first to know how big the + * buffer should be before calling flatten() + * + * @return Count of bytes flattened, or zero on error. The likely error + * is that the buffer is of insufficient size. + */ + uint64_t flatten( void * o_pBuffer, const uint64_t i_cbBuffer ); + + + + // Instance data + + ErrlSctnHdr iv_header; // section header for any/all sections + + uint64_t iv_created; // TODO Expects BCD_time8_t, but using timebase + uint64_t iv_committed; // TODO Expects BCD_time8_t, but using timebase + uint8_t iv_cid; // Creator 'B' (enum errlCreator) + uint8_t iv_sctns; // count of sections + uint32_t iv_plid; // error log id + + // uint8_t iv_cssver[CSS_VER]; // TODO unused now, do we need this? + // uint32_t iv_eid; // TODO Error ID now same as PLID + + +}; + + + +/*****************************************************************************/ +// Destructor + +inline ErrlPrvt::~ErrlPrvt() +{ +} + + +/*****************************************************************************/ +// Export data size + +inline uint64_t ErrlPrvt::flatSize() const +{ + return ( iv_header.flatSize() + ErrlPrvt::SLEN ); +} + + + + +} // namespace + + +#endif //ERRLPRVT_H diff --git a/src/include/usr/errl/errlsctn.H b/src/include/usr/errl/errlsctn.H new file mode 100644 index 000000000..bd31aec40 --- /dev/null +++ b/src/include/usr/errl/errlsctn.H @@ -0,0 +1,106 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/errl/errlsctn.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef ERRLSCTN_H +#define ERRLSCTN_H +/** + * @file errlsctn.H + * + * @brief Base class for adding sections of data to an error log. + * A section may be used to store unique data for the + * error such as SRC or user-defined data or + * component traces, etc. + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <stdint.h> +#include <stdlib.h> +#include <errl/errltypes.H> +#include <hbotcompid.H> +#include <errl/errlsctnhdr.H> + + + +namespace ERRORLOG +{ + +/** + * @brief Base class of a section in an error log object. Derivations + * may include ErrlCallHome, ErrlExtUH, ErrlSrc, ErrlUD, etc. + */ +class ErrlSctn +{ + + + +protected: + + /** + * @brief Constructor + * Initializes the base object with section information + * + * @param[in] i_sid Section id + * @param[in] i_slen Section length + * @param[in] i_ver Section version + * @param[in] i_sst Subsection type + * @param[in] i_compId Component id + * + * @return void + */ + ErrlSctn( const uint16_t i_sid, + const uint16_t i_slen, + const uint8_t i_ver, + const uint8_t i_sst, + const compId_t i_compId ); + + + /** + * @brief Default destructor + * + * @return void + */ + virtual ~ErrlSctn(); + + + + /** + * @brief Disabled copy constructor and assignment operator + */ + ErrlSctn(const ErrlSctn& i_right); + ErrlSctn& operator=(const ErrlSctn& i_right); + + + + // PEL section header for flattening. + ErrlSctnHdr iv_header; + +}; + + + +} // End namespace + + +#endif //ERRLSCTN_H + diff --git a/src/include/usr/errl/errlsctnhdr.H b/src/include/usr/errl/errlsctnhdr.H new file mode 100644 index 000000000..069fa58ba --- /dev/null +++ b/src/include/usr/errl/errlsctnhdr.H @@ -0,0 +1,164 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/errl/errlsctnhdr.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef ERRLSCTNHDR_H +#define ERRLSCTNHDR_H +/** + * @file errlsctnhdr.H + * + * @brief This file contain the class that abstracts the header of + * an error log section. Every section in PEL binary data starts with + * eight bytes of data. This class manages those 8 bytes for all manner + * of PEL sections, including PH (private header), UH (user header), + * UD (user defined), etc. + * + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <stdint.h> +#include <stdlib.h> +#include <errl/errltypes.H> +#include <hbotcompid.H> +#include <string.h> + +namespace ERRORLOG +{ + +/** + * @brief class ErrlSctnHdr abstracts a header of each PEL section in an + * error log object. Objects of classes ErrlSctn, ErrlUH, ErrlPrvt + * have one of these. + */ +class ErrlSctnHdr +{ + + + // All these classes have a ErrlSctnHdr + friend class ErrlSctn; + friend class ErrlPrvt; + friend class ErrlUH; + friend class ErrlUD; + friend class ErrlSrc; + + + +private: + + /** + * @brief Section header constructor + * + * Comp ID, section type and version uniquely identify exactly what + * kind of a section it is. These fields can be used by a post-dump + * parser to call the user-supplied parser code to interpret and + * the data nicely. + * + * @param[in] i_sid Section ID destined for iv_sid + * @param[in] i_slen Section length + * @param[in] i_ver Section version + * @param[in] i_sst Subsection type + * @param[in] i_compId Component Id of the caller + * + * @return void + */ + ErrlSctnHdr( const uint16_t i_sid, + const uint16_t i_slen, + const uint8_t i_ver, + const uint8_t i_sst, + const compId_t i_compId ); + + + + + /** + * @brief Default destructor + * + * @return void + */ + ~ErrlSctnHdr(); + + + + /** + * @brief Disabled copy constructor and assignment operator + */ + ErrlSctnHdr(const ErrlSctnHdr& i_right); + ErrlSctnHdr& operator=(const ErrlSctnHdr& i_right); + + + + + /** + * @brief Compute the flattened size of this. + * + * @return Size in bytes of the flattened data, which is 8 + * for an ErrlSctnHdr. + */ + uint64_t flatSize() const; + + + + /** + * @brief Flatten to buffer provided. + * + * @param[in,out] o_buffer Points to data block to be filled + * @param[in] i_cbBuffer Count of bytes in buffer supplied + * + * @return Count of bytes copied to caller's + * buffer or else zero if it does not fit. + */ + uint64_t flatten( void * o_pbuffer, const uint64_t i_cbBuffer ); + + + + + + // Instance data. + uint16_t iv_sid; // section id 'PH' 'UH' etc (errlSectionId_t) + uint16_t iv_slen; // section length + uint8_t iv_ver; // section version + uint8_t iv_sst; // subsection type + compId_t iv_compId; // hostboot component id + + +}; + + + +//*************************************************************************** + +inline uint64_t ErrlSctnHdr::flatSize() const +{ + // 2 for section id (errlSectionId) + // 2 for section len + // 1 for ver + // 1 for subsection type + // 2 for component id + CPPASSERT( 8 == sizeof( pelSectionHeader_t )); + return sizeof( pelSectionHeader_t ); +} + +} // End namespace + +#endif //ERRLSCTNHDR_H + diff --git a/src/include/usr/errl/errlsrc.H b/src/include/usr/errl/errlsrc.H new file mode 100644 index 000000000..ab48a93d8 --- /dev/null +++ b/src/include/usr/errl/errlsrc.H @@ -0,0 +1,146 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/errl/errlsrc.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef ERRLSRC_H +#define ERRLSRC_H + +/** + * @file errlsrc.H + * + * @brief Manage the data that make up the 'PS' section in an + * error log PEL. PS stands for Primary System Reference Code, or SRC. + * Part of that data management is the flattening of data into PEL. + * +*/ + +#include <errl/errlsctn.H> +#include <errl/errlsctnhdr.H> + + +namespace ERRORLOG +{ + +class ErrlSrc : public ErrlSctn +{ + + // ErrlEntry may access private elements of this class. Data items that + // you would expect to be part of ErrlEntry are actually instance data + // in this class. + friend class ErrlEntry; + + +private: + + + enum constants + { + SLEN = 72, // section length w/o sizeof(ErrlSctnHdr) + SST = 1, // section type + VER = 1, // section version + SRCVER = 2, // SRC version (not section version) + WORDCOUNT = 9 // SRC word count + // CSS_VER = 8 // TODO unused, relates to iv_cssver[] + }; + + + /** + * @brief Constructor. Pass in items destined for the primary SRC + * section in the error log. + * + * @param[in] i_srcType SRC type + * @param[in] i_modId Module ID + * @param[in] i_reasonCode Reason code + * @param[in] i_user1 User data 1 + * @param[in] i_user2 User data 2 + * + */ + ErrlSrc( srcType_t i_srcType, + uint8_t i_modId, + uint16_t i_reasonCode, + uint64_t i_user1, + uint64_t i_user2 ); + + + /** @brief Destructor. */ + ~ErrlSrc(); + + + + /** + * @brief Disable copy constructor and assignment operator. + */ + ErrlSrc(const ErrlSrc& i_right); + ErrlSrc& operator=(const ErrlSrc& i_right); + + + + /** + * @brief Data export facility to flatten data to PEL. + * Exports the object into the 'PS' primary SRC PEL section. + * + * @param[out] o_pBuffer Pointer to buffer where flattened data will go. + * @param[in] i_cbBuffer Count of bytes in target buffer + * + */ + uint64_t flatten( void * o_pBuffer, const uint64_t i_cbBuffer ); + + /** + * @brief Data export size. Presently, Hostboot returns + * creates an 80-byte PS section: 72 bytes in the SRC + * and 8 bytes for the PEL section header. This is the + * amount of flat storage (in bytes) required to + * store the object. + * + * @return Size in bytes. + * + */ + uint64_t flatSize() const; + + + // Instance data + srcType_t iv_srcType; // SRC type, the ?? in SRC ??xxxxxx + uint8_t iv_modId; // module ID + uint16_t iv_reasonCode; // reason code + epubSubSystem_t iv_ssid; // subsystem type, the ?? in SRC xx??xxxx + uint64_t iv_user1; // user data 1 + uint64_t iv_user2; // user data 2 + + +}; + + +//************************************************************************** +// Hostboot PS SRC section generates minimal section with no additional +// words of data. +inline uint64_t ErrlSrc::flatSize() const +{ + // 72 bytes in SRC structure + 8 byte section header. + CPPASSERT( 80 == sizeof( pelSRCSection_t )); + return sizeof( pelSRCSection_t ); +} + + + +} // namespace + +#endif //ERRLSRC_H + diff --git a/src/include/usr/errl/errltypes.H b/src/include/usr/errl/errltypes.H index 10d9e7542..af5067ea4 100644 --- a/src/include/usr/errl/errltypes.H +++ b/src/include/usr/errl/errltypes.H @@ -79,25 +79,114 @@ typedef ERRORLOG::ErrlEntry* errlHndl_t; namespace ERRORLOG { + + +/** + * @brief Scope is found in user header section. + + */ +enum errlScope_t +{ + ERRL_SCOPE_PLATFORM = 0x03, ///< Entire Platform +}; + + + +/** + * @brief Domain as found in user header section. + */ +enum errlDomain_t +{ + ERRL_DOMAIN_DEFAULT = 0xFF // Field based on Subsystem ID +}; + + +/** + * @brief Vector as found in user header section. + */ +enum errlVector_t +{ + ERRL_VECTOR_DEFAULT = 0xFF // Vector that triggered the base class + // of problem in Problem Domain Field. + // Unique field based on Subsystem ID +}; + + + +/** + * @brief Platform Event Log actions + * + * Several action flags used to trigger various + * handling mechanisms for an event log such as + * calling home and sending to the hypervisor. + */ +enum errlActions_t +{ + ERRL_ACTION_NONE = 0x0000, // No action required +}; + + + + +/** + * @brief Creator types. + */ +enum errlCreator_t +{ + ERRL_CID_HOSTBOOT = 'B', +}; + + + + +/** + * @brief Enumeration of PEL section eyecatchers. These are + * usually handled as a uint16_t. See + * "eCLipz and P7 Platform Event Log and SRC PLDD" documentation + * https://mcdoc.boeblingen.de.ibm.com/out/out.ViewDocument.php?documentid=1675 + */ +enum errlSectionId_t +{ + ERRL_SID_PRIVATE_HEADER = 0x5048, // PH private header + ERRL_SID_USER_HEADER = 0x5548, // UH user header + ERRL_SID_PRIMARY_SRC = 0x5053, // PS + ERRL_SID_USER_DEFINED = 0x5544 // UD user defined +}; + + /** * @brief Enumeration of error log severity. * Needs to fit into 1 byte for flattening purposes. + * + * Severity resides in the user header of the PEL log. + * + * Refer to this ErrlEntry setter: + * void ErrlEntry::setSev(const errlSeverity_t i_sev) */ enum errlSeverity_t { - ERRL_SEV_INFORMATIONAL = 0x00, - ERRL_SEV_UNRECOVERABLE = 0x10, + ERRL_SEV_INFORMATIONAL = 0x00, + ERRL_SEV_UNRECOVERABLE = 0x10, ERRL_SEV_CRITICAL_SYS_TERM = 0x20, - ERRL_SEV_UNKNOWN = 0xFF + ERRL_SEV_UNKNOWN = 0xFF }; + + + /** * @brief Event (error) type * Needs to fit into 1 byte for flattening purposes. + * + * Event type resides in user header of PEL log. + * + * Refer to this ErrlEntry setter: + * void ErrlEntry::setEventType(const errlEventType_t i_eventType) */ enum errlEventType_t { ERRL_ETYPE_NOT_APPLICABLE = 0x00, + ERRL_ETYPE_MISCELLANEOUS = 0x01, ERRL_ETYPE_DUMP_NOTIFICATION = 0x08, ERRL_ETYPE_USER_DECONFIG = 0x20, ERRL_ETYPE_SYS_DECONFIG = 0x21, @@ -105,39 +194,54 @@ enum errlEventType_t ERRL_ETYPE_CAPACITY_UPGRADE = 0x60, }; -/** - * @brief Error log call out priority - * Needs to fit into 1 byte for flattening purposes. - */ -enum callOutPriority_t -{ - CALLOUT_PRIORITY_LOW = 1, - CALLOUT_PRIORITY_MED = 2, - CALLOUT_PRIORITY_HIGH = 3, -}; + + /** - * @brief Error log procedure Id + * @brief SRC type definitions * Needs to fit into 1 byte for flattening purposes. + * + * This represents the byte in an SRC in position + * XX...... such as B1 in B181F00B. + * + * Refer to errlentry.H and this setter: + * void ErrlEntry::setSrcType(const srcType_t i_srcType) + * */ -enum epubProcedureId_t +enum srcType_t { - EPUB_PRC_NONE = 0x00, + SRC_INTERVENTION_REQ = 0xA1, + SRC_ERR_INFO = 0xB1, + SRC_IPL_STATUS = 0xC1, + SRC_GENERAL_STATUS = 0xD1, }; + + + /** * @brief Sub system definitions * Needs to fit into 1 byte for flattening purposes. + * This represents the byte in an SRC in position + * ..XX.... such as 81 in B181F00B. + * + * Refer to errentry.H and this setter: + * void ErrlEntry::setSubSys(const epubSubSystem_t i_subSys); */ enum epubSubSystem_t { - EPUB_RESERVED_0 = 0x00, - EPUB_UNKNOWN = 0xFF, + EPUB_RESERVED_0 = 0x00, + EPUB_FIRMWARE_SUBSYS = 0x80, + EPUB_FIRMWARE_SP = 0x81, + EPUB_UNKNOWN = 0xFF, }; + + /** * @brief Terminating flag definitions * Needs to fit into 1 word (32-bits) for flattening purposes. + * TODO Termination state and termination action. */ enum errlTermState_t { @@ -146,16 +250,41 @@ enum errlTermState_t }; -/** - * @brief SRC type definitions - * Needs to fit into 1 byte for flattening purposes. - */ -enum srcType_t + + +/** @enum errlUserDataType_t + * + * These are section type identifiers for the ERRL component for + * user-defined data sections. For example, if somebody calls + * errl->collectTrace("INITSVC") + * then the resulting UD PEL section header will be tagged with + * component id: ERRL_COMP_ID + * section type: ERRL_UDT_TRACE + * version: ERRL_UDV_DEFAULT_VER_1 + * + * Other components will have to code a similar enum so that + * the the errl parser/pretty printer can "dispatch" a user-defined + * PEL section to them for printing based on the three values in + * the UD PEL section: component id, section type, and version. + * + * The section type field in the PEL header is one byte long. + */ +enum errlUserDataType_t { - SRC_INTERVENTION_REQ = 0xA1, - SRC_ERR_INFO = 0xB1, - SRC_IPL_STATUS = 0xC1, - SRC_GENERAL_STATUS = 0xD1, + ERRL_UDT_TRACE = 0x0C, // A trace buffer +}; + + +/** @enum errlUserDataVersion + * + * Identifier for the version of user data in an error log. + * This value is used in conjuction with the type field to format + * of the additional data in an error log. Versions and type should + * be unique across subcomponents of the errl component. +*/ +enum errlUserDataVersion +{ + ERRL_UDV_DEFAULT_VER_1 = 0x0001, // Version 1, default info }; @@ -171,47 +300,6 @@ const uint32_t ERRL_STORAGE_SIZE = 65536; /** - * @brief Flattened error log header structure contains the basic - * instance variables of the ErrlEntry class. Note the - * alignment of the fields, and that the structure is packed. - */ -typedef struct errl_header -{ - uint32_t cbytes; // count of bytes in this struct - uint32_t csections; // count of sections in this error log - uint16_t reasonCode; // reason code - uint8_t unused1; // need this for alignment - uint8_t modId; // module id - uint8_t sev; // severity - uint8_t eventType; // event type - uint8_t subSys; // subsystem - uint8_t srcType; // SRC type - uint32_t termState; // Terminate state - uint32_t logId; // This log's unique ID - uint64_t user1; // Optional user data 1 - uint64_t user2; // Optional user data 2 - uint64_t CreationTime; // time error log was created -} __attribute__((packed)) errl_header_t; - - - -/** - * @brief Error logs may have a number of sections/FFDC sections added. - * This is a section header that preceeds the user-defined - * data that follows this header. Note the alignment of the fields, - * and that this structure is packed. - */ -typedef struct section_header -{ - uint32_t cbHeader; // count of bytes in this struct (flattening) - uint32_t cbSection; // count of bytes in the user-added data - uint16_t compId; // component id - uint8_t sctnVer; // section version - uint8_t subSect; // subsection -} __attribute__((packed)) section_header_t; - - -/** * @brief The RAM storage for committed error logs starts with this * header. This structure is org'ed at &g_ErrlStorage[0]. All * offsets are based from &g_achErrlStorage[0], so the first @@ -242,6 +330,152 @@ typedef struct marker + + + +/** + * @brief pelSectionHeader_t + * + * A PEL structure used to flatten error logs to PEL format. + * + * This structure represents the first 8 bytes of any PEL section. + * Populated by the flatten code of class ErrlSctnHdr for any PEL + * section. Classes ErrlUH, ErrlPrvt, and ErrlSctn each have a + * ErrlSctnHdr. User-defined sections derive from ErrlSctn, so + * their section header works though ErrlSctn parent class. + * + * When parsing a PEL data set, start at offset 0 (the + * first section). Then add "len" to know the starting offset + * of the second section, and so on. + * + * When pretty-printing a user-defined PEL section, the + * controlling logic will "dispatch" a PEL section to a + * user-supplied printing function based on the component ID, + * section type, and version. + */ +typedef struct pelsectionheader +{ + uint16_t sid; // section identifier + uint16_t len; // overall length of this section + uint8_t ver; // section version + uint8_t sst; // section type + uint16_t compId; // component ID +} __attribute__((packed)) pelSectionHeader_t; + + + +/** + * @brief pelPrivateHeaderSection_t + * + * A PEL structure used to flatten error logs to PEL format. + * + * This structure represents an entire Private Header (PH) + * PEL section. This section is a fixed overall + * length of 48 bytes including the PEL section header. + * This the first section found in a flat PEL dataset. + * Populated by the flatten code of class ErrlPrvt. + * + * The component named in the section header is the + * creating component of the error log. + */ +typedef struct pelprivateheadersection +{ + pelSectionHeader_t sectionheader; + uint64_t creationTime; + uint64_t commitTime; + uint8_t creatorId; // 'B' for Hostboot + uint8_t reserved0; + uint8_t reserved1; + uint8_t sectionCount; + uint32_t reserved2; + uint64_t creatorImplementation; + uint32_t plid; + uint32_t eid; +} __attribute__((packed)) pelPrivateHeaderSection_t; + + + +/** + * @brief pelUserHeaderSection_t + * + * A PEL structure used to flatten error logs to PEL format. + * + * This structure represents an entire User Header (UH) + * PEL section. This section is a fixed overall + * length of 0x18 bytes including the PEL section header. + * This the second section found in a flat PEL dataset. + * Populated by the flatten code of class ErrlUH. + * + * The component named in the section header is the + * committing component of the error log. + */ +typedef struct peluserheadersection +{ + pelSectionHeader_t sectionheader; + uint8_t ssid; // subsystem id + uint8_t scope; // event scope + uint8_t sev; // severity + uint8_t etype; // event type + uint32_t reserved0; // for error log return code + uint8_t domain; // TODO not used in Hostboot + uint8_t vector; // TODO not used in Hostboot + uint16_t actions; // TODO not used in Hostboot + uint32_t reserved1; +} __attribute__((packed)) pelUserHeaderSection_t; + + + + +/** + * @brief pelSRCSection_t + * + * A PEL structure used to flatten error logs to PEL format. + * + * This structure represents an entire Primary SRC (PS) + * PEL section. This section is a fixed overall + * length of 80 bytes including the PEL section header. + * This the usually the third section found in a flat PEL dataset. + * Populated by the flatten code of class ErrlSRC. + * + * Hostboot generates a minimal SRC as described under + * "Common Usage of the SRC Structure" (p.69) in the PEL + * reference (mcdoc 1675). The page numbers below refer + * to version 0.8 of that document. + */ + +typedef struct pelsrcsection +{ + pelSectionHeader_t sectionheader; + uint8_t ver; // src version, usually a 2 + uint8_t flags; // src flags + uint8_t reserved0; + uint8_t wordcount; // usually 9 + uint16_t reserved1; // usually 0, but I put reasonCode here + uint16_t srcLength; // usually 72 + // "Hex word 2" is the legacy nomenclature. p. 71. + // Low byte of this word is SRC format 0xF0. + uint32_t word2; + // "Hex word 3" p. 71 + uint16_t word3; + uint8_t moduleId; + uint8_t reserved2; + // "Hex word 4" p. 71 last progress code + uint32_t word4; + // "Hex word 5" p. 72 error status flags, etc. + uint32_t word5; + // "Hex word 6-7" p. 72 optional, iv_user1 + uint64_t word6; + // "Hex word 8-9" p. 72 optional, iv_user2 + uint64_t word8; + char srcString[32]; +} __attribute__((packed)) pelSRCSection_t; + + + + + + + } // End namespace #endif // ERRLTYPES_H diff --git a/src/include/usr/errl/errlud.H b/src/include/usr/errl/errlud.H new file mode 100644 index 000000000..30817e112 --- /dev/null +++ b/src/include/usr/errl/errlud.H @@ -0,0 +1,185 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/errl/errlud.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef ERRLUD_H +#define ERRLUD_H +/** + * @file errlud.H + * + * @brief Derive the ErrlUD (user defined) error log section from the + * more general ErrlSctn class. +*/ + + +#include <errl/errlsctn.H> +#include <errl/errlsctnhdr.H> + + + +namespace ERRORLOG +{ + + + +class ErrlUD : public ErrlSctn +{ + + + // ErrlEntry may access private elements of this class. Data items that + // you would expect to be part of ErrlEntry are actually instance data + // in this class. + friend class ErrlEntry; + + +private: + + + /** + * @brief Constructor + * + * Create a user data section with the given input data. + * + * @param i_data Pointer to data + * @param i_size Length of data + * @param i_cid Component ID of the section + * @param i_ver Section version + * @param i_sst Section type + * + */ + ErrlUD( + const void *i_data, + uint64_t i_size, + compId_t i_cid, + uint8_t i_ver, + uint8_t i_sst ); + + + + /** + * @brief Destructor + * + * Releases allocated resources + * + */ + virtual ~ErrlUD(); + + + /** + * @brief Disable copy constructor and assignment operator. + */ + ErrlUD(const ErrlUD& i_right); + ErrlUD& operator=(const ErrlUD& i_right); + + + /** + * @brief Data export size. Amount of flat storage (in bytes) required to + * store the object. + * + * @return size in bytes + */ + uint64_t flatSize(); + + + /** + * @brief Data Export facility. + * Exports the object into the architecturally + * defined format for a user data section. + * + * @param[in,out] io_pBuffer Pointer to buffer where flat data will go. + * @param[in] i_cbBuffer Count of bytes in target buffer + * + */ + uint64_t flatten( void * io_pBuffer, const uint64_t i_cbBuffer ); + + + + + + /** + * @brief Appends data to the section. + * Grows the section by the given amount + * + * @param[in] i_data Source data + * @param[in] i_size Additional size + * + * @return Size of new data or else zero on error. + * + */ + uint64_t addData( const void *i_data, uint64_t i_size ); + + + + + /** + * @brief Data size of the section + * + * The distinction is made between data size + * and object flat size. This method returns + * the size of the data only + * + * @return Length + * + */ + uint64_t dataSize( void ) const; + + + + /** + * @brief Data access + * + * Direct Access to the data of the object + * ( dangerous - use with caution ) + * + * @return Data pointer + * + */ + void * data( void ) const; + + + + + uint8_t * iv_pData; // Data Pointer + uint64_t iv_Size; // Data Length + +}; + + + +/*****************************************************************************/ +// Get data size +/*****************************************************************************/ +inline uint64_t ErrlUD::dataSize( void ) const +{ + return iv_Size; +} + + +/*****************************************************************************/ +// Data access pointer +/*****************************************************************************/ +inline void * ErrlUD::data( void ) const +{ + return iv_pData; +} + +} // namespace +#endif /* ERRLUD_H */ diff --git a/src/include/usr/errl/errluh.H b/src/include/usr/errl/errluh.H new file mode 100644 index 000000000..5768d85d1 --- /dev/null +++ b/src/include/usr/errl/errluh.H @@ -0,0 +1,165 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/errl/errluh.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef ERRLUH_H +#define ERRLUH_H + +/** + * @file errluh.H + * + * @brief A class for the user header 'UH' section of an error log. + * This classes manages those ErrlEntry data items that are destined + * to be saved in the user header PEL section. +*/ + +#include <errl/errlentry.H> +#include <errl/errlsctnhdr.H> + + +namespace ERRORLOG +{ + + +class ErrlUH +{ + + // ErrlEntry may access private elements of this class. Data items that + // you would expect to be part of ErrlEntry are actually instance data + // in this class. + friend class ErrlEntry; + + + +private: + + enum constants + { + // for generating UH section of PEL + SLEN = 16, // 16 does not include the 8 bytes of ErrlSctnHdr + VER = 1, // section version + SST = 0 // section type + }; + + /** @brief User header constructor. */ + ErrlUH( errlSeverity_t i_sev ); + + /** @brief User header destructor. */ + ~ErrlUH(); + + + /** + * @brief Disable copy constructor and assignment operator. + */ + ErrlUH(const ErrlUH& i_right); + ErrlUH& operator=(const ErrlUH& i_right); + + + /** + * @brief Data export size. Amount of flat storage (in bytes) required to + * store the object. + * + * @return size in bytes + */ + uint64_t flatSize() const; + + + /** + * @brief Data Export facility. Flatten the object into PEL for the + * 'UH' user header section. + * + * @param[in,out] io_pBuffer Pointer to buffer where flat data will go. + * @param[in] i_cbBuffer Count of bytes in target buffer + * + */ + uint64_t flatten( void * io_pBuffer, const uint64_t i_cbBuffer ); + + + /** @brief Set the component ID into the user header. + * Only should be called from ErrlEntry instance. + * The component ID in the user header identifies + * the component that committed the error log. + * + * @param[in] i_compId component ID + */ + void setComponentId( compId_t i_compId ); + + + + + // Instance variables + // SctnHdr for 'UH' section + ErrlSctnHdr iv_header; + + + errlSeverity_t iv_severity; + errlEventType_t iv_etype; + + + // TODO may need getters/setters for these fields. Presently, + // they are defaulted at object creation time, and not set + // or gotten by anyone. + epubSubSystem_t iv_ssid; + errlDomain_t iv_domain; + errlVector_t iv_vector; + uint16_t iv_actions; + errlScope_t iv_scope; + +}; + + + + + +/*****************************************************************************/ +// Destructor + +inline ErrlUH::~ErrlUH() +{ +} + + +/*****************************************************************************/ +// Export data size + +inline uint64_t ErrlUH::flatSize() const +{ + return ( iv_header.flatSize() + SLEN ); +} + + + + +/*****************************************************************************/ +// For user headers, the comp ID represents the committing component. + +inline void ErrlUH::setComponentId( compId_t i_compId ) +{ + iv_header.iv_compId = i_compId; +} + + + + +} // namespace + + +#endif //ERRLUH_H diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H index 94eb2f33d..8f1c6e382 100644 --- a/src/include/usr/hbotcompid.H +++ b/src/include/usr/hbotcompid.H @@ -53,10 +53,20 @@ const char MY_COMP_NAME[] = "myname"; //@} /** @name ERRL - * Error Logging component + * Error Logging component. + * + * Oct 2011: Temporarily set ERRL component ID to the + * same as FSP ERRL in order to make the FSP x86 errl tool + * format Hostboot error logs with traces. For user-defined + * trace sections, that tools expects component 0x3100, + * section ID 0x0C, and version 1. + * + * Requirement SW105241 is opened for fips8xx errl tool + * to start becoming Hostboot aware. TODO When errl becomes + * Hostboot aware, ERRL comp id can revert to 0x0100. Monte */ //@{ -const compId_t ERRL_COMP_ID = 0x0100; +const compId_t ERRL_COMP_ID = 0x3100; const char ERRL_COMP_NAME[] = "errl"; //@} diff --git a/src/include/usr/trace/trace.H b/src/include/usr/trace/trace.H index cb4277603..c5d0a0d2a 100644 --- a/src/include/usr/trace/trace.H +++ b/src/include/usr/trace/trace.H @@ -40,6 +40,7 @@ #include <sys/sync.h> #include <stdarg.h> + /******************************************************************************/ // Globals/Constants /******************************************************************************/ @@ -137,6 +138,9 @@ typedef Singleton<Trace> theTrace; */ class Trace { + /* ErrlEntry will call getBuffer() */ + friend class ErrlEntry; + public: /** @@ -200,6 +204,31 @@ public: const uint32_t i_size, const int32_t i_type); + + /** + * @brief Retrieve full trace buffer for component i_comp. + * + * Caller must allocate memory for the output buffer. Caller may + * first query the size of the buffer by calling with the desired + * component/trace buffer name and with o_data null and with i_bufferSize + * zero. The value returned will be the buffer size. Caller then + * allocates the buffer and calls again. + * + * @param [in] i_pComp pointer to name string + * @param [out] o_data pointer to where data will be stored + * @param [in] i_bufferSize size of buffer in bytes + * + * @return Count of bytes copied, or if given null parameters, + * the size of the buffer, or else zero for error, perhaps the + * component name/trace buffer name is not found. + */ + uint64_t getBuffer( const char * i_pComp, + void * o_data, + uint64_t i_bufferSize ); + + + + protected: /** @@ -212,6 +241,10 @@ protected: */ ~Trace(); + + + + private: /** @@ -248,21 +281,6 @@ private: const uint32_t i_size); - /** - * @brief Retrieve full trace buffer for component i_comp - * - * This function assumes memory has already been allocated for - * the full trace buffer in o_data. - * - * @param [in] i_td_ptr Trace descriptor of buffer to retrieve. - * @param [out] o_data Pre-allocated pointer to where data will be stored. - * - * TODO - Not Supported Yet - * - * @return Non-zero return code on error - */ - int32_t getBuffer(const trace_desc_t * i_td_ptr, - void *o_data); /** * @brief Retrieve partial trace buffer for component i_comp diff --git a/src/usr/errl/errlentry.C b/src/usr/errl/errlentry.C index c935ccffc..fc171fbfc 100644 --- a/src/usr/errl/errlentry.C +++ b/src/usr/errl/errlentry.C @@ -31,11 +31,10 @@ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <hbotcompid.H> #include <errl/errlentry.H> #include <errl/errlmanager.H> -#include "errlsctn.H" -#include "errlffdc.H" #include <trace/interface.H> #include <arch/ppc.H> @@ -53,70 +52,81 @@ ErrlEntry::ErrlEntry(const errlSeverity_t i_sev, const uint16_t i_reasonCode, const uint64_t i_user1, const uint64_t i_user2) : - iv_reasonCode(i_reasonCode), - iv_sev(i_sev), - iv_eventType(ERRL_ETYPE_NOT_APPLICABLE), - iv_subSys(EPUB_RESERVED_0), - iv_srcType(SRC_ERR_INFO), - iv_termState(TERM_STATE_UNKNOWN), - iv_modId(i_modId), - iv_user1(i_user1), - iv_user2(i_user2), - iv_logId(0) + iv_Private( static_cast<compId_t>(i_reasonCode & 0xFF00)), + iv_User( i_sev ), + // The SRC_ERR_INFO becomes part of the SRC; example, B1 in SRC B180xxxx + // iv_Src assigns the epubSubSystem_t; example, 80 in SRC B180xxxx + iv_Src( SRC_ERR_INFO, i_modId, i_reasonCode, i_user1, i_user2 ), + iv_termState(TERM_STATE_UNKNOWN) { - // record time of creation - iv_CreationTime = getTB(); } + + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// ErrlEntry::~ErrlEntry() { // Free memory of all sections - for (std::vector<ErrlSctn*>::iterator l_itr = iv_SectionVector.begin(); + for (std::vector<ErrlUD*>::iterator l_itr = iv_SectionVector.begin(); l_itr != iv_SectionVector.end(); ++l_itr) { delete (*l_itr); } + } /////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -ErrlFFDC* ErrlEntry::addFFDC(const compId_t i_compId, +// add a new UD section to the list of optional sections + +ErrlUD * ErrlEntry::addFFDC(const compId_t i_compId, const void * i_dataPtr, const uint32_t i_ffdcLen, const uint8_t i_ffdcVer, const uint8_t i_ffdcSubSect) { - ErrlFFDC* l_ffdcSection = NULL; + ErrlUD * l_ffdcSection = NULL; if ( (i_dataPtr == NULL) || (i_ffdcLen == 0) ) { - TRACFCOMP( ERRORLOG::g_trac_errl, - "Invalid FFDC data pointer or size, no add"); + TRACFCOMP( g_trac_errl, + "ErrlEntry::addFFDC(): Invalid FFDC data pointer or size, no add"); } else { - // Create - l_ffdcSection = new ErrlFFDC(i_compId, i_dataPtr, i_ffdcLen, - i_ffdcVer, i_ffdcSubSect); - - // Add to the end of the vector of sections for this error log. + // Create a user-defined section. + l_ffdcSection = new ErrlUD( i_dataPtr, + i_ffdcLen, + i_compId, + i_ffdcVer, + i_ffdcSubSect ); + + // Add to the vector of sections for this error log. iv_SectionVector.push_back( l_ffdcSection ); } return l_ffdcSection; } + + + + + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -void ErrlEntry::appendToFFDC(ErrlFFDC* i_ffdcPtr, +void ErrlEntry::appendToFFDC(ErrlUD * i_pErrlUD, const void *i_dataPtr, const uint32_t i_dataLen) { - // class ErrlFFDC inherits addData() from its parent class ErrlSctn - i_ffdcPtr->addData( i_dataPtr, i_dataLen ); + uint64_t l_rc; + + l_rc = i_pErrlUD->addData( i_dataPtr, i_dataLen ); + if( 0 == l_rc ) + { + TRACFCOMP( g_trac_errl, "ErrlEntry::appendToFFDC() rets zero" ); + } return; } @@ -124,39 +134,164 @@ void ErrlEntry::appendToFFDC(ErrlFFDC* i_ffdcPtr, /////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// +// Return a Boolean indication of success. -uint64_t ErrlEntry::flattenedSize() +bool ErrlEntry::collectTrace(const char i_name[], const uint32_t i_max) { - uint64_t l_bytecount = sizeof( errl_header_t ); + bool l_rc = false; - // add the bytes in the sections, if any - std::vector<ErrlSctn*>::iterator it; - for( it = iv_SectionVector.begin(); it != iv_SectionVector.end(); it++ ) + do { - l_bytecount += (*it)->flattenedSize(); + // By passing nil arguments, obtain the size of the buffer. + uint64_t l_cbFull = TRACE::Trace::getTheInstance().getBuffer( i_name, + NULL, + 0 ); + if( 0 == l_cbFull ) + { + TRACFCOMP( g_trac_errl, + "ErrlEntry::collectTrace(): getBuffer(%s) rets zero.", i_name ); + break; + } + + if( 0 == i_max ) + { + // Full trace buffer desired. Allocate the buffer. + char l_traceBuffer[ l_cbFull ]; + + // Get the data into the buffer. + TRACE::Trace::getTheInstance().getBuffer( i_name, + l_traceBuffer, + l_cbFull ); + + // Save the trace buffer as a UD section on this. + ErrlUD * l_udSection = new ErrlUD( l_traceBuffer, + l_cbFull, + ERRL_COMP_ID, + ERRL_UDV_DEFAULT_VER_1, + ERRL_UDT_TRACE ); + + // Add the trace section to the vector of sections + // for this error log. + iv_SectionVector.push_back( l_udSection ); + + l_rc = true; + break; + } + + // else partial buffer desired... future sprint + TRACFCOMP( g_trac_errl, + "ErrlEntry::collectTrace(): partial buffer not impl'd" ); + break; } + while(0); - return l_bytecount; + return l_rc; +} + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +errlSeverity_t ErrlEntry::sev() const +{ + return iv_User.iv_severity; +} + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +void ErrlEntry::setSev(const errlSeverity_t i_sev) +{ + iv_User.iv_severity = i_sev; + return; +} + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +errlEventType_t ErrlEntry::eventType() const +{ + return iv_User.iv_etype; +} + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +void ErrlEntry::setEventType(const errlEventType_t i_eventType) +{ + iv_User.iv_etype = i_eventType; + return; +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +epubSubSystem_t ErrlEntry::subSys() const +{ + return iv_User.iv_ssid; } +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +void ErrlEntry::setSubSys(const epubSubSystem_t i_subSys) +{ + iv_User.iv_ssid = i_subSys; + return; +} + + /////////////////////////////////////////////////////////////////////////////// -// Flatten object instance data into a packed structure. -// See errl/erltypes.H and the errl_header_t struct. +// for use by ErrlManager +void ErrlEntry::commit( compId_t i_committerComponent ) +{ + // TODO need a better timepiece, or else apply a transform onto timebase + // for an approximation of real time. + iv_Private.iv_committed = getTB(); + + // User header contains the component ID of the committer. + iv_User.setComponentId( i_committerComponent ); +} + + +////////////////////////////////////////////////////////////////////////////// +// for use by ErrlManager + +uint64_t ErrlEntry::flattenedSize() +{ + uint64_t l_bytecount = iv_Private.flatSize() + + iv_User.flatSize() + + iv_Src.flatSize(); + + // plus the sizes of the other optional sections + + std::vector<ErrlUD*>::iterator it; + for( it = iv_SectionVector.begin(); it != iv_SectionVector.end(); it++ ) + { + l_bytecount += (*it)->flatSize(); + } + return l_bytecount; +} + + +///////////////////////////////////////////////////////////////////////////// +// Flatten this object and all its sections into PEL +// for use by ErrlManager. Return how many bytes flattened to the output +// buffer, or else zero on error. -uint64_t ErrlEntry::flatten( void * io_pBuffer, uint64_t i_bufsize ) +uint64_t ErrlEntry::flatten( void * o_pBuffer, uint64_t i_bufsize ) { uint64_t l_flatCount = 0; + uint64_t l_cb = 0; do { l_flatCount = flattenedSize(); if ( i_bufsize < l_flatCount ) { - // error path; return zero + // buffer is not big enough; return zero TRACFCOMP( ERRORLOG::g_trac_errl, "Invalid buffer size"); l_flatCount = 0; break; @@ -165,50 +300,69 @@ uint64_t ErrlEntry::flatten( void * io_pBuffer, uint64_t i_bufsize ) // The CPPASSERT() macro will cause the compile to abend // when the expression given evaluates to false. If ever // these cause the compile to fail, then perhaps the size - // of enum'ed types has grown unexpectedly. At any rate, - // errl_header_t defined in errl/errltypes.H will need to - // be adjusted for the changes in size of these instance - // variables. Monte - CPPASSERT( 1 == sizeof(iv_sev)); - CPPASSERT( 1 == sizeof(iv_eventType)); - CPPASSERT( 1 == sizeof(iv_subSys)); - CPPASSERT( 1 == sizeof(iv_srcType)); - CPPASSERT( 2 == sizeof(iv_reasonCode)); + // of enum'ed types has grown unexpectedly. + CPPASSERT( 1 == sizeof(iv_Src.iv_srcType)); + CPPASSERT( 2 == sizeof(iv_Src.iv_reasonCode)); CPPASSERT( 2 == sizeof(compId_t)); - CPPASSERT( 1 == sizeof(iv_modId)); - CPPASSERT( 0 == (sizeof(errl_header_t) % sizeof(uint32_t))); - - - // Marshall the instance var data into a struct. - errl_header_t l_hdr; - memset( &l_hdr, 0, sizeof( l_hdr )); - l_hdr.cbytes = sizeof( l_hdr ); - l_hdr.csections = iv_SectionVector.size(); - l_hdr.reasonCode = iv_reasonCode; - l_hdr.modId = iv_modId; - l_hdr.sev = iv_sev; - l_hdr.eventType = iv_eventType; - l_hdr.subSys = iv_subSys; - l_hdr.srcType = iv_srcType; - l_hdr.termState = iv_termState; - l_hdr.logId = iv_logId; - l_hdr.user1 = iv_user1; - l_hdr.user2 = iv_user2; - l_hdr.CreationTime = iv_CreationTime; - - - // Write the flat data. - char * l_pchar = reinterpret_cast<char*>(io_pBuffer); - memcpy( l_pchar, &l_hdr, sizeof( l_hdr )); - l_pchar += sizeof( l_hdr ); - - // Append all the sections. - std::vector<ErrlSctn*>::iterator it; - for(it=iv_SectionVector.begin(); it != iv_SectionVector.end(); it++ ) + CPPASSERT( 1 == sizeof(iv_Src.iv_modId)); + + // Inform the private header how many sections there are, + // counting the PH, UH, PS, and the optionals. + iv_Private.iv_sctns = 3 + iv_SectionVector.size(); + + // Flatten the PH private header section + char * pBuffer = static_cast<char *>(o_pBuffer); + l_cb = iv_Private.flatten( pBuffer, i_bufsize ); + if( 0 == l_cb ) { - uint64_t l_countofbytes = (*it)->flattenedSize(); - (*it)->flatten( l_pchar, l_countofbytes ); - l_pchar += l_countofbytes; + // Rare. + TRACFCOMP( g_trac_errl, "ph.flatten error"); + l_flatCount = 0; + break; + } + + pBuffer += l_cb; + i_bufsize -= l_cb; + + // flatten the UH user header section + l_cb = iv_User.flatten( pBuffer, i_bufsize ); + if( 0 == l_cb ) + { + // Rare. + TRACFCOMP( g_trac_errl, "uh.flatten error"); + l_flatCount = 0; + break; + } + pBuffer += l_cb; + i_bufsize -= l_cb; + + // flatten the PS primary SRC section + l_cb = iv_Src.flatten( pBuffer, i_bufsize ); + if( 0 == l_cb ) + { + // Rare. + TRACFCOMP( g_trac_errl, "ps.flatten error"); + l_flatCount = 0; + break; + } + pBuffer += l_cb; + i_bufsize -= l_cb; + + + // flatten the optional user-defined sections + std::vector<ErrlUD*>::iterator it; + for(it = iv_SectionVector.begin(); it != iv_SectionVector.end(); it++) + { + l_cb = (*it)->flatten( pBuffer, i_bufsize ); + if( 0 == l_cb ) + { + // Rare. + TRACFCOMP( g_trac_errl, "ud.flatten error"); + l_flatCount = 0; + break; + } + pBuffer += l_cb; + i_bufsize -= l_cb; } } while( 0 ); @@ -218,6 +372,5 @@ uint64_t ErrlEntry::flatten( void * io_pBuffer, uint64_t i_bufsize ) - } // End namespace diff --git a/src/usr/errl/errlffdc.C b/src/usr/errl/errlffdc.C deleted file mode 100644 index cc8d6e7fc..000000000 --- a/src/usr/errl/errlffdc.C +++ /dev/null @@ -1,66 +0,0 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/usr/errl/errlffdc.C $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END -/** - * @file errlffdc.C - * - * @brief Implementation of ErrlFFDC class - */ - -/*****************************************************************************/ -// I n c l u d e s -/*****************************************************************************/ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <trace/interface.H> -#include "errlffdc.H" - - -namespace ERRORLOG -{ - -extern trace_desc_t* g_trac_errl; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -ErrlFFDC::ErrlFFDC(const compId_t i_compId, - const void* i_ffdcPtr, - const uint32_t i_ffdcLen, - const uint8_t i_ffdcVer, - const uint8_t i_ffdcSubSect) -: ErrlSctn(i_compId, i_ffdcVer, i_ffdcSubSect) -{ - - // addData is inherited from parent class ErrlSctn - addData(i_ffdcPtr, i_ffdcLen); -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -ErrlFFDC::~ErrlFFDC() -{ -} - - - -} // End namespace diff --git a/src/usr/errl/errlffdc.H b/src/usr/errl/errlffdc.H deleted file mode 100644 index c6be4c8a7..000000000 --- a/src/usr/errl/errlffdc.H +++ /dev/null @@ -1,96 +0,0 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/usr/errl/errlffdc.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END -#ifndef ERRLFFDC_H -#define ERRLFFDC_H -/** - * @file errlffdc.H - * - * @brief FFDC data section within ErrlEntry object - * - * This header file contains the definition of FFDC data class that - * is attached within the ErrlEntry object. - * - */ - -/*****************************************************************************/ -// I n c l u d e s -/*****************************************************************************/ -#include <stdint.h> -#include <stdlib.h> -#include "errlsctn.H" - - -namespace ERRORLOG -{ - -/** - * @brief Abstract an FFDC data section in an error log - * This class contains FFDC data that users add to an error log. - */ -class ErrlFFDC: public ErrlSctn -{ - -public: - - /** - * @brief Constructor - * Create a user data FFDC section with the given - * input data. - * - * @param[in] i_compId Creator (component id) - * @param[in] i_ffdcPtr Data pointer - * @param[in] i_ffdcLen Data length (bytes) - * @param[in] i_ffdcVer Data identifier - * @param[in] i_ffdcSubSect Sub section identifier - * - * @return void - */ - ErrlFFDC(const compId_t i_compId, - const void* i_ffdcPtr, - const uint32_t i_ffdcLen, - const uint8_t i_ffdcVer, - const uint8_t i_ffdcSubSect); - - - /** - * @brief Cleanup ( destructor ) - * - * Releases allocated resources - * - */ - ~ErrlFFDC(); - - -private: - /** - * @brief Disabled copy constructor and assignment operator - */ - ErrlFFDC(const ErrlFFDC& i_right); - ErrlFFDC& operator=(const ErrlFFDC& i_right); - -}; - - -} // End namespace - -#endif //ERRLFFDC_H diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C index 42cd3def8..48bc22325 100644 --- a/src/usr/errl/errlmanager.C +++ b/src/usr/errl/errlmanager.C @@ -105,6 +105,7 @@ ErrlManager::ErrlManager() // marker_t* l_pMarker = OFFSET2MARKER( iv_pStorage->offsetStart ); // l_pMarker->offsetNext = 0; // l_pMarker->length = 0; + } /////////////////////////////////////////////////////////////////////////////// @@ -117,7 +118,7 @@ ErrlManager::~ErrlManager() // // Save and delete this error log. On output, io_err will be nul. // -void ErrlManager::commitErrLog(errlHndl_t& io_err) +void ErrlManager::commitErrLog(errlHndl_t& io_err, compId_t i_committerComp ) { do { @@ -132,9 +133,8 @@ void ErrlManager::commitErrLog(errlHndl_t& io_err) // lock sem mutex_lock(&iv_mutex); - // Assign a unique error ID to the committed log - uint32_t l_errId = getUniqueErrId(); - io_err->setLogId(l_errId); + // Ask the ErrlEntry to assign commit component, commit time, etc. + io_err->commit( i_committerComp ); // Get flattened count of bytes. uint32_t l_cbActualFlat = io_err->flattenedSize(); @@ -185,20 +185,18 @@ void ErrlManager::commitErrLog(errlHndl_t& io_err) /////////////////////////////////////////////////////////////////////////////// -// This operation is protected by the callers use of a mutex. +// Atomically increment log id and return it. uint32_t ErrlManager::getUniqueErrId() { - /* return (__sync_add_and_fetch(&iv_currLogId, 1)); */ - iv_currLogId++; - return iv_currLogId; + return (__sync_add_and_fetch(&iv_currLogId, 1)); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Global function (not a method on an object) to commit the error log. -void errlCommit(errlHndl_t& io_err) +void errlCommit(errlHndl_t& io_err, compId_t i_committerComp ) { - ERRORLOG::theErrlManager::instance().commitErrLog(io_err); + ERRORLOG::theErrlManager::instance().commitErrLog(io_err, i_committerComp ); return; } diff --git a/src/usr/errl/errlprvt.C b/src/usr/errl/errlprvt.C new file mode 100644 index 000000000..064d842b8 --- /dev/null +++ b/src/usr/errl/errlprvt.C @@ -0,0 +1,135 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/errl/errlprvt.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file errlprvt.C + * + * @brief Implemenation of ErrlPrvt, a class for the management + * of the Private Header (PH) section of PEL. + * +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <hbotcompid.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> + + + + +namespace ERRORLOG +{ + + +extern trace_desc_t* g_trac_errl; + + + +/****************************************************************************/ +// Constructor for the private header (PH) section of PEL. + +ErrlPrvt::ErrlPrvt( compId_t i_CreatorCompId ) : + // contruct the ErrlSctnHdr + iv_header( ERRL_SID_PRIVATE_HEADER, + ErrlPrvt::SLEN, + ErrlPrvt::VER, + ErrlPrvt::SST, + i_CreatorCompId ), + iv_created( 0 ), // created time + iv_committed( 0 ), // committed time + iv_cid( ERRL_CID_HOSTBOOT ), // 'B' See errlCreator_t in errltypes.H + iv_sctns( 0 ) +{ + // Ask the errl manager for the next ID to assign. + iv_plid = ERRORLOG::theErrlManager::instance().getUniqueErrId(); + + // Set the time of creation. + // TODO The field iv_created and iv_committed expect an 8-byte + // BCD-encoded timestamp. However, the FSP errl tool does not complain + // about displaying the timebase value. Perhaps we can apply a transform + // on time base to get an approximation of real time. + iv_created = getTB(); + +} + + +/*****************************************************************************/ +// Data export. +// Flatten the data to the output pointer given as PEL as defined in +// eCLipz and P7 Platform Event Log and SRC PLDD mcdoc 1675 +// Return how many bytes flattened, or else zero for error. + + +uint64_t ErrlPrvt::flatten( void * o_pBuffer, const uint64_t i_cbBuffer ) +{ + uint64_t l_rc = 0; + uint64_t l_cb = 0; + + do + { + + if( i_cbBuffer < iv_header.iv_slen ) + { + TRACFCOMP( g_trac_errl, "ErrlPrvt::flatten: buffer too small"); + break; + } + + CPPASSERT( 48 == sizeof( pelPrivateHeaderSection_t )); + + // See errltypes.H for pelPrivateHeaderSection_t + pelPrivateHeaderSection_t * p; + p = static_cast<pelPrivateHeaderSection_t *>(o_pBuffer); + memset( p, 0, sizeof( *p )); + + // Get the ErrlSctnHdr to flatten its data first. + l_cb = iv_header.flatten( &p->sectionheader, i_cbBuffer ); + if( 0 == l_cb ) + { + // Rare. + TRACFCOMP(g_trac_errl,"ErrlPrvt::flatten: header.flatten problem"); + break; + } + + // Set the ErrlPrvt instance data items. + p->creationTime = iv_created; + p->commitTime = iv_committed; + p->creatorId = iv_cid; + p->sectionCount = iv_sctns; + p->plid = iv_plid; + + // TODO In the future, eid may be different than PLID + p->eid = iv_plid; + + // return amount of bytes flattened + l_rc = iv_header.iv_slen; + } + while( 0 ); + + return l_rc; +} + + + +} // namespace diff --git a/src/usr/errl/errlsctn.C b/src/usr/errl/errlsctn.C index d82a6869f..14e815bf5 100644 --- a/src/usr/errl/errlsctn.C +++ b/src/usr/errl/errlsctn.C @@ -23,15 +23,19 @@ /** * @file errlsctn.C * - * @brief Implementation of ErrlSctn class + * @brief Implementation of ErrlSctn class. */ /*****************************************************************************/ // I n c l u d e s /*****************************************************************************/ -#include <trace/interface.H> -#include "errlsctn.H" #include <assert.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <trace/interface.H> +#include <errl/errlentry.H> + namespace ERRORLOG { @@ -41,110 +45,24 @@ extern trace_desc_t* g_trac_errl; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -ErrlSctn::ErrlSctn(const compId_t i_compId, - const uint8_t i_sctnVer, - const uint8_t i_subSect) -:iv_ErrlSctnHdr(i_compId, i_sctnVer, i_subSect),iv_pData(NULL),iv_cbData(0) -{ -} -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -ErrlSctn::~ErrlSctn() +ErrlSctn::ErrlSctn( const uint16_t i_sid, + const uint16_t i_slen, + const uint8_t i_ver, + const uint8_t i_sst, + const compId_t i_compId ) : + iv_header( i_sid, i_slen, i_ver, i_sst, i_compId ) { - delete iv_pData; -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -uint64_t ErrlSctn::addData(const void *i_data, const uint64_t i_size) -{ - uint64_t l_rc = 0; - - // Expected new size of user data. - uint64_t l_newsize = iv_cbData + i_size; - - // Resize memory block - iv_pData = static_cast<uint8_t*>(realloc(iv_pData, l_newsize)); - // Make sure reallocate call succeeds - if (iv_pData != NULL) - { - // Copy new data to new area, past existing data (if any) - memcpy( iv_pData+iv_cbData, i_data, i_size ); - - // Save new size of the user-provided data. - l_rc = iv_cbData = l_newsize; - } - else - { - TRACFCOMP( g_trac_errl, - "ErrlFFDC::addData() - Reallocate memory failed!"); - } - return l_rc; } -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -uint64_t ErrlSctn::flattenedSize() -{ - return sizeof(section_header_t) + iv_cbData; -} - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -uint64_t ErrlSctn::flatten( void* io_pBuffer, uint64_t i_bufsize ) +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlSctn::~ErrlSctn() { - uint64_t l_flatCount = 0; - - do - { - l_flatCount = flattenedSize(); - if( i_bufsize < l_flatCount ) - { - // error path, return 0 - TRACFCOMP( g_trac_errl, "Invalid buffer size" ); - l_flatCount = 0; - break; - } - // CPPASSERT() makes an assertion to the compiler, and if the - // expression is false, the compile will end in error. If these - // compiler asserts should fail, then the packed structures - // defined in errl/errltypes.H will need to be adjusted. - CPPASSERT( 2 == sizeof(iv_ErrlSctnHdr.iv_compId)); - CPPASSERT( 1 == sizeof(iv_ErrlSctnHdr.iv_sctnVer)); - CPPASSERT( 1 == sizeof(iv_ErrlSctnHdr.iv_subSect)); - CPPASSERT( 0 == sizeof( section_header_t ) % sizeof( uint32_t )); - - - // Marshall the data into a section_header_t - section_header_t l_Header; - memset( &l_Header, 0, sizeof( l_Header )); - l_Header.cbHeader = sizeof( l_Header ); - l_Header.cbSection = iv_cbData; - l_Header.compId = iv_ErrlSctnHdr.iv_compId; - l_Header.sctnVer = iv_ErrlSctnHdr.iv_sctnVer; - l_Header.subSect = iv_ErrlSctnHdr.iv_subSect; - - - // Write data to caller's memory. - char * l_pchar = static_cast<char *>(io_pBuffer); - memcpy( l_pchar, &l_Header, sizeof( l_Header )); - l_pchar += sizeof( l_Header ); - - // Write any user-defined data. - if( iv_cbData ) - { - memcpy( l_pchar, iv_pData, iv_cbData ); - } - } - while( 0 ); - - return l_flatCount; } - } // end namespace diff --git a/src/usr/errl/errlsctnhdr.C b/src/usr/errl/errlsctnhdr.C index 175476e34..dbdefa26a 100644 --- a/src/usr/errl/errlsctnhdr.C +++ b/src/usr/errl/errlsctnhdr.C @@ -23,31 +23,36 @@ /** * @file errlsctnhdr.C * - * @brief Abstract header of all error log's sections - * - * This header file contains the definition of common section header in - * each error log's section + * @brief Header data for any/all sections in an error log. * */ -/*****************************************************************************/ -// I n c l u d e s -/*****************************************************************************/ -#include "errlsctnhdr.H" + + + +#include <assert.h> +#include <errl/errlsctnhdr.H> namespace ERRORLOG { +extern trace_desc_t* g_trac_errl; + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -ErrlSctnHdr::ErrlSctnHdr(const compId_t i_compId, - const uint8_t i_sctnVer, - const uint8_t i_subSect) -:iv_compId(i_compId), -iv_sctnVer(i_sctnVer), -iv_subSect(i_subSect) +ErrlSctnHdr::ErrlSctnHdr( const uint16_t i_sid, + const uint16_t i_slen, + const uint8_t i_ver, + const uint8_t i_sst, + const compId_t i_compId ) : +iv_sid( i_sid ), +iv_ver( i_ver ), +iv_sst( i_sst ), +iv_compId(i_compId) { - + // Caller/owner of this instance has provided the slen (section length) + // for its data, but does not include the size of its ErrlSctnHdr. + iv_slen = i_slen + flatSize(); } @@ -58,4 +63,47 @@ ErrlSctnHdr::~ErrlSctnHdr() } + +/////////////////////////////////////////////////////////////////////////////// +// Flatten the data to the output pointer given as PEL as defined in +// eCLipz and P7 Platform Event Log and SRC PLDD mcdoc 1675 + +uint64_t ErrlSctnHdr::flatten( void * o_pBuffer, const uint64_t i_cbBuffer ) +{ + uint64_t l_rc = 0; + + // Compile-time assertions + CPPASSERT( 8 == sizeof( pelSectionHeader_t )); + CPPASSERT( 2 == sizeof( iv_sid )); + CPPASSERT( 2 == sizeof( iv_slen )); + CPPASSERT( 1 == sizeof( iv_ver )); + CPPASSERT( 1 == sizeof( iv_sst )); + CPPASSERT( 2 == sizeof( iv_compId )); + + if( i_cbBuffer >= sizeof( pelSectionHeader_t )) + { + // See errltypes.H for pelSectionHeader_t. Flatten to + // local, temporary l_header because it will be word aligned, + // whereas caller's output address is not guaranteed to be. + pelSectionHeader_t l_header; + + l_header.sid = iv_sid; + l_header.len = iv_slen; + l_header.ver = iv_ver; + l_header.sst = iv_sst; + l_header.compId = iv_compId; + + // memcpy out to callers buffer + memcpy( o_pBuffer, &l_header, sizeof( pelSectionHeader_t )); + l_rc = sizeof( pelSectionHeader_t ); + } + else + { + TRACFCOMP( g_trac_errl, "ErrlSctnHdr::flatten: buffer too small"); + } + + return l_rc; +}; + + } // End namespace diff --git a/src/usr/errl/errlsctnhdr.H b/src/usr/errl/errlsctnhdr.H deleted file mode 100644 index 55e9cf295..000000000 --- a/src/usr/errl/errlsctnhdr.H +++ /dev/null @@ -1,102 +0,0 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/usr/errl/errlsctnhdr.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END -#ifndef ERRLSCTNHDR_H -#define ERRLSCTNHDR_H -/** - * @file errlsctnhdr.H - * - * @brief This file contain the class that abstracts the header of - * an error log section. - * - */ - -/*****************************************************************************/ -// I n c l u d e s -/*****************************************************************************/ -#include <stdint.h> -#include <stdlib.h> -#include <errl/errltypes.H> -#include <hbotcompid.H> -#include <string.h> - -namespace ERRORLOG -{ - -/** - * @brief This class abstracts a header of a section in an error log object - */ -class ErrlSctnHdr -{ - // ErrlSctn accesses ErrlSctnHdr directly. - friend class ErrlSctn; - - /** - * @brief Section header constructor - * - * @param[in] i_compId Component Id of the caller - * @param[in] i_sctnVer A user supplied identifier which - * classifies the data in the section - * @param[in] i_subSect A user supplied sub section identifier - * which classifies the data. This in - * conjunction with the version can be used - * to decode the data. - * @return void - */ - ErrlSctnHdr(const compId_t i_compId, - const uint8_t i_sctnVer, - const uint8_t i_subSect); - - /** - * @brief Default destructor - * - * @return void - */ - ~ErrlSctnHdr(); - - //@todo - Need to add serialization interfaces for ErrlSctnHdr object. - // Serialization method (boost serialization?) for HostBoot - // is currently not yet determined. - // Note: stream is currently not supported - - - -private: - - /** - * @brief Disabled copy constructor and assignment operator - */ - ErrlSctnHdr(const ErrlSctnHdr& i_right); - ErrlSctnHdr& operator=(const ErrlSctnHdr& i_right); - - // Data - // Can/will be accessed by friend class ErrlSctn - compId_t iv_compId; - uint8_t iv_sctnVer; - uint8_t iv_subSect; - -}; - -} // End namespace - -#endif //ERRLSCTNHDR_H - diff --git a/src/usr/errl/errlsrc.C b/src/usr/errl/errlsrc.C new file mode 100644 index 000000000..3c50aed25 --- /dev/null +++ b/src/usr/errl/errlsrc.C @@ -0,0 +1,164 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/errl/errlsrc.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file errlsrc.C + * + * @brief Manage the data items that make up the 'PS' section in an + * error log PEL. PS stands for Primary System Reference Code, or SRC. + * ErrlSrc is a derivation of ErrlSctn. + * +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <hbotcompid.H> +#include <errl/errlentry.H> + + + +namespace ERRORLOG +{ + + +extern trace_desc_t* g_trac_errl; + + + +//************************************************************************** +// constructor + + +ErrlSrc::ErrlSrc( srcType_t i_srcType, + uint8_t i_modId, + uint16_t i_reasonCode, + uint64_t i_user1, + uint64_t i_user2 ) : + + ErrlSctn( ERRL_SID_PRIMARY_SRC, + ErrlSrc::SLEN, + ErrlSrc::VER, + ErrlSrc::SST, + 0 ), // Component ID zero for now. + iv_srcType( i_srcType ), + iv_modId( i_modId ), + iv_reasonCode( i_reasonCode ), + iv_ssid( EPUB_FIRMWARE_SUBSYS ), + iv_user1( i_user1 ), + iv_user2( i_user2 ) +{ + + +} + + +//**************************************************************************** +// + +ErrlSrc::~ErrlSrc() +{ + +} + + + +//************************************************************************** +// Flatten the PS primary SRC data to a minimum standard 72-byte structure. +// Page numbers refer to Platform Event Log and SRC PLDD +// https://mcdoc.boeblingen.de.ibm.com/out/out.ViewDocument.php?documentid=1675 +// Version 0.8 (markup). See also src/include/usr/errl/errltypes.H +// for the typedef pelSRCSection_t. + +uint64_t ErrlSrc::flatten( void * o_pBuffer, const uint64_t i_cbBuffer ) +{ + uint64_t l_rc = 0; + + do + { + if( i_cbBuffer < flatSize() ) + { + TRACFCOMP( g_trac_errl, "ErrlSrc::flatten: buffer too small"); + break; + } + + pelSRCSection_t * psrc = static_cast<pelSRCSection_t *>(o_pBuffer); + + // memset zero up to the char array. + memset( psrc, 0, flatSize() - sizeof( psrc->srcString )); + + // memset spaces into the char array + memset( psrc->srcString, ' ', sizeof( psrc->srcString )); + + l_rc = iv_header.flatten( o_pBuffer, i_cbBuffer ); + if( 0 == l_rc ) + { + // Rare. + TRACFCOMP( g_trac_errl, "ErrlSrc::flatten: header flatten error"); + break; + } + + + // Place data into the flat structure. + psrc->ver = ErrlSrc::SRCVER; // 2; See p.69 + // psrc->flags = 0; // p.69 + psrc->wordcount = ErrlSrc::WORDCOUNT; // 9; See p.69 + + // TODO FSP firmware puts zero here. Cheat and put reasonCode here. + // Makes for easier retrieval than teasing it out of the SRC + // ascii string. (Am I missing something?) + psrc->reserved1 = iv_reasonCode; + + CPPASSERT( ErrlSrc::SLEN == sizeof(pelSRCSection_t)-iv_header.flatSize()); + psrc->srcLength = ErrlSrc::SLEN; + + // SRC format p.71 of PEL reference. + psrc->word2 = 0xF0; + + // Stash the Hostboot module id into hex word 3 + psrc->moduleId = iv_modId; // p.71 + + // Stash the Hostboot long long words into the hexwords of the SRC. + psrc->word6 = iv_user1; // spans 6-7 + psrc->word8 = iv_user2; // spans 8-9 + + // Build the char string for the SRC. + uint32_t l_u32; + l_u32 = (iv_srcType<< 24)|(iv_ssid<<16)| iv_reasonCode; + + char l_tmpString[ 20 ]; + uint64_t cb = sprintf( l_tmpString, "%X", l_u32 ); + memcpy( psrc->srcString, l_tmpString, cb ); + + l_rc = flatSize(); + } + while( 0 ); + + return l_rc; +} + + +} // namespace + + + diff --git a/src/usr/errl/errlud.C b/src/usr/errl/errlud.C new file mode 100644 index 000000000..f7b51ebd2 --- /dev/null +++ b/src/usr/errl/errlud.C @@ -0,0 +1,168 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/errl/errlud.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file errlud.C + * + * @brief <Brief Description of this file> + * + * <Detailed description of what this file does, functions it includes, + * etc,> +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <hbotcompid.H> +#include <errl/errlentry.H> + + + +namespace ERRORLOG +{ + + +extern trace_desc_t* g_trac_errl; + + +//*************************************************************************** +// Constructor + +ErrlUD::ErrlUD( + const void * i_data, + uint64_t i_size, + compId_t i_compid, + uint8_t i_ver, + uint8_t i_sst ) : + + ErrlSctn( ERRL_SID_USER_DEFINED, 0, i_ver, i_sst, i_compid ), + iv_pData( NULL ), + iv_Size( 0 ) +{ + uint64_t l_cb; + + l_cb = addData( i_data, i_size ); + if( 0 == l_cb ) + { + // Rare. + TRACFCOMP( g_trac_errl, "ErrlUD::ErrlUD(): addData rets error"); + } +} + + + + + +/*****************************************************************************/ +// Destructor + +ErrlUD::~ErrlUD() +{ + if( iv_pData ) free( iv_pData ); +} + + + + + +/*****************************************************************************/ +// Add data. This works the first time when there is no data and works for +// subsequent times when you want to append data. Return [new] size of buffer. + +uint64_t ErrlUD::addData(const void *i_data, const uint64_t i_size) +{ + uint64_t l_rc = 0; + + // Expected new size of user data. + uint64_t l_newsize = iv_Size + i_size; + + // Resize memory block + iv_pData = static_cast<uint8_t*>(realloc(iv_pData, l_newsize)); + + // Make sure reallocate call succeeds + if (iv_pData != NULL) + { + // Copy new data to new area, past existing data (if any) + memcpy( iv_pData + iv_Size, i_data, i_size ); + + // Save new size of the user-provided data. This will also + // be what this method returns. + iv_Size = l_newsize; + l_rc = iv_Size; + + // Tell the PEL header what is the new length. + iv_header.iv_slen = iv_header.flatSize() + iv_Size; + } + else + { + TRACFCOMP( g_trac_errl, + "ErrlUD::addData() - Reallocate memory failed!"); + } + return l_rc; +} + + + +/*****************************************************************************/ +// Data Export size + +uint64_t ErrlUD::flatSize() +{ + uint64_t l_rc = 0; + + l_rc = iv_header.flatSize() + iv_Size; + + return l_rc; +} + + +/*****************************************************************************/ +// Data Export. Return how many bytes were written or zero on error. + +uint64_t ErrlUD::flatten( void * o_pBuffer, const uint64_t i_cbBuffer ) +{ + uint64_t l_rc = 0; + uint64_t cb = 0; + uint8_t * pBuffer = static_cast<uint8_t *>(o_pBuffer); + + if ( i_cbBuffer >= this->flatSize() ) + { + // flatten the section header + cb = iv_header.flatten( pBuffer, i_cbBuffer ); + pBuffer += cb; + + // followed by the user data + memcpy( pBuffer, iv_pData, iv_Size ); + + // return how many bytes were flattened + l_rc = iv_Size + cb; + } + else + { + TRACFCOMP( g_trac_errl, "ErrlUD::flatten: buffer too small"); + } + + + return l_rc; +} + +} //namespace diff --git a/src/usr/errl/errluh.C b/src/usr/errl/errluh.C new file mode 100644 index 000000000..cdaaa1619 --- /dev/null +++ b/src/usr/errl/errluh.C @@ -0,0 +1,114 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/errl/errluh.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file errluh.C + * + * @brief Code to manage the contents of the user header + * section of an error log. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <hbotcompid.H> +#include <errl/errlentry.H> + + + + +namespace ERRORLOG +{ + + +extern trace_desc_t* g_trac_errl; + + +/*****************************************************************************/ +// Constructor + +ErrlUH::ErrlUH( errlSeverity_t i_sev ) : + iv_header( ERRL_SID_USER_HEADER, + ErrlUH::SLEN, + ErrlUH::VER, + ErrlUH::SST, + 0), // Component ID is zero until commit time + iv_severity( i_sev ), + iv_etype( ERRL_ETYPE_NOT_APPLICABLE ), + iv_ssid( EPUB_FIRMWARE_SUBSYS ), // 0x80 here yields SRC B180xxxx + iv_domain( ERRL_DOMAIN_DEFAULT ), + iv_vector( ERRL_VECTOR_DEFAULT ), + iv_actions( ERRL_ACTION_NONE ), + iv_scope( ERRL_SCOPE_PLATFORM ) +{ + +} + + + +/***************************************************************************/ +// Data Export + +uint64_t ErrlUH::flatten( void * io_pBuffer, const uint64_t i_cbBuffer ) +{ + uint64_t l_rc = 0; + + + // compile-type assertion + CPPASSERT( 24 == sizeof( pelUserHeaderSection_t )); + + + if( i_cbBuffer >= iv_header.iv_slen ) + { + pelUserHeaderSection_t * p; + p = static_cast<pelUserHeaderSection_t*>(io_pBuffer); + memset( p, 0, sizeof(*p)); + + // Get the ErrlSctnHdr to flatten its data first. + iv_header.flatten( &p->sectionheader, i_cbBuffer ); + + // Set the ErrlUH instance data items in to the + // flat user header PEL struct. + p->ssid = iv_ssid; + p->scope = iv_scope; + p->sev = iv_severity; + p->etype = iv_etype; + p->domain = iv_domain; + p->vector = iv_vector; + p->actions = iv_actions; + + // Return count of bytes flattened + l_rc = iv_header.iv_slen; + } + else + { + TRACFCOMP( g_trac_errl, "ErrlUH::flatten: buffer too small" ); + } + return l_rc; +} + + + + + + +} // namespace diff --git a/src/usr/errl/makefile b/src/usr/errl/makefile index 6c53192e7..924f34623 100644 --- a/src/usr/errl/makefile +++ b/src/usr/errl/makefile @@ -23,7 +23,7 @@ ROOTPATH = ../../.. MODULE = errl -OBJS = errlentry.o errlmanager.o errlsctn.o errlffdc.o errlsctnhdr.o +OBJS = errlentry.o errlmanager.o errlsctn.o errlsctnhdr.o errlprvt.o errluh.o errlud.o errlsrc.o SUBDIRS = test.d parser.d diff --git a/src/usr/errl/parser/errlparser.C b/src/usr/errl/parser/errlparser.C index 5880e6db2..ccf9bf915 100644 --- a/src/usr/errl/parser/errlparser.C +++ b/src/usr/errl/parser/errlparser.C @@ -20,11 +20,33 @@ // Origin: 30 // // IBM_PROLOG_END + + /** * @file errlparser.C * - * @brief Parse and display committed error logs. Enter - * errlparser ? (or -? or -h or --help) to print help. + * @brief Builds a program to display committed Hostboot error logs. + * Enter errlparser ? (or -? or -h or --help) to print help. + * This program can be run standalone using a Simics + * L3 memory image and the HB syms file, however it is more likely + * spawned as "simcis> hb-errl" from the Hostboot/Simics python + * script. + * + * This program spawns the FSP x86 version of errl and fsp-trace + * which may or may not be in your $PATH. Candidates are: + * + * Classic FSP errl: + * /esw/fips730/Builds/b0829a_1130.730/obj/x86.nfp/errl/nfp/tool/errl + * + * Or this version in Monte's sandbox which is more Hostboot aware: + * /gsa/ausgsa/home/c/o/copelanm/public/bin/errl + * + * Building Blocks version of fsp-trace: + * /opt/mcp/shared/fr_DEV-37/opt/fsp/usr/bin/fsp-trace + * + * Camvan has a solution for PATHing to fsp-trace when in Simics. + * TODO Will need a copy of FSP x86 errl too in the near future. + * */ @@ -37,32 +59,41 @@ #include <errno.h> #include <assert.h> #include <string> +#include <vector> using namespace std; #include <errl/errltypes.H> #include <hbotcompid.H> + + +// Include the file that was generated by scanforsrcs.pl #include <hostBootSrcParse.H> + + using namespace ERRORLOG; + #define USAGE "\ Usage:\n\ \n\ -errlparser [-i] <imagefile> [[-s] <symsfile>] [-l | -d [<logid>|all]] [-v]\n\ +errlparser [-i]<image> [[-s]<syms>] [-l|-d[<logid>|all]] [-t <stringfile>]\n\ \n\ Arguments:\n\ - <imagefile> data file name\n\ - <symsfile> symbols file name\n\ + <image> data file name\n\ + <syms> symbols file name\n\ -l summarize all error logs (default)\n\ -d id print detail from specific error log\n\ - -s name explicitly name the symbols file\n\ -i name explicitly name the image file\n\ + -s name explicitly name the symbols file\n\ + -t name name the hbotStringFile\n\ -v verbose output to stdout\n\ \n\ Sample command lines:\n\ errlparser image.bin hbicore.syms # list logs from a full L3 image\n\ - errlparser image.bin hbicore.syms -d 1 # print detail about log 1\n\ + errlparser image.bin hbicore.syms -d 1 # display log 1\n\ + errlparser image.bin hbicore.syms -d 1 -t hbotStringFile # display traces\n\ errlparser buffer.bin # list logs from pre-extracted storage buffer\n\ errlparser buffer.bin -d 1 # detail log 1 from pre-extracted storage buffer\n\ \n\ @@ -74,9 +105,13 @@ Remarks:\n\ [] '-s' is optional if the symbols file name contains 'syms'\n\ [] '-i' can be optional in most cases\n\ \n\ +Developer switches:\n\ + -p -o <dirname> Extract all as PEL binaries to output <dirname>\n\ Contact: Monte Copeland\n\ " + + //------------------------------------------------------------------------ // Stop the program with a message. This message is often USAGE. Since // this program will be spawned from traceHB.py, I think we're better @@ -84,6 +119,7 @@ Contact: Monte Copeland\n\ // think Simics is piping stderr to its console. void halt( const char * msg ) { + // stdout out because Simics does not appear to display stderr (?) fprintf( stdout, "%s", msg ); // exit the process with a non-zero process exit level. @@ -111,6 +147,8 @@ ERRLCOMPNAME_t g_errlcompnames[] = { #include <comps.C> }; + +//------------------------------------------------------------- // Given a reason code which has a comp id mangled into // it, return a char* to the component name. Return // null if not found, which printf seems to handle @@ -133,157 +171,110 @@ const char * FindComp( uint16_t reasoncode ) -//------------------------------------------------------------ -// Print a hex dump of the input buffer to the output file -// given, probably stdout. -int FormatBytes( FILE * f, char * pchInput, int count, int indent ) +//------------------------------------------------------------- +// endian switch a uint64 +uint64_t ntohll( uint64_t i ) { - char szChars[ 80 ]; - char szHex[ 80 ]; - char szOffset[ 64 ]; - char szWork[ 256 ]; - int i; - unsigned int ul; - char * pch; - char * pchLine; - int cb; - char * pszIndent = NULL; - - - - pszIndent = static_cast<char*>(malloc( indent+1 )); - memset( pszIndent, 0, indent+1 ); - memset( pszIndent, ' ', indent ); - - - - pchLine = pchInput; - - - while( pchLine < pchInput + count ) - { - /* current offset */ - ul = pchLine - pchInput; - - sprintf( szOffset, "%08X", ul ); - - memset( szHex, ' ', sizeof( szHex )); - pch = szHex; - - cb = ((pchInput+count)-pchLine) > 16 ? 16 : ((pchInput+count)-pchLine); - - for( i = 0; i < cb; i++ ) - { - ul = (unsigned char) pchLine[ i ]; - - sprintf( szWork, "%02x", ul ); - memcpy( pch, szWork, 2 ); + uint64_t hi; + uint64_t lo; + uint32_t * pword = reinterpret_cast<uint32_t*>(&i); - pch += 3; - } + hi = ntohl( *pword ); + lo = ntohl( *(pword+1) ); - szHex[ 23 ] = '-'; - szHex[ 48 ] = 0; + return (hi<<32)|lo; +} - memset( szChars, 0, sizeof( szChars )); - for( i = 0; i < cb; i++ ) - { - szChars[i] = '.'; - int t = pchLine[i]; - if( t > 31 ) - { - szChars[i] = pchLine[ i ]; - } - } - sprintf( szWork, "%s %s %s", szOffset, szHex, szChars ); - fprintf( f, "%s%s\n", pszIndent, szWork ); - fflush( f ); - pchLine += 16; - } - return 0; +//------------------------------------------------------------- +// endian stuff, convert a errl storage marker in place +marker_t* ConvertMarker( marker_t* p) +{ + p->offsetNext = ntohl( p->offsetNext ); + p->length = ntohl( p->length ); + return p; } - //------------------------------------------------------------- -// endian stuff -section_header_t* ConvertSectionHeader( section_header_t* p) +// endian stuff, convert the data stored at the beginning of the +// errl storage buffer +storage_header_t * ConvertStorageHeader( storage_header_t * p ) { - p->cbHeader = ntohl( p->cbHeader ); - p->cbSection = ntohl( p->cbSection ); - p->compId = ntohs( p->compId ); - // sctnVer is byte long - // subSect is byte long + p->cbStorage = ntohl( p->cbStorage ); + p->cInserted = ntohl( p->cInserted ); + p->offsetMarker = ntohl( p->offsetMarker ); + p->offsetStart = ntohl( p->offsetStart ); return p; } - //------------------------------------------------------------- -// endian stuff -marker_t* ConvertMarker( marker_t* p) +// endian stuff,convert in place, return a pointer to what +// you passed in. PEL is made up of multiple sections, each +// one starting with a header that has these 8 bytes. +pelSectionHeader_t * ConvertPELSectionHeader( pelSectionHeader_t * p ) { - p->offsetNext = ntohl( p->offsetNext ); - p->length = ntohl( p->length ); + p->sid = ntohs( p->sid ); + p->len = ntohs( p->len ); + // byte: p->ver + // byte: p->sst + p->compId = ntohs( p->compId ); return p; } - //------------------------------------------------------------- -// endian switch a uint64 -uint64_t ntohll( uint64_t i ) +// endian stuff, convert in place. This converts the first section +// encountered in PEL, the PH section (private header). +pelPrivateHeaderSection_t* ConvertPrivateHeader(pelPrivateHeaderSection_t* p) { - uint64_t hi; - uint64_t lo; - uint32_t * pword = reinterpret_cast<uint32_t*>(&i); - - hi = ntohl( *pword ); - lo = ntohl( *(pword+1) ); - - return (hi<<32)|lo; + ConvertPELSectionHeader( &p->sectionheader ); + p->creationTime = ntohll( p->creationTime ); + p->commitTime = ntohll( p->commitTime ); + p->creatorImplementation = ntohll( p->creatorImplementation ); + p->plid = ntohl( p->plid ); + p->eid = ntohl( p->eid ); + return p; } //------------------------------------------------------------- -// endian stuff -errl_header_t* ConvertErrlHeader( errl_header_t* p ) +// endian stuff, convert in place. Convert the 2nd section in PEL, +// the UH (user header). +pelUserHeaderSection_t * ConvertUserHeader( pelUserHeaderSection_t * p ) { - p->cbytes = ntohl( p->cbytes ); - p->csections = ntohl( p->csections ); - p->reasonCode = ntohs( p->reasonCode ); - // p->modId is a byte - // p->sev is a byte - // p->eventType is a byte - // p->subSys is a byte - // p->srcType is a byte - p->termState = ntohl( p->termState ); - p->logId = ntohl( p->logId ); - p->user1 = ntohll( p->user1 ); - p->user2 = ntohll( p->user2 ); - p->CreationTime = ntohll( p->CreationTime ); + ConvertPELSectionHeader( &p->sectionheader ); + // mostly byte sized stuff + p->actions = ntohs( p->actions ); return p; } - //------------------------------------------------------------- -// endian stuff -storage_header_t * ConvertStorageHeader( storage_header_t * p ) +// endian stuff, convert in place. The PS (primary SRC) section +// in PEL is the 3rd section. +pelSRCSection_t * ConvertSRC( pelSRCSection_t * p ) { - p->cbStorage = ntohl( p->cbStorage ); - p->cInserted = ntohl( p->cInserted ); - p->offsetMarker = ntohl( p->offsetMarker ); - p->offsetStart = ntohl( p->offsetStart ); + ConvertPELSectionHeader( &p->sectionheader ); + // mostly byte sized stuff + p->srcLength = ntohs( p->srcLength ); + p->reserved1 = ntohs( p->reserved1 ); + p->word2 = ntohl( p->word2 ); + p->word3 = ntohs( p->word3 ); + p->word4 = ntohl( p->word4 ); + p->word5 = ntohl( p->word5 ); + p->word6 = ntohll( p->word6 ); + p->word8 = ntohll( p->word8 ); return p; } + //----------------------------------------------------------------------- // Given the binary image file name, return the errl storage part of the file. // Caller must endian convert anything/everything in the output buffer. @@ -418,6 +409,7 @@ uint32_t FindSymbol( char * pszSymbolFile, const char * pszSearch ) pch = strstr( szWork, pszSearch ); if( pch ) { + // tease out the address for this symbol pszAddr = szWork + 2; pch = strchr( pszAddr, ',' ); assert( pch ); @@ -433,6 +425,7 @@ uint32_t FindSymbol( char * pszSymbolFile, const char * pszSearch ) exit(2); } + // Convert ascii hex representation of address to a unsigned long int c = sscanf( pszAddr, "%x", &ulAddr ); if( 1 != c ) { @@ -446,103 +439,111 @@ uint32_t FindSymbol( char * pszSymbolFile, const char * pszSearch ) -// -------------------------------------------------------------------------- -// Print a summary of the error log, no user-defined data nor detail. -// perrlog is already endian converted +//----------------------------------------------------------------------------- +// Output a vector of endian-converted PEL sections, without altering the caller's +// pchNativePEL input buffer. The vector will have pointers to PEL section +// headers, and the user of the vector contents will have to cast according to +// pelSectionHeader_t.sid (section id ). -void PrintErrlSummary( errl_header_t * perrlog ) +bool ParseForPEL( char * i_pchNativePEL, + int i_cbPEL, + vector<pelSectionHeader_t*> &o_vector ) { - // print headline - // comp id sev rc mod evt u1 u2 csec - printf( "%-7s %10s %4s %-6s %-4s %-4s %-18s %-18s %5s\n", - "comp", - "logid", - "sev", - "reason", - "mod", - "evnt", - "user1", - "user2", - "csect" ); - - - // comp id sev reason mod event user1 user2 csec - // code - printf( "%-7s %10d 0x%02x 0x%04x 0x%02x 0x%02x 0x%016llx 0x%016llx %5d\n", - FindComp( perrlog->reasonCode ), - perrlog->logId, - perrlog->sev, - perrlog->reasonCode, - perrlog->modId, - perrlog->eventType, - perrlog->user1, - perrlog->user2, - perrlog->csections // count of sections - ); -} - + // use pch to bump along through the PEL sections + char * pch = i_pchNativePEL; -//--------------------------------------------------------------------------- -// -// -void PrintErrlDetail( errl_header_t * perrlog ) -{ + while( pch < (i_pchNativePEL+i_cbPEL)) + { + void * pvoid; + pelSectionHeader_t sectionHeader; - // print the summary line - PrintErrlSummary( perrlog ); + // Convert a copy of just the PEL section header so I can look at the + // sid (section id/type) and the overall section length. + memcpy( §ionHeader, pch, sizeof( pelSectionHeader_t )); + ConvertPELSectionHeader( §ionHeader ); - // print the Errorlog tags - printErrorTags( perrlog->reasonCode, - perrlog->modId ); - // print sections if any - if( perrlog->csections ) - { - int i; - section_header_t* psect; + // For each section, allocate space for it, endian convert the + // section, then insert into output vector. + switch( sectionHeader.sid ) { + case ERRL_SID_PRIVATE_HEADER: + { + pvoid = malloc(sectionHeader.len); + pelPrivateHeaderSection_t * p; + p = static_cast<pelPrivateHeaderSection_t*>(pvoid); + memcpy( p, pch, sectionHeader.len ); + ConvertPrivateHeader( p ); + o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) ); + } + break; + case ERRL_SID_USER_HEADER: + { + pvoid = malloc(sectionHeader.len); + pelUserHeaderSection_t * p; + p = static_cast<pelUserHeaderSection_t*>(pvoid); + memcpy( p, pch, sectionHeader.len ); + ConvertUserHeader( p ); + o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) ); + } + break; + case ERRL_SID_PRIMARY_SRC: + { + pvoid = malloc(sectionHeader.len); + pelSRCSection_t * p; + p = static_cast<pelSRCSection_t*>(pvoid); + memcpy( p, pch, sectionHeader.len ); + ConvertSRC( p ); + o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) ); + } + break; + case ERRL_SID_USER_DEFINED: + { + pvoid = malloc(sectionHeader.len); + pelSectionHeader_t * p; + p = static_cast<pelSectionHeader_t*>(pvoid); + memcpy( p, pch, sectionHeader.len ); + // Only converts the PEL section header, but none of the + // user-defined content. No way to know what's in there. + ConvertPELSectionHeader(p); + o_vector.push_back(p); + } + break; + default: + assert( 0 ); + break; + } - // first section header resides just past the errl_header_t - psect = reinterpret_cast<section_header_t*>(perrlog+1); + pch += sectionHeader.len; + } - // Endian convert it - ConvertSectionHeader( psect ); + return true; +} - i = 0; - do - { - printf( - "\nSection %d: %-8s len=0x%04x, ver=0x%04x, subsection=0x%04x\n", - i, - FindComp( psect->compId ), - psect->cbSection, - psect->sctnVer, - psect->subSect - ); - // The user-provided data resides just past the section header. - char * pUserData = reinterpret_cast<char*>(psect+1); - // Print a hex dump (for now) of the user-provided data. - FormatBytes( stdout, pUserData, (int)psect->cbSection, 4 ); - i++; - if( i >= perrlog->csections ) - { - // Leave the loop, and do not ConvertSectionHeader(). - break; - } +//----------------------------------------------------------------------------- +// Scan the vector of endian-converted PEL sections. Locate the target section +// and return it. Return NULL if not found. Caller will have to cast +// the returned section header pointer to the desired PEL section struct. - // There's more; point to the next section. - int cb = psect->cbHeader + psect->cbSection; - char * p = (reinterpret_cast<char*>(psect)) + cb; - psect = reinterpret_cast<section_header_t*>(p); +pelSectionHeader_t * FindPELSection( unsigned int i_target, + vector<pelSectionHeader_t*> &o_vector ) +{ + pelSectionHeader_t * p = NULL; - // Endian convert it. - ConvertSectionHeader( psect ); + vector<pelSectionHeader_t*>::iterator it; + for( it = o_vector.begin(); it != o_vector.end(); it++ ) + { + if( (*it)->sid == i_target ) + { + p = *it; + break; } - while( 1 ); } + + return p; } @@ -550,13 +551,25 @@ void PrintErrlDetail( errl_header_t * perrlog ) + + + + + + //------------------------------------------------------------- int main( int argc, char *argv[] ) { char * pch; + char * pchNativePEL; + const char * pszErrlTool = NULL; char * pszImageFile = NULL; char * pszSymbolFile = NULL; + char * pszStringFile = NULL; + char * pszOutputDir = NULL; char szWork[ 1024 ]; + char szTmpFilename[ 1024 ]; + char szCommand[ 128 ]; unsigned char * puch; char * pszSearch; char * pszAddr = NULL; @@ -579,13 +592,17 @@ int main( int argc, char *argv[] ) off_t offsetEnd; int fVerbose = 0; int fList = 1; + int fListHead = 0; int fDetail = 0; int fAll = 0; int fFound = 0; + int fExtractPEL = 0; + void * pvoid; + struct stat statbuffer; // build a =========== divider for printfing - cb = 84; + cb = 78; assert( cb < sizeof( szDivider )); memset( szDivider, '=', sizeof( szDivider )); szDivider[ cb ] = 0; @@ -634,6 +651,41 @@ int main( int argc, char *argv[] ) } pszImageFile = strdup( argv[i] ); } + else if( 0 == strcmp( "-o", argv[i] )) + { + i++; + if( i >= argc ) + { + fprintf( stdout, "Provide -o <dirname>\n" ); + exit( 2 ); + } + pszOutputDir = strdup( argv[i] ); + } + else if( 0 == strcmp( "-p", argv[i] )) + { + fExtractPEL = 1; + fList = 0; + fDetail = 0; + } + else if( 0 == strcmp( "-t", argv[i] )) + { + i++; + if( i >= argc ) + { + fprintf( stdout, "Provide -t <string file>\n" ); + exit( 2 ); + } + pszStringFile = strdup( argv[i] ); + + // errl messes up ~ somehow, I thought bash + // would substitute this. + pch = strchr( pszStringFile, '~' ); + if( pch ) + { + printf( "Don't use ~ for file naming.\n" ); + exit(2); + } + } else if( 0 == strcmp( "-s", argv[i] )) { i++; @@ -694,6 +746,56 @@ int main( int argc, char *argv[] ) halt( USAGE ); } + if(( fExtractPEL ) && ( NULL == pszOutputDir )) + { + printf( "Provide output dir for PEL extraction.\n" ); + exit(1); + } + + // TODO Need to put a copy of FSP x86 errl tool in the simics path. + // Try for Monte's sandbox copy, temporary for Sprint 6. + pszErrlTool = "/gsa/ausgsa/home/c/o/copelanm/public/bin/errl"; + + rc = stat( pszErrlTool, &statbuffer ); + if( -1 == rc ) + { + // Not found, so this one should be found for most users. + pszErrlTool = + "/esw/fips730/Builds/b0829a_1130.730/obj/x86.nfp/errl/nfp/tool/errl"; + + rc = stat( pszErrlTool, &statbuffer ); + if( -1 == rc ) + { + printf( "Unable to find a copy of errl, including %s.\n", + pszErrlTool ); + exit(2); + } + } + + if( fVerbose ) + { + printf( "Using errl tool %s\n", pszErrlTool ); + } + + + if( pszStringFile ) + { + int fd = open( pszStringFile, O_RDONLY ); + if( -1 == fd ) + { + printf( "String file %s not found.\n", pszStringFile ); + exit(2); + } + rc = fstat( fd, &statbuffer ); + close(fd); + if( ( -1 == rc ) || !(S_ISREG(statbuffer.st_mode))) + { + printf( "String file %s is not valid.\n", pszStringFile ); + exit(2); + } + } + + if( pszSymbolFile ) { @@ -717,7 +819,6 @@ int main( int argc, char *argv[] ) } } - // Given the image file, read the portion that contains the // error log storage buffer. pchBuffer = ReadStorageBuffer( pszImageFile, ulAddr, cbBuffer ); @@ -770,7 +871,6 @@ int main( int argc, char *argv[] ) if( pMarker->offsetNext == 0 ) { // This is the list-ending marker. - printf( "%s\n", szDivider ); break; } @@ -778,24 +878,135 @@ int main( int argc, char *argv[] ) logcount++; - // Flattened struct of an error log resides just past marker. - errl_header_t* perr = reinterpret_cast<errl_header_t*>(pMarker+1); - ConvertErrlHeader( perr ); + // Flattened PEL of an error log resides just past marker + // for a length of pMarker->length. It is "native" meaning big endian. + pchNativePEL = reinterpret_cast<char*>(pMarker+1); + + // Make a copy of PH that I can endian convert without screwing up + // the native one. + pvoid = malloc( pMarker->length ); + pelPrivateHeaderSection_t * pPrivateHdr; + pPrivateHdr = static_cast<pelPrivateHeaderSection_t*>(pvoid); + memcpy( pPrivateHdr, pchNativePEL, pMarker->length ); + + // Convert the PEL private header copy to local endianness. + ConvertPrivateHeader( pPrivateHdr ); if( fList ) { - // Just list the error log headers. - printf( "%s\n", szDivider ); - PrintErrlSummary( perr ); + // print a simple list of error log IDs + if( !fListHead ) + { + // print a head line + printf( "%-16s %8s\n", "Component", "PLID" ); + printf( "%s\n", szDivider ); + fListHead = 1; + } + printf( "%-16s %8d\n", + FindComp(pPrivateHdr->sectionheader.compId), + pPrivateHdr->plid ); } - else if(( fDetail ) && (( perr->logId == ulLogId ) || (fAll))) + else if(( fDetail ) && (( pPrivateHdr->plid == ulLogId ) || (fAll))) { - // Print the detail for the one error log. - printf( "%s\n", szDivider ); - PrintErrlDetail( perr ); + // Write the native PEL to a temporary file + // for x86 errl tool to display. + sprintf( szTmpFilename, "/tmp/pel%d.bin", pPrivateHdr->plid ); + + int fd = open( szTmpFilename, O_RDWR | O_CREAT , 0664 ); + if( -1 == fd ) + { + printf( "Unable to write %s. Exiting.\n", szTmpFilename ); + exit(2); + } + cb = write( fd, pchNativePEL, pMarker->length ); + assert( cb == pMarker->length ); + close(fd); + + // Spawn the FSP x86 errl tool to display + // the detail for this error log. + cb=sprintf(szCommand,"%s -d --file=%s",pszErrlTool,szTmpFilename); + if( pszStringFile ) + { + sprintf( &szCommand[cb], " --trace=%s", pszStringFile ); + } + + // Run errl -d to display the error log. + system( szCommand ); + + + // Build a vector containing pointers to each PEL section + // in the error log. On return, each section will be endian + // converted as much as possible. Do not alter the endianness + // of the native pel buffer, however. + vector<pelSectionHeader_t*> vectorPEL; + ParseForPEL( pchNativePEL, pMarker->length, vectorPEL ); + assert( vectorPEL.size() ); + + + + // Print the tag detail gleaned from the code by + // the errl tag parser. That requires getting the reason + // code and module ID from the error log. They live in + // the Primary SRC section. + uint32_t l_reasonCode = 0; + + + // Find the PS section in the vector of PEL sections. + pelSectionHeader_t* pPELHead; + pPELHead = FindPELSection( ERRL_SID_PRIMARY_SRC, vectorPEL ); + assert( pPELHead ); + + // Cast to Primary SRC section. + pelSRCSection_t * pSRCSection; + pSRCSection = reinterpret_cast<pelSRCSection_t*>(pPELHead); + +#if 0 + // reasonCode has been "stringified" into the SRC string + pch = strchr( pSRCSection->srcString, ' ' ); + assert( pch ); + *pch = 0; + assert( 8 == strlen( pSRCSection->srcString)); + sscanf( pSRCSection->srcString + 4, "%X", &l_reasonCode ); +#else + // I have cheated and put reasonCode here: + l_reasonCode = pSRCSection->reserved1; +#endif + + printf( "%-20s%s\n", + "Component", + FindComp(pPrivateHdr->sectionheader.compId)); + + // print the Errorlog tags from scanforsrcs.pl + printErrorTags( l_reasonCode, pSRCSection->moduleId ); + + // done with this tmp file + unlink( szTmpFilename ); + + // found at least one fFound = 1; } + + if( fExtractPEL ) + { + // Write the native PEL to a temporary file for debug later. + sprintf( szTmpFilename, "%s/pel%d.bin", pszOutputDir, pPrivateHdr->plid ); + + int fd = open( szTmpFilename, O_RDWR | O_CREAT , 0664 ); + if( -1 == fd ) + { + printf( "Unable to write %s. Exiting.\n", szTmpFilename ); + exit(2); + } + cb = write( fd, pchNativePEL, pMarker->length ); + assert( cb == pMarker->length ); + close(fd); + + printf( "Saved as %s\n", szTmpFilename ); + } + + + // next marker/error log pMarker = ConvertMarker( OFFSET2MARKER(pMarker->offsetNext) ); } diff --git a/src/usr/errl/parser/makefile b/src/usr/errl/parser/makefile index a48373c65..8b91e14ab 100644 --- a/src/usr/errl/parser/makefile +++ b/src/usr/errl/parser/makefile @@ -20,49 +20,59 @@ # Origin: 30 # # IBM_PROLOG_END + + # makefile for errlparser, -# a 32-bit x86 linux binary suitable for running on GFW pool machines. +# a 32-bit x86 linux binary suitable for running on GFW pool machines. ROOTPATH=../../../.. -GENFILES = ${ROOTPATH}/obj/genfiles +GENDIR = ${ROOTPATH}/obj/genfiles +IMGDIR = ${ROOTPATH}/img + +OBJDIR = ${ROOTPATH}/obj/modules/errlparser SRCPARSE_HEADER_TARGET = \ - ${GENFILES}/hostBootSrcParse.H + ${GENDIR}/hostBootSrcParse.H -CC=g++ -m32 +CC=i686-mcp6-g++ -m32 CFLAGS:=-g -O0 -I $(ROOTPATH)/src/include/usr -D PARSER -BIN:=bin all: gen_pass code_pass gen_pass: -code_pass: $(BIN)/errlparser ${SRCPARSE_HEADER_TARGET} +code_pass: makeobjdir ${IMGDIR}/errlparser ${SRCPARSE_HEADER_TARGET} clean: - rm -fr $(BIN) rm -fr ${SRCPARSE_HEADER_TARGET} + rm -fr ${OBJDIR}/errlparser.o + rm -fr ${GENDIR}/errlparser + rm -fr ${GENDIR}/comps.C + +beam: -beam: -$(BIN)/comps.C: $(ROOTPATH)/src/include/usr/hbotcompid.H - mkdir -p $(BIN) +makeobjdir: + mkdir -p ${OBJDIR} + +${GENDIR}/comps.C: $(ROOTPATH)/src/include/usr/hbotcompid.H grep "const compId_t [A-Z0-9]*_COMP_ID" $^ | \ grep -v MY_COMP_ID | \ sed 's/const compId_t \([A-Z0-9]*\)_COMP_ID[ =\t]*\(0[xX][0-9a-fA-F]*\).*/{ "\1", \2 },/' \ > $@ -$(BIN)/errlparser.o: errlparser.C $(ROOTPATH)/src/include/usr/errl/errltypes.H $(BIN)/comps.C \ +${OBJDIR}/errlparser.o: errlparser.C $(ROOTPATH)/src/include/usr/errl/errltypes.H ${GENDIR}/comps.C \ ${SRCPARSE_HEADER_TARGET} - mkdir -p $(BIN) - $(CC) -c $(CFLAGS) -I bin -I${ROOTPATH}/obj/genfiles -o $@ $< + $(CC) -c $(CFLAGS) -I${ROOTPATH}/obj/genfiles -o $@ $< -$(BIN)/errlparser: $(BIN)/errlparser.o +${IMGDIR}/errlparser: ${OBJDIR}/errlparser.o $(CC) -o $@ $< + ${SRCPARSE_HEADER_TARGET} : - ./scanforsrcs.pl -b ${ROOTPATH} -o ${GENFILES} + ./scanforsrcs.pl -b ${ROOTPATH} -o ${GENDIR} + diff --git a/src/usr/errl/test/errltest.H b/src/usr/errl/test/errltest.H index 0ac45d019..c2808b32c 100644 --- a/src/usr/errl/test/errltest.H +++ b/src/usr/errl/test/errltest.H @@ -66,15 +66,16 @@ public: */ void testErrl1(void) { - ERRORLOG::ErrlFFDC * pffdc; + bool fOK; + ERRORLOG::ErrlUD * pffdc; // An example that shows how to use macros to stuff data into // the two 64-bit user data parameters in the error log. // l_userData1 = 16bit(0):l_bit8_1:l_bit8_2:l_32bit_1 uint8_t l_8bit_1 = TEST_USR_8BIT_1; // 0x80 - uint8_t l_8bit_2 = TEST_USR_8BIT_2; // 0x93 + uint8_t l_8bit_2 = TEST_USR_8BIT_2; // 0x93 uint32_t l_32bit_1 = TEST_USR_32BIT_1; // 0x80000001 - uint64_t l_userData1 = + uint64_t l_userData1 = TWO_UINT32_TO_UINT64( TO_UINT32(TWO_UINT8_TO_UINT16(l_8bit_1, l_8bit_2)), l_32bit_1); // yields 0x0000809380000001 @@ -86,8 +87,6 @@ public: uint64_t l_userData2 = TWO_UINT16_ONE_UINT32_TO_UINT64(l_16bit_1, l_16bit_2, l_32bit_2); // yields 0x8000900390000003 - TRACDCOMP( g_trac_test, "testErrl1"); - TS_TRACE( "testErrl1, Create error log..."); // Create an error log errlHndl_t l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_INFORMATIONAL, @@ -108,7 +107,6 @@ public: // but errlffdc.H is not publicly includable to give me the definition // for it. addFFDC() should return a Boolean indication of success. - TS_TRACE( "Add ffdc1"); const char * pch = "martha washington"; pffdc = l_err->addFFDC( ERRL_COMP_ID, pch, strlen( pch ), 1, 2 ); if ( NULL == pffdc ) @@ -116,23 +114,20 @@ public: TS_FAIL("testErrl1: addFFDC() output NULL pointer"); } - TS_TRACE( "Add ffdc2"); - pch = "george washington"; + pch = "george washington"; pffdc = l_err->addFFDC( DEVFW_COMP_ID, pch, strlen( pch ), 3, 4 ); if ( NULL == pffdc ) { TS_FAIL("testErrl1: addFFDC() output NULL pointer"); } - TS_TRACE( "Add ffdc3"); - pch = "dwight eisenhour"; + pch = "dwight eisenhour"; pffdc = l_err->addFFDC( SCOM_COMP_ID, pch, strlen( pch ), 5, 6 ); if ( NULL == pffdc ) { TS_FAIL("testErrl1: addFFDC() output NULL pointer"); } - TS_TRACE( "Add ffdc4"); pch = "ronald "; pffdc = l_err->addFFDC( ERRL_COMP_ID, pch, strlen( pch ), 7, 8 ); if ( NULL == pffdc ) @@ -140,27 +135,35 @@ public: TS_FAIL("testErrl1: addFFDC() output NULL pointer"); } - TS_TRACE( "Append ffdc1"); // Append data to something already added. pch = "reagan"; l_err->appendToFFDC( pffdc, pch, strlen(pch) ); + // Collect trace + fOK = l_err->collectTrace( "INITSVC" ); + if( !fOK ) + { + TS_FAIL( "collectTrace(INITSVC) rets false." ); + } + + fOK = l_err->collectTrace( "XSCOM" ); + if( !fOK ) + { + TS_FAIL( "collectTrace(XSCOM) rets false." ); + } + + fOK = l_err->collectTrace( "UNK" ); + if( fOK ) + { + TS_FAIL( "collectTrace(UNK) rets true" ); + } // Add null data. - TS_TRACE( "Append ffdc2"); pffdc = l_err->addFFDC( ERRL_COMP_ID, NULL, 0, 9, 10 ); if ( NULL != pffdc ) { TS_FAIL("testErrl1: addFFDC() returned non null"); } - - - - - - - - // Verify log data else if (l_err->sev() != ERRORLOG::ERRL_SEV_INFORMATIONAL) { @@ -174,7 +177,7 @@ public: { TS_FAIL("testErrl1: createErrlLog() returns incorrect event type!"); } - else if (l_err->subSys() != ERRORLOG::EPUB_RESERVED_0) + else if (l_err->subSys() != ERRORLOG::EPUB_FIRMWARE_SUBSYS ) { TS_FAIL("testErrl1: createErrlLog() returns incorrect sub system!"); } @@ -188,8 +191,8 @@ public: } else { - // Commit error log - errlCommit(l_err); + // Commit error log with different component ID. + errlCommit(l_err, FSI_COMP_ID); // Make sure error log has been deleted by manager if (l_err != NULL) { @@ -216,7 +219,6 @@ public: uint64_t l_userData2 = TWO_UINT32_TO_UINT64(TO_UINT32(l_8bit_1), TO_UINT32(l_16bit_1)); - TS_TRACE( "testErrl2"); // Create an error log errlHndl_t l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, diff --git a/src/usr/trace/trace.C b/src/usr/trace/trace.C index f14978854..447fad968 100644 --- a/src/usr/trace/trace.C +++ b/src/usr/trace/trace.C @@ -785,47 +785,64 @@ trace_desc_t * Trace::getTd(const char *i_comp) return(l_td); } -/******************************************************************************/ -// getBuffer - TODO -/******************************************************************************/ -int32_t Trace::getBuffer(const trace_desc_t *i_td_ptr, - void *o_data) -{ - /*------------------------------------------------------------------------*/ - /* Local Variables */ - /*------------------------------------------------------------------------*/ - int64_t l_rc = 0; - /*------------------------------------------------------------------------*/ - /* Code */ - /*------------------------------------------------------------------------*/ - if((i_td_ptr) && (o_data != NULL)) + +/*****************************************************************************/ +// getBuffer() called by ErrlEntry.CollectTrace() +// Return how many bytes copied, or if given a null pointer or zero buffer +// size, then return the size of the buffer. +// +// Otherwise return zero on error; perhaps the component name/trace buffer +// name is not found. + +uint64_t Trace::getBuffer( const char * i_pComp, + void * o_data, + uint64_t i_bufferSize ) +{ + int64_t l_rc = 0; + trace_desc_t * l_pDescriptor = NULL; + + do { - // Get the lock - // TODO Mutex -#if 0 - l_rc = UTIL_MUTEX_GET(&iv_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT); - if(l_rc != 0) + l_pDescriptor = getTd( i_pComp ); + if( NULL == l_pDescriptor ) { - // Badness + break; } - else + + if( ( NULL == o_data ) || ( 0 == i_bufferSize )) { - l_rc = SUCCESS; + // return how big is the buffer. + l_rc = TRAC_DEFAULT_BUFFER_SIZE; + break; } -#endif - // Copy it's buffer into temp one - memcpy(o_data,i_td_ptr,(size_t)TRAC_DEFAULT_BUFFER_SIZE); - // Always try to release even if error above - // TODO - mutex - //UTIL_MUTEX_PUT(&iv_trac_mutex); + // Not to exceed buffer size. + uint64_t l_copyCount = i_bufferSize; + if( i_bufferSize > TRAC_DEFAULT_BUFFER_SIZE ) + { + l_copyCount = TRAC_DEFAULT_BUFFER_SIZE; + } + + // Get the lock + mutex_lock(&iv_trac_mutex); + + // Copy buffer to caller's space + memcpy( o_data, l_pDescriptor, (size_t)l_copyCount ); + + mutex_unlock(&iv_trac_mutex); + + l_rc = l_copyCount; } + while( 0 ); - return(l_rc); + return l_rc; } + + + #if 0 /******************************************************************************/ // getBufferPartial - TODO |