summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorStephen Cprek <smcprek@us.ibm.com>2013-06-21 16:34:25 -0700
committerA. Patrick Williams III <iawillia@us.ibm.com>2014-10-16 10:42:46 -0500
commit60a6933fb818b282fb7aa50b4a7f4d98ebd4657f (patch)
tree67d0b14ec56b358e004c10526bb61135b7dd6f56 /src/usr
parent1ca3b284749604f3984b002fb292e68e86b1227a (diff)
downloadtalos-hostboot-60a6933fb818b282fb7aa50b4a7f4d98ebd4657f.tar.gz
talos-hostboot-60a6933fb818b282fb7aa50b4a7f4d98ebd4657f.zip
Add human-readable dumps of error log entries as they are committed.
Origin: Google Shared Technology Change-Id: I1d0a30faa27c0b8bd1b76418706e24378a5da7eb RTC: 97491 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/11266 Tested-by: Jenkins Server Reviewed-by: Brian Silver <bsilver@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/errl/errlmanager.C368
-rwxr-xr-xsrc/usr/errl/parser/genErrlParsers.pl64
-rw-r--r--src/usr/errl/parser/makefile2
-rw-r--r--src/usr/errldisplay/errldisplay.C195
-rw-r--r--src/usr/errldisplay/makefile37
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvctasks.H17
-rw-r--r--src/usr/makefile1
7 files changed, 521 insertions, 163 deletions
diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C
index 14a58b05f..0da331a44 100644
--- a/src/usr/errl/errlmanager.C
+++ b/src/usr/errl/errlmanager.C
@@ -6,6 +6,7 @@
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2011,2014 */
+/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -46,6 +47,10 @@
#include <pnor/pnorif.H>
#include <sys/mm.h>
#include <intr/interrupt.H>
+#include <errldisplay/errldisplay.H>
+#include <console/consoleif.H>
+#include <config.h>
+#include <functional>
namespace ERRORLOG
{
@@ -87,6 +92,13 @@ const uint32_t PNOR_ERROR_LENGTH = 4096;
const uint32_t EMPTY_ERRLOG_IN_PNOR = 0xFFFFFFFF;
const uint32_t FIRST_BYTE_ERRLOG = 0xF0000000;
+// Comparator function to check if a eid and a plid are equal
+bool compareEidToPlid(const uint32_t i_plid,
+ const std::pair<errlHndl_t, uint8_t> i_pair)
+{
+ return (i_pair.first->eid() == i_plid);
+}
+
class AtLoadFunctions
{
public:
@@ -109,7 +121,8 @@ ErrlManager::ErrlManager() :
iv_pnorOpenSlot(0),
iv_isSpBaseServices(true), // queue msgs for fsp until we find we shouldnt
iv_isMboxEnabled(false), // but mbox isn't ready yet..
- iv_nonInfoCommitted(false)
+ iv_nonInfoCommitted(false),
+ iv_isErrlDisplayEnabled(false)
{
TRACFCOMP( g_trac_errl, ENTER_MRK "ErrlManager::ErrlManager constructor" );
@@ -258,15 +271,15 @@ void ErrlManager::errlogMsgHndlr ()
{
iv_isSpBaseServices = false;
- // if there are queued msgs, delete them
- while (!iv_errlToSend.empty())
+ // if there are queued msgs, delete the errors that
+ // have been fully processed
+ ErrlListItr_t it = iv_errlList.begin();
+ while(it != iv_errlList.end())
{
- msg_t * msg = iv_errlToSend.front();
- free( msg->extra_data );
- msg_free( msg );
- // delete from the list
- iv_errlToSend.pop_front();
- } // while items on iv_errlToSend list
+ // Mark MBOX processing complete
+ _clearMboxFlag(*it);
+ _updateErrlListIter(it);
+ }
}
//We are done with the msg
@@ -313,38 +326,29 @@ void ErrlManager::errlogMsgHndlr ()
// if error(s) came in before MBOX was ready,
// the msg(s) would be on this list. send it now.
- while (!iv_errlToSend.empty())
+ ErrlListItr_t it = iv_errlList.begin();
+ while(it != iv_errlList.end())
{
- msg_t * msg = iv_errlToSend.front();
-
- l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg );
- if( l_err )
+ // Check if MBOX processing is needed
+ if (_isMboxFlagSet(*it))
{
- TRACFCOMP(g_trac_errl, ERR_MRK "Failed sending error log to FSP");
-
- //Free the extra data due to the error
- free( msg->extra_data );
- msg_free( msg );
-
- delete l_err;
- l_err = NULL;
+ // Mark MBOX processing complete
+ sendErrLogToMbox(it->first);
+ _clearMboxFlag(*it);
}
-
- // delete from the list
- iv_errlToSend.pop_front();
- } // while items on list
+ _updateErrlListIter(it);
+ }
}
else
{
- // if there are queued msgs, delete them
- while (!iv_errlToSend.empty())
+ // Delete errors that have been completely processed
+ ErrlListItr_t it = iv_errlList.begin();
+ while(it != iv_errlList.end())
{
- msg_t * msg = iv_errlToSend.front();
- free( msg->extra_data );
- msg_free( msg );
- // delete from the list
- iv_errlToSend.pop_front();
- } // while items on iv_errlToSend list
+ // Mark MBOX processing complete
+ _clearMboxFlag(*it);
+ _updateErrlListIter(it);
+ }
}
//We are done with the msg
@@ -353,9 +357,37 @@ void ErrlManager::errlogMsgHndlr ()
// go back and wait for a next msg
break;
}
+ case ERRLOG_ACCESS_ERRLDISP_TYPE:
+ {
+#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY
+ // Errldisplay now ready
+ iv_isErrlDisplayEnabled = true;
+
+ CONSOLE::displayf("ERRL",
+ "Dumping errors reported prior to registration\n");
+
+ // Display errlogs to errldisplay
+ ErrlListItr_t it = iv_errlList.begin();
+ while(it != iv_errlList.end())
+ {
+ // Check if ERRLDISP processing is needed
+ if (_isErrlDispFlagSet(*it))
+ {
+ ERRORLOGDISPLAY::errLogDisplay().msgDisplay
+ (it->first,
+ ((it->first->reasonCode()) & 0xFF00));
+ // Mark ERRLDISP processing complete
+ _clearErrlDispFlag(*it);
+ }
+ _updateErrlListIter(it);
+ }
+#endif
+ //We are done with the msg
+ msg_free(theMsg);
+ }
case ERRLOG_NEEDS_TO_BE_COMMITTED_TYPE:
{
- //Extract error log handle from the message. We need the
+ // Extract error log handle from the message. We need the
// error log handle to pass along to saveErrLogEntry and
// sendErrLogToMbox
errlHndl_t l_err = (errlHndl_t) theMsg->extra_data;
@@ -363,25 +395,47 @@ void ErrlManager::errlogMsgHndlr ()
//Ask the ErrlEntry to assign commit component, commit time
l_err->commit( (compId_t) theMsg->data[0] );
+ // Pair with all flags set to add to the errlList
+ std::pair<errlHndl_t, uint8_t> l_pair(l_err, ALL_FLAGS);
+
+ // Display errl to errldisplay
+#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY
+ if (iv_isErrlDisplayEnabled)
+ {
+ ERRORLOGDISPLAY::errLogDisplay().msgDisplay
+ (l_err,
+ ( (l_err->reasonCode()) & 0xFF00));
+ // Mark ERRLDISP processing complete on this error
+ _clearErrlDispFlag(l_pair);
+ }
+#endif
//Save the error log to PNOR
bool l_savedToPnor = saveErrLogToPnor(l_err);
+ // Check if we actually saved the msg to PNOR
+ if (l_savedToPnor)
+ {
+ // Mark PNOR processing complete on this error
+ _clearPnorFlag(l_pair);
+ }
+
#ifdef STORE_ERRL_IN_L3
//Write the error log to L3 memory
//useful ONLY for the hb-errl tool
saveErrLogEntry ( l_err );
#endif
- //Try to send the error log if someone is there to receive
- if (iv_isSpBaseServices)
+ // Try to send the error log if someone is there to receive
+ if (!iv_isSpBaseServices)
{
- msg_t *l_sentToMbox = sendErrLogToMbox ( l_err );
- if (l_sentToMbox != NULL)
- {
- // we were supposed to send it and couldn't;
- // save it on the queue.
- iv_errlToSend.push_back(l_sentToMbox);
- }
+ // Mark MBOX processing complete on this error
+ _clearMboxFlag(l_pair);
+ }
+ else if (iv_isSpBaseServices && iv_isMboxEnabled)
+ {
+ sendErrLogToMbox(l_err);
+ // Mark MBOX processing complete on this error
+ _clearMboxFlag(l_pair);
}
//Ask the ErrlEntry to process any callouts
@@ -400,17 +454,16 @@ void ErrlManager::errlogMsgHndlr ()
INFO_MRK"shutdown in progress" );
}
- // check if we actually saved the msg to PNOR
- if (l_savedToPnor)
+ // If l_errl has not been fully proccessed delete it
+ // otherwise add to list
+ if (l_pair.second == 0)
{
- //done with the error log handle so delete it.
delete l_err;
l_err = NULL;
}
else
- { // save didn't work - push into a list to do when
- // the next ACK gets processed.
- iv_errlToSave.push_back(l_err);
+ {
+ iv_errlList.push_back(l_pair);
}
//We are done with the msg
@@ -427,53 +480,43 @@ void ErrlManager::errlogMsgHndlr ()
TRACFCOMP( g_trac_errl, INFO_MRK"ack: %.8x", l_tmpPlid);
bool didAck = ackErrLogInPnor(l_tmpPlid);
-
if (!didAck)
{
// couldn't find that errlog in PNOR, look in our
- // ToSave list - maybe it's there waiting
- for (std::list<errlHndl_t>::iterator
- it = iv_errlToSave.begin();
- it != iv_errlToSave.end();
- it++)
+ // errlMsgList - maybe it's there waiting
+ ErrlListItr_t it = std::find_if(iv_errlList.begin(),
+ iv_errlList.end(),
+ std::bind1st(ptr_fun(&compareEidToPlid)
+ ,l_tmpPlid));
+ // Check if such errl was found
+ if (it != iv_errlList.end())
{
- errlHndl_t l_err = *it;
- if (l_err->eid() == l_tmpPlid)
- {
- // we found it
- // done with the error log handle so delete it.
- delete l_err;
- l_err = NULL;
-
- // delete from the list
- iv_errlToSave.erase(it);
-
- // break out of the for loop - we're done
- break;
- }
- } // for
+ // We found the errlog
+ // Mark PNOR processing complete
+ _clearPnorFlag(*it);
+ _updateErrlListIter(it);
+ }
}
msg_free(theMsg);
- if (!iv_errlToSave.empty())
- {
- //we didn't have room before in PNOR to save an
- // error log, so try now since we just ACKed one.
- errlHndl_t l_err = iv_errlToSave.front();
+ // We didn't have room before in PNOR to save an
+ // error log, so try now since we just ACKed one.
+ ErrlListItr_t it = std::find_if(iv_errlList.begin(),
+ iv_errlList.end(),
+ _isPnorFlagSet);
- bool l_savedToPnor = saveErrLogToPnor(l_err);
+ // Check if such errl was found
+ if (it != iv_errlList.end())
+ {
+ bool l_savedToPnor = saveErrLogToPnor(it->first);
// check if we actually saved the msg to PNOR
if (l_savedToPnor)
- { // if so, we're done - clean up
-
- //done with the error log handle so delete it.
- delete l_err;
- l_err = NULL;
-
- // delete from the list
- iv_errlToSave.pop_front();
+ {
+ // Mark PNOR processing complete
+ _clearPnorFlag(*it);
+ _updateErrlListIter(it);
}
// else, still couldn't save it (for some reason) so
// it's still on the list.
@@ -513,7 +556,7 @@ void ErrlManager::errlogMsgHndlr ()
///////////////////////////////////////////////////////////////////////////////
// ErrlManager::sendErrLogToMbox()
///////////////////////////////////////////////////////////////////////////////
-msg_t *ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err )
+void ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err )
{
msg_t *msg = NULL;
@@ -532,50 +575,35 @@ msg_t *ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err )
msg->data[0] = io_err->eid();
msg->data[1] = l_msgSize;
- void * temp_buff = NULL;
- if( iv_isMboxEnabled )
- {
- temp_buff = MBOX::allocate( l_msgSize );
- }
- else
- {
- temp_buff = malloc( l_msgSize );
- }
+ void * temp_buff = MBOX::allocate( l_msgSize );
io_err->flatten ( temp_buff, l_msgSize );
msg->extra_data = temp_buff;
TRACDCOMP( g_trac_errl, INFO_MRK"Send msg to FSP for errlogId %.8x",
io_err->eid() );
-
- if (iv_isMboxEnabled)
+ errlHndl_t l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg );
+ if( !l_err )
{
- errlHndl_t l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg );
- if( !l_err )
- {
- // clear this - we're done with the message;
- // the receiver will free the storage when it's done
- msg = NULL;
- }
- else
- {
- TRACFCOMP(g_trac_errl, ERR_MRK"Failed sending error log to FSP");
+ // clear this - we're done with the message;
+ // the receiver will free the storage when it's done
+ msg = NULL;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_errl, ERR_MRK"Failed sending error log to FSP");
- //Free the extra data due to the error
- MBOX::deallocate( msg->extra_data );
- msg_free( msg );
- msg = NULL;
+ //Free the extra data due to the error
+ MBOX::deallocate( msg->extra_data );
+ msg_free( msg );
+ msg = NULL;
- delete l_err;
- l_err = NULL;
- }
+ delete l_err;
+ l_err = NULL;
}
- // else, we created the msg, but couldn't send it - return it so that
- // it can be saved and sent later when the MBOX is up.
} while (0);
- TRACFCOMP( g_trac_errl, EXIT_MRK"sendErrLogToMbox() returning %p", msg);
- return msg;
+ TRACFCOMP( g_trac_errl, EXIT_MRK"ErrlManager::sendErrLogToMbox" );
} // sendErrLogToMbox
///////////////////////////////////////////////////////////////////////////////
@@ -695,7 +723,6 @@ void errlCommit(errlHndl_t& io_err, compId_t i_committerComp )
}
///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
// Global function (not a method on an object) to commit the error log.
void ErrlManager::errlResourceReady(errlManagerNeeds i_needs)
{
@@ -721,6 +748,9 @@ void ErrlManager::sendResourcesMsg(errlManagerNeeds i_needs)
case MBOX:
msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_MBOX_TYPE;
break;
+ case ERRLDISP:
+ msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_ERRLDISP_TYPE;
+ break;
default:
{
TRACFCOMP( g_trac_errl, ERR_MRK "bad msg!!");
@@ -797,30 +827,22 @@ void ErrlManager::sendErrlogToMessageQueue ( errlHndl_t& io_err,
///////////////////////////////////////////////////////////////////////////////
void ErrlManager::errlogShutdown()
{
- // if there are errorlogs that didn't get sent via the MBOX to FSP,
- // trace them and clean up
- while (!iv_errlToSend.empty())
+ // if there are errorlogs that didn't get fully processed, trace them
+ // and clean up
+ while (!iv_errlList.empty())
{
- msg_t * msg = iv_errlToSend.front();
- TRACDCOMP(g_trac_errl, INFO_MRK "Failed to send to FSP: eid %.8x",
- msg->data[0]);
- free( msg->extra_data );
- msg_free( msg );
- // delete from the list
- iv_errlToSend.pop_front();
- } // while items on iv_errlToSend list
+ // Get errl and its flags
+ std::pair<errlHndl_t, uint8_t> l_pair = iv_errlList.front();
+ // If still true that means it was not processed
- // if there are errorlogs that didn't get stored in PNOR,
- // trace them and clean up
- while (!iv_errlToSave.empty())
- {
- errlHndl_t l_err = iv_errlToSave.front();
- TRACFCOMP(g_trac_errl, ERR_MRK "Failed to store to PNOR: eid %.8x",
- l_err->eid());
- delete l_err;
+ TRACFCOMP(g_trac_errl, INFO_MRK "Failed to fully process Errl(eid %.8x) - Errl Flags Bitfield = 0x%X",
+ l_pair.second);
+
+ delete l_pair.first;
+ l_pair.first = NULL;
// delete from the list
- iv_errlToSave.pop_front();
- } // while items on iv_errlToSave list
+ iv_errlList.pop_front();
+ } // while items on iv_errlList list
// Ensure that all the error logs are pushed out to PNOR
// prior to the PNOR resource provider shutting down.
@@ -928,32 +950,34 @@ void ErrlManager::setupPnorInfo()
// if error(s) came in before PNOR was ready,
// the error log(s) would be on this list. save now.
- while (!iv_errlToSave.empty())
+ ErrlListItr_t it = iv_errlList.begin();
+ while(it != iv_errlList.end())
{
- errlHndl_t l_err = iv_errlToSave.front();
-
- //ACK it if no one is there to receive
- bool l_savedToPnor = saveErrLogToPnor(l_err);
-
- // check if we actually saved the msg to PNOR
- if (l_savedToPnor)
- { // if so, we're done - clean up
-
- //done with the error log handle so delete it.
- delete l_err;
- l_err = NULL;
+ // Check if PNOR processing is needed
+ if (_isPnorFlagSet(*it))
+ {
+ //ACK it if no one is there to receive
+ bool l_savedToPnor = saveErrLogToPnor(it->first);
- // delete from the list
- iv_errlToSave.pop_front();
+ // check if we actually saved the msg to PNOR
+ if (l_savedToPnor)
+ {
+ // Mark PNOR processing complete
+ _clearPnorFlag(*it);
+ _updateErrlListIter(it);
+ }
+ else
+ {
+ // still couldn't save it (PNOR maybe full) so
+ // it's still on the list.
+ break; // get out of this while loop.
+ }
}
else
{
- // still couldn't save it (PNOR maybe full) so
- // it's still on the list.
- break; // get out of this while loop.
+ ++it;
}
- } // while entries on list
-
+ }
} while (0);
TRACFCOMP( g_trac_errl, EXIT_MRK"setupPnorInfo");
@@ -985,8 +1009,8 @@ bool ErrlManager::incrementPnorOpenSlot()
///////////////////////////////////////////////////////////////////////////////
bool ErrlManager::saveErrLogToPnor( errlHndl_t& io_err)
{
- TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor eid=%.8x", io_err->eid());
bool rc = false;
+ TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor eid=%.8x", io_err->eid());
// actually, if it's an INFORMATIONAL log, we don't want to waste the write
// cycles, so we'll just 'say' that we saved it and go on.
@@ -1041,9 +1065,8 @@ bool ErrlManager::saveErrLogToPnor( errlHndl_t& io_err)
}
// else no open slot - return false
}
-
TRACFCOMP( g_trac_errl, EXIT_MRK"saveErrLogToPnor returning %s",
- rc ? "true" : "false");
+ rc ? "true" : "false");
return rc;
} // saveErrLogToPnor
@@ -1155,4 +1178,23 @@ void ErrlManager::setACKInFlattened(uint32_t i_position)
return;
}
+bool ErrlManager::_updateErrlListIter(ErrlListItr_t & io_it)
+{
+ bool l_removed = false;
+ // Delete if this error has been fully processed (flags cleared)
+ if (io_it->second == 0)
+ {
+ // Delete errl
+ delete io_it->first;
+ io_it->first = NULL;
+ io_it = iv_errlList.erase(io_it);
+ l_removed = true;
+ }
+ else
+ {
+ ++io_it;
+ }
+ return l_removed;
+}
+
} // End namespace
diff --git a/src/usr/errl/parser/genErrlParsers.pl b/src/usr/errl/parser/genErrlParsers.pl
index 626b6b763..7fb516683 100755
--- a/src/usr/errl/parser/genErrlParsers.pl
+++ b/src/usr/errl/parser/genErrlParsers.pl
@@ -7,6 +7,7 @@
# OpenPOWER HostBoot Project
#
# Contributors Listed Below - COPYRIGHT 2013,2014
+# [+] Google Inc.
# [+] International Business Machines Corp.
#
#
@@ -442,6 +443,7 @@ close(OFILE);
my %compValueToParseHash;
my %rcModValuesUsed;
my %srcList;
+my %displayDataEntries;
foreach my $file (@filesToParse)
{
@@ -479,6 +481,7 @@ foreach my $file (@filesToParse)
my $rc = "";
my $rcValue = "";
my @userData;
+ my @userDataTextOnly;
my $desc = "";
my $cdesc = "";
@@ -607,6 +610,7 @@ foreach my $file (@filesToParse)
my $udString = "\"$udDesc\", \"$udText\"";
push(@userData, $udString);
+ push(@userDataTextOnly, $udText);
}
elsif ($line =~ /\@devdesc\s+(\S+.*)/i)
{
@@ -740,12 +744,26 @@ foreach my $file (@filesToParse)
}
$parserCode .= " break;\n\n";
+ # Create the data entry code for this error
+ my $dataEntryCode = " {\n"
+ . " 0x$modIdValue, // Module Id\n"
+ . " 0x$rcValue, // ReasonCode\n"
+ . " \"$desc\",\n"
+ . " \"$modId\",\n"
+ . " \"$rc\",\n"
+ . " \"$userDataTextOnly[0]\",\n"
+ . " \"$userDataTextOnly[1]\"\n"
+ . " },\n\n";
+
# The component value is the first two characters of the 4 character rc
my $compValue = $rcValue;
$compValue =~ s/..$//;
# Add the parser code to compValueToParseHash
$compValueToParseHash{$compValue} .= $parserCode;
+
+ # Add the data entry code to displayDataEntries
+ $displayDataEntries{$modIdValue}{$rcValue} = $dataEntryCode;
}
}
@@ -1028,6 +1046,52 @@ print OFILE "\n\n.include<\${RULES_MK}>\n";
close(OFILE);
#------------------------------------------------------------------------------
+# Generate the errldisplaydata.C file that contains the set of Hostboot
+# component IDs and detailed error data.
+# Note: This file is placed one directory up from the other generated files
+# because this is actually part of hostboot.
+#------------------------------------------------------------------------------
+$outputFileName = $outputDir . "/../errldisplaydata.C";
+open(OFILE, ">", $outputFileName) or die("Cannot open: $outputFileName: $!");
+
+print OFILE "/*\n";
+print OFILE " * Automatically generated by Hostboot's $0\n";
+print OFILE " * Do not modify this file in the hostboot tree, it is automatically\n";
+print OFILE " * generated every build.\n";
+print OFILE " *\n";
+print OFILE " * TimeStamp: $timestamp\n";
+print OFILE " * Image Id: $imageId\n";
+print OFILE " *\n";
+print OFILE " */\n\n";
+print OFILE "#include <errldisplay/errldisplay.H>\n";
+print OFILE "#include <stdlib.h>\n\n";
+print OFILE "namespace ERRORLOGDISPLAY\n{\n\n";
+print OFILE "// Error Info Table\n";
+print OFILE "ErrLogDisplay::errLogInfo ErrLogDisplay::errorInfo [] = {\n";
+foreach my $modID (sort keys %displayDataEntries)
+{
+ foreach my $rc (sort keys %{$displayDataEntries{$modID}})
+ {
+ print OFILE $displayDataEntries{$modID}{$rc};
+ }
+}
+
+print OFILE "};\n";
+print OFILE "uint16_t ErrLogDisplay::errorInfoTableSize = sizeof(errorInfo) / sizeof(errorInfo[0]);\n\n";
+print OFILE "\n\n// Component Id Table\n";
+print OFILE "#include <hbotcompid.H>\n";
+print OFILE "ErrLogDisplay::compTableInfo ErrLogDisplay::compTable [] = {\n";
+foreach my $key (sort keys %compIdToValueHash)
+{
+ $key = substr($key,0,length($key)-3);
+ print OFILE " {" . $key . "_ID, " . $key . "_NAME},\n";
+}
+print OFILE "};\n";
+print OFILE "uint16_t ErrLogDisplay::compTableSize = sizeof(compTable) / sizeof(compTable[0]);\n\n";
+print OFILE "} // End Namespace\n";
+close(OFILE);
+
+#------------------------------------------------------------------------------
# Subroutine that prints the usage
#------------------------------------------------------------------------------
sub usage
diff --git a/src/usr/errl/parser/makefile b/src/usr/errl/parser/makefile
index e008e6974..05a3ab0fa 100644
--- a/src/usr/errl/parser/makefile
+++ b/src/usr/errl/parser/makefile
@@ -6,6 +6,7 @@
# OpenPOWER HostBoot Project
#
# Contributors Listed Below - COPYRIGHT 2011,2014
+# [+] Google Inc.
# [+] International Business Machines Corp.
#
#
@@ -96,6 +97,7 @@ clean:
rm -f ${GENDIR}/comps.C
rm -f ${IMGDIR}/errlparser
rm -fr ${OBJDIR}
+ rm -f ${GENDIR}/errldisplaydata.C
debug:
ls -l ${GENDIR}
diff --git a/src/usr/errldisplay/errldisplay.C b/src/usr/errldisplay/errldisplay.C
new file mode 100644
index 000000000..f3a80b839
--- /dev/null
+++ b/src/usr/errldisplay/errldisplay.C
@@ -0,0 +1,195 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/errldisplay/errldisplay.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2013,2014 */
+/* [+] Google Inc. */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file /src/usr/errl/display/errldisplay.C
+ *
+ * @brief Implementation of ErrlDisplay class
+ * This will display human-readable dumps of error log entries.
+ *
+ * The strings displayed are automatically extracted from source code by
+ * the script ../errl/parser/genErrlParsers.pl
+ *
+ * The base image is limited to 512K, and inclusion of the error strings
+ * in the base make it grow beyond that limit, so the text and display
+ * functions are put into the extended image.
+ *
+ * The errl module in the base image will provide an interface for the
+ * display functions to register with it.
+ * When an errl is generated, the base image will see if a display function
+ * has been registered. If so, then it will be called to display the error.
+ * If not, then the base image will display the raw error data and save the
+ * error information into a list.
+ * When the display function does register itself, the errl module in the
+ * base image will pretty-print all of the pending errors from the list
+ * it generated before that point.
+ */
+
+/*****************************************************************************/
+// I n c l u d e s
+/*****************************************************************************/
+#include <trace/interface.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <errldisplay/errldisplay.H>
+#include <stdlib.h>
+#include <string.h>
+#include <initservice/taskargs.H>
+#include <algorithm>
+#include <console/consoleif.H>
+
+namespace ERRORLOGDISPLAY
+{
+
+// Trace definition
+trace_desc_t* g_trac_errldisp = NULL;
+TRAC_INIT(&g_trac_errldisp, "ERRLDISP", KILOBYTE, TRACE::BUFFER_SLOW);
+
+/**
+ * @brief Default error log to display when we can't find one in the errorInfo
+ * table.
+ *
+ * The data tables and size variables
+ * static errLogInfo errorInfo []
+ * static compTableInfo compTable []
+ * static uint16_t errorInfoTableSize
+ * static uint16_t compTableSize
+ * are automatically generated by the ../errl/parser/genErrlTable.pl script
+ * and placed in the file $GENDIR/errldisplaydata.C
+ */
+static const ErrLogDisplay::errLogInfo unknownErrorInfo = {
+ 0, // Module Id
+ 0, // Reason Code
+ "<none>", // Description
+ "unknown", // Module Name
+ "unknown", // Reason
+ "unknown", // User Data 1 string
+ "unknown" // User Data 2 string
+};
+
+
+ErrLogDisplay& errLogDisplay()
+{
+ return Singleton<ErrLogDisplay>::instance();
+}
+
+const ErrLogDisplay::errLogInfo* ErrLogDisplay::findErrLogInfo (
+ uint8_t i_moduleId, uint16_t i_reasonCode)
+{
+ // Create local errLogInfo to search for
+ struct ErrLogDisplay::errLogInfo l_errLogInfo = {i_moduleId,i_reasonCode,
+ NULL,NULL,NULL,NULL,NULL};
+
+ errLogInfo* l_result = std::lower_bound(errorInfo,
+ errorInfo + errorInfoTableSize,
+ l_errLogInfo,
+ ErrLogDisplay::errorLogInfoCompare);
+
+ // Check if the lower_bound found the correct result
+ if ( (l_result != (errorInfo + errorInfoTableSize)) &&
+ (l_result->moduleId == i_moduleId) &&
+ (l_result->reasonCode == i_reasonCode) )
+ {
+ return l_result;
+ }
+
+ // Couldn't find it, so return the default unknown structure.
+ return &unknownErrorInfo;
+}
+
+const char * ErrLogDisplay::findComponentName (compId_t i_compId)
+{
+ // Create local compTableInfo to search for
+ struct ErrLogDisplay::compTableInfo l_compTableInfo = {i_compId, NULL};
+
+ compTableInfo* l_result = std::lower_bound(compTable,
+ compTable + compTableSize,
+ l_compTableInfo,
+ ErrLogDisplay::compTableCompare);
+
+ // Check if the lower_bound found the correct result
+ if ( (l_result != (compTable + errorInfoTableSize)) &&
+ (l_result->value == i_compId) )
+ {
+ return l_result->name;
+ }
+ return "unknown";
+}
+
+void ErrLogDisplay::msgDisplay (const errlHndl_t &i_err,
+ compId_t i_committerComp)
+{
+ TRACFCOMP( g_trac_errldisp, ENTER_MRK "ErrLogDisplay::msgDisplay" );
+
+ const ErrLogDisplay::errLogInfo* info = findErrLogInfo(i_err->moduleId(),
+ i_err->reasonCode());
+
+ CONSOLE::displayf(NULL,
+ "================================================\n");
+ CONSOLE::displayf(NULL, "Error reported by %s (0x%04X)\n",
+ findComponentName(i_committerComp), i_committerComp);
+ CONSOLE::displayf(NULL, " %s\n", info->descriptString);
+ CONSOLE::displayf(NULL, " ModuleId 0x%02x %s\n",
+ i_err->moduleId(), info->moduleName);
+ CONSOLE::displayf(NULL, " ReasonCode 0x%04x %s\n",
+ i_err->reasonCode(), info->reasonString);
+ CONSOLE::displayf(NULL, " UserData1 %s : 0x%016lx\n",
+ info->userData1String, i_err->getUserData1());
+ CONSOLE::displayf(NULL, " UserData2 %s : 0x%016lx\n",
+ info->userData2String, i_err->getUserData2());
+
+ CONSOLE::flush();
+
+ TRACFCOMP( g_trac_errldisp, EXIT_MRK "ErrLogDisplay::msgDisplay" );
+}
+
+
+/**
+ * @brief This is the task entry point. It will register ErrlDisplay module with
+ * the base image Errl module.
+ *
+ * @param[in/out] io_taskRetErrl Errl module to register with ErrlDisplay
+ * instance
+ *
+ * @return None
+ */
+static void errLogDisplayEntryPoint (errlHndl_t &io_taskRetErrl)
+{
+ TRACFCOMP( g_trac_errldisp, ENTER_MRK "ErrLogDisplay::errLogDisplayEntryPoint" );
+
+ io_taskRetErrl = Singleton<ErrLogDisplay>::instance().init();
+
+ TRACFCOMP( g_trac_errldisp, EXIT_MRK "ErrLogDisplay::errLogDisplayEntryPoint" );
+}
+TASK_ENTRY_MACRO( errLogDisplayEntryPoint );
+
+
+errlHndl_t ErrLogDisplay::init()
+{
+ ERRORLOG::ErrlManager::errlResourceReady(ERRORLOG::ERRLDISP);
+ return NULL;
+}
+
+} // End namespace
diff --git a/src/usr/errldisplay/makefile b/src/usr/errldisplay/makefile
new file mode 100644
index 000000000..7c70f2bb5
--- /dev/null
+++ b/src/usr/errldisplay/makefile
@@ -0,0 +1,37 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/errldisplay/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2013,2014
+# [+] Google Inc.
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+ROOTPATH = ../../..
+MODULE = errldisplay
+
+OBJS += errldisplay.o
+OBJS += errldisplaydata.o
+
+include ${ROOTPATH}/config.mk
+
+# To find errldisplaydata.C - it is generated
+# by ../errl/parser/genErrlParsers.pl
+vpath %.C ${GENDIR}
diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H
index 19fe70a84..9996bc994 100644
--- a/src/usr/initservice/extinitsvc/extinitsvctasks.H
+++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H
@@ -120,6 +120,23 @@ const TaskInfo g_exttaskinfolist[] = {
}
},
+#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY
+ /**
+ * @brief Human readable error log display
+ * Note: Because of dependencies, this must come after libmbox.so
+ * or hostboot will hang with an Inst Storage exception
+ * (the ErrlManager constructor tries to talk to MBOX.)
+ */
+ {
+ "liberrldisplay.so", // taskname
+ NULL, // no ptr to fnct
+ {
+ START_TASK, // task type
+ EXT_IMAGE, // Extended Module
+ }
+ },
+#endif
+
/**
* @brief Trace daemon
*/
diff --git a/src/usr/makefile b/src/usr/makefile
index 746868f18..02f622520 100644
--- a/src/usr/makefile
+++ b/src/usr/makefile
@@ -62,5 +62,6 @@ SUBDIRS += sbe.d
SUBDIRS += gpio.d
SUBDIRS += lpc.d
SUBDIRS += console.d
+SUBDIRS += errldisplay.d
include ${ROOTPATH}/config.mk
OpenPOWER on IntegriCloud