summaryrefslogtreecommitdiffstats
path: root/src/usr/errl/parser/errlparser.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/errl/parser/errlparser.C')
-rw-r--r--src/usr/errl/parser/errlparser.C631
1 files changed, 421 insertions, 210 deletions
diff --git a/src/usr/errl/parser/errlparser.C b/src/usr/errl/parser/errlparser.C
index 5880e6db2..ccf9bf915 100644
--- a/src/usr/errl/parser/errlparser.C
+++ b/src/usr/errl/parser/errlparser.C
@@ -20,11 +20,33 @@
// Origin: 30
//
// IBM_PROLOG_END
+
+
/**
* @file errlparser.C
*
- * @brief Parse and display committed error logs. Enter
- * errlparser ? (or -? or -h or --help) to print help.
+ * @brief Builds a program to display committed Hostboot error logs.
+ * Enter errlparser ? (or -? or -h or --help) to print help.
+ * This program can be run standalone using a Simics
+ * L3 memory image and the HB syms file, however it is more likely
+ * spawned as "simcis> hb-errl" from the Hostboot/Simics python
+ * script.
+ *
+ * This program spawns the FSP x86 version of errl and fsp-trace
+ * which may or may not be in your $PATH. Candidates are:
+ *
+ * Classic FSP errl:
+ * /esw/fips730/Builds/b0829a_1130.730/obj/x86.nfp/errl/nfp/tool/errl
+ *
+ * Or this version in Monte's sandbox which is more Hostboot aware:
+ * /gsa/ausgsa/home/c/o/copelanm/public/bin/errl
+ *
+ * Building Blocks version of fsp-trace:
+ * /opt/mcp/shared/fr_DEV-37/opt/fsp/usr/bin/fsp-trace
+ *
+ * Camvan has a solution for PATHing to fsp-trace when in Simics.
+ * TODO Will need a copy of FSP x86 errl too in the near future.
+ *
*/
@@ -37,32 +59,41 @@
#include <errno.h>
#include <assert.h>
#include <string>
+#include <vector>
using namespace std;
#include <errl/errltypes.H>
#include <hbotcompid.H>
+
+
+// Include the file that was generated by scanforsrcs.pl
#include <hostBootSrcParse.H>
+
+
using namespace ERRORLOG;
+
#define USAGE "\
Usage:\n\
\n\
-errlparser [-i] <imagefile> [[-s] <symsfile>] [-l | -d [<logid>|all]] [-v]\n\
+errlparser [-i]<image> [[-s]<syms>] [-l|-d[<logid>|all]] [-t <stringfile>]\n\
\n\
Arguments:\n\
- <imagefile> data file name\n\
- <symsfile> symbols file name\n\
+ <image> data file name\n\
+ <syms> symbols file name\n\
-l summarize all error logs (default)\n\
-d id print detail from specific error log\n\
- -s name explicitly name the symbols file\n\
-i name explicitly name the image file\n\
+ -s name explicitly name the symbols file\n\
+ -t name name the hbotStringFile\n\
-v verbose output to stdout\n\
\n\
Sample command lines:\n\
errlparser image.bin hbicore.syms # list logs from a full L3 image\n\
- errlparser image.bin hbicore.syms -d 1 # print detail about log 1\n\
+ errlparser image.bin hbicore.syms -d 1 # display log 1\n\
+ errlparser image.bin hbicore.syms -d 1 -t hbotStringFile # display traces\n\
errlparser buffer.bin # list logs from pre-extracted storage buffer\n\
errlparser buffer.bin -d 1 # detail log 1 from pre-extracted storage buffer\n\
\n\
@@ -74,9 +105,13 @@ Remarks:\n\
[] '-s' is optional if the symbols file name contains 'syms'\n\
[] '-i' can be optional in most cases\n\
\n\
+Developer switches:\n\
+ -p -o <dirname> Extract all as PEL binaries to output <dirname>\n\
Contact: Monte Copeland\n\
"
+
+
//------------------------------------------------------------------------
// Stop the program with a message. This message is often USAGE. Since
// this program will be spawned from traceHB.py, I think we're better
@@ -84,6 +119,7 @@ Contact: Monte Copeland\n\
// think Simics is piping stderr to its console.
void halt( const char * msg )
{
+ // stdout out because Simics does not appear to display stderr (?)
fprintf( stdout, "%s", msg );
// exit the process with a non-zero process exit level.
@@ -111,6 +147,8 @@ ERRLCOMPNAME_t g_errlcompnames[] = {
#include <comps.C>
};
+
+//-------------------------------------------------------------
// Given a reason code which has a comp id mangled into
// it, return a char* to the component name. Return
// null if not found, which printf seems to handle
@@ -133,157 +171,110 @@ const char * FindComp( uint16_t reasoncode )
-//------------------------------------------------------------
-// Print a hex dump of the input buffer to the output file
-// given, probably stdout.
-int FormatBytes( FILE * f, char * pchInput, int count, int indent )
+//-------------------------------------------------------------
+// endian switch a uint64
+uint64_t ntohll( uint64_t i )
{
- char szChars[ 80 ];
- char szHex[ 80 ];
- char szOffset[ 64 ];
- char szWork[ 256 ];
- int i;
- unsigned int ul;
- char * pch;
- char * pchLine;
- int cb;
- char * pszIndent = NULL;
-
-
-
- pszIndent = static_cast<char*>(malloc( indent+1 ));
- memset( pszIndent, 0, indent+1 );
- memset( pszIndent, ' ', indent );
-
-
-
- pchLine = pchInput;
-
-
- while( pchLine < pchInput + count )
- {
- /* current offset */
- ul = pchLine - pchInput;
-
- sprintf( szOffset, "%08X", ul );
-
- memset( szHex, ' ', sizeof( szHex ));
- pch = szHex;
-
- cb = ((pchInput+count)-pchLine) > 16 ? 16 : ((pchInput+count)-pchLine);
-
- for( i = 0; i < cb; i++ )
- {
- ul = (unsigned char) pchLine[ i ];
-
- sprintf( szWork, "%02x", ul );
- memcpy( pch, szWork, 2 );
+ uint64_t hi;
+ uint64_t lo;
+ uint32_t * pword = reinterpret_cast<uint32_t*>(&i);
- pch += 3;
- }
+ hi = ntohl( *pword );
+ lo = ntohl( *(pword+1) );
- szHex[ 23 ] = '-';
- szHex[ 48 ] = 0;
+ return (hi<<32)|lo;
+}
- memset( szChars, 0, sizeof( szChars ));
- for( i = 0; i < cb; i++ )
- {
- szChars[i] = '.';
- int t = pchLine[i];
- if( t > 31 )
- {
- szChars[i] = pchLine[ i ];
- }
- }
- sprintf( szWork, "%s %s %s", szOffset, szHex, szChars );
- fprintf( f, "%s%s\n", pszIndent, szWork );
- fflush( f );
- pchLine += 16;
- }
- return 0;
+//-------------------------------------------------------------
+// endian stuff, convert a errl storage marker in place
+marker_t* ConvertMarker( marker_t* p)
+{
+ p->offsetNext = ntohl( p->offsetNext );
+ p->length = ntohl( p->length );
+ return p;
}
-
//-------------------------------------------------------------
-// endian stuff
-section_header_t* ConvertSectionHeader( section_header_t* p)
+// endian stuff, convert the data stored at the beginning of the
+// errl storage buffer
+storage_header_t * ConvertStorageHeader( storage_header_t * p )
{
- p->cbHeader = ntohl( p->cbHeader );
- p->cbSection = ntohl( p->cbSection );
- p->compId = ntohs( p->compId );
- // sctnVer is byte long
- // subSect is byte long
+ p->cbStorage = ntohl( p->cbStorage );
+ p->cInserted = ntohl( p->cInserted );
+ p->offsetMarker = ntohl( p->offsetMarker );
+ p->offsetStart = ntohl( p->offsetStart );
return p;
}
-
//-------------------------------------------------------------
-// endian stuff
-marker_t* ConvertMarker( marker_t* p)
+// endian stuff,convert in place, return a pointer to what
+// you passed in. PEL is made up of multiple sections, each
+// one starting with a header that has these 8 bytes.
+pelSectionHeader_t * ConvertPELSectionHeader( pelSectionHeader_t * p )
{
- p->offsetNext = ntohl( p->offsetNext );
- p->length = ntohl( p->length );
+ p->sid = ntohs( p->sid );
+ p->len = ntohs( p->len );
+ // byte: p->ver
+ // byte: p->sst
+ p->compId = ntohs( p->compId );
return p;
}
-
//-------------------------------------------------------------
-// endian switch a uint64
-uint64_t ntohll( uint64_t i )
+// endian stuff, convert in place. This converts the first section
+// encountered in PEL, the PH section (private header).
+pelPrivateHeaderSection_t* ConvertPrivateHeader(pelPrivateHeaderSection_t* p)
{
- uint64_t hi;
- uint64_t lo;
- uint32_t * pword = reinterpret_cast<uint32_t*>(&i);
-
- hi = ntohl( *pword );
- lo = ntohl( *(pword+1) );
-
- return (hi<<32)|lo;
+ ConvertPELSectionHeader( &p->sectionheader );
+ p->creationTime = ntohll( p->creationTime );
+ p->commitTime = ntohll( p->commitTime );
+ p->creatorImplementation = ntohll( p->creatorImplementation );
+ p->plid = ntohl( p->plid );
+ p->eid = ntohl( p->eid );
+ return p;
}
//-------------------------------------------------------------
-// endian stuff
-errl_header_t* ConvertErrlHeader( errl_header_t* p )
+// endian stuff, convert in place. Convert the 2nd section in PEL,
+// the UH (user header).
+pelUserHeaderSection_t * ConvertUserHeader( pelUserHeaderSection_t * p )
{
- p->cbytes = ntohl( p->cbytes );
- p->csections = ntohl( p->csections );
- p->reasonCode = ntohs( p->reasonCode );
- // p->modId is a byte
- // p->sev is a byte
- // p->eventType is a byte
- // p->subSys is a byte
- // p->srcType is a byte
- p->termState = ntohl( p->termState );
- p->logId = ntohl( p->logId );
- p->user1 = ntohll( p->user1 );
- p->user2 = ntohll( p->user2 );
- p->CreationTime = ntohll( p->CreationTime );
+ ConvertPELSectionHeader( &p->sectionheader );
+ // mostly byte sized stuff
+ p->actions = ntohs( p->actions );
return p;
}
-
//-------------------------------------------------------------
-// endian stuff
-storage_header_t * ConvertStorageHeader( storage_header_t * p )
+// endian stuff, convert in place. The PS (primary SRC) section
+// in PEL is the 3rd section.
+pelSRCSection_t * ConvertSRC( pelSRCSection_t * p )
{
- p->cbStorage = ntohl( p->cbStorage );
- p->cInserted = ntohl( p->cInserted );
- p->offsetMarker = ntohl( p->offsetMarker );
- p->offsetStart = ntohl( p->offsetStart );
+ ConvertPELSectionHeader( &p->sectionheader );
+ // mostly byte sized stuff
+ p->srcLength = ntohs( p->srcLength );
+ p->reserved1 = ntohs( p->reserved1 );
+ p->word2 = ntohl( p->word2 );
+ p->word3 = ntohs( p->word3 );
+ p->word4 = ntohl( p->word4 );
+ p->word5 = ntohl( p->word5 );
+ p->word6 = ntohll( p->word6 );
+ p->word8 = ntohll( p->word8 );
return p;
}
+
//-----------------------------------------------------------------------
// Given the binary image file name, return the errl storage part of the file.
// Caller must endian convert anything/everything in the output buffer.
@@ -418,6 +409,7 @@ uint32_t FindSymbol( char * pszSymbolFile, const char * pszSearch )
pch = strstr( szWork, pszSearch );
if( pch )
{
+ // tease out the address for this symbol
pszAddr = szWork + 2;
pch = strchr( pszAddr, ',' );
assert( pch );
@@ -433,6 +425,7 @@ uint32_t FindSymbol( char * pszSymbolFile, const char * pszSearch )
exit(2);
}
+ // Convert ascii hex representation of address to a unsigned long
int c = sscanf( pszAddr, "%x", &ulAddr );
if( 1 != c )
{
@@ -446,103 +439,111 @@ uint32_t FindSymbol( char * pszSymbolFile, const char * pszSearch )
-// --------------------------------------------------------------------------
-// Print a summary of the error log, no user-defined data nor detail.
-// perrlog is already endian converted
+//-----------------------------------------------------------------------------
+// Output a vector of endian-converted PEL sections, without altering the caller's
+// pchNativePEL input buffer. The vector will have pointers to PEL section
+// headers, and the user of the vector contents will have to cast according to
+// pelSectionHeader_t.sid (section id ).
-void PrintErrlSummary( errl_header_t * perrlog )
+bool ParseForPEL( char * i_pchNativePEL,
+ int i_cbPEL,
+ vector<pelSectionHeader_t*> &o_vector )
{
- // print headline
- // comp id sev rc mod evt u1 u2 csec
- printf( "%-7s %10s %4s %-6s %-4s %-4s %-18s %-18s %5s\n",
- "comp",
- "logid",
- "sev",
- "reason",
- "mod",
- "evnt",
- "user1",
- "user2",
- "csect" );
-
-
- // comp id sev reason mod event user1 user2 csec
- // code
- printf( "%-7s %10d 0x%02x 0x%04x 0x%02x 0x%02x 0x%016llx 0x%016llx %5d\n",
- FindComp( perrlog->reasonCode ),
- perrlog->logId,
- perrlog->sev,
- perrlog->reasonCode,
- perrlog->modId,
- perrlog->eventType,
- perrlog->user1,
- perrlog->user2,
- perrlog->csections // count of sections
- );
-}
-
+ // use pch to bump along through the PEL sections
+ char * pch = i_pchNativePEL;
-//---------------------------------------------------------------------------
-//
-//
-void PrintErrlDetail( errl_header_t * perrlog )
-{
+ while( pch < (i_pchNativePEL+i_cbPEL))
+ {
+ void * pvoid;
+ pelSectionHeader_t sectionHeader;
- // print the summary line
- PrintErrlSummary( perrlog );
+ // Convert a copy of just the PEL section header so I can look at the
+ // sid (section id/type) and the overall section length.
+ memcpy( &sectionHeader, pch, sizeof( pelSectionHeader_t ));
+ ConvertPELSectionHeader( &sectionHeader );
- // print the Errorlog tags
- printErrorTags( perrlog->reasonCode,
- perrlog->modId );
- // print sections if any
- if( perrlog->csections )
- {
- int i;
- section_header_t* psect;
+ // For each section, allocate space for it, endian convert the
+ // section, then insert into output vector.
+ switch( sectionHeader.sid ) {
+ case ERRL_SID_PRIVATE_HEADER:
+ {
+ pvoid = malloc(sectionHeader.len);
+ pelPrivateHeaderSection_t * p;
+ p = static_cast<pelPrivateHeaderSection_t*>(pvoid);
+ memcpy( p, pch, sectionHeader.len );
+ ConvertPrivateHeader( p );
+ o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) );
+ }
+ break;
+ case ERRL_SID_USER_HEADER:
+ {
+ pvoid = malloc(sectionHeader.len);
+ pelUserHeaderSection_t * p;
+ p = static_cast<pelUserHeaderSection_t*>(pvoid);
+ memcpy( p, pch, sectionHeader.len );
+ ConvertUserHeader( p );
+ o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) );
+ }
+ break;
+ case ERRL_SID_PRIMARY_SRC:
+ {
+ pvoid = malloc(sectionHeader.len);
+ pelSRCSection_t * p;
+ p = static_cast<pelSRCSection_t*>(pvoid);
+ memcpy( p, pch, sectionHeader.len );
+ ConvertSRC( p );
+ o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) );
+ }
+ break;
+ case ERRL_SID_USER_DEFINED:
+ {
+ pvoid = malloc(sectionHeader.len);
+ pelSectionHeader_t * p;
+ p = static_cast<pelSectionHeader_t*>(pvoid);
+ memcpy( p, pch, sectionHeader.len );
+ // Only converts the PEL section header, but none of the
+ // user-defined content. No way to know what's in there.
+ ConvertPELSectionHeader(p);
+ o_vector.push_back(p);
+ }
+ break;
+ default:
+ assert( 0 );
+ break;
+ }
- // first section header resides just past the errl_header_t
- psect = reinterpret_cast<section_header_t*>(perrlog+1);
+ pch += sectionHeader.len;
+ }
- // Endian convert it
- ConvertSectionHeader( psect );
+ return true;
+}
- i = 0;
- do
- {
- printf(
- "\nSection %d: %-8s len=0x%04x, ver=0x%04x, subsection=0x%04x\n",
- i,
- FindComp( psect->compId ),
- psect->cbSection,
- psect->sctnVer,
- psect->subSect
- );
- // The user-provided data resides just past the section header.
- char * pUserData = reinterpret_cast<char*>(psect+1);
- // Print a hex dump (for now) of the user-provided data.
- FormatBytes( stdout, pUserData, (int)psect->cbSection, 4 );
- i++;
- if( i >= perrlog->csections )
- {
- // Leave the loop, and do not ConvertSectionHeader().
- break;
- }
+//-----------------------------------------------------------------------------
+// Scan the vector of endian-converted PEL sections. Locate the target section
+// and return it. Return NULL if not found. Caller will have to cast
+// the returned section header pointer to the desired PEL section struct.
- // There's more; point to the next section.
- int cb = psect->cbHeader + psect->cbSection;
- char * p = (reinterpret_cast<char*>(psect)) + cb;
- psect = reinterpret_cast<section_header_t*>(p);
+pelSectionHeader_t * FindPELSection( unsigned int i_target,
+ vector<pelSectionHeader_t*> &o_vector )
+{
+ pelSectionHeader_t * p = NULL;
- // Endian convert it.
- ConvertSectionHeader( psect );
+ vector<pelSectionHeader_t*>::iterator it;
+ for( it = o_vector.begin(); it != o_vector.end(); it++ )
+ {
+ if( (*it)->sid == i_target )
+ {
+ p = *it;
+ break;
}
- while( 1 );
}
+
+ return p;
}
@@ -550,13 +551,25 @@ void PrintErrlDetail( errl_header_t * perrlog )
+
+
+
+
+
+
//-------------------------------------------------------------
int main( int argc, char *argv[] )
{
char * pch;
+ char * pchNativePEL;
+ const char * pszErrlTool = NULL;
char * pszImageFile = NULL;
char * pszSymbolFile = NULL;
+ char * pszStringFile = NULL;
+ char * pszOutputDir = NULL;
char szWork[ 1024 ];
+ char szTmpFilename[ 1024 ];
+ char szCommand[ 128 ];
unsigned char * puch;
char * pszSearch;
char * pszAddr = NULL;
@@ -579,13 +592,17 @@ int main( int argc, char *argv[] )
off_t offsetEnd;
int fVerbose = 0;
int fList = 1;
+ int fListHead = 0;
int fDetail = 0;
int fAll = 0;
int fFound = 0;
+ int fExtractPEL = 0;
+ void * pvoid;
+ struct stat statbuffer;
// build a =========== divider for printfing
- cb = 84;
+ cb = 78;
assert( cb < sizeof( szDivider ));
memset( szDivider, '=', sizeof( szDivider ));
szDivider[ cb ] = 0;
@@ -634,6 +651,41 @@ int main( int argc, char *argv[] )
}
pszImageFile = strdup( argv[i] );
}
+ else if( 0 == strcmp( "-o", argv[i] ))
+ {
+ i++;
+ if( i >= argc )
+ {
+ fprintf( stdout, "Provide -o <dirname>\n" );
+ exit( 2 );
+ }
+ pszOutputDir = strdup( argv[i] );
+ }
+ else if( 0 == strcmp( "-p", argv[i] ))
+ {
+ fExtractPEL = 1;
+ fList = 0;
+ fDetail = 0;
+ }
+ else if( 0 == strcmp( "-t", argv[i] ))
+ {
+ i++;
+ if( i >= argc )
+ {
+ fprintf( stdout, "Provide -t <string file>\n" );
+ exit( 2 );
+ }
+ pszStringFile = strdup( argv[i] );
+
+ // errl messes up ~ somehow, I thought bash
+ // would substitute this.
+ pch = strchr( pszStringFile, '~' );
+ if( pch )
+ {
+ printf( "Don't use ~ for file naming.\n" );
+ exit(2);
+ }
+ }
else if( 0 == strcmp( "-s", argv[i] ))
{
i++;
@@ -694,6 +746,56 @@ int main( int argc, char *argv[] )
halt( USAGE );
}
+ if(( fExtractPEL ) && ( NULL == pszOutputDir ))
+ {
+ printf( "Provide output dir for PEL extraction.\n" );
+ exit(1);
+ }
+
+ // TODO Need to put a copy of FSP x86 errl tool in the simics path.
+ // Try for Monte's sandbox copy, temporary for Sprint 6.
+ pszErrlTool = "/gsa/ausgsa/home/c/o/copelanm/public/bin/errl";
+
+ rc = stat( pszErrlTool, &statbuffer );
+ if( -1 == rc )
+ {
+ // Not found, so this one should be found for most users.
+ pszErrlTool =
+ "/esw/fips730/Builds/b0829a_1130.730/obj/x86.nfp/errl/nfp/tool/errl";
+
+ rc = stat( pszErrlTool, &statbuffer );
+ if( -1 == rc )
+ {
+ printf( "Unable to find a copy of errl, including %s.\n",
+ pszErrlTool );
+ exit(2);
+ }
+ }
+
+ if( fVerbose )
+ {
+ printf( "Using errl tool %s\n", pszErrlTool );
+ }
+
+
+ if( pszStringFile )
+ {
+ int fd = open( pszStringFile, O_RDONLY );
+ if( -1 == fd )
+ {
+ printf( "String file %s not found.\n", pszStringFile );
+ exit(2);
+ }
+ rc = fstat( fd, &statbuffer );
+ close(fd);
+ if( ( -1 == rc ) || !(S_ISREG(statbuffer.st_mode)))
+ {
+ printf( "String file %s is not valid.\n", pszStringFile );
+ exit(2);
+ }
+ }
+
+
if( pszSymbolFile )
{
@@ -717,7 +819,6 @@ int main( int argc, char *argv[] )
}
}
-
// Given the image file, read the portion that contains the
// error log storage buffer.
pchBuffer = ReadStorageBuffer( pszImageFile, ulAddr, cbBuffer );
@@ -770,7 +871,6 @@ int main( int argc, char *argv[] )
if( pMarker->offsetNext == 0 )
{
// This is the list-ending marker.
- printf( "%s\n", szDivider );
break;
}
@@ -778,24 +878,135 @@ int main( int argc, char *argv[] )
logcount++;
- // Flattened struct of an error log resides just past marker.
- errl_header_t* perr = reinterpret_cast<errl_header_t*>(pMarker+1);
- ConvertErrlHeader( perr );
+ // Flattened PEL of an error log resides just past marker
+ // for a length of pMarker->length. It is "native" meaning big endian.
+ pchNativePEL = reinterpret_cast<char*>(pMarker+1);
+
+ // Make a copy of PH that I can endian convert without screwing up
+ // the native one.
+ pvoid = malloc( pMarker->length );
+ pelPrivateHeaderSection_t * pPrivateHdr;
+ pPrivateHdr = static_cast<pelPrivateHeaderSection_t*>(pvoid);
+ memcpy( pPrivateHdr, pchNativePEL, pMarker->length );
+
+ // Convert the PEL private header copy to local endianness.
+ ConvertPrivateHeader( pPrivateHdr );
if( fList )
{
- // Just list the error log headers.
- printf( "%s\n", szDivider );
- PrintErrlSummary( perr );
+ // print a simple list of error log IDs
+ if( !fListHead )
+ {
+ // print a head line
+ printf( "%-16s %8s\n", "Component", "PLID" );
+ printf( "%s\n", szDivider );
+ fListHead = 1;
+ }
+ printf( "%-16s %8d\n",
+ FindComp(pPrivateHdr->sectionheader.compId),
+ pPrivateHdr->plid );
}
- else if(( fDetail ) && (( perr->logId == ulLogId ) || (fAll)))
+ else if(( fDetail ) && (( pPrivateHdr->plid == ulLogId ) || (fAll)))
{
- // Print the detail for the one error log.
- printf( "%s\n", szDivider );
- PrintErrlDetail( perr );
+ // Write the native PEL to a temporary file
+ // for x86 errl tool to display.
+ sprintf( szTmpFilename, "/tmp/pel%d.bin", pPrivateHdr->plid );
+
+ int fd = open( szTmpFilename, O_RDWR | O_CREAT , 0664 );
+ if( -1 == fd )
+ {
+ printf( "Unable to write %s. Exiting.\n", szTmpFilename );
+ exit(2);
+ }
+ cb = write( fd, pchNativePEL, pMarker->length );
+ assert( cb == pMarker->length );
+ close(fd);
+
+ // Spawn the FSP x86 errl tool to display
+ // the detail for this error log.
+ cb=sprintf(szCommand,"%s -d --file=%s",pszErrlTool,szTmpFilename);
+ if( pszStringFile )
+ {
+ sprintf( &szCommand[cb], " --trace=%s", pszStringFile );
+ }
+
+ // Run errl -d to display the error log.
+ system( szCommand );
+
+
+ // Build a vector containing pointers to each PEL section
+ // in the error log. On return, each section will be endian
+ // converted as much as possible. Do not alter the endianness
+ // of the native pel buffer, however.
+ vector<pelSectionHeader_t*> vectorPEL;
+ ParseForPEL( pchNativePEL, pMarker->length, vectorPEL );
+ assert( vectorPEL.size() );
+
+
+
+ // Print the tag detail gleaned from the code by
+ // the errl tag parser. That requires getting the reason
+ // code and module ID from the error log. They live in
+ // the Primary SRC section.
+ uint32_t l_reasonCode = 0;
+
+
+ // Find the PS section in the vector of PEL sections.
+ pelSectionHeader_t* pPELHead;
+ pPELHead = FindPELSection( ERRL_SID_PRIMARY_SRC, vectorPEL );
+ assert( pPELHead );
+
+ // Cast to Primary SRC section.
+ pelSRCSection_t * pSRCSection;
+ pSRCSection = reinterpret_cast<pelSRCSection_t*>(pPELHead);
+
+#if 0
+ // reasonCode has been "stringified" into the SRC string
+ pch = strchr( pSRCSection->srcString, ' ' );
+ assert( pch );
+ *pch = 0;
+ assert( 8 == strlen( pSRCSection->srcString));
+ sscanf( pSRCSection->srcString + 4, "%X", &l_reasonCode );
+#else
+ // I have cheated and put reasonCode here:
+ l_reasonCode = pSRCSection->reserved1;
+#endif
+
+ printf( "%-20s%s\n",
+ "Component",
+ FindComp(pPrivateHdr->sectionheader.compId));
+
+ // print the Errorlog tags from scanforsrcs.pl
+ printErrorTags( l_reasonCode, pSRCSection->moduleId );
+
+ // done with this tmp file
+ unlink( szTmpFilename );
+
+ // found at least one
fFound = 1;
}
+
+ if( fExtractPEL )
+ {
+ // Write the native PEL to a temporary file for debug later.
+ sprintf( szTmpFilename, "%s/pel%d.bin", pszOutputDir, pPrivateHdr->plid );
+
+ int fd = open( szTmpFilename, O_RDWR | O_CREAT , 0664 );
+ if( -1 == fd )
+ {
+ printf( "Unable to write %s. Exiting.\n", szTmpFilename );
+ exit(2);
+ }
+ cb = write( fd, pchNativePEL, pMarker->length );
+ assert( cb == pMarker->length );
+ close(fd);
+
+ printf( "Saved as %s\n", szTmpFilename );
+ }
+
+
+
// next marker/error log
pMarker = ConvertMarker( OFFSET2MARKER(pMarker->offsetNext) );
}
OpenPOWER on IntegriCloud