summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMonte Copeland <copelanm@us.ibm.com>2011-08-11 15:57:40 -0500
committerMonte K. Copeland <copelanm@us.ibm.com>2011-08-16 13:24:44 -0500
commitf24bf89ab0cb82fee8ab80ed6f5aa8142e3db462 (patch)
tree8647432fc82bbd34becc2ebcd7f50f2fccd469b8 /src
parent802274b948ef4a52deb4285368a086f669d3913b (diff)
downloadblackbird-hostboot-f24bf89ab0cb82fee8ab80ed6f5aa8142e3db462.tar.gz
blackbird-hostboot-f24bf89ab0cb82fee8ab80ed6f5aa8142e3db462.zip
Changes to errl to commit error logs to L3 RAM 7
Change-Id: Ic058a5b9ea6f8f1d79fc0ff30097cc32f18423bd Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/221 Reviewed-by: Monte K. Copeland <copelanm@us.ibm.com> Tested-by: Jenkins Server
Diffstat (limited to 'src')
-rwxr-xr-xsrc/build/tools/cpfiles.pl1
-rw-r--r--src/include/assert.h21
-rw-r--r--src/include/usr/errl/errlentry.H217
-rw-r--r--src/include/usr/errl/errlmanager.H28
-rw-r--r--src/include/usr/errl/errltypes.H99
-rw-r--r--src/usr/errl/errlentry.C143
-rw-r--r--src/usr/errl/errlffdc.C32
-rw-r--r--src/usr/errl/errlffdc.H13
-rw-r--r--src/usr/errl/errlmanager.C150
-rw-r--r--src/usr/errl/errlsctn.C100
-rw-r--r--src/usr/errl/errlsctn.H59
-rw-r--r--src/usr/errl/errlsctnhdr.C1
-rw-r--r--src/usr/errl/errlsctnhdr.H6
-rw-r--r--src/usr/errl/makefile2
-rw-r--r--src/usr/errl/parser/errlparser.C701
-rw-r--r--src/usr/errl/parser/makefile35
-rw-r--r--src/usr/errl/parser/readcomps.rex58
-rw-r--r--src/usr/errl/test/errltest.H87
18 files changed, 1554 insertions, 199 deletions
diff --git a/src/build/tools/cpfiles.pl b/src/build/tools/cpfiles.pl
index b17764e0f..41182a187 100755
--- a/src/build/tools/cpfiles.pl
+++ b/src/build/tools/cpfiles.pl
@@ -36,6 +36,7 @@ sub printUsage;
my @files = ("src/build/tools/exthbdump.pl",
"src/build/simics/post_model_hook.simics",
"src/build/trace/traceHB.py",
+ "src/usr/errl/parser/bin/errlparser",
"img/hbotStringFile",
"img/hbicore.syms",
"img/hbicore_test.syms",
diff --git a/src/include/assert.h b/src/include/assert.h
index a8f3fb664..1abeb5e2a 100644
--- a/src/include/assert.h
+++ b/src/include/assert.h
@@ -156,6 +156,27 @@ void __assert(AssertBehavior i_assertb, int i_line);
#define crit_assert(expr,...) { }
#endif
+
+
+/** @brief Make an assertion at compile time. If Boolean expression exp
+ * is false, then the compile will stop with an error. Example usage:
+ * CPPASSERT( 2 == sizeof(compId_t));
+ * which would be used in front of errl flattening code that assumes
+ * compId_t is 2 bytes in size. Also with the use of -f short-enums
+ * compiler switch, one could assert
+ * CPPASSERT( 1 == sizeof(errlEventType_t));
+ * If the assertion fails, it will be a wakeup call that the errlEventType_t
+ * enum has grown larger than a byte in size. The mechanism to abend the
+ * compile when the expression is false is to cause a typedef of a char array
+ * that is -1 bytes in size.
+ *
+ * Similar: #define CHECK_SIZE(DATA, EXPECTED_SIZE)\
+ * typedef char CHECKSIZEVAR[(EXPECTED_SIZE == sizeof(DATA)) -1]
+ *
+ */
+#define CPPASSERT(exp) typedef char compile_time_assert_failed[2*((exp)!=0)-1]
+
+
#ifdef __cplusplus
};
#endif
diff --git a/src/include/usr/errl/errlentry.H b/src/include/usr/errl/errlentry.H
index 71d2102ae..7e9d91a50 100644
--- a/src/include/usr/errl/errlentry.H
+++ b/src/include/usr/errl/errlentry.H
@@ -29,7 +29,7 @@ class ErrlSctn;
class ErrlFFDC;
/**
- * @brief Host Boot Error log entry class.
+ * @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)
@@ -43,7 +43,7 @@ class ErrlEntry
public:
/**
- * @brief ErrlEntry constructor. Builds an error log with info
+ * @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
@@ -66,7 +66,7 @@ public:
* in the primary SRC
* @param[in] i_user2 64 bits of user data which are placed
* in the primary SRC
- * @return None
+ * @return None
*/
ErrlEntry(const errlSeverity_t i_sev,
const uint8_t i_modId,
@@ -79,7 +79,9 @@ public:
*
* 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.
+ * All logs not committed must be deleted to avoid a resource leak.
+ * Committing an error log via ErrlManager will cause ErrlManager
+ * to delete the log after saving it.
*
* @return None
*
@@ -92,6 +94,7 @@ public:
* problem is perceived to be. The severity is
* initially set by the parameter in the constructor
* and can be changed at any point thereafter.
+ * See errl/errltypes.H
*
* @return Current Log Severity
*
@@ -105,37 +108,70 @@ public:
* initially set by the parameter in the constructor
* and can be changed at any point thereafter.
*
- * @return void
+ * @param[in] i_sev Severity. See errl/errltypes.H
*
+ * @return void
*/
void setSev(const errlSeverity_t i_sev);
+
/**
- * @brief Returns the log's reason code
- *
- * @return uint16_t
+ * @brief Get reason code. See errl/errlreasoncodes.H
*
+ * @return reason code
*/
uint16_t reasonCode() const;
/**
- * @brief Returns the log's event type
+ * @brief Set reason code
+ *
+ * @param[in] i_reasonCode The reason code. The upper byte
+ * of a reason code is the component ID.
+ * See errl/errlreasoncodes.H
+ *
+ * @return void
+ */
+ void setReasonCode( const uint16_t i_reasonCode );
+
+ /**
+ * @brief Get module id. See errl/errlreasoncodes.H
+ *
+ * @return module id
+ */
+ uint8_t moduleId() const;
+
+
+
+ /**
+ * @brief Set module id
*
+ * @param[in] i_moduleId The module ID. See errl/errlreasoncodes.H
+ *
+ * @return void
+ */
+ void setModuleId( const uint8_t i_moduleId );
+
+
+ /**
+ * @brief Get the event type of the error log.
+ * See errl/errltypes.H
* @return errlEventType_t
*
*/
errlEventType_t eventType() const;
/**
- * @brief Set the log's event type
- *
- * @return void
- *
- */
+ * @brief Set the log's event type
+ *
+ * @param[in] i_eventType Event type. See errl/errltypes.H
+ *
+ * @return void
+ *
+ */
void setEventType(const errlEventType_t i_eventType);
/**
- * @brief Returns the log's sub system
+ * @brief Returns the log's sub system. See errl/errltypes.H
*
* @return epubSubSystem_t
*
@@ -143,15 +179,17 @@ public:
epubSubSystem_t subSys() const;
/**
- * @brief Set the log's sub system
+ * @brief Set the log's ePub sub system type.
*
- * @return void
+ * @param[in] i_subSys Subsystem type. See errl/errltypes.H
*
+ * @return void
*/
void setSubSys(const epubSubSystem_t i_subSys);
+
/**
- * @brief Returns the log's SRC type
+ * @brief Returns the log's SRC type. See errl/errltypes.H
*
* @return srcType_t
*
@@ -161,13 +199,16 @@ public:
/**
* @brief Set the log's SRC type
*
- * @return void
+ * @param[in] i_srcType The SRC type for this error log. See
+ * errl/errltypes.H
*
+ * @return void
*/
void setSrcType(const srcType_t i_srcType);
/**
- * @brief Returns the log's terminate state type
+ * @brief Returns the log's terminate state type. See
+ * errl/errltypes.H
*
* @return errlTermState_t
*
@@ -177,6 +218,8 @@ public:
/**
* @brief Set the log's Terminating state
*
+ * @param[in] i_termState See errl/errltypes.H
+ *
* @return void
*
*/
@@ -194,6 +237,7 @@ public:
* 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
*/
@@ -211,35 +255,48 @@ public:
* 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);
-private:
+
+
+
+
/**
- * @brief Disabled copy constructor and assignment operator
- */
- ErrlEntry(const ErrlEntry& i_right);
- ErrlEntry& operator=(const ErrlEntry& i_right);
+ * @brief Compute the flattened size of an error log.
+ *
+ * @return size in bytes of the flattened data.
+ */
+ uint64_t flattenedSize();
+
/**
- * @brief Add a data section to error log object
+ * @brief Flatten the data to caller's buffer.
*
- * @param[in] i_sctn Pointer to data section to be added
+ * @param[in,out] io_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 addSection(ErrlSctn* i_sctn);
+ uint64_t flatten( void * io_buffer, const uint64_t i_cbBuffer );
+
+
+
+
+private:
/**
- * @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 Disabled copy constructor and assignment operator
+ */
+ ErrlEntry(const ErrlEntry& i_right);
+ ErrlEntry& operator=(const ErrlEntry& i_right);
+
+
/**
* @brief Set the log's id
@@ -247,14 +304,17 @@ private:
* set this log's ID to a unique input number.
* This is to be called by ErrlManager only.
*
+ * There is no call to get the log id because it
+ * would just be zero until the log is committed.
+ *
+ * @param[in] i_val Log ID as assigned by ErrlManager
+ *
* @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
@@ -334,21 +394,19 @@ private:
#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;
+ 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
};
@@ -360,48 +418,65 @@ private:
////////////////////////////////////////////////////////////////////////////
inline errlSeverity_t ErrlEntry::sev() const
{
- return (iv_sev);
+ 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);
+ return iv_reasonCode;
+}
+
+inline void ErrlEntry::setReasonCode( const uint16_t i_reasonCode )
+{
+ iv_reasonCode = i_reasonCode;
+ return;
}
+
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
-inline errlEventType_t ErrlEntry::eventType() const
+inline uint8_t ErrlEntry::moduleId() const
+{
+ return iv_modId;
+}
+
+inline void ErrlEntry::setModuleId( const uint8_t i_moduleId )
{
- return (iv_eventType);
+ iv_modId = i_moduleId;
+ return;
}
+
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
+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);
+ return iv_subSys;
}
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
inline void ErrlEntry::setSubSys(const epubSubSystem_t i_subSys)
{
iv_subSys = i_subSys;
@@ -413,11 +488,9 @@ inline void ErrlEntry::setSubSys(const epubSubSystem_t i_subSys)
////////////////////////////////////////////////////////////////////////////
inline srcType_t ErrlEntry::srcType() const
{
- return (iv_srcType);
+ return iv_srcType;
}
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
inline void ErrlEntry::setSrcType(const srcType_t i_srcType)
{
iv_srcType = i_srcType;
@@ -428,11 +501,9 @@ inline void ErrlEntry::setSrcType(const srcType_t i_srcType)
////////////////////////////////////////////////////////////////////////////
inline errlTermState_t ErrlEntry::termState() const
{
- return (iv_termState);
+ return iv_termState;
}
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
inline void ErrlEntry::setTermState(const errlTermState_t i_termState)
{
iv_termState = i_termState;
@@ -440,18 +511,10 @@ inline void ErrlEntry::setTermState(const errlTermState_t i_termState)
}
////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-inline uint32_t ErrlEntry::logId() const
-{
- return (iv_logId);
-}
-
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
+// Called by errlmanager at log commit time.
inline void ErrlEntry::setLogId(const uint32_t i_val)
{
iv_logId = i_val;
- return;
}
} // End namespace
diff --git a/src/include/usr/errl/errlmanager.H b/src/include/usr/errl/errlmanager.H
index 559353d87..445188f5a 100644
--- a/src/include/usr/errl/errlmanager.H
+++ b/src/include/usr/errl/errlmanager.H
@@ -14,10 +14,15 @@
#include <stdlib.h>
#include <util/singleton.H>
#include <errl/errltypes.H>
+#include <sys/sync.h>
+#include <vector>
+#include <kernel/timemgr.H>
namespace ERRORLOG
{
+
+
/**
* @brief Global function to log an error
* Writes the log to PNOR where committed logs are kept.
@@ -79,7 +84,7 @@ public:
* @brief Returns a unique error log ID
*
* This routine generates a unique Error ID and assign it to
- * the input error log
+ * the input error log. Mutates iv_currLogId.
*
* @return Unique generated error log ID
*/
@@ -112,9 +117,28 @@ 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.
+ */
uint32_t iv_currLogId;
+
+ /**
+ * @brief
+ * Pointer to the header that preceeds the error log storage buffer
+ * in L3 RAM. This may go away when we adopt PNOR, or else become
+ * instance variables instead of a pointer pointing within the
+ * storage buffer.
+ */
+ storage_header_t * iv_pStorage;
+
+ /**
+ * @brief Serialization for error log commits.
+ */
+ mutex_t iv_mutex;
+
};
} // End namespace
diff --git a/src/include/usr/errl/errltypes.H b/src/include/usr/errl/errltypes.H
index ca1deef9f..94f630f72 100644
--- a/src/include/usr/errl/errltypes.H
+++ b/src/include/usr/errl/errltypes.H
@@ -8,6 +8,9 @@
* This header file contains the definition of ErrlEntry related
* parameters.
*
+ * This file will be included by error log parsers that run
+ * on pool machines, so the stuff in here needs to be generic.
+ *
*/
/**
@@ -55,7 +58,8 @@ namespace ERRORLOG
{
/**
- * @brief Enumeration of error log severity
+ * @brief Enumeration of error log severity.
+ * Needs to fit into 1 byte for flattening purposes.
*/
enum errlSeverity_t
{
@@ -67,11 +71,12 @@ enum errlSeverity_t
/**
* @brief Event (error) type
+ * Needs to fit into 1 byte for flattening purposes.
*/
enum errlEventType_t
{
- ERRL_ETYPE_NOT_APPLICABLE = 0,
- ERRL_ETYPE_DUMP_NOTIFICATION = 8,
+ ERRL_ETYPE_NOT_APPLICABLE = 0x00,
+ ERRL_ETYPE_DUMP_NOTIFICATION = 0x08,
ERRL_ETYPE_USER_DECONFIG = 0x20,
ERRL_ETYPE_SYS_DECONFIG = 0x21,
ERRL_ETYPE_CONCURRENT_MAINTENANCE = 0x40,
@@ -80,6 +85,7 @@ enum errlEventType_t
/**
* @brief Error log call out priority
+ * Needs to fit into 1 byte for flattening purposes.
*/
enum callOutPriority_t
{
@@ -90,6 +96,7 @@ enum callOutPriority_t
/**
* @brief Error log procedure Id
+ * Needs to fit into 1 byte for flattening purposes.
*/
enum epubProcedureId_t
{
@@ -98,6 +105,7 @@ enum epubProcedureId_t
/**
* @brief Sub system definitions
+ * Needs to fit into 1 byte for flattening purposes.
*/
enum epubSubSystem_t
{
@@ -107,6 +115,7 @@ enum epubSubSystem_t
/**
* @brief Terminating flag definitions
+ * Needs to fit into 1 word (32-bits) for flattening purposes.
*/
enum errlTermState_t
{
@@ -117,6 +126,7 @@ enum errlTermState_t
/**
* @brief SRC type definitions
+ * Needs to fit into 1 byte for flattening purposes.
*/
enum srcType_t
{
@@ -127,6 +137,89 @@ enum srcType_t
};
+/**
+ * @brief This is the size of the storage buffer, presently
+ * in L3 RAM. When this storage is filled, no more error logs
+ * will be committed. The L3 RAM storage is g_ErrlStorage[]
+ * declared in errlmanager.C in BSS data. This will change
+ * when switching to PNOR.
+ */
+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
+ * marker will appear at offset sizeof( storage_header_t )
+ */
+typedef struct storage_header
+{
+ uint32_t cbStorage; // count of bytes in buffer
+ uint32_t cInserted; // count of logs ever commited
+ uint32_t offsetStart; // start-of-list marker
+ uint32_t offsetMarker; // next-insertion marker
+} __attribute__((packed)) storage_header_t;
+
+
+
+
+/**
+ * @brief The storage buffer is a series of flattened error logs
+ * interspersed with markers.
+ * A typical marker will give the offset to the next marker and also
+ * the length of the flattened error log data.
+ */
+typedef struct marker
+{
+ uint32_t offsetNext;
+ uint32_t length;
+} __attribute__((packed)) marker_t;
+
+
+
} // End namespace
#endif // ERRLTYPES_H
diff --git a/src/usr/errl/errlentry.C b/src/usr/errl/errlentry.C
index 40138051c..f25d0cd29 100644
--- a/src/usr/errl/errlentry.C
+++ b/src/usr/errl/errlentry.C
@@ -9,12 +9,13 @@
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
+#include <hbotcompid.H>
#include <errl/errlentry.H>
#include <errl/errlmanager.H>
-#include <trace/interface.H>
-#include <hbotcompid.H>
#include "errlsctn.H"
#include "errlffdc.H"
+#include <trace/interface.H>
+#include <arch/ppc.H>
namespace ERRORLOG
{
@@ -29,20 +30,21 @@ 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)
+ 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_logId = theErrlManager::instance().getUniqueErrId();
- TRACFCOMP(ERRORLOG::g_trac_errl, "Error %d created : modid=%X, rc=%X", iv_logId, iv_modId, iv_reasonCode);
+
+ // record time of creation
+ iv_CreationTime = getTB();
}
///////////////////////////////////////////////////////////////////////////////
@@ -50,8 +52,8 @@ iv_sections(NULL)
ErrlEntry::~ErrlEntry()
{
// Free memory of all sections
- for (std::vector<ErrlSctn*>::iterator l_itr = iv_sections.begin();
- l_itr != iv_sections.end(); ++l_itr)
+ for (std::vector<ErrlSctn*>::iterator l_itr = iv_SectionVector.begin();
+ l_itr != iv_SectionVector.end(); ++l_itr)
{
delete (*l_itr);
}
@@ -69,15 +71,17 @@ ErrlFFDC* ErrlEntry::addFFDC(const compId_t i_compId,
if ( (i_dataPtr == NULL) || (i_ffdcLen == 0) )
{
- TRACFCOMP(ERRORLOG::g_trac_errl, "Invalid FFDC data pointer or size, no add");
+ 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);
+
+ // Add to the end of the vector of sections for this error log.
+ iv_SectionVector.push_back( l_ffdcSection );
}
return l_ffdcSection;
@@ -89,20 +93,109 @@ 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
+ // class ErrlFFDC inherits addData() from its parent class ErrlSctn
+ i_ffdcPtr->addData( i_dataPtr, i_dataLen );
return;
}
+
+
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-void ErrlEntry::addSection(ErrlSctn* i_sctn)
+
+uint64_t ErrlEntry::flattenedSize()
{
- // Add pointer
- iv_sections.push_back(i_sctn);
- return;
+ uint64_t l_bytecount = sizeof( errl_header_t );
+
+ // add the bytes in the sections, if any
+ std::vector<ErrlSctn*>::iterator it;
+ for( it = iv_SectionVector.begin(); it != iv_SectionVector.end(); it++ )
+ {
+ l_bytecount += (*it)->flattenedSize();
+ }
+
+ return l_bytecount;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Flatten object instance data into a packed structure.
+// See errl/erltypes.H and the errl_header_t struct.
+
+uint64_t ErrlEntry::flatten( void * io_pBuffer, uint64_t i_bufsize )
+{
+ uint64_t l_flatCount = 0;
+
+ do
+ {
+ l_flatCount = flattenedSize();
+ if ( i_bufsize < l_flatCount )
+ {
+ // error path; return zero
+ TRACFCOMP( ERRORLOG::g_trac_errl, "Invalid buffer size");
+ l_flatCount = 0;
+ break;
+ }
+
+ // 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));
+ 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++ )
+ {
+ uint64_t l_countofbytes = (*it)->flattenedSize();
+ (*it)->flatten( l_pchar, l_countofbytes );
+ l_pchar += l_countofbytes;
+ }
+ }
+ while( 0 );
+
+ return l_flatCount;
}
+
} // End namespace
diff --git a/src/usr/errl/errlffdc.C b/src/usr/errl/errlffdc.C
index 6fc4388fa..7e0204d12 100644
--- a/src/usr/errl/errlffdc.C
+++ b/src/usr/errl/errlffdc.C
@@ -12,7 +12,7 @@
#include <string.h>
#include <trace/interface.H>
#include "errlffdc.H"
-#include "errlsctn.H"
+
namespace ERRORLOG
{
@@ -26,10 +26,10 @@ ErrlFFDC::ErrlFFDC(const compId_t i_compId,
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 )
+: ErrlSctn(i_compId, i_ffdcVer, i_ffdcSubSect)
{
+
+ // addData is inherited from parent class ErrlSctn
addData(i_ffdcPtr, i_ffdcLen);
}
@@ -37,32 +37,8 @@ ErrlFFDC::ErrlFFDC(const compId_t i_compId,
///////////////////////////////////////////////////////////////////////////////
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
index 7e945527e..bbeea96a4 100644
--- a/src/usr/errl/errlffdc.H
+++ b/src/usr/errl/errlffdc.H
@@ -58,17 +58,6 @@ public:
*/
~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:
/**
@@ -77,8 +66,6 @@ private:
ErrlFFDC(const ErrlFFDC& i_right);
ErrlFFDC& operator=(const ErrlFFDC& i_right);
- uint8_t* iv_data; // Data Pointer
- uint32_t iv_size; // Data Length
};
diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C
index 10eccbc66..166fbe6c9 100644
--- a/src/usr/errl/errlmanager.C
+++ b/src/usr/errl/errlmanager.C
@@ -10,28 +10,79 @@
#include <errl/errlmanager.H>
#include <trace/interface.H>
#include <errl/errlentry.H>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+
namespace ERRORLOG
{
extern trace_desc_t* g_trac_errl;
+
+
+// Scaffolding
+// Store error logs in this memory buffer in L3 RAM.
+char g_ErrlStorage[ ERRL_STORAGE_SIZE ];
+
+
+/**
+* @brief
+* In storage, the flattened error logs are interspersed with "markers."
+* CBMARKER is the count of bytes in one marker.
+* CB2MARKERS is the count of bytes in two markers.
+*/
+#define CBMARKER (sizeof(marker_t))
+#define CB2MARKERS (2*sizeof(marker_t))
+
+/**
+* @brief OFFSET2MARKER()
+* Convert an offset within the buffer to a marker_t pointer.
+*/
+#define OFFSET2MARKER(off) (reinterpret_cast<marker_t*>(&g_ErrlStorage[off]))
+
+/**
+* @brief POINTER2OFFSET()
+* Convert a marker_t pointer to its offset within the buffer.
+*/
+#define POINTER2OFFSET(p) ((reinterpret_cast<char*>(p))-(g_ErrlStorage))
+
+
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
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.
+ // PNOR will be reinitialized every time hostboot runs
+ iv_currLogId = 0;
+
+ mutex_init(&iv_mutex);
+
+ // Scaffolding.
+ // For now, put error logs in a 64KB buffer in L3 RAM
+ // This buffer has a header (storage_header_t) followed by
+ // storage.
+ iv_pStorage = reinterpret_cast<storage_header_t*>(g_ErrlStorage);
+
+ // g_ErrlStorage is in BSS segment, therefore already zeroed.
+ // memset( iv_pStorage, 0, sizeof(storage_header_t));
+ // Storage size is placed here for benefit of downstream parsers.
+ iv_pStorage->cbStorage = sizeof( g_ErrlStorage );
+ // Offsets are zero-based at &g_ErrlStorage[0],
+ // so the first usable offset is just past the header.
+ iv_pStorage->offsetMarker = sizeof(storage_header_t);
+ iv_pStorage->offsetStart = sizeof(storage_header_t);
+
+ // g_ErrlStorage is in BSS segment, therefore already zeroed.
+ // Thus, the prime marker in storage is already zero.
+ // marker_t* l_pMarker = OFFSET2MARKER( iv_pStorage->offsetStart );
+ // l_pMarker->offsetNext = 0;
+ // l_pMarker->length = 0;
}
///////////////////////////////////////////////////////////////////////////////
@@ -41,41 +92,88 @@ ErrlManager::~ErrlManager()
}
///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
+//
+// Save and delete this error log. On output, io_err will be nul.
+//
void ErrlManager::commitErrLog(errlHndl_t& io_err)
{
- // If NULL, put out warning trace
- if (io_err == NULL)
+ do
{
- TRACFCOMP(g_trac_errl, "commitErrLog() - NULL pointer");
- }
- else
- {
- TRACFCOMP( g_trac_errl, "commitErrLog()> Reasoncode=%X, Id=%d", io_err->reasonCode(), io_err->logId() );
+ if (io_err == NULL)
+ {
+ // put out warning trace
+ TRACFCOMP(g_trac_errl, "commitErrLog() - NULL pointer");
+ break;
+ }
+
+
+ // 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);
+
+ // Get flattened count of bytes.
+ uint32_t l_cbActualFlat = io_err->flattenedSize();
+
+ // Round this copy up to next nearest word (32-bit) boundary.
+ uint32_t l_cbflat = ((l_cbActualFlat+3) & ~3);
+
+ // Save/flatten the error log to the storage buffer.
+ uint32_t l_extent = iv_pStorage->offsetMarker + CB2MARKERS + l_cbflat;
- //@fixme - an id is already assigned in the constructor, which one do we want?
- // Assign a unique error ID to the committed log
- //uint32_t l_errId = getUniqueErrId();
- //io_err->setLogId(l_errId);
+ if( l_extent < ERRL_STORAGE_SIZE)
+ {
+ // New data and its surrounding markers can fit between
+ // the insertion point and the end of the storage buffer.
+ // Flatten the data at the insertion point.
+ marker_t * l_pMarker = OFFSET2MARKER( iv_pStorage->offsetMarker );
+ io_err->flatten( l_pMarker+1, l_cbflat );
+ l_pMarker->length = l_cbActualFlat;
- // @todo:
- // - Flatten error into PNOR
+ // Assign offset to next marker to this marker.
+ l_pMarker->offsetNext=iv_pStorage->offsetMarker+CBMARKER+l_cbflat;
+
+ // Save new insertion point in header.
+ iv_pStorage->offsetMarker = l_pMarker->offsetNext;
+
+ // Initialize the marker at the new insertion point.
+ marker_t * pNew = OFFSET2MARKER( iv_pStorage->offsetMarker );
+ pNew->offsetNext = 0;
+ pNew->length = 0;
+ }
+
+
+ // Count of error logs called to commit, regardless if there was
+ // room to commit them or not.
+ iv_pStorage->cInserted++;
+
+
+ // unlock sem
+ mutex_unlock(&iv_mutex);
delete io_err;
io_err = NULL;
}
+ while( 0 );
return;
}
+
+
///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
+// This operation is protected by the callers use of a mutex.
uint32_t ErrlManager::getUniqueErrId()
{
- return (__sync_add_and_fetch(&iv_currLogId, 1));
+ /* return (__sync_add_and_fetch(&iv_currLogId, 1)); */
+ iv_currLogId++;
+ return iv_currLogId;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+// Global function (not a method on an object) to commit the error log.
void errlCommit(errlHndl_t& io_err)
{
ERRORLOG::theErrlManager::instance().commitErrLog(io_err);
diff --git a/src/usr/errl/errlsctn.C b/src/usr/errl/errlsctn.C
index 75d06c5bb..707bbf14b 100644
--- a/src/usr/errl/errlsctn.C
+++ b/src/usr/errl/errlsctn.C
@@ -7,26 +7,122 @@
/*****************************************************************************/
// I n c l u d e s
/*****************************************************************************/
+#include <trace/interface.H>
#include "errlsctn.H"
+#include <assert.h>
namespace ERRORLOG
{
+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_header(i_compId, i_sctnVer, i_subSect)
+:iv_ErrlSctnHdr(i_compId, i_sctnVer, i_subSect),iv_pData(NULL),iv_cbData(0)
{
-
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ErrlSctn::~ErrlSctn()
{
+ 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 )
+{
+ 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/errlsctn.H b/src/usr/errl/errlsctn.H
index 800665d48..682d59033 100644
--- a/src/usr/errl/errlsctn.H
+++ b/src/usr/errl/errlsctn.H
@@ -82,6 +82,46 @@ public:
*/
compId_t compId() const;
+
+ /**
+ * @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 Size of new data or else zero on error.
+ */
+ uint64_t addData(const void *i_data, const uint64_t i_size);
+
+
+ /**
+ * @brief Get flattened size. Typically called prior to flatten().
+ * Allocate space for the flat data, then call flatten(). These
+ * functions commonly used by ErrlManager when committing error
+ * logs.
+ *
+ * @return size
+ *
+ */
+ uint64_t flattenedSize();
+
+ /**
+ * @brief Get flattened data.
+ *
+ * @param[in,out] io_pBuffer Pointer to memory where flattened
+ * error log will go.
+ * @param[in] i_cbBuffer Count of bytes of memory available
+ * at io_pBuffer. Caller should ensure there is enough memory
+ * available by calling flattenedSize() first.
+ *
+ * @return Count of bytes flattened.
+ *
+ */
+ uint64_t flatten( void * io_pBuffer, const uint64_t i_cbBuffer );
+
+
+
private:
/**
@@ -90,8 +130,14 @@ private:
ErrlSctn(const ErrlSctn& i_right);
ErrlSctn& operator=(const ErrlSctn& i_right);
- // Section header
- ErrlSctnHdr iv_header;
+ // A section header object for this section.
+ ErrlSctnHdr iv_ErrlSctnHdr;
+
+ // Pointer to user-added data
+ uint8_t* iv_pData;
+
+ // Count of bytes of user-added data
+ uint64_t iv_cbData;
};
@@ -103,25 +149,28 @@ private:
////////////////////////////////////////////////////////////////////////////
inline uint8_t ErrlSctn::sctnVer() const
{
- return iv_header.iv_sctnVer;
+ return iv_ErrlSctnHdr.iv_sctnVer;
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
inline uint8_t ErrlSctn::subSect() const
{
- return iv_header.iv_subSect;
+ return iv_ErrlSctnHdr.iv_subSect;
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
inline compId_t ErrlSctn::compId() const
{
- return iv_header.iv_compId;
+ return iv_ErrlSctnHdr.iv_compId;
}
+
+
} // End namespace
+
#endif //ERRLSCTN_H
diff --git a/src/usr/errl/errlsctnhdr.C b/src/usr/errl/errlsctnhdr.C
index a663b34b9..3d2a15841 100644
--- a/src/usr/errl/errlsctnhdr.C
+++ b/src/usr/errl/errlsctnhdr.C
@@ -28,6 +28,7 @@ iv_subSect(i_subSect)
}
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ErrlSctnHdr::~ErrlSctnHdr()
diff --git a/src/usr/errl/errlsctnhdr.H b/src/usr/errl/errlsctnhdr.H
index cd741f42f..18dd75110 100644
--- a/src/usr/errl/errlsctnhdr.H
+++ b/src/usr/errl/errlsctnhdr.H
@@ -15,6 +15,7 @@
#include <stdlib.h>
#include <errl/errltypes.H>
#include <hbotcompid.H>
+#include <string.h>
namespace ERRORLOG
{
@@ -24,7 +25,7 @@ namespace ERRORLOG
*/
class ErrlSctnHdr
{
- // ErrlSctn needs to set the header's parameters
+ // ErrlSctn accesses ErrlSctnHdr directly.
friend class ErrlSctn;
/**
@@ -55,6 +56,8 @@ class ErrlSctnHdr
// is currently not yet determined.
// Note: stream is currently not supported
+
+
private:
/**
@@ -64,6 +67,7 @@ private:
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;
diff --git a/src/usr/errl/makefile b/src/usr/errl/makefile
index 22cd0ce00..eb826436a 100644
--- a/src/usr/errl/makefile
+++ b/src/usr/errl/makefile
@@ -3,6 +3,6 @@ MODULE = errl
OBJS = errlentry.o errlmanager.o errlsctn.o errlffdc.o errlsctnhdr.o
-SUBDIRS = test.d
+SUBDIRS = test.d parser.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/errl/parser/errlparser.C b/src/usr/errl/parser/errlparser.C
new file mode 100644
index 000000000..739e65558
--- /dev/null
+++ b/src/usr/errl/parser/errlparser.C
@@ -0,0 +1,701 @@
+/**
+ * @file errlparser.C
+ *
+ * @brief Parse and display committed error logs. Enter
+ * errlparser ? (or -? or -h or --help) to print help.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <string>
+using namespace std;
+
+
+#include <errl/errltypes.H>
+#include <hbotcompid.H>
+using namespace ERRORLOG;
+
+
+#define USAGE "\
+Usage:\n\
+\n\
+errlparser <imagefile> <symsfile> [-l | -d <logid>]\n\
+\n\
+Provide L3 memory image file and its hbicore*.syms file.\n\
+ -l summarize all error logs (default)\n\
+ -d id print detail from specific error log\n\
+\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
+// served sending the error message to stdout, not stderr. I don't
+// think Simics is piping stderr to its console.
+void halt( char * msg )
+{
+ fprintf( stdout, "%s", msg );
+
+ // exit the process with a non-zero process exit level.
+ exit(2);
+}
+
+
+
+
+//-------------------------------------------------------------------------
+// The file src/include/usr/hbotcompid.H provide a mapping from compId_t
+// to component name.
+// that maps comp id to a string label for it.
+struct _errlcompname
+{
+ char * pszName;
+ uint32_t value;
+};
+typedef _errlcompname ERRLCOMPNAME_t;
+
+ERRLCOMPNAME_t g_errlcompnames[] = {
+// comps.C generated at build time by a script
+// that parses data from src/include/usr/hbotcompid.H.
+// Refer to src/usr/errl/parser/makefile
+#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
+// OK by printing (null).
+char * FindComp( uint16_t reasoncode )
+{
+ char * pch = NULL;
+ uint32_t id = (reasoncode & 0xFF00 );
+ int c = sizeof( g_errlcompnames ) / sizeof( g_errlcompnames[0] );
+ for( int i = 0; i < c; i++ )
+ {
+ if( id == g_errlcompnames[i].value )
+ {
+ pch = g_errlcompnames[i].pszName;
+ break;
+ }
+ }
+ return pch;
+}
+
+
+
+//------------------------------------------------------------
+// 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 )
+{
+ 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 );
+
+ pch += 3;
+ }
+
+ szHex[ 23 ] = '-';
+ szHex[ 48 ] = 0;
+
+ 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
+section_header_t* ConvertSectionHeader( section_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
+ return p;
+}
+
+
+//-------------------------------------------------------------
+// endian stuff
+marker_t* ConvertMarker( marker_t* p)
+{
+ p->offsetNext = ntohl( p->offsetNext );
+ p->length = ntohl( p->length );
+ return p;
+}
+
+
+
+//-------------------------------------------------------------
+// endian switch a uint64
+uint64_t ntohll( uint64_t i )
+{
+ 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;
+}
+
+
+//-------------------------------------------------------------
+// endian stuff
+errl_header_t* ConvertErrlHeader( errl_header_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 );
+ return p;
+}
+
+
+
+//-------------------------------------------------------------
+// endian stuff
+storage_header_t * ConvertStorageHeader( storage_header_t * p )
+{
+ p->cbStorage = ntohl( p->cbStorage );
+ p->cInserted = ntohl( p->cInserted );
+ p->offsetMarker = ntohl( p->offsetMarker );
+ p->offsetStart = ntohl( p->offsetStart );
+ 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.
+// This function will allocate (malloc) the buffer and return a pointer to it.
+// On fatal error, this function will print a diagnostic and end the process.
+// Return how many bytes allocated for the buffer in io_cbBuffer.
+char* ReadStorageBuffer(char* i_Image, uint32_t i_ulAddr, uint32_t &io_cbBuffer)
+{
+ int fd;
+ int rc;
+ int cb;
+ off_t offsetEnd;
+ char * l_pchBuffer = NULL; // pointer to return
+ storage_header_t header;
+
+ // open the binary image of L3 RAM and read the errl log buffer
+ fd = open( i_Image, O_RDONLY );
+ if ( fd == -1 )
+ {
+ // write the error to stdout because more likely to be seen in Simics
+ fprintf(stdout, "Unable to open %s for reading.\n", i_Image);
+ fprintf(stdout, "Failed with errno %s\n", strerror(errno) );
+ exit(2);
+ }
+
+ offsetEnd = lseek( fd, 0, SEEK_END );
+ if( i_ulAddr >= offsetEnd )
+ {
+ fprintf( stdout, "Image file %s appears to be truncated. "
+ "Offset 0x%X exceeds size of image file.\n",
+ i_Image, i_ulAddr );
+ exit(2);
+ }
+
+ rc = lseek( fd, i_ulAddr, SEEK_SET );
+ assert( -1 != rc );
+
+
+ // Read just the header for the size of the buffer is
+ // stored in the header.
+ cb = read( fd, &header, sizeof( header ));
+ assert( -1 != cb );
+
+ // endian convert this copy of the header
+ ConvertStorageHeader( &header );
+
+ // io_cbBuffer is a count of bytes in storage
+ io_cbBuffer = header.cbStorage;
+
+ if( ( i_ulAddr + io_cbBuffer ) > offsetEnd )
+ {
+ fprintf( stdout, "Image file %s appears to be truncated. "
+ "Offset 0x%X exceeds size of image file.\n",
+ i_Image, i_ulAddr+io_cbBuffer );
+ exit(2);
+ }
+
+ // re-seek and re-read entire buffer this time.
+ rc = lseek( fd, i_ulAddr, SEEK_SET );
+ assert( -1 != rc );
+
+ l_pchBuffer = static_cast<char *>(malloc( io_cbBuffer ));
+ assert( l_pchBuffer );
+
+ cb = read( fd, l_pchBuffer, io_cbBuffer );
+ assert( -1 != cb );
+
+ close( fd );
+#if 0
+ {
+ // Write the error log storage buffer to its own file.
+ // Offsets stored in the buffer are relative to the
+ // start of the buffer. When this file is saved in
+ // its own file, the same offsets are relative to the
+ // start of the file. This is convenient when debugging.
+ fd = open( "storagebuffer.bin", O_CREAT | O_RDWR, 0666 );
+ if( -1 != fd )
+ {
+ write( fd, l_pchBuffer, io_cbBuffer );
+ close( fd );
+ }
+ }
+#endif
+ return l_pchBuffer;
+}
+
+
+
+
+
+
+//----------------------------------------------------------------------------
+// Open the given symbols file name, a text file, and find the storage address
+// of error logs given by the symbol in pszSearch.
+uint32_t FindSymbol( char * pszSymbolFile, char * pszSearch )
+{
+ char * pszAddr = NULL;
+ char * pch;
+ char szWork[ 1024 ];
+ uint32_t ulAddr = 0;
+ FILE * f;
+
+ f = fopen( pszSymbolFile, "r" );
+ if ( !f )
+ {
+ fprintf(stdout, "Unable to open file %s for reading.\n", pszSymbolFile);
+ fprintf(stdout, "Failed with errno %s\n", strerror(errno) );
+ exit(2);
+ }
+
+ while( fgets( szWork, sizeof( szWork ), f ))
+ {
+ pch = strstr( szWork, pszSearch );
+ if( pch )
+ {
+ pszAddr = szWork + 2;
+ pch = strchr( pszAddr, ',' );
+ assert( pch );
+ *pch = 0;
+ break;
+ }
+ }
+ fclose(f);
+
+ if( NULL == pszAddr )
+ {
+ fprintf( stdout, "Cannot find %s in syms file.\n", pszSearch );
+ exit(2);
+ }
+
+ int c = sscanf( pszAddr, "%x", &ulAddr );
+ if( 1 != c )
+ {
+ fprintf( stdout,
+ "Error, expecting '%s' to convert to hexidecimal.\n",
+ pszAddr );
+ exit(2);
+ }
+ return ulAddr;
+}
+
+
+
+// --------------------------------------------------------------------------
+// Print a summary of the error log, no user-defined data nor detail.
+// perrlog is already endian converted
+
+void PrintErrlSummary( errl_header_t * perrlog )
+{
+
+ // 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
+ );
+}
+
+
+//---------------------------------------------------------------------------
+//
+//
+void PrintErrlDetail( errl_header_t * perrlog )
+{
+
+ // print the summary line
+ PrintErrlSummary( perrlog );
+
+ // print sections if any
+ if( perrlog->csections )
+ {
+ int i;
+ section_header_t* psect;
+
+ // first section header resides just past the errl_header_t
+ psect = reinterpret_cast<section_header_t*>(perrlog+1);
+
+ // Endian convert it
+ ConvertSectionHeader( psect );
+
+ 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;
+ }
+
+ // 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);
+
+ // Endian convert it.
+ ConvertSectionHeader( psect );
+ }
+ while( 1 );
+ }
+}
+
+
+
+
+
+
+//-------------------------------------------------------------
+int main( int argc, char *argv[] )
+{
+ char * pch;
+ char * pszImageFile = NULL;
+ char * pszSymbolFile = NULL;
+ char szWork[ 1024 ];
+ unsigned char * puch;
+ char * pszSearch;
+ char * pszAddr = NULL;
+ char * pchBuffer;
+ uint32_t ulAddr;
+ char szDivider[ 256 ];
+ uint32_t ulLogId = 0;
+ int c;
+ int cb;
+ int cbSearch;
+ int fd;
+ int i;
+ int k;
+ int item;
+ int fOK;
+ int rc;
+ int exitcode = 0;
+ uint32_t cbBuffer = 0;
+ off_t offset;
+ off_t offsetEnd;
+ int fVerbose = 0;
+ int fList = 1;
+ int fDetail = 0;
+ int fFound = 0;
+
+
+ // build a =========== divider for printfing
+ cb = 84;
+ assert( cb < sizeof( szDivider ));
+ memset( szDivider, '=', sizeof( szDivider ));
+ szDivider[ cb ] = 0;
+
+
+ // Examine args.
+ i = 1;
+ while ( i < argc )
+ {
+ if( 0 == strcmp( "-v", argv[i] ))
+ {
+ fVerbose = 1;
+ }
+ else if( 0 == strcmp( "-d", argv[i] ))
+ {
+ i++;
+ if( i >= argc )
+ {
+ fprintf( stdout, "Provide -d <logid>\n" );
+ exit( 2 );
+ }
+ int c = sscanf( argv[i], "%d", &ulLogId );
+ if( c != 1 )
+ {
+ fprintf( stdout, "Provide -d <decimal log ID>\n" );
+ exit( 2 );
+ }
+ fList = 0;
+ fDetail = 1;
+ }
+ else if( 0 == strcmp( "-l", argv[i] ))
+ {
+ fList = 1;
+ fDetail = 0;
+ }
+ else if( 0 == strcmp("?", argv[i]) ||
+ 0 == strcmp("-?", argv[i]) ||
+ 0 == strcmp("-h", argv[i]) ||
+ 0 == strcmp("--help", argv[i]))
+ {
+ // help
+ halt( USAGE );
+ }
+ else if( 0 == strcmp( "-", argv[i] ))
+ {
+ // unrecognized switch
+ halt( USAGE );
+ }
+ else
+ {
+ // must be a file name
+ pch = strstr( argv[i], "syms" );
+ if( pch )
+ {
+ pszSymbolFile = strdup( argv[i] );
+ }
+ else
+ {
+ pszImageFile = strdup( argv[i] );
+ }
+ }
+
+ i++;
+ }
+
+
+ // Check args.
+ if((!pszImageFile) || (!pszSymbolFile))
+ {
+ halt( USAGE );
+ }
+
+
+
+ // Given the symbols file, locate the address/offset of the errl storage
+ // buffer.
+ ulAddr = FindSymbol( pszSymbolFile, "g_ErrlStorage" );
+ if( fVerbose )
+ {
+ printf( "Error log storage buffer offset: 0x%08x\n", ulAddr );
+ }
+
+
+ // Given the image file, read the portion that contains the
+ // error logs.
+ pchBuffer = ReadStorageBuffer( pszImageFile, ulAddr, cbBuffer );
+ assert( pchBuffer );
+ assert( cbBuffer );
+ if( fVerbose )
+ {
+ printf("Errlog storage buffer size: %d (decimal) bytes\n", cbBuffer );
+ }
+
+
+ // Convert the endianess of the storage header.
+ storage_header_t* pHeader = reinterpret_cast<storage_header_t*>(pchBuffer);
+ ConvertStorageHeader( pHeader );
+ if( fVerbose )
+ {
+ printf( "%d error logs were committed.\n", pHeader->cInserted );
+ printf( "Start offset: 0x%08x\n", pHeader->offsetStart );
+ printf( "Ending offset: 0x%08x\n", pHeader->offsetMarker );
+ }
+
+
+/** @brief Convert an offset to a marker_t pointer. */
+#define OFFSET2MARKER(offset) (reinterpret_cast<marker_t*>(pchBuffer+offset))
+
+
+/** @brief Convert a marker_t pointer to an offset within the buffer. */
+#define MARKER2OFFSET(p) ((reinterpret_cast<char*>(p))-pchBuffer)
+
+
+
+ // Count how many error logs found
+ int logcount = 0;
+
+ // Traverse the list of error logs in the buffer. At this time, the
+ // buffer does not wrap. It is a straight shot from start to finish.
+ // Follow the markers. The start-of-list marker:
+ marker_t* pMarker = ConvertMarker( OFFSET2MARKER(pHeader->offsetStart));
+
+ while( 1 )
+ {
+ if( fVerbose )
+ {
+ cb = printf( "Marker at 0x%06x: next 0x%06x, length 0x%06x\n",
+ MARKER2OFFSET(pMarker),
+ pMarker->offsetNext,
+ pMarker->length );
+ }
+
+ if( pMarker->offsetNext == 0 )
+ {
+ // This is the list-ending marker.
+ printf( "%s\n", szDivider );
+ break;
+ }
+
+ assert( pMarker->length );
+
+ logcount++;
+
+ // Flattened struct of an error log resides just past marker.
+ errl_header_t* perr = reinterpret_cast<errl_header_t*>(pMarker+1);
+ ConvertErrlHeader( perr );
+
+ if( fList )
+ {
+ // Just list the error log headers.
+ printf( "%s\n", szDivider );
+ PrintErrlSummary( perr );
+ }
+ else if(( fDetail ) && ( perr->logId == ulLogId ))
+ {
+ // Print the detail for the one error log.
+ printf( "%s\n", szDivider );
+ PrintErrlDetail( perr );
+ fFound = 1;
+ }
+
+ // next marker/error log
+ pMarker = ConvertMarker( OFFSET2MARKER(pMarker->offsetNext) );
+ }
+
+
+ if( fVerbose )
+ {
+ printf( "%d error logs found.\n", logcount );
+ }
+
+ if( fDetail && !fFound )
+ {
+ printf( "Error log %d not found.\n", ulLogId );
+ exitcode = 2;
+ }
+ return exitcode;
+}
+
diff --git a/src/usr/errl/parser/makefile b/src/usr/errl/parser/makefile
new file mode 100644
index 000000000..f0d8e180b
--- /dev/null
+++ b/src/usr/errl/parser/makefile
@@ -0,0 +1,35 @@
+# makefile for errlparser,
+# a 32-bit x86 linux binary suitable for running on GFW pool machines.
+
+
+ROOTPATH=../../../..
+
+CC=g++ -m32
+CFLAGS:=-g -O0 -I $(ROOTPATH)/src/include/usr
+BIN:=bin
+
+
+all: code_pass
+
+gen_pass:
+
+code_pass: bindir $(BIN)/errlparser
+
+clean:
+ rm -fr $(BIN)
+
+beam:
+
+bindir:
+ mkdir -p $(BIN)
+
+$(BIN)/comps.C: $(ROOTPATH)/src/include/usr/hbotcompid.H readcomps.rex
+ rexx readcomps.rex $(ROOTPATH)/src/include/usr/hbotcompid.H >$(BIN)/comps.C
+
+$(BIN)/errlparser.o: errlparser.C $(ROOTPATH)/src/include/usr/errl/errltypes.H $(BIN)/comps.C
+ $(CC) -c $(CFLAGS) -I bin -o $(BIN)/errlparser.o errlparser.C
+
+$(BIN)/errlparser: $(BIN)/errlparser.o
+ $(CC) -o $(BIN)/errlparser $(BIN)/errlparser.o
+
+
diff --git a/src/usr/errl/parser/readcomps.rex b/src/usr/errl/parser/readcomps.rex
new file mode 100644
index 000000000..9aad554d8
--- /dev/null
+++ b/src/usr/errl/parser/readcomps.rex
@@ -0,0 +1,58 @@
+/*
+ * @file readcomps.rex
+ *
+ * Input file name is expected to be hbotcompid.H
+ * Output to stdout a snippet of C code that can
+ * be included by errlparser.C
+ */
+
+parse arg szInput .
+
+if length( szInput ) = 0 then do
+ say 'Give filename on command line.'
+ signal halt
+end
+
+szRC = stream( szInput, 'C', 'OPEN READ' )
+if left( szRC, 5 ) <> 'READY' then do
+ say 'File' szInput 'not found.'
+ signal halt
+end
+
+do while lines( szInput )
+ szCompName = ''
+ szCompID = ''
+
+ szLine = linein( szInput )
+ p1 = pos( "compId_t", szLine );
+ p2 = pos( "_COMP_ID", szLine );
+ p3 = pos( "MY_COMP_", szLine );
+ if p1 > 0 & p2 > p1 & p3=0 then do
+
+ /* interesting COMP_ID line */
+ do i = 1 to words( szLine )
+ w = translate( word( szLine, i ))
+ if pos( "_COMP_ID", w ) > 0 then szCompName = w
+ if pos( "0X", w ) > 0 then szCompID = w
+ end
+
+ /* clean them up */
+ szCompName = left( szCompName, pos( "_", szCompName )-1 )
+ szCompID = strip( szCompID, 'B', ';' )
+
+ /* This output will be included by errlparser.C */
+ say " {" '"'szCompName'",' szCompID "},"
+
+ end
+end
+
+
+szRC = stream( szInput, 'C', 'CLOSE' )
+if left( szRC, 5 ) <> 'READY' then signal halt
+
+return 0
+
+
+halt:
+say 'Error: readcomps.rex problem'
+exit 2
diff --git a/src/usr/errl/test/errltest.H b/src/usr/errl/test/errltest.H
index 7d10c3a34..40e58a266 100644
--- a/src/usr/errl/test/errltest.H
+++ b/src/usr/errl/test/errltest.H
@@ -10,9 +10,9 @@
#include <cxxtest/TestSuite.H>
#include <errl/errlmanager.H>
#include <errl/errlentry.H>
-#include <errl/errltypes.H>
+#include <hbotcompid.H>
-#define TEST_REASON_CODE 0x0F0F
+#define TEST_REASON_CODE (ERRL_COMP_ID | 0x0F)
#define TEST_SEVERITY ERRORLOG::ERRL_SEV_INFORMATIONAL
#define TEST_MOD_ID 0x0022
@@ -29,7 +29,6 @@
#define TEST_USR_64BIT_2 0x9000000000000003
-#define TEST_RETURN_CODE 0xF0F0
class ErrlTest: public CxxTest::TestSuite
{
@@ -45,37 +44,93 @@ public:
*/
void testErrl1(void)
{
+ ERRORLOG::ErrlFFDC * 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;
- uint8_t l_8bit_2 = TEST_USR_8BIT_2;
- uint32_t l_32bit_1 = TEST_USR_32BIT_1;
- uint64_t l_userData1 =
- TWO_UINT32_TO_UINT64(
- TO_UINT32(TWO_UINT8_TO_UINT16(l_8bit_1, l_8bit_2)), l_32bit_1);
+ uint8_t l_8bit_1 = TEST_USR_8BIT_1; // 0x80
+ uint8_t l_8bit_2 = TEST_USR_8BIT_2; // 0x93
+ uint32_t l_32bit_1 = TEST_USR_32BIT_1; // 0x80000001
+ 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
+
+
// l_userData2 = l_16bit_1:l_16bit_2:l_32bit_2
- uint16_t l_16bit_1 = TEST_USR_16BIT_1;
- uint16_t l_16bit_2 = TEST_USR_16BIT_2;
- uint32_t l_32bit_2 = TEST_USR_32BIT_2;
- uint64_t l_userData2 =
- TWO_UINT16_ONE_UINT32_TO_UINT64(l_16bit_1, l_16bit_2, l_32bit_2);
+ uint16_t l_16bit_1 = TEST_USR_16BIT_1; // 0x8000
+ uint16_t l_16bit_2 = TEST_USR_16BIT_2; // 0x9003
+ uint32_t l_32bit_2 = TEST_USR_32BIT_2; // 0x90000003
+ uint64_t l_userData2 = TWO_UINT16_ONE_UINT32_TO_UINT64(l_16bit_1, l_16bit_2, l_32bit_2);
+ // yields 0x8000900390000003
// Create an error log
errlHndl_t l_err = new ERRORLOG::ErrlEntry(
- TEST_SEVERITY,
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
TEST_MOD_ID,
TEST_REASON_CODE,
l_userData1,
l_userData2);
+
// Make sure log is created
if (l_err == NULL)
{
TS_FAIL("testErrl1: createErrlLog() outputs NULL pointer!");
}
+
+ // These addFFDC() calls return a pointer to class ERRORLOG::ErrlFFDC
+ // but errlffdc.H is not publicly includable to give me the definition
+ // for it. addFFDC() should return a Boolean indication of success.
+
+ const char * pch = "martha washington";
+ pffdc = l_err->addFFDC( ERRL_COMP_ID, pch, strlen( pch ), 1, 2 );
+ if ( NULL == pffdc )
+ {
+ TS_FAIL("testErrl1: addFFDC() output NULL pointer");
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+ pch = "ronald ";
+ pffdc = l_err->addFFDC( ERRL_COMP_ID, pch, strlen( pch ), 7, 8 );
+ if ( NULL == pffdc )
+ {
+ TS_FAIL("testErrl1: addFFDC() output NULL pointer");
+ }
+
+ // Append data to something already added.
+ pch = "reagan";
+ l_err->appendToFFDC( pffdc, pch, strlen(pch) );
+
+
+ // Add null data.
+ 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)
{
@@ -133,7 +188,7 @@ public:
// Create an error log
errlHndl_t l_err = new ERRORLOG::ErrlEntry(
- TEST_SEVERITY,
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
TEST_MOD_ID,
TEST_REASON_CODE,
l_userData1,
OpenPOWER on IntegriCloud