diff options
| author | Monte Copeland <copelanm@us.ibm.com> | 2011-10-24 09:30:49 -0500 | 
|---|---|---|
| committer | Monte K. Copeland <copelanm@us.ibm.com> | 2011-10-31 11:07:10 -0500 | 
| commit | 723239d5a14fe82713a2aa57fef3130534b15a41 (patch) | |
| tree | b6d19b1d1d66ec9ea4acd19c0dfdb47bcf86babd /src/usr/errl/parser/errlparser.C | |
| parent | f2794eed87ca9c35140c601dfcbb5baf299d834b (diff) | |
| download | blackbird-hostboot-723239d5a14fe82713a2aa57fef3130534b15a41.tar.gz blackbird-hostboot-723239d5a14fe82713a2aa57fef3130534b15a41.zip | |
Error log changes for Sprint 6
Change-Id: I44ad678cfae8cd84e5370391dc7e20d74f59c9ca
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/449
Tested-by: Jenkins Server
Reviewed-by: Mark W. Wenning <wenning@us.ibm.com>
Reviewed-by: Monte K. Copeland <copelanm@us.ibm.com>
Diffstat (limited to 'src/usr/errl/parser/errlparser.C')
| -rw-r--r-- | src/usr/errl/parser/errlparser.C | 631 | 
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( §ionHeader, pch, sizeof( pelSectionHeader_t )); +        ConvertPELSectionHeader( §ionHeader ); -    // print the Errorlog tags -    printErrorTags( perrlog->reasonCode, -                    perrlog->modId ); -    // print sections if any -    if( perrlog->csections ) -    { -        int i; -        section_header_t* psect; +        // For each section, allocate space for it, endian convert the +        // section, then insert into output vector. +        switch( sectionHeader.sid ) { +        case ERRL_SID_PRIVATE_HEADER: +            { +                pvoid = malloc(sectionHeader.len); +                pelPrivateHeaderSection_t * p; +                p = static_cast<pelPrivateHeaderSection_t*>(pvoid); +                memcpy( p, pch, sectionHeader.len ); +                ConvertPrivateHeader( p ); +                o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) ); +            } +            break; +        case ERRL_SID_USER_HEADER: +            { +                pvoid = malloc(sectionHeader.len); +                pelUserHeaderSection_t * p; +                p = static_cast<pelUserHeaderSection_t*>(pvoid); +                memcpy( p, pch, sectionHeader.len ); +                ConvertUserHeader( p ); +                o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) ); +            } +            break; +        case ERRL_SID_PRIMARY_SRC: +            { +                pvoid = malloc(sectionHeader.len); +                pelSRCSection_t * p; +                p = static_cast<pelSRCSection_t*>(pvoid); +                memcpy( p, pch, sectionHeader.len ); +                ConvertSRC( p ); +                o_vector.push_back( reinterpret_cast<pelSectionHeader_t*>(p) ); +            } +            break; +        case ERRL_SID_USER_DEFINED: +            { +                pvoid = malloc(sectionHeader.len); +                pelSectionHeader_t * p; +                p = static_cast<pelSectionHeader_t*>(pvoid); +                memcpy( p, pch, sectionHeader.len ); +                // Only converts the PEL section header, but none of the +                // user-defined content.  No way to know what's in there. +                ConvertPELSectionHeader(p); +                o_vector.push_back(p); +            } +            break; +        default: +	    assert( 0 ); +            break; +        } -        // first section header resides just past the errl_header_t -        psect = reinterpret_cast<section_header_t*>(perrlog+1); +        pch +=  sectionHeader.len; +    } -        // Endian convert it -        ConvertSectionHeader( psect ); +    return true; +} -        i = 0; -        do -        { -            printf( -              "\nSection %d: %-8s len=0x%04x, ver=0x%04x, subsection=0x%04x\n", -              i, -              FindComp( psect->compId ), -              psect->cbSection, -              psect->sctnVer, -              psect->subSect -            ); -            // The user-provided data resides just past the section header. -            char * pUserData = reinterpret_cast<char*>(psect+1); -            // Print a hex dump (for now) of the user-provided data. -            FormatBytes( stdout, pUserData, (int)psect->cbSection, 4 ); -            i++; -            if( i >= perrlog->csections ) -            { -                // Leave the loop, and do not ConvertSectionHeader(). -                break; -            } +//----------------------------------------------------------------------------- +// Scan the vector of endian-converted PEL sections. Locate the target section +// and return it.  Return NULL if not found.  Caller will have to cast +// the returned section header pointer to the desired PEL section struct. -            // There's more; point to the next section. -            int cb = psect->cbHeader + psect->cbSection; -            char * p =  (reinterpret_cast<char*>(psect)) + cb; -            psect = reinterpret_cast<section_header_t*>(p); +pelSectionHeader_t * FindPELSection( unsigned int i_target, +                                     vector<pelSectionHeader_t*> &o_vector ) +{ +    pelSectionHeader_t * p = NULL; -            // Endian convert it. -            ConvertSectionHeader( psect ); +    vector<pelSectionHeader_t*>::iterator it; +    for( it = o_vector.begin(); it != o_vector.end(); it++ ) +    { +        if( (*it)->sid == i_target ) +        { +            p = *it; +            break;          } -        while( 1 );      } + +    return p;  } @@ -550,13 +551,25 @@ void PrintErrlDetail(  errl_header_t * perrlog  ) + + + + + +  //-------------------------------------------------------------  int main( int argc,  char *argv[] )  {      char * pch; +    char * pchNativePEL; +    const char * pszErrlTool = NULL;      char * pszImageFile = NULL;      char * pszSymbolFile = NULL; +    char * pszStringFile = NULL; +    char * pszOutputDir  = NULL;      char szWork[ 1024 ]; +    char szTmpFilename[ 1024 ]; +    char szCommand[ 128 ];      unsigned char * puch;      char * pszSearch;      char * pszAddr = NULL; @@ -579,13 +592,17 @@ int main( int argc,  char *argv[] )      off_t offsetEnd;      int fVerbose = 0;      int fList = 1; +    int fListHead = 0;      int fDetail = 0;      int fAll    = 0;      int fFound = 0; +    int fExtractPEL = 0; +    void * pvoid; +    struct stat statbuffer;      // build a =========== divider for printfing -    cb = 84; +    cb = 78;      assert( cb < sizeof( szDivider ));      memset( szDivider, '=', sizeof( szDivider ));      szDivider[ cb ] = 0; @@ -634,6 +651,41 @@ int main( int argc,  char *argv[] )              }              pszImageFile = strdup( argv[i] );          } +        else if( 0 == strcmp( "-o", argv[i] )) +        { +            i++; +            if( i >= argc ) +            { +              fprintf( stdout, "Provide -o <dirname>\n" ); +              exit( 2 ); +            } +            pszOutputDir = strdup( argv[i] ); +        } +        else if( 0 == strcmp( "-p", argv[i] )) +        { +            fExtractPEL = 1; +            fList = 0; +            fDetail = 0; +        } +        else if( 0 == strcmp( "-t", argv[i] )) +        { +            i++; +            if( i >= argc ) +            { +              fprintf( stdout, "Provide -t <string file>\n" ); +              exit( 2 ); +            } +            pszStringFile = strdup( argv[i] ); + +            // errl messes up ~ somehow, I thought bash +            // would substitute this. +            pch = strchr( pszStringFile, '~' ); +            if( pch ) +            { +                printf( "Don't use ~ for file naming.\n" ); +                exit(2); +            } +        }          else if( 0 == strcmp( "-s", argv[i] ))          {              i++; @@ -694,6 +746,56 @@ int main( int argc,  char *argv[] )          halt( USAGE );      } +    if(( fExtractPEL ) && ( NULL == pszOutputDir )) +    { +        printf( "Provide output dir for PEL extraction.\n" ); +        exit(1); +    } + +    // TODO Need to put a copy of FSP x86 errl tool in the simics path. +    // Try for Monte's sandbox copy, temporary for Sprint 6. +    pszErrlTool = "/gsa/ausgsa/home/c/o/copelanm/public/bin/errl"; + +    rc = stat( pszErrlTool, &statbuffer ); +    if(  -1 == rc ) +    { +        // Not found, so this one should be found for most users. +        pszErrlTool = +        "/esw/fips730/Builds/b0829a_1130.730/obj/x86.nfp/errl/nfp/tool/errl"; + +        rc = stat( pszErrlTool, &statbuffer ); +        if(  -1 == rc ) +        { +            printf( "Unable to find a copy of errl, including %s.\n", +                    pszErrlTool ); +            exit(2); +        } +    } + +    if( fVerbose ) +    { +        printf( "Using errl tool %s\n", pszErrlTool ); +    } + + +    if( pszStringFile ) +    { +        int fd = open( pszStringFile, O_RDONLY ); +        if( -1 == fd ) +        { +            printf( "String file %s not found.\n", pszStringFile ); +            exit(2); +        } +        rc = fstat( fd, &statbuffer ); +        close(fd); +        if( ( -1 == rc ) ||  !(S_ISREG(statbuffer.st_mode))) +        { +            printf( "String file %s is not valid.\n", pszStringFile ); +            exit(2); +        } +    } + +      if( pszSymbolFile )      { @@ -717,7 +819,6 @@ int main( int argc,  char *argv[] )          }      } -      // Given the image file, read the portion that contains the      // error log storage buffer.      pchBuffer = ReadStorageBuffer( pszImageFile, ulAddr, cbBuffer ); @@ -770,7 +871,6 @@ int main( int argc,  char *argv[] )          if( pMarker->offsetNext == 0 )          {              // This is the list-ending marker. -            printf( "%s\n", szDivider );              break;          } @@ -778,24 +878,135 @@ int main( int argc,  char *argv[] )          logcount++; -        // Flattened struct of an error log resides just past marker. -        errl_header_t* perr = reinterpret_cast<errl_header_t*>(pMarker+1); -        ConvertErrlHeader( perr ); +        // Flattened PEL of an error log resides just past marker +        // for a length of pMarker->length.  It is "native" meaning big endian. +        pchNativePEL = reinterpret_cast<char*>(pMarker+1); + +        // Make a copy of PH that I can endian convert without screwing up +        // the native one. +        pvoid = malloc( pMarker->length ); +        pelPrivateHeaderSection_t * pPrivateHdr; +        pPrivateHdr = static_cast<pelPrivateHeaderSection_t*>(pvoid); +        memcpy( pPrivateHdr, pchNativePEL, pMarker->length ); + +        // Convert the PEL private header copy to local endianness. +        ConvertPrivateHeader( pPrivateHdr );          if( fList )          { -            // Just list the error log headers. -            printf( "%s\n", szDivider ); -            PrintErrlSummary( perr ); +            // print a simple list of error log IDs +            if( !fListHead ) +            { +                // print a head line +                printf( "%-16s %8s\n", "Component", "PLID" ); +                printf( "%s\n", szDivider ); +                fListHead  = 1; +            } +            printf( "%-16s %8d\n", +                    FindComp(pPrivateHdr->sectionheader.compId), +                    pPrivateHdr->plid );          } -        else if(( fDetail ) && (( perr->logId ==  ulLogId ) || (fAll))) +        else if(( fDetail ) && (( pPrivateHdr->plid == ulLogId ) || (fAll)))          { -            // Print the detail for the one error log. -            printf( "%s\n", szDivider ); -            PrintErrlDetail( perr ); +            // Write the native PEL to a temporary file +            // for x86 errl tool to display. +            sprintf( szTmpFilename, "/tmp/pel%d.bin", pPrivateHdr->plid ); + +            int fd = open( szTmpFilename,  O_RDWR | O_CREAT , 0664 ); +            if( -1 == fd ) +            { +                printf( "Unable to write %s. Exiting.\n", szTmpFilename ); +                exit(2); +            } +            cb = write( fd, pchNativePEL, pMarker->length ); +            assert( cb  == pMarker->length ); +            close(fd); + +            // Spawn the FSP x86 errl tool to display +            // the detail for this error log. +            cb=sprintf(szCommand,"%s -d --file=%s",pszErrlTool,szTmpFilename); +            if( pszStringFile ) +            { +                sprintf( &szCommand[cb], " --trace=%s", pszStringFile ); +            } + +            // Run errl -d  to display the error log. +            system( szCommand ); + + +            // Build a vector containing pointers to each PEL section +            // in the error log. On return, each section will be endian +            // converted as much as possible.  Do not alter the endianness +            // of the native pel buffer, however. +            vector<pelSectionHeader_t*> vectorPEL; +            ParseForPEL( pchNativePEL, pMarker->length, vectorPEL ); +            assert( vectorPEL.size() ); + + + +            // Print the tag detail gleaned from the code by +            // the errl tag parser. That requires getting the reason +            // code and module ID from the error log. They live in +            // the Primary SRC section. +            uint32_t l_reasonCode = 0; + + +            // Find the PS section in the vector of PEL sections. +            pelSectionHeader_t* pPELHead; +            pPELHead = FindPELSection( ERRL_SID_PRIMARY_SRC, vectorPEL ); +            assert( pPELHead ); + +            // Cast to Primary SRC section. +            pelSRCSection_t * pSRCSection; +            pSRCSection = reinterpret_cast<pelSRCSection_t*>(pPELHead); + +#if 0 +            // reasonCode has been "stringified" into the SRC string +            pch = strchr( pSRCSection->srcString, ' ' ); +            assert( pch ); +            *pch = 0; +            assert( 8 == strlen( pSRCSection->srcString)); +            sscanf( pSRCSection->srcString + 4, "%X", &l_reasonCode ); +#else +            // I have cheated and put reasonCode here: +            l_reasonCode = pSRCSection->reserved1; +#endif + +            printf( "%-20s%s\n", +                    "Component", +                    FindComp(pPrivateHdr->sectionheader.compId)); + +            // print the Errorlog tags from scanforsrcs.pl +            printErrorTags( l_reasonCode, pSRCSection->moduleId ); + +            // done with this tmp file +            unlink( szTmpFilename ); + +            // found at least one              fFound = 1;          } + +        if( fExtractPEL ) +        { +            // Write the native PEL to a temporary file for debug later. +            sprintf( szTmpFilename, "%s/pel%d.bin", pszOutputDir, pPrivateHdr->plid ); + +            int fd = open( szTmpFilename,  O_RDWR | O_CREAT , 0664 ); +            if( -1 == fd ) +            { +                printf( "Unable to write %s. Exiting.\n", szTmpFilename ); +                exit(2); +            } +            cb = write( fd, pchNativePEL, pMarker->length ); +            assert( cb  == pMarker->length ); +            close(fd); + +            printf( "Saved as %s\n", szTmpFilename ); +        } + + +          // next marker/error log          pMarker = ConvertMarker( OFFSET2MARKER(pMarker->offsetNext) );      } | 

