diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/errl/errlentry.H | 460 | ||||
-rw-r--r-- | src/include/usr/errl/errlmanager.H | 103 | ||||
-rw-r--r-- | src/include/usr/errl/errltypes.H | 97 | ||||
-rw-r--r-- | src/include/usr/example/example.H | 9 | ||||
-rw-r--r-- | src/include/usr/example/examplerc.H | 33 | ||||
-rw-r--r-- | src/include/usr/hbotcompid.H | 43 | ||||
-rw-r--r-- | src/makefile | 4 | ||||
-rw-r--r-- | src/usr/errl/errlentry.C | 107 | ||||
-rw-r--r-- | src/usr/errl/errlffdc.C | 68 | ||||
-rw-r--r-- | src/usr/errl/errlffdc.H | 87 | ||||
-rw-r--r-- | src/usr/errl/errlmanager.C | 74 | ||||
-rw-r--r-- | src/usr/errl/errlsctn.C | 32 | ||||
-rw-r--r-- | src/usr/errl/errlsctn.H | 127 | ||||
-rw-r--r-- | src/usr/errl/errlsctnhdr.C | 38 | ||||
-rw-r--r-- | src/usr/errl/errlsctnhdr.H | 76 | ||||
-rw-r--r-- | src/usr/errl/errlservicecodes.H | 30 | ||||
-rw-r--r-- | src/usr/errl/makefile | 8 | ||||
-rw-r--r-- | src/usr/errl/test/errltest.H | 143 | ||||
-rw-r--r-- | src/usr/errl/test/makefile | 6 | ||||
-rw-r--r-- | src/usr/example/example.C | 25 | ||||
-rw-r--r-- | src/usr/makefile | 2 |
21 files changed, 1569 insertions, 3 deletions
diff --git a/src/include/usr/errl/errlentry.H b/src/include/usr/errl/errlentry.H new file mode 100644 index 000000000..9a9683992 --- /dev/null +++ b/src/include/usr/errl/errlentry.H @@ -0,0 +1,460 @@ +#ifndef ERRLENTRY_H +#define ERRLENTRY_H +/** + * @file errlentry.H + * + * @brief Error Log entry object for Host Boot environment. + * + * This header file contains the definition of error log entry class that + * is used to log errors from all firmware running in Host Boot environment. + * + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <stdint.h> +#include <vector> +#include <errl/errltypes.H> +#include <hbotcompid.H> + +namespace ERRORLOG +{ + +/*****************************************************************************/ +// Forward class declarations +/*****************************************************************************/ +class ErrlManager; +class ErrlSctn; +class ErrlFFDC; + +/** + * @brief Host Boot Error log entry class. + * This class contains all of the entry management logic and necessary + * information to create a PEL or IPMI event type logs. + * A pointer to this class is known as an errlHndl_t (the error log handle) + * and it is the data type passed by applications on the stack to convey + * a failure. + */ +class ErrlEntry +{ + + friend class ErrlManager; + +public: + /** + * @brief ErrlEntry constructor. Builds an error log with info + * constructed from the input. + * Event type, Sub System, SRC type, and Terminate state are defaulted + * to the most common values for Host Boot environment. These values + * can also be set to specific values by users if needed. + * For available values, see errltypes.H + * To understand the meaning of these values, refer to the + * Platform Event Log and SRC PLDD at: https://mcdoc.boeblingen.de. + * ibm.com/out/out.ViewDocument.php?documentid=1675 + * + * The order of parameters is arranged so that Host Boot error log + * is as close to SP as possible. + * + * @param[in] i_sev Log's severity. See errltypes.H for + * available values + * @param[in] i_modId The module (interface) where this log is + * created from. + * @param[in] i_reasonCode Bits 00-07: Component Id + * Bits 08-15: Reason code + * @param[in] i_user1 64 bits of user data which are placed + * in the primary SRC + * @param[in] i_user2 64 bits of user data which are placed + * in the primary SRC + * @return None + */ + ErrlEntry(const errlSeverity_t i_sev, + const uint8_t i_modId, + const uint16_t i_reasonCode, + const uint64_t i_user1 = 0, + const uint64_t i_user2 = 0); + + /** + * @brief Destructor + * + * Releases all resources owned by the handle. If the log has not + * been committed, it effectively aborts the log. + * All logs (committed or not) must be deleted to avoid a resource leak. + * + * @return None + * + */ + ~ErrlEntry(); + + /** + * @brief Read the log's severity + * The severity of a log determines how severe the + * problem is perceived to be. The severity is + * initially set by the parameter in the constructor + * and can be changed at any point thereafter. + * + * @return Current Log Severity + * + */ + errlSeverity_t sev() const; + + /** + * @brief Set the log's severity + * The severity of a log determines how severe the + * problem is perceived to be. The severity is + * initially set by the parameter in the constructor + * and can be changed at any point thereafter. + * + * @return void + * + */ + void setSev(const errlSeverity_t i_sev); + + /** + * @brief Returns the log's reason code + * + * @return uint16_t + * + */ + uint16_t reasonCode() const; + + /** + * @brief Returns the log's event type + * + * @return errlEventType_t + * + */ + errlEventType_t eventType() const; + + /** + * @brief Set the log's event type + * + * @return void + * + */ + void setEventType(const errlEventType_t i_eventType); + + /** + * @brief Returns the log's sub system + * + * @return epubSubSystem_t + * + */ + epubSubSystem_t subSys() const; + + /** + * @brief Set the log's sub system + * + * @return void + * + */ + void setSubSys(const epubSubSystem_t i_subSys); + + /** + * @brief Returns the log's SRC type + * + * @return srcType_t + * + */ + srcType_t srcType() const; + + /** + * @brief Set the log's SRC type + * + * @return void + * + */ + void setSrcType(const srcType_t i_srcType); + + /** + * @brief Returns the log's terminate state type + * + * @return errlTermState_t + * + */ + errlTermState_t termState() const; + + /** + * @brief Set the log's Terminating state + * + * @return void + * + */ + void setTermState(const errlTermState_t i_termState); + + /** + * @brief Allows the caller to add a chunk of data in a log + * + * @param[in] i_compId Component Id of the caller + * @param[in] i_dataPtr Pointer to FFDC data + * @param[in] i_ffdcLen Length of the data in bytes + * @param[in] i_ffdcVer A user supplied identifier which + * classifies the data + * @param[in] i_ffdcSubSect A user supplied sub section identifier + * which classifies the data. This in + * conjunction with the version can be used + * to decode the data. + * @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); + + /** + * @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 + * function is called earlier. + * @param[in] i_compId Component Id of the caller + * @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); +private: + + /** + * @brief Disabled copy constructor and assignment operator + */ + ErrlEntry(const ErrlEntry& i_right); + ErrlEntry& operator=(const ErrlEntry& i_right); + + /** + * @brief Add a data section to error log object + * + * @param[in] i_sctn Pointer to data section to be added + * + * @return void + */ + void addSection(ErrlSctn* i_sctn); + + /** + * @brief Returns the unique Error Entry Id. This ID is assigned to + * the entry when it's created. + * This is to be called by ErrlManager only. + * @return 32 bit unsigned identifier + */ + uint32_t logId() const; + + /** + * @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. + * + * @return void + */ + void setLogId(const uint32_t i_val); + + //@todo - Need to add serialization interfaces for ErrlSctn object. + // Serialization method (boost serialization?) is for HostBoot + // is currently not yet determined. + // Note: stream is currently not supported + + +#if 0 + + //@todo - The interfaces in this block still need support in order + // to have code written. + + + //@todo: Need to set EPUB_Sub system based on highest + // priority call out FRU + /** + * @brief Add a hardware ( FRU ) callout + * + * @param[in] i_resourceId The resource identifier for the part + * @param[in] i_target The hardware target + * + * @return void + */ + void addFruCallout(const target_t i_target, + const callOutPriority_t i_priority); + + + //@todo: Need to set EPUB_Sub system based on highest + // priority procedure call out + /** + * @brief Add a procedure ( software ) callout + * Adds the given service procedure to the list + * of callouts for the log + * + * @param[in] i_priority Priority of the callout + * @param[in] i_procedure Procedure identifier. + * + * @return void + */ + void addProcedureCallout(const epubProcedureId_t i_procedure, + 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 + * + * @param[in] i_cid Component for which the section is being logged + * @param[in] i_returnCode User supplied return code. + * @param[in] i_fileId User supplied file identifier + * @param[in] i_codeloc User supplied code location ( line # ) + * @param[in] i_objId User supplied object identifier + * + * @return Token which identifies the newly added section + * A negative token is considered to be invalid + * + * @note The section may be dropped if there is not enough + * room available to contain it + * + * + */ + void addSwErr(const compId_t i_cid, + const uint32_t i_returnCode, + const uint16_t i_fileId, + const uint16_t i_codeLoc, + const uint32_t i_objId = 0); + +#endif + +private: + + // Data Members + uint16_t iv_reasonCode; // Component ID and reason code, 2 nibbles each + 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 + uint32_t iv_logId; // This log's unique ID + + // Sections in this log object + std::vector<ErrlSctn*> iv_sections; + +}; + +//----------------------------------------------------------------------- +// 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 +{ + return (iv_reasonCode); +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline errlEventType_t ErrlEntry::eventType() const +{ + return (iv_eventType); +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline void ErrlEntry::setEventType(const errlEventType_t i_eventType) +{ + iv_eventType = i_eventType; + return; +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline epubSubSystem_t ErrlEntry::subSys() const +{ + return (iv_subSys); +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline void ErrlEntry::setSubSys(const epubSubSystem_t i_subSys) +{ + iv_subSys = i_subSys; + return; +} + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline srcType_t ErrlEntry::srcType() const +{ + return (iv_srcType); +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline void ErrlEntry::setSrcType(const srcType_t i_srcType) +{ + 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; +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline uint32_t ErrlEntry::logId() const +{ + return (iv_logId); +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline void ErrlEntry::setLogId(const uint32_t i_val) +{ + iv_logId = i_val; + return; +} + +} // End namespace + +#endif //ERRLENTRY_H diff --git a/src/include/usr/errl/errlmanager.H b/src/include/usr/errl/errlmanager.H new file mode 100644 index 000000000..f8074e8f0 --- /dev/null +++ b/src/include/usr/errl/errlmanager.H @@ -0,0 +1,103 @@ +#ifndef ERRLMANAGER_H +#define ERRLMANAGER_H +/** + * @file errlmanager.H + * + * @brief Error Log management for Host Boot environment. + * + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <stdint.h> +#include <stdlib.h> +#include <util/singleton.H> +#include <errl/errltypes.H> + +namespace ERRORLOG +{ + +/*****************************************************************************/ +// Forward class declarations +/*****************************************************************************/ +class ErrlEntry; +class ErrlManager; + +// Singleton - Use "theErrlManager::instance()" to access the singleton +typedef Singleton<ErrlManager> theErrlManager; + +/** + * @brief Error log manager + * This class provides interfaces to perform some specific tasks + * on existing error objects such as committing a log, sending the + * log to the SP, etc.. + */ +class ErrlManager +{ + +public: + + /** + * @brief Commit an error log by sending it to the repository + * - Writes the log to PNOR where committed logs are kept. + * If there's not enough room, remove the latest log(s) to make + * enough room to commit this log. + * - The error log will be automatically deleted after the + * commit. The input handle will be set to NULL. + * - For Host Boot environment, there's no individual committer + * (i.e. committer = Host Boot), so no component ID of + * committer is specified. + * + * @param[in/out] io_err Error log handle to be committed + * + * @return None + */ + void commitErrLog(errlHndl_t& io_err); + + + /** + * @brief Returns a unique error log ID + * + * This routine generates a unique Error ID and assign it to + * the input error log + * + * @return Unique generated error log ID + */ + uint32_t getUniqueErrId(); + +protected: + /** + * @brief Destructor + * + * Releases all resources owned by the handle. If the log has not + * been committed, it effectively aborts the log. + * All logs (committed or not) must be deleted to avoid a resource leak. + * + * @return None + * + */ + ~ErrlManager(); + + /** + * @brief Default constructor + * Protected so only SingletonHolder can call + */ + ErrlManager(); + +private: + + /** + * @brief Disabled copy constructor and assignment operator + */ + ErrlManager(const ErrlManager& i_right); + ErrlManager& operator=(const ErrlManager& i_right); + + + uint32_t iv_currLogId; + +}; + +} // End namespace + +#endif //ERRLMANAGER_H diff --git a/src/include/usr/errl/errltypes.H b/src/include/usr/errl/errltypes.H new file mode 100644 index 000000000..cf558a110 --- /dev/null +++ b/src/include/usr/errl/errltypes.H @@ -0,0 +1,97 @@ +#ifndef ERRLTYPES_H +#define ERRLTYPES_H +/** + * @file errltypes.H + * + * @brief Common ErrlEntry definitions. + * + * This header file contains the definition of ErrlEntry related + * parameters. + * + */ + +/** + * @brief Pointer to an ErrlEntry object + */ +namespace ERRORLOG { class ErrlEntry; }; +typedef ERRORLOG::ErrlEntry* errlHndl_t; + +namespace ERRORLOG +{ + +/** + * @brief Enumeration of error log severity + */ +enum errlSeverity_t +{ + ERRL_SEV_INFORMATIONAL = 0x00, + ERRL_SEV_UNRECOVERABLE = 0x10, + ERRL_SEV_CRITICAL_SYS_TERM = 0x20, + ERRL_SEV_UNKNOWN = 0xFF +}; + +/** + * @brief Event (error) type + */ +enum errlEventType_t +{ + ERRL_ETYPE_NOT_APPLICABLE = 0, + ERRL_ETYPE_DUMP_NOTIFICATION = 8, + ERRL_ETYPE_USER_DECONFIG = 0x20, + ERRL_ETYPE_SYS_DECONFIG = 0x21, + ERRL_ETYPE_CONCURRENT_MAINTENANCE = 0x40, + ERRL_ETYPE_CAPACITY_UPGRADE = 0x60, +}; + +/** + * @brief Error log call out priority + */ +enum callOutPriority_t +{ + CALLOUT_PRIORITY_LOW = 1, + CALLOUT_PRIORITY_MED = 2, + CALLOUT_PRIORITY_HIGH = 3, +}; + +/** + * @brief Error log procedure Id + */ +enum epubProcedureId_t +{ + EPUB_PRC_NONE = 0x00, +}; + +/** + * @brief Sub system definitions + */ +enum epubSubSystem_t +{ + EPUB_RESERVED_0 = 0x00, + EPUB_UNKNOWN = 0xFF, +}; + +/** + * @brief Terminating flag definitions + */ +enum errlTermState_t +{ + TERM_STATE_NO_FLAGS = 0x00000000, + TERM_STATE_UNKNOWN = 0xFFFFFFFF, +}; + + +/** + * @brief SRC type definitions + */ +enum srcType_t +{ + SRC_INTERVENTION_REQ = 0xA1, + SRC_ERR_INFO = 0xB1, + SRC_IPL_STATUS = 0xC1, + SRC_GENERAL_STATUS = 0xD1, +}; + + +} // End namespace + +#endif // ERRLTYPES_H diff --git a/src/include/usr/example/example.H b/src/include/usr/example/example.H index 1444893b2..b22c38da2 100644 --- a/src/include/usr/example/example.H +++ b/src/include/usr/example/example.H @@ -15,4 +15,13 @@ */ uint64_t example1_function(); +/** + * @brief Example of creating an error log function + * + * @return void + * + */ +void example2_create_errorlog_function(); + + #endif diff --git a/src/include/usr/example/examplerc.H b/src/include/usr/example/examplerc.H new file mode 100644 index 000000000..9e65d3515 --- /dev/null +++ b/src/include/usr/example/examplerc.H @@ -0,0 +1,33 @@ +// This file is an example how you create a reason code to pass in an +// error log creation + +#ifndef __EXAMPLE_RC_H +#define __EXAMPLE_RC_H + +#include <hbotcompid.H> + +// The definitions in this file is an example that shows how to define +// reason codes. Each Host Boot component should have a service code +// file (<component>servicecodes.H) that defines its module IDs and +// unique reason codes. +// See errlservicecodes.H for example of this file for ERRL component. + +// Below is an example of defining reason codes +enum myModuleId +{ + MY_MODULE_ID_1 = 0x00, + //........ + MY_LAST_MODULE_ID = 0xFF +}; + +// This enum definition should be in an .H file in your component area. +// MY_COMPONENT_ID is your component name defined in hbotcompid.H file +// included above. +enum myReasonCode +{ + MY_REASON_CODE_1 = MY_COMP_ID | 0x01, + //........ + ERRL_LAST_REASON_CODE = MY_COMP_ID | 0xFF +}; + +#endif diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H new file mode 100644 index 000000000..49fad6ea9 --- /dev/null +++ b/src/include/usr/hbotcompid.H @@ -0,0 +1,43 @@ +#ifndef HBOTCOMPID_H +#define HBOTCOMPID_H +/** + * @file hbotcompid.H + * + * @brief Component IDs in Host Boot environment + * This header file contains the definition of all component IDs in + * Host Boot environment. This component ID is to be used to identify + * the firmware such as in error logging (or somewhere else). + * + */ + +typedef unsigned short compId_t; + +/** + * @brief Component ID declarations + * Range of component IDs is from 01-FF, which is stored in + * the LSB (left) of the value. + * Note that the MSB (right) of the value are to be used as + * error code in the component code. + * Together, the 4-digit value is called Reason Code, which + * is to be passed in when the component creates an error log. + */ + +/** @name My component ID + * Example of defining my component ID + */ +//@{ +const compId_t MY_COMP_ID = 0x0000; +const char MY_COMP_NAME[] = "myname"; +//@} + +/** @name ERRL + * Error Logging component + */ +//@{ +const compId_t ERRL_COMP_ID = 0x0100; +const char ERRL_COMP_NAME[] = "errl"; +//@} + + + +#endif diff --git a/src/makefile b/src/makefile index 233376531..5f65cb74e 100644 --- a/src/makefile +++ b/src/makefile @@ -15,10 +15,10 @@ DIRECT_BOOT_OBJECTS = start.o kernel.o taskmgr.o cpumgr.o syscall.o \ RUNTIME_OBJECTS = -BASE_MODULES = trace +BASE_MODULES = trace errl DIRECT_BOOT_MODULES = example RUNTIME_MODULES = -TESTCASE_MODULES = cxxtest testexample testtrace +TESTCASE_MODULES = cxxtest testexample testtrace testerrl RELOCATABLE_IMAGE_LDFLAGS = -pie --export-dynamic diff --git a/src/usr/errl/errlentry.C b/src/usr/errl/errlentry.C new file mode 100644 index 000000000..fcff1c204 --- /dev/null +++ b/src/usr/errl/errlentry.C @@ -0,0 +1,107 @@ +/** + * @file errlentry.C + * + * @brief Implementation of ErrlEntry class + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <trace/interface.H> +#include <hbotcompid.H> +#include "errlsctn.H" +#include "errlffdc.H" + +namespace ERRORLOG +{ + +// Trace definition +trace_desc_t* g_trac_errl = NULL; +TRAC_INIT(&g_trac_errl, "ERRL", 4096); + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlEntry::ErrlEntry(const errlSeverity_t i_sev, + const uint8_t i_modId, + 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_sections(NULL) +{ + iv_logId = theErrlManager::instance().getUniqueErrId(); +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlEntry::~ErrlEntry() +{ + // Free memory of all sections + for (std::vector<ErrlSctn*>::iterator l_itr = iv_sections.begin(); + l_itr != iv_sections.end(); ++l_itr) + { + delete (*l_itr); + } +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlFFDC* 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; + + if ( (i_dataPtr == NULL) || (i_ffdcLen == 0) ) + { + TRACFCOMP(ERRORLOG::g_trac_errl, "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 error log + addSection(l_ffdcSection); + } + + return l_ffdcSection; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void ErrlEntry::appendToFFDC(ErrlFFDC* i_ffdcPtr, + const void *i_dataPtr, + const uint32_t i_dataLen) +{ + //@todo Need to support append data to an existing FFDC data block + return; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void ErrlEntry::addSection(ErrlSctn* i_sctn) +{ + // Add pointer + iv_sections.push_back(i_sctn); + return; +} + + + +} // End namespace + diff --git a/src/usr/errl/errlffdc.C b/src/usr/errl/errlffdc.C new file mode 100644 index 000000000..6fc4388fa --- /dev/null +++ b/src/usr/errl/errlffdc.C @@ -0,0 +1,68 @@ +/** + * @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" +#include "errlsctn.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), + iv_data( NULL ), + iv_size( 0 ) +{ + addData(i_ffdcPtr, i_ffdcLen); +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlFFDC::~ErrlFFDC() +{ + // Free FFDC data memory + delete iv_data; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void ErrlFFDC::addData(const void *i_data, + const uint32_t i_size) +{ + // Resize memory block + iv_data = (uint8_t*)realloc(iv_data, iv_size + i_size); + + // Make sure reallocate call successes + if (iv_data != NULL) + { + // Copy data to new area + memcpy(iv_data + iv_size, i_data, i_size); + + // Total extra data + iv_size += i_size; + } + else + { + TRACFCOMP(g_trac_errl, "ErrlFFDC::addData() - Reallocate memory failed!"); + } +} + + +} // End namespace diff --git a/src/usr/errl/errlffdc.H b/src/usr/errl/errlffdc.H new file mode 100644 index 000000000..7e945527e --- /dev/null +++ b/src/usr/errl/errlffdc.H @@ -0,0 +1,87 @@ +#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(); + + /** + * @brief Appends data to the section + * Grows the section by the given amount + * + * @param[in] i_data Pointer to data source + * @param[in] i_size Data size (bytes) + * + * @return None + */ + void addData(const void *i_data, + const uint32_t i_size); + +private: + /** + * @brief Disabled copy constructor and assignment operator + */ + ErrlFFDC(const ErrlFFDC& i_right); + ErrlFFDC& operator=(const ErrlFFDC& i_right); + + uint8_t* iv_data; // Data Pointer + uint32_t iv_size; // Data Length +}; + + +} // End namespace + +#endif //ERRLFFDC_H diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C new file mode 100644 index 000000000..d3501e8ae --- /dev/null +++ b/src/usr/errl/errlmanager.C @@ -0,0 +1,74 @@ +/** + * @file errlmanager.C + * + * @brief Implementation of ErrlManager class + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <errl/errlmanager.H> +#include <trace/interface.H> +#include <errl/errlentry.H> + +namespace ERRORLOG +{ + +extern trace_desc_t* g_trac_errl; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlManager::ErrlManager() +:iv_currLogId(0) +{ + //@todo + // This is done in order to avoid reading logID from PNOR for every + // error log created. + // When ErrlManager singleton instantiated: + // 1. Parse the last committed error from PNOR + // 2. Get the logID from that error + // 3. Load iv_currLogId with that value. + // 4. When next error is committed, assign the next ID value to it + // before writing to PNOR. + + +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlManager::~ErrlManager() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void ErrlManager::commitErrLog(errlHndl_t& io_err) +{ + // If NULL, put out warning trace + if (io_err == NULL) + { + //@thi TRACFCOMP(g_trac_errl, "commitErrLog() - NULL pointer"); + } + else + { + // Assign a unique error ID to the committed log + uint32_t l_errId = getUniqueErrId(); + io_err->setLogId(l_errId); + + // @todo: + // - Flatten error into PNOR + + delete io_err; + io_err = NULL; + } + return; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +uint32_t ErrlManager::getUniqueErrId() +{ + return (__sync_add_and_fetch(&iv_currLogId, 1)); +} + +} // End namespace diff --git a/src/usr/errl/errlsctn.C b/src/usr/errl/errlsctn.C new file mode 100644 index 000000000..75d06c5bb --- /dev/null +++ b/src/usr/errl/errlsctn.C @@ -0,0 +1,32 @@ +/** + * @file errlsctn.C + * + * @brief Implementation of ErrlSctn class + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include "errlsctn.H" + +namespace ERRORLOG +{ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlSctn::ErrlSctn(const compId_t i_compId, + const uint8_t i_sctnVer, + const uint8_t i_subSect) +:iv_header(i_compId, i_sctnVer, i_subSect) +{ + +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +ErrlSctn::~ErrlSctn() +{ + +} + +} // end namespace diff --git a/src/usr/errl/errlsctn.H b/src/usr/errl/errlsctn.H new file mode 100644 index 000000000..800665d48 --- /dev/null +++ b/src/usr/errl/errlsctn.H @@ -0,0 +1,127 @@ +#ifndef ERRLSCTN_H +#define ERRLSCTN_H +/** + * @file errlsctn.H + * + * @brief Base class that abstracts a section in an error log. + * A section may be used to store unique data for the + * error such as FFDC, Software error information, etc... + * + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <stdint.h> +#include <stdlib.h> +#include <errl/errltypes.H> +#include "errlsctnhdr.H" + +namespace ERRORLOG +{ + +/** + * @brief Base class that abstracts a section in an error log object. + */ +class ErrlSctn +{ + +public: + + /** + * @brief Constructor + * Initializes the base object with section information + * + * @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 + * + */ + ErrlSctn(const compId_t i_compId, + const uint8_t i_sctnVer, + const uint8_t i_subSect); + + /** + * @brief Default destructor + * + * @return void + */ + virtual ~ErrlSctn(); + + //@todo - Need to add serialization interfaces for ErrlSctn object. + // Serialization method (boost serialization?) for HostBoot + // is currently not yet determined. + // Note: stream is currently not supported + + /** + * @brief Get section's version + * + * @return Section version (uint8_t) + * + */ + uint8_t sctnVer() const; + + /** + * @brief Get section's subsection type + * + * @return Subsection type (uint8_t) + * + */ + uint8_t subSect() const; + + /** + * @brief Get section's component Id + * + * @return Component Id of the section creator + * + */ + compId_t compId() const; + +private: + + /** + * @brief Disabled copy constructor and assignment operator + */ + ErrlSctn(const ErrlSctn& i_right); + ErrlSctn& operator=(const ErrlSctn& i_right); + + // Section header + ErrlSctnHdr iv_header; + +}; + +//----------------------------------------------------------------------- +// In-line functions +//----------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline uint8_t ErrlSctn::sctnVer() const +{ + return iv_header.iv_sctnVer; +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline uint8_t ErrlSctn::subSect() const +{ + return iv_header.iv_subSect; +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +inline compId_t ErrlSctn::compId() const +{ + return iv_header.iv_compId; +} + + +} // End namespace + +#endif //ERRLSCTN_H + diff --git a/src/usr/errl/errlsctnhdr.C b/src/usr/errl/errlsctnhdr.C new file mode 100644 index 000000000..a663b34b9 --- /dev/null +++ b/src/usr/errl/errlsctnhdr.C @@ -0,0 +1,38 @@ +/** + * @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 + * + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include "errlsctnhdr.H" + +namespace ERRORLOG +{ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +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() +{ + +} + +} // End namespace diff --git a/src/usr/errl/errlsctnhdr.H b/src/usr/errl/errlsctnhdr.H new file mode 100644 index 000000000..cd741f42f --- /dev/null +++ b/src/usr/errl/errlsctnhdr.H @@ -0,0 +1,76 @@ +#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> + +namespace ERRORLOG +{ + +/** + * @brief This class abstracts a header of a section in an error log object + */ +class ErrlSctnHdr +{ + // ErrlSctn needs to set the header's parameters + 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 + compId_t iv_compId; + uint8_t iv_sctnVer; + uint8_t iv_subSect; + +}; + +} // End namespace + +#endif //ERRLSCTNHDR_H + diff --git a/src/usr/errl/errlservicecodes.H b/src/usr/errl/errlservicecodes.H new file mode 100644 index 000000000..8884d6cd1 --- /dev/null +++ b/src/usr/errl/errlservicecodes.H @@ -0,0 +1,30 @@ +#ifndef __ERRL_SERVICE_CODE_H +#define __ERRL_SERVICE_CODE_H + +/** + * @file errlservicecodes.H + * + * @brief Reason code and Module ID definitions for ERRL component. + * + */ + +#include <hbotcompid.H> + +// Module IDs for ERRL component +enum +{ + ERRL_FIRST_MODULE_ID = 0x00, + //........ + ERRL_LAST_MODULE_ID = 0xFF +}; + +// Reason codes for ERRL component +enum errlReasonCode +{ + ERRL_FIRST_ERR = ERRL_COMP_ID | 0x01, + //........ + ERRL_LAST_ERR = ERRL_COMP_ID | 0xFF +}; + + +#endif diff --git a/src/usr/errl/makefile b/src/usr/errl/makefile new file mode 100644 index 000000000..22cd0ce00 --- /dev/null +++ b/src/usr/errl/makefile @@ -0,0 +1,8 @@ +ROOTPATH = ../../.. +MODULE = errl + +OBJS = errlentry.o errlmanager.o errlsctn.o errlffdc.o errlsctnhdr.o + +SUBDIRS = test.d + +include ${ROOTPATH}/config.mk diff --git a/src/usr/errl/test/errltest.H b/src/usr/errl/test/errltest.H new file mode 100644 index 000000000..ab3f40b65 --- /dev/null +++ b/src/usr/errl/test/errltest.H @@ -0,0 +1,143 @@ +#ifndef __ERRLTEST_H +#define __ERRLTEST_H + +/** + * @file errltest.H + * + * @brief Test case for Error Logging +*/ + +#include <cxxtest/TestSuite.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <errl/errltypes.H> + +#define TEST_REASON_CODE 0x0F0F +#define TEST_SEVERITY ERRORLOG::ERRL_SEV_INFORMATIONAL +#define TEST_MOD_ID 0x0022 +#define TEST_USR_DATA_1 0x8000000000000001 +#define TEST_USR_DATA_2 0x9000000000000003 +#define TEST_RETURN_CODE 0xF0F0 + +class ErrlTest: public CxxTest::TestSuite +{ +public: + + + /** + * @brief Test error log creation + * - Create an error log + * - Verify data of created log + * - Commit an error log + * - Delete an error log + */ + void testErrl1(void) + { + // Create an error log + errlHndl_t l_err = new ERRORLOG::ErrlEntry( + TEST_SEVERITY, + TEST_MOD_ID, + TEST_REASON_CODE, + TEST_USR_DATA_1, + TEST_USR_DATA_2); + + // Make sure log is created + if (l_err == NULL) + { + TS_FAIL("testErrl1: createErrlLog() outputs NULL pointer!"); + } + + // Verify log data + else if (l_err->sev() != ERRORLOG::ERRL_SEV_INFORMATIONAL) + { + TS_FAIL("testErrl1: createErrlLog() returns incorrect severity!"); + } + else if (l_err->reasonCode() != TEST_REASON_CODE) + { + TS_FAIL("testErrl1: createErrlLog() returns incorrect reason code!"); + } + else if (l_err->eventType() != ERRORLOG::ERRL_ETYPE_NOT_APPLICABLE) + { + TS_FAIL("testErrl1: createErrlLog() returns incorrect event type!"); + } + else if (l_err->subSys() != ERRORLOG::EPUB_RESERVED_0) + { + TS_FAIL("testErrl1: createErrlLog() returns incorrect sub system!"); + } + else if (l_err->srcType() != ERRORLOG::SRC_ERR_INFO) + { + TS_FAIL("testErrl1: createErrlLog() returns incorrect SRC type!"); + } + else if (l_err->termState() != ERRORLOG::TERM_STATE_UNKNOWN) + { + TS_FAIL("testErrl1: termState() returns incorrect term state!"); + } + else + { + // Commit error log + ERRORLOG::theErrlManager::instance().commitErrLog(l_err); + // Make sure error log has been deleted by manager + if (l_err != NULL) + { + TS_FAIL("testErrl1: commitErrLog() did not delete error!"); + } + } + } + + /** + * @brief Test error log parameter settings + */ + void testErrl2(void) + { + // Create an error log + errlHndl_t l_err = new ERRORLOG::ErrlEntry( + TEST_SEVERITY, + TEST_MOD_ID, + TEST_REASON_CODE, + TEST_USR_DATA_1, + TEST_USR_DATA_2); + + // Make sure log is created + if (l_err == NULL) + { + TS_FAIL("testErrl2: createErrlLog() returns NULL pointer!"); + } + else + { + // Set and verify log data + l_err->setSev(ERRORLOG::ERRL_SEV_UNKNOWN); + l_err->setEventType(ERRORLOG::ERRL_ETYPE_CAPACITY_UPGRADE); + l_err->setSubSys(ERRORLOG::EPUB_UNKNOWN); + l_err->setSrcType(ERRORLOG::SRC_ERR_INFO); + l_err->setTermState(ERRORLOG::TERM_STATE_NO_FLAGS); + + if (l_err->sev() != ERRORLOG::ERRL_SEV_UNKNOWN) + { + TS_FAIL("testErrl2: setSev() fails!"); + } + else if (l_err->eventType() != ERRORLOG::ERRL_ETYPE_CAPACITY_UPGRADE) + { + TS_FAIL("testErrl2: setEventType() fails!"); + } + else if (l_err->subSys() != ERRORLOG::EPUB_UNKNOWN) + { + TS_FAIL("testErrl2: setSubSys() fails!"); + } + else if (l_err->srcType() != ERRORLOG::SRC_ERR_INFO) + { + TS_FAIL("testErrl2: setSrcType() fails!"); + } + else if (l_err->termState() != ERRORLOG::TERM_STATE_NO_FLAGS) + { + TS_FAIL("testErrl2: setTermState() fails!"); + } + + // Delete the log + delete l_err; + l_err = NULL; + + } + } +}; + +#endif diff --git a/src/usr/errl/test/makefile b/src/usr/errl/test/makefile new file mode 100644 index 000000000..d27860550 --- /dev/null +++ b/src/usr/errl/test/makefile @@ -0,0 +1,6 @@ +ROOTPATH = ../../../.. + +MODULE = testerrl +TESTS = *.H + +include ${ROOTPATH}/config.mk diff --git a/src/usr/example/example.C b/src/usr/example/example.C index 803f719b0..536100368 100644 --- a/src/usr/example/example.C +++ b/src/usr/example/example.C @@ -4,6 +4,8 @@ #include <sys/task.h> #include <trace/interface.H> #include <example/example.H> +#include <example/examplerc.H> +#include <errl/errlentry.H> //static mutex_t value = mutex_create(); trace_desc_t *g_trac_test = NULL; @@ -25,3 +27,26 @@ uint64_t example1_function() return l_rc; } + +// This example shows how to create an error log with passed-in +// defined parameters +void example2_create_errorlog_function() +{ + /*@ + * @errortype + * @moduleid MY_MODULE_ID_1 + * @reasoncode MY_REASON_CODE_1 + * @userdata1 Meaning of userdata1 value + * @userdata2 Meaning of userdata2 value + * @devdesc Example of creating an error log + */ + errlHndl_t l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + MY_MODULE_ID_1, + MY_REASON_CODE_1, + 0x8000000000000001, + 0x9000000000000003); + delete l_err; + l_err = NULL; + return; +} diff --git a/src/usr/makefile b/src/usr/makefile index 7f48ff5c6..aa24cf6cd 100644 --- a/src/usr/makefile +++ b/src/usr/makefile @@ -1,6 +1,6 @@ ROOTPATH = ../.. OBJS = module_init.o -SUBDIRS = example.d trace.d cxxtest.d +SUBDIRS = example.d trace.d cxxtest.d errl.d include ${ROOTPATH}/config.mk |