<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/errldisplay/errldisplay.C $                           */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2013,2019                        */
/* [+] 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 <errldisplay/errldisplay.H>
#include <errl/errlmanager.H>
#include <errl/errlentry.H>
#include <errl/errlud.H>
#include <errl/errludtarget.H>
#include <errl/errlsctn.H>
#include <errl/errlreasoncodes.H>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <initservice/taskargs.H>
#include <algorithm>
#include <console/consoleif.H>
#include <targeting/common/targetservice.H>
#include <targeting/common/iterators/targetiterator.H>
#include <targeting/common/target.H>

#ifdef CONFIG_CONSOLE_OUTPUT_FFDCDISPLAY
//Generated hearder files for HWP parsing
#include <hbfwErrDisplayPlatHwpErr.H>
#include <hbfwErrDisplayPlatHwpFFDC.H>
#include <prdrErrlDisplaySupt.H>

namespace PRDF
{
namespace HOSTBOOT
{
PrdrErrSigTable & GetErrorSigTable()
{
    static PrdrErrSigTable l_sigTable = PrdrErrSigTable();
    return l_sigTable;
}
}
}
#endif


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
    "",          // User Data 1 string
    ""           // 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 displayCalloutTarget (uint8_t * epRaw, size_t& o_size)
{
    // Data is formatted as a callout_ud_t followed by an entity path.
    // Note that in error data unused entity path elements are
    // eliminated, so use data to find the length
    const uint8_t pathTypeLength = *epRaw;

    //# of ep elements (2 bytes each) are in lower nibble of first elem
    //Master sentinel is 0xF0 so size is correct @ 1
    o_size = ((pathTypeLength & 0x0F) * 2)+1;

    const char * ep_str = "MASTER PROCESSOR SENTINEL";
    char * tmp_str = NULL;
    if( *epRaw != HWAS::TARGET_IS_SENTINEL )
    {
        TARGETING::EntityPath ep;

        if ((o_size > sizeof(TARGETING::EntityPath)))
        {
            ep_str = "MALFORMED UD Entity Path";
            o_size = 0; //stay safe
        }
        else
        {
            memcpy (reinterpret_cast<uint8_t*>(&ep), epRaw,o_size);
            tmp_str = ep.toString();
            ep_str = tmp_str;
        }
    }

    CONSOLE::displayf(NULL, "  Target                   : %s", ep_str);
    free(tmp_str);
}

void ErrLogDisplay::displayPrdf (uint64_t i_ud1, uint64_t i_ud2)
{
    //PRD stores the HUID of the callout in top word of ud1
    // and the signature in the top word of ud2
    uint32_t l_huid = i_ud1 >> 32;
    uint32_t l_sig = i_ud2 >> 32;

    CONSOLE::displayf(NULL, "  PRD Signature            : 0x%X 0x%X",
                      l_huid, l_sig);

#ifdef CONFIG_CONSOLE_OUTPUT_FFDCDISPLAY
    //Find the Target from the HUID
    TARGETING::Target* l_pTopLevel = NULL;
    TARGETING::targetService().getTopLevelTarget(l_pTopLevel);
    TARGETING::Target * l_target = l_pTopLevel->getTargetFromHuid(l_huid);

    if(l_target)
    {
        TARGETING::TYPE l_targetType =
          l_target->getAttr<TARGETING::ATTR_TYPE>();

        const char * l_nameStr =
           PRDF::HOSTBOOT::GetErrorSigTable()[l_targetType][l_sig].first;
        const char * l_descStr =
           PRDF::HOSTBOOT::GetErrorSigTable()[l_targetType][l_sig].second;

        TARGETING::ATTR_FAPI_NAME_type l_fapiStr = {0};
        l_target->tryGetAttr<TARGETING::ATTR_FAPI_NAME>(l_fapiStr);

        if(l_nameStr)
        {
            CONSOLE::displayf(NULL, "  Signature Description    : %s (%s) %s",
                              l_fapiStr, l_nameStr, l_descStr);
        }
        else
        {
            CONSOLE::displayf(NULL, "  Signature Description    : %s UNKNOWN",
                              l_fapiStr);
        }
    }
#endif
}


void ErrLogDisplay::displayCallout (void *data, size_t size)
{
    CONSOLE::displayf(NULL,
                      "------------------------------------------------");

    // Parse encoded callout data.  See ErrlUserDetailsCallout class in
    // errludcallout.C for (undocumented) encoding details.
    if (size >= sizeof(HWAS::callout_ud_t))
    {
        HWAS::callout_ud_t* callout =
            reinterpret_cast<HWAS::callout_ud_t*>(data);

        size_t  displayTarget = 0;
        bool displayGard = false;
        HWAS::GARD_ErrorType l_gard = HWAS::GARD_Fatal;
        bool displayDeconfig = false;
        HWAS::DeconfigEnum   l_deconfig = HWAS::DECONFIG;

        switch ( callout->type )
        {
            case HWAS::CLOCK_CALLOUT:
                switch (callout->clockType)
                {
#define case_CLOCK_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Clock Type               : %s", #_type); break;
                    case_CLOCK_TYPE(TODCLK_TYPE)
                    case_CLOCK_TYPE(MEMCLK_TYPE)
                    case_CLOCK_TYPE(OSCREFCLK_TYPE)
                    case_CLOCK_TYPE(OSCPCICLK_TYPE)
                    default:
                        CONSOLE::displayf(NULL, "  Clock Type               : UNKNOWN 0x%X",
                                          callout->clockType);
                } // switch clockType
#undef case_CLOCK_TYPE

                displayGard = true;
                l_gard = callout->clkGardErrorType;
                displayDeconfig = true;
                l_deconfig = callout->clkDeconfigState;
                displayTarget = 1;
                break;

            case HWAS::PART_CALLOUT:
                switch (callout->partType)
                {
#define case_PART_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Part Type                : %s", #_type); break;
                    case_PART_TYPE(FLASH_CONTROLLER_PART_TYPE)
                    case_PART_TYPE(PNOR_PART_TYPE)
                    case_PART_TYPE(SBE_SEEPROM_PART_TYPE)
                    case_PART_TYPE(VPD_PART_TYPE)
                    case_PART_TYPE(LPC_SLAVE_PART_TYPE)
                    case_PART_TYPE(GPIO_EXPANDER_PART_TYPE)
                    case_PART_TYPE(SPIVID_SLAVE_PART_TYPE)
                    case_PART_TYPE(BPM_CABLE_PART_TYPE)
                    case_PART_TYPE(NV_CONTROLLER_PART_TYPE)
                    case_PART_TYPE(BPM_PART_TYPE)
                    default:
                        CONSOLE::displayf(NULL, "  Part Type                : UNKNOWN 0x%X",
                                          callout->partType);
                } // switch partType
#undef case_PART_TYPE

                displayGard = true;
                l_gard = callout->partGardErrorType;
                displayDeconfig = true;
                l_deconfig = callout->partDeconfigState;
                displayTarget = 1;
                break;

            case HWAS::BUS_CALLOUT:
                switch (callout->busType)
                {
#define case_BUS_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Bus Type                 : %s", #_type); break;
                    case_BUS_TYPE(FSI_BUS_TYPE)
                    case_BUS_TYPE(DMI_BUS_TYPE)
                    case_BUS_TYPE(A_BUS_TYPE)
                    case_BUS_TYPE(X_BUS_TYPE)
                    case_BUS_TYPE(I2C_BUS_TYPE)
                    case_BUS_TYPE(PSI_BUS_TYPE)
                    case_BUS_TYPE(O_BUS_TYPE)
                    default:
                        CONSOLE::displayf(NULL, "  Bus Type                 : UNKNOWN 0x%X",
                                          callout->busType);
                } // switch partType
#undef case_BUS_TYPE

                // Data is formatted as a callout_ud_t followed by 2 entity
                // paths representing each side of the link.
                displayTarget = 2;
                break;

            case HWAS::HW_CALLOUT:
                CONSOLE::displayf(NULL, "  Callout type             : Hardware Callout");
                CONSOLE::displayf(NULL, "  CPU id                   : %d", callout->cpuid);

                displayGard = true;
                l_gard = callout->gardErrorType;
                displayDeconfig = true;
                l_deconfig = callout->deconfigState;
                displayTarget = 1;
                break;

            case HWAS::PROCEDURE_CALLOUT:
                CONSOLE::displayf(NULL, "  Callout type             : Procedure Callout");
                switch (callout->procedure)
                {
#define case_PROCEDURE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Procedure                : %s", #_type); break;
                    case_PROCEDURE(EPUB_PRC_NONE)
                    case_PROCEDURE(EPUB_PRC_FIND_DECONFIGURED_PART)
                    case_PROCEDURE(EPUB_PRC_SP_CODE)
                    case_PROCEDURE(EPUB_PRC_PHYP_CODE)
                    case_PROCEDURE(EPUB_PRC_ALL_PROCS)
                    case_PROCEDURE(EPUB_PRC_ALL_MEMCRDS)
                    case_PROCEDURE(EPUB_PRC_INVALID_PART)
                    case_PROCEDURE(EPUB_PRC_LVL_SUPP)
                    case_PROCEDURE(EPUB_PRC_PROCPATH)
                    case_PROCEDURE(EPUB_PRC_NO_VPD_FOR_FRU)
                    case_PROCEDURE(EPUB_PRC_MEMORY_PLUGGING_ERROR)
                    case_PROCEDURE(EPUB_PRC_FSI_PATH)
                    case_PROCEDURE(EPUB_PRC_PROC_AB_BUS)
                    case_PROCEDURE(EPUB_PRC_PROC_XYZ_BUS)
                    case_PROCEDURE(EPUB_PRC_MEMBUS_ERROR)
                    case_PROCEDURE(EPUB_PRC_EIBUS_ERROR)
                    case_PROCEDURE(EPUB_PRC_POWER_ERROR)
                    case_PROCEDURE(EPUB_PRC_MEMORY_UE)
                    case_PROCEDURE(EPUB_PRC_PERFORMANCE_DEGRADED)
                    case_PROCEDURE(EPUB_PRC_HB_CODE)
                    case_PROCEDURE(EPUB_PRC_TOD_CLOCK_ERR)
                    case_PROCEDURE(EPUB_PRC_COOLING_SYSTEM_ERR)
                    case_PROCEDURE(EPUB_PRC_FW_VERIFICATION_ERR)
                    case_PROCEDURE(EPUB_PRC_GPU_ISOLATION_PROCEDURE)
                    default:
                        CONSOLE::displayf(NULL, "  Procedure                : UNKNOWN: 0x%X",
                                          callout->procedure);
                        break;
                } // switch procedure
#undef case_PROCEDURE
                break;

              case HWAS::SENSOR_CALLOUT:
                CONSOLE::displayf(NULL, "  Sensor ID                   : 0x%x", callout->sensorId);

                switch (callout->sensorType)
                {
#define case_SENSOR_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Sensor Type                : %s", #_type); break;
                    case_SENSOR_TYPE(UNKNOWN_SENSOR)
                    case_SENSOR_TYPE(GPU_FUNC_SENSOR)
                    case_SENSOR_TYPE(GPU_TEMPERATURE_SENSOR)
                    case_SENSOR_TYPE(GPU_MEMORY_TEMP_SENSOR)
                    default:
                        CONSOLE::displayf(NULL, "  Sensor Type                : UNKNOWN 0x%X",
                                          callout->sensorType);
                } // switch sensorType
#undef case_SENSOR_TYPE
                break;

              case HWAS::I2C_DEVICE_CALLOUT:
                CONSOLE::displayf(nullptr, "  Callout type             : I2C Device Callout");

                break;

            default:
                CONSOLE::displayf(NULL, "  Callout type             : UNKNOWN: 0x%X",
                                  callout->type);
                break;
        }


        ///////////////////////////
        // Display all the common stuff
        ///////////////////////////

        //Display the number of targets indicated above
        uint8_t * epRaw = reinterpret_cast<uint8_t*>( callout+1 ); //ptr math
        size_t l_size = 0;
        for(size_t numT = 0 ; numT < displayTarget; numT++)
        {
            // Data is formatted as a callout_ud_t followed by an entity path
            // Multiple EP are packed together
            epRaw += l_size;
            displayCalloutTarget(epRaw,l_size);
        }

        if(displayDeconfig)
        {
            switch (l_deconfig)
            {
#define case_DECONFIG_STATE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Deconfig State           : %s", #_type); break;
                case_DECONFIG_STATE(NO_DECONFIG)
                case_DECONFIG_STATE(DECONFIG)
                case_DECONFIG_STATE(DELAYED_DECONFIG)
                default:
                    CONSOLE::displayf(NULL, "  Deconfig State           : UNKNOWN: 0x%X",
                                      l_deconfig);
                    break;
            } // switch deconfigState
#undef case_DECONFIG_STATE
        }

        if(displayGard)
        {
            switch (l_gard)
            {
#define case_GARD_ERROR_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  GARD Error Type          : %s", #_type); break;
                case_GARD_ERROR_TYPE(GARD_NULL)
                case_GARD_ERROR_TYPE(GARD_User_Manual)
                case_GARD_ERROR_TYPE(GARD_Unrecoverable)
                case_GARD_ERROR_TYPE(GARD_Fatal)
                case_GARD_ERROR_TYPE(GARD_Predictive)
                case_GARD_ERROR_TYPE(GARD_Power)
                case_GARD_ERROR_TYPE(GARD_PHYP)
                case_GARD_ERROR_TYPE(GARD_Reconfig)
                case_GARD_ERROR_TYPE(GARD_Void)
                default:
                    CONSOLE::displayf(NULL, "  GARD Error Type          : UNKNOWN: 0x%X",
                                      l_gard);
                    break;
            } // switch gardState
#undef case_GARD_ERROR_TYPE
        }

        switch (callout->priority)
        {
#define case_PRIORITY(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Priority                 : %s", #_type); break;
            case_PRIORITY(SRCI_PRIORITY_NONE)
            case_PRIORITY(SRCI_PRIORITY_LOW)
            case_PRIORITY(SRCI_PRIORITY_MEDC)
            case_PRIORITY(SRCI_PRIORITY_MEDB)
            case_PRIORITY(SRCI_PRIORITY_MEDA)
            case_PRIORITY(SRCI_PRIORITY_MED)
            case_PRIORITY(SRCI_PRIORITY_HIGH)
            default:
                CONSOLE::displayf(NULL, "  Priority                 : UNKNOWN: 0x%X",
                                  callout->priority);
                break;
        } // switch priority
#undef case_PRIORITY
    }
}

//Display a "Target".  This is a misnomer in that HB uses a "target"
// User detail section for lots of things.  We are only going to look
// for HWPF subtypes and display those

void ErrLogDisplay::displayTarget(void *data, size_t size)
{
    char *char_buf = reinterpret_cast<char*>( data );

    // The first part of the buffer is a TargetLabel_t.
    ERRORLOG::TargetLabel_t *label =
      reinterpret_cast<ERRORLOG::TargetLabel_t*>( char_buf );

    if( label->tag == 0xffffffff )
    {
        CONSOLE::displayf(NULL, "  MASTER PROCESSOR SENTINEL" );
    }
    else
    {
        // The second part of the buffer contains the encoded target.
        // See Target::targetFFDC for encoding details.
        // We only care about the HUID and can look up the Target based on that.
        char_buf += sizeof(ERRORLOG::TargetLabel_t);
        TARGETING::AttributeTraits<TARGETING::ATTR_HUID>::Type *huid =
          reinterpret_cast<TARGETING::AttributeTraits<
          TARGETING::ATTR_HUID>::Type*>( char_buf );
        CONSOLE::displayf(NULL, "  HUID: %08x", *huid );

        // Look up the HUID across all targets.
        for ( TARGETING::TargetIterator ti = TARGETING::targetService().begin();
              ti != TARGETING::targetService().end(); ++ti )
        {
            TARGETING::AttributeTraits<TARGETING::ATTR_HUID>::Type tmp_huid;
            if( ti->tryGetAttr<TARGETING::ATTR_HUID>( tmp_huid ) &&
                tmp_huid == *huid )
            {
                TARGETING::Target *target = *ti;
                CONSOLE::displayf(NULL,
                  "  Phys path: %s",
                  target->getAttr<TARGETING::ATTR_PHYS_PATH>().toString() );
                CONSOLE::displayf(NULL,
                  "  Affinity path: %s",
                  target->getAttr<TARGETING::ATTR_AFFINITY_PATH>().toString());
                break;
            }
        }
    }
}

#ifdef CONFIG_CONSOLE_OUTPUT_FFDCDISPLAY
static void printHex(char *i_buf, const size_t i_size)
{
    char byte_str[256] = { 0, };
    size_t pos = 0;
    // Limit dump to first 32 bytes.
    for ( size_t i = 0; i < std::min( i_size, 32ul ); ++i )
        pos += sprintf( byte_str + pos, "%s%02X", (i % 4) == 0 ? " " : "",
                        i_buf[i] );
    CONSOLE::displayf( NULL, "    %s", byte_str );
}
#endif

void ErrLogDisplay::displayHwpf(void *data, size_t size, uint8_t i_type)
{
#ifdef CONFIG_CONSOLE_OUTPUT_FFDCDISPLAY

    uint32_t *word_buf = reinterpret_cast<uint32_t*>( data );

    switch ( i_type )
    {
    case ERRORLOG::ERRL_UDT_STRING:
        //this is error code str -- single word of data is HWPF RC
        CONSOLE::displayf( NULL,
                           "------------------------------------------------" );
        const char *rc;
        const char *desc;
        fapi2::hbfwErrLookupHwpRc( *word_buf, rc, desc );
        CONSOLE::displayf( NULL, "  HwpReturnCode              : %s",
                           rc ? rc : "Unknown" );
        CONSOLE::displayf( NULL, "  HWP Error description      : %s",
                           desc ? desc : "Unknown" );
        break;

    case ERRORLOG::ERRL_UDT_TARGET:
        {
        //this is HWPF FFDC.  First word is hash, rest of data is hex
        //reserve space for 16 words of data with spaces between
        CONSOLE::displayf( NULL,
                           "------------------------------------------------" );
        fapi2::hbfwFfdcType type;
        uint64_t value;
        const char *str;
        int index = 0;
        char *buf = reinterpret_cast<char*>( data ) + sizeof( *word_buf );
        size -= sizeof( *word_buf );
        while ( fapi2::hbfwErrLookupHwpRcFFDC( *word_buf, index, type, value,
                                               str ) )
        {
            if( type == fapi2::HBFW_FFDC_TYPE_HWP_RC_FFDC )
            {
                const char *rc;
                const char *desc;
                fapi2::hbfwErrLookupHwpRc( value, rc, desc );
                CONSOLE::displayf( NULL, "  HwpReturnCode              : %s",
                                   rc ? rc : "Unknown" );
                CONSOLE::displayf( NULL, "  FFDC                       : %s",
                                   str ? str : "Unknown" );
                printHex(buf, size);
                size = 0;
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_SCOM_FAIL )
            {
                uint64_t val64 = be64toh( *reinterpret_cast<uint64_t*>( buf ) );
                CONSOLE::displayf( NULL, "  Failed SCOM address        : %#016lX",
                                   val64 );
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_PIB_RC )
            {
                uint64_t val32 = be64toh( *reinterpret_cast<uint32_t*>( buf ) );
                CONSOLE::displayf( NULL, "  PIB RC                     : %#08lX",
                                   val32 );
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_REGISTER_SET )
            {
                CONSOLE::displayf( NULL, "  Register FFDC              : %s",
                                   str ? str : "Unknown" );
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_CHIP_POSITION
                && (size >= sizeof(uint32_t)) )
            {
                uint32_t val32 = be32toh( *reinterpret_cast<uint32_t*>( buf ) );
                CONSOLE::displayf( NULL, "  Chip Position              : %X",
                                   val32 );
                buf += sizeof(uint32_t);
                size -= sizeof(uint32_t);
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_CFAM_REG
                && (size >= sizeof(uint32_t)) )
            {
                uint32_t val32 = be32toh( *reinterpret_cast<uint32_t*>( buf ) );
                CONSOLE::displayf( NULL, "  CFAM Register              : %s",
                                   str ? str : "Unknown" );
                CONSOLE::displayf( NULL, "    %08X", val32 );
                buf += sizeof(uint32_t);
                size -= sizeof(uint32_t);
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_SCOM_REG
                && (size >= sizeof(uint64_t)) )
            {
                uint64_t val64 = be64toh( *reinterpret_cast<uint64_t*>( buf ) );
                CONSOLE::displayf( NULL, "  SCOM Register              : %s",
                                   str ? str : "Unknown" );
                CONSOLE::displayf( NULL, "    %08llX %08llX",
                                   (val64 >> 32) & 0xffffffff,
                                   (val64 & 0xffffffff) );
                buf += sizeof(uint64_t);
                size -= sizeof(uint64_t);
            }
            index++;
        }
        break;
    }
    }
#endif
}

//
// Display a human-readable form of an error.
void ErrLogDisplay::msgDisplay (const errlHndl_t &i_err,
                                compId_t i_committerComp)
{
    TRACDCOMP( g_trac_errldisp, ENTER_MRK "ErrLogDisplay::msgDisplay" );

    do
    {
        // Decide whether or not to skip the error log
        if( i_err->getSkipShowingLog() )
        {
            TRACDCOMP( g_trac_errldisp, INFO_MRK"msgDisplay: %.8X is INFORMATIONAL/RECOVERED; skipping...", i_err->eid());
            break;
        }
        const errLogInfo *info = findErrLogInfo ( i_err->moduleId(),
                                              i_err->reasonCode());

        CONSOLE::displayf(NULL,
                          "================================================");
        CONSOLE::displayf(NULL, "Error reported by %s (0x%04X) PLID 0x%08X",
                         findComponentName( i_committerComp ),
                         i_committerComp, i_err->plid() );

        //PRD doesn't follow the rest of the HB conventions
        // Handle them special
        if(i_committerComp == PRDF_COMP_ID)
        {
            displayPrdf(i_err->getUserData1(), i_err->getUserData2());
        }
        else
        {
            CONSOLE::displayf(NULL, "  %s", info->descriptString);
            CONSOLE::displayf(NULL, "  ModuleId   0x%02x %s",
                          i_err->moduleId(), info->moduleName);
            CONSOLE::displayf(NULL, "  ReasonCode 0x%04x %s",
                          i_err->reasonCode(), info->reasonString);
        }

        CONSOLE::displayf(NULL, "  UserData1  %s : 0x%016lx",
                          info->userData1String, i_err->getUserData1());
        CONSOLE::displayf(NULL, "  UserData2  %s : 0x%016lx",
                          info->userData2String, i_err->getUserData2());

        // Loop through and print interesting  user data sections.
        for ( size_t i = 0; i < i_err->iv_SectionVector.size(); ++i )
        {
            ERRORLOG::ErrlUD *user_data = i_err->iv_SectionVector[i];
            //HWPF subsections abuse the rules... handle it special
            if(user_data->iv_header.iv_compId == HWPF_COMP_ID)
            {
                displayHwpf( user_data->iv_pData, user_data->iv_Size,
                             user_data->iv_header.iv_sst);
            }
            else<commit_msg>Only display ERRL user details callouts/strings when dumping error to console<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/errldisplay/errldisplay.C $                           */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2013,2019                        */
/* [+] 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 <errldisplay/errldisplay.H>
#include <errl/errlmanager.H>
#include <errl/errlentry.H>
#include <errl/errlud.H>
#include <errl/errludtarget.H>
#include <errl/errlsctn.H>
#include <errl/errlreasoncodes.H>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <initservice/taskargs.H>
#include <algorithm>
#include <console/consoleif.H>
#include <targeting/common/targetservice.H>
#include <targeting/common/iterators/targetiterator.H>
#include <targeting/common/target.H>

#ifdef CONFIG_CONSOLE_OUTPUT_FFDCDISPLAY
//Generated hearder files for HWP parsing
#include <hbfwErrDisplayPlatHwpErr.H>
#include <hbfwErrDisplayPlatHwpFFDC.H>
#include <prdrErrlDisplaySupt.H>

namespace PRDF
{
namespace HOSTBOOT
{
PrdrErrSigTable & GetErrorSigTable()
{
    static PrdrErrSigTable l_sigTable = PrdrErrSigTable();
    return l_sigTable;
}
}
}
#endif


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
    "",          // User Data 1 string
    ""           // 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 displayCalloutTarget (uint8_t * epRaw, size_t& o_size)
{
    // Data is formatted as a callout_ud_t followed by an entity path.
    // Note that in error data unused entity path elements are
    // eliminated, so use data to find the length
    const uint8_t pathTypeLength = *epRaw;

    //# of ep elements (2 bytes each) are in lower nibble of first elem
    //Master sentinel is 0xF0 so size is correct @ 1
    o_size = ((pathTypeLength & 0x0F) * 2)+1;

    const char * ep_str = "MASTER PROCESSOR SENTINEL";
    char * tmp_str = NULL;
    if( *epRaw != HWAS::TARGET_IS_SENTINEL )
    {
        TARGETING::EntityPath ep;

        if ((o_size > sizeof(TARGETING::EntityPath)))
        {
            ep_str = "MALFORMED UD Entity Path";
            o_size = 0; //stay safe
        }
        else
        {
            memcpy (reinterpret_cast<uint8_t*>(&ep), epRaw,o_size);
            tmp_str = ep.toString();
            ep_str = tmp_str;
        }
    }

    CONSOLE::displayf(NULL, "  Target                   : %s", ep_str);
    free(tmp_str);
}

void ErrLogDisplay::displayPrdf (uint64_t i_ud1, uint64_t i_ud2)
{
    //PRD stores the HUID of the callout in top word of ud1
    // and the signature in the top word of ud2
    uint32_t l_huid = i_ud1 >> 32;
    uint32_t l_sig = i_ud2 >> 32;

    CONSOLE::displayf(NULL, "  PRD Signature            : 0x%X 0x%X",
                      l_huid, l_sig);

#ifdef CONFIG_CONSOLE_OUTPUT_FFDCDISPLAY
    //Find the Target from the HUID
    TARGETING::Target* l_pTopLevel = NULL;
    TARGETING::targetService().getTopLevelTarget(l_pTopLevel);
    TARGETING::Target * l_target = l_pTopLevel->getTargetFromHuid(l_huid);

    if(l_target)
    {
        TARGETING::TYPE l_targetType =
          l_target->getAttr<TARGETING::ATTR_TYPE>();

        const char * l_nameStr =
           PRDF::HOSTBOOT::GetErrorSigTable()[l_targetType][l_sig].first;
        const char * l_descStr =
           PRDF::HOSTBOOT::GetErrorSigTable()[l_targetType][l_sig].second;

        TARGETING::ATTR_FAPI_NAME_type l_fapiStr = {0};
        l_target->tryGetAttr<TARGETING::ATTR_FAPI_NAME>(l_fapiStr);

        if(l_nameStr)
        {
            CONSOLE::displayf(NULL, "  Signature Description    : %s (%s) %s",
                              l_fapiStr, l_nameStr, l_descStr);
        }
        else
        {
            CONSOLE::displayf(NULL, "  Signature Description    : %s UNKNOWN",
                              l_fapiStr);
        }
    }
#endif
}


void ErrLogDisplay::displayCallout (void *data, size_t size)
{
    CONSOLE::displayf(NULL,
                      "------------------------------------------------");

    // Parse encoded callout data.  See ErrlUserDetailsCallout class in
    // errludcallout.C for (undocumented) encoding details.
    if (size >= sizeof(HWAS::callout_ud_t))
    {
        HWAS::callout_ud_t* callout =
            reinterpret_cast<HWAS::callout_ud_t*>(data);

        size_t  displayTarget = 0;
        bool displayGard = false;
        HWAS::GARD_ErrorType l_gard = HWAS::GARD_Fatal;
        bool displayDeconfig = false;
        HWAS::DeconfigEnum   l_deconfig = HWAS::DECONFIG;

        switch ( callout->type )
        {
            case HWAS::CLOCK_CALLOUT:
                switch (callout->clockType)
                {
#define case_CLOCK_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Clock Type               : %s", #_type); break;
                    case_CLOCK_TYPE(TODCLK_TYPE)
                    case_CLOCK_TYPE(MEMCLK_TYPE)
                    case_CLOCK_TYPE(OSCREFCLK_TYPE)
                    case_CLOCK_TYPE(OSCPCICLK_TYPE)
                    default:
                        CONSOLE::displayf(NULL, "  Clock Type               : UNKNOWN 0x%X",
                                          callout->clockType);
                } // switch clockType
#undef case_CLOCK_TYPE

                displayGard = true;
                l_gard = callout->clkGardErrorType;
                displayDeconfig = true;
                l_deconfig = callout->clkDeconfigState;
                displayTarget = 1;
                break;

            case HWAS::PART_CALLOUT:
                switch (callout->partType)
                {
#define case_PART_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Part Type                : %s", #_type); break;
                    case_PART_TYPE(FLASH_CONTROLLER_PART_TYPE)
                    case_PART_TYPE(PNOR_PART_TYPE)
                    case_PART_TYPE(SBE_SEEPROM_PART_TYPE)
                    case_PART_TYPE(VPD_PART_TYPE)
                    case_PART_TYPE(LPC_SLAVE_PART_TYPE)
                    case_PART_TYPE(GPIO_EXPANDER_PART_TYPE)
                    case_PART_TYPE(SPIVID_SLAVE_PART_TYPE)
                    case_PART_TYPE(BPM_CABLE_PART_TYPE)
                    case_PART_TYPE(NV_CONTROLLER_PART_TYPE)
                    case_PART_TYPE(BPM_PART_TYPE)
                    default:
                        CONSOLE::displayf(NULL, "  Part Type                : UNKNOWN 0x%X",
                                          callout->partType);
                } // switch partType
#undef case_PART_TYPE

                displayGard = true;
                l_gard = callout->partGardErrorType;
                displayDeconfig = true;
                l_deconfig = callout->partDeconfigState;
                displayTarget = 1;
                break;

            case HWAS::BUS_CALLOUT:
                switch (callout->busType)
                {
#define case_BUS_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Bus Type                 : %s", #_type); break;
                    case_BUS_TYPE(FSI_BUS_TYPE)
                    case_BUS_TYPE(DMI_BUS_TYPE)
                    case_BUS_TYPE(A_BUS_TYPE)
                    case_BUS_TYPE(X_BUS_TYPE)
                    case_BUS_TYPE(I2C_BUS_TYPE)
                    case_BUS_TYPE(PSI_BUS_TYPE)
                    case_BUS_TYPE(O_BUS_TYPE)
                    default:
                        CONSOLE::displayf(NULL, "  Bus Type                 : UNKNOWN 0x%X",
                                          callout->busType);
                } // switch partType
#undef case_BUS_TYPE

                // Data is formatted as a callout_ud_t followed by 2 entity
                // paths representing each side of the link.
                displayTarget = 2;
                break;

            case HWAS::HW_CALLOUT:
                CONSOLE::displayf(NULL, "  Callout type             : Hardware Callout");
                CONSOLE::displayf(NULL, "  CPU id                   : %d", callout->cpuid);

                displayGard = true;
                l_gard = callout->gardErrorType;
                displayDeconfig = true;
                l_deconfig = callout->deconfigState;
                displayTarget = 1;
                break;

            case HWAS::PROCEDURE_CALLOUT:
                CONSOLE::displayf(NULL, "  Callout type             : Procedure Callout");
                switch (callout->procedure)
                {
#define case_PROCEDURE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Procedure                : %s", #_type); break;
                    case_PROCEDURE(EPUB_PRC_NONE)
                    case_PROCEDURE(EPUB_PRC_FIND_DECONFIGURED_PART)
                    case_PROCEDURE(EPUB_PRC_SP_CODE)
                    case_PROCEDURE(EPUB_PRC_PHYP_CODE)
                    case_PROCEDURE(EPUB_PRC_ALL_PROCS)
                    case_PROCEDURE(EPUB_PRC_ALL_MEMCRDS)
                    case_PROCEDURE(EPUB_PRC_INVALID_PART)
                    case_PROCEDURE(EPUB_PRC_LVL_SUPP)
                    case_PROCEDURE(EPUB_PRC_PROCPATH)
                    case_PROCEDURE(EPUB_PRC_NO_VPD_FOR_FRU)
                    case_PROCEDURE(EPUB_PRC_MEMORY_PLUGGING_ERROR)
                    case_PROCEDURE(EPUB_PRC_FSI_PATH)
                    case_PROCEDURE(EPUB_PRC_PROC_AB_BUS)
                    case_PROCEDURE(EPUB_PRC_PROC_XYZ_BUS)
                    case_PROCEDURE(EPUB_PRC_MEMBUS_ERROR)
                    case_PROCEDURE(EPUB_PRC_EIBUS_ERROR)
                    case_PROCEDURE(EPUB_PRC_POWER_ERROR)
                    case_PROCEDURE(EPUB_PRC_MEMORY_UE)
                    case_PROCEDURE(EPUB_PRC_PERFORMANCE_DEGRADED)
                    case_PROCEDURE(EPUB_PRC_HB_CODE)
                    case_PROCEDURE(EPUB_PRC_TOD_CLOCK_ERR)
                    case_PROCEDURE(EPUB_PRC_COOLING_SYSTEM_ERR)
                    case_PROCEDURE(EPUB_PRC_FW_VERIFICATION_ERR)
                    case_PROCEDURE(EPUB_PRC_GPU_ISOLATION_PROCEDURE)
                    default:
                        CONSOLE::displayf(NULL, "  Procedure                : UNKNOWN: 0x%X",
                                          callout->procedure);
                        break;
                } // switch procedure
#undef case_PROCEDURE
                break;

              case HWAS::SENSOR_CALLOUT:
                CONSOLE::displayf(NULL, "  Sensor ID                   : 0x%x", callout->sensorId);

                switch (callout->sensorType)
                {
#define case_SENSOR_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Sensor Type                : %s", #_type); break;
                    case_SENSOR_TYPE(UNKNOWN_SENSOR)
                    case_SENSOR_TYPE(GPU_FUNC_SENSOR)
                    case_SENSOR_TYPE(GPU_TEMPERATURE_SENSOR)
                    case_SENSOR_TYPE(GPU_MEMORY_TEMP_SENSOR)
                    default:
                        CONSOLE::displayf(NULL, "  Sensor Type                : UNKNOWN 0x%X",
                                          callout->sensorType);
                } // switch sensorType
#undef case_SENSOR_TYPE
                break;

              case HWAS::I2C_DEVICE_CALLOUT:
                CONSOLE::displayf(nullptr, "  Callout type             : I2C Device Callout");

                break;

            default:
                CONSOLE::displayf(NULL, "  Callout type             : UNKNOWN: 0x%X",
                                  callout->type);
                break;
        }


        ///////////////////////////
        // Display all the common stuff
        ///////////////////////////

        //Display the number of targets indicated above
        uint8_t * epRaw = reinterpret_cast<uint8_t*>( callout+1 ); //ptr math
        size_t l_size = 0;
        for(size_t numT = 0 ; numT < displayTarget; numT++)
        {
            // Data is formatted as a callout_ud_t followed by an entity path
            // Multiple EP are packed together
            epRaw += l_size;
            displayCalloutTarget(epRaw,l_size);
        }

        if(displayDeconfig)
        {
            switch (l_deconfig)
            {
#define case_DECONFIG_STATE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Deconfig State           : %s", #_type); break;
                case_DECONFIG_STATE(NO_DECONFIG)
                case_DECONFIG_STATE(DECONFIG)
                case_DECONFIG_STATE(DELAYED_DECONFIG)
                default:
                    CONSOLE::displayf(NULL, "  Deconfig State           : UNKNOWN: 0x%X",
                                      l_deconfig);
                    break;
            } // switch deconfigState
#undef case_DECONFIG_STATE
        }

        if(displayGard)
        {
            switch (l_gard)
            {
#define case_GARD_ERROR_TYPE(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  GARD Error Type          : %s", #_type); break;
                case_GARD_ERROR_TYPE(GARD_NULL)
                case_GARD_ERROR_TYPE(GARD_User_Manual)
                case_GARD_ERROR_TYPE(GARD_Unrecoverable)
                case_GARD_ERROR_TYPE(GARD_Fatal)
                case_GARD_ERROR_TYPE(GARD_Predictive)
                case_GARD_ERROR_TYPE(GARD_Power)
                case_GARD_ERROR_TYPE(GARD_PHYP)
                case_GARD_ERROR_TYPE(GARD_Reconfig)
                case_GARD_ERROR_TYPE(GARD_Void)
                default:
                    CONSOLE::displayf(NULL, "  GARD Error Type          : UNKNOWN: 0x%X",
                                      l_gard);
                    break;
            } // switch gardState
#undef case_GARD_ERROR_TYPE
        }

        switch (callout->priority)
        {
#define case_PRIORITY(_type) \
case HWAS::_type: CONSOLE::displayf(NULL, "  Priority                 : %s", #_type); break;
            case_PRIORITY(SRCI_PRIORITY_NONE)
            case_PRIORITY(SRCI_PRIORITY_LOW)
            case_PRIORITY(SRCI_PRIORITY_MEDC)
            case_PRIORITY(SRCI_PRIORITY_MEDB)
            case_PRIORITY(SRCI_PRIORITY_MEDA)
            case_PRIORITY(SRCI_PRIORITY_MED)
            case_PRIORITY(SRCI_PRIORITY_HIGH)
            default:
                CONSOLE::displayf(NULL, "  Priority                 : UNKNOWN: 0x%X",
                                  callout->priority);
                break;
        } // switch priority
#undef case_PRIORITY
    }
}

//Display a "Target".  This is a misnomer in that HB uses a "target"
// User detail section for lots of things.  We are only going to look
// for HWPF subtypes and display those

void ErrLogDisplay::displayTarget(void *data, size_t size)
{
    char *char_buf = reinterpret_cast<char*>( data );

    // The first part of the buffer is a TargetLabel_t.
    ERRORLOG::TargetLabel_t *label =
      reinterpret_cast<ERRORLOG::TargetLabel_t*>( char_buf );

    if( label->tag == 0xffffffff )
    {
        CONSOLE::displayf(NULL, "  MASTER PROCESSOR SENTINEL" );
    }
    else
    {
        // The second part of the buffer contains the encoded target.
        // See Target::targetFFDC for encoding details.
        // We only care about the HUID and can look up the Target based on that.
        char_buf += sizeof(ERRORLOG::TargetLabel_t);
        TARGETING::AttributeTraits<TARGETING::ATTR_HUID>::Type *huid =
          reinterpret_cast<TARGETING::AttributeTraits<
          TARGETING::ATTR_HUID>::Type*>( char_buf );
        CONSOLE::displayf(NULL, "  HUID: %08x", *huid );

        // Look up the HUID across all targets.
        for ( TARGETING::TargetIterator ti = TARGETING::targetService().begin();
              ti != TARGETING::targetService().end(); ++ti )
        {
            TARGETING::AttributeTraits<TARGETING::ATTR_HUID>::Type tmp_huid;
            if( ti->tryGetAttr<TARGETING::ATTR_HUID>( tmp_huid ) &&
                tmp_huid == *huid )
            {
                TARGETING::Target *target = *ti;
                CONSOLE::displayf(NULL,
                  "  Phys path: %s",
                  target->getAttr<TARGETING::ATTR_PHYS_PATH>().toString() );
                CONSOLE::displayf(NULL,
                  "  Affinity path: %s",
                  target->getAttr<TARGETING::ATTR_AFFINITY_PATH>().toString());
                break;
            }
        }
    }
}

#ifdef CONFIG_CONSOLE_OUTPUT_FFDCDISPLAY
static void printHex(char *i_buf, const size_t i_size)
{
    char byte_str[256] = { 0, };
    size_t pos = 0;
    // Limit dump to first 32 bytes.
    for ( size_t i = 0; i < std::min( i_size, 32ul ); ++i )
        pos += sprintf( byte_str + pos, "%s%02X", (i % 4) == 0 ? " " : "",
                        i_buf[i] );
    CONSOLE::displayf( NULL, "    %s", byte_str );
}
#endif

void ErrLogDisplay::displayHwpf(void *data, size_t size, uint8_t i_type)
{
#ifdef CONFIG_CONSOLE_OUTPUT_FFDCDISPLAY

    uint32_t *word_buf = reinterpret_cast<uint32_t*>( data );

    switch ( i_type )
    {
    case ERRORLOG::ERRL_UDT_STRING:
        //this is error code str -- single word of data is HWPF RC
        CONSOLE::displayf( NULL,
                           "------------------------------------------------" );
        const char *rc;
        const char *desc;
        fapi2::hbfwErrLookupHwpRc( *word_buf, rc, desc );
        CONSOLE::displayf( NULL, "  HwpReturnCode              : %s",
                           rc ? rc : "Unknown" );
        CONSOLE::displayf( NULL, "  HWP Error description      : %s",
                           desc ? desc : "Unknown" );
        break;

    case ERRORLOG::ERRL_UDT_TARGET:
        {
        //this is HWPF FFDC.  First word is hash, rest of data is hex
        //reserve space for 16 words of data with spaces between
        CONSOLE::displayf( NULL,
                           "------------------------------------------------" );
        fapi2::hbfwFfdcType type;
        uint64_t value;
        const char *str;
        int index = 0;
        char *buf = reinterpret_cast<char*>( data ) + sizeof( *word_buf );
        size -= sizeof( *word_buf );
        while ( fapi2::hbfwErrLookupHwpRcFFDC( *word_buf, index, type, value,
                                               str ) )
        {
            if( type == fapi2::HBFW_FFDC_TYPE_HWP_RC_FFDC )
            {
                const char *rc;
                const char *desc;
                fapi2::hbfwErrLookupHwpRc( value, rc, desc );
                CONSOLE::displayf( NULL, "  HwpReturnCode              : %s",
                                   rc ? rc : "Unknown" );
                CONSOLE::displayf( NULL, "  FFDC                       : %s",
                                   str ? str : "Unknown" );
                printHex(buf, size);
                size = 0;
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_SCOM_FAIL )
            {
                uint64_t val64 = be64toh( *reinterpret_cast<uint64_t*>( buf ) );
                CONSOLE::displayf( NULL, "  Failed SCOM address        : %#016lX",
                                   val64 );
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_PIB_RC )
            {
                uint64_t val32 = be64toh( *reinterpret_cast<uint32_t*>( buf ) );
                CONSOLE::displayf( NULL, "  PIB RC                     : %#08lX",
                                   val32 );
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_REGISTER_SET )
            {
                CONSOLE::displayf( NULL, "  Register FFDC              : %s",
                                   str ? str : "Unknown" );
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_CHIP_POSITION
                && (size >= sizeof(uint32_t)) )
            {
                uint32_t val32 = be32toh( *reinterpret_cast<uint32_t*>( buf ) );
                CONSOLE::displayf( NULL, "  Chip Position              : %X",
                                   val32 );
                buf += sizeof(uint32_t);
                size -= sizeof(uint32_t);
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_CFAM_REG
                && (size >= sizeof(uint32_t)) )
            {
                uint32_t val32 = be32toh( *reinterpret_cast<uint32_t*>( buf ) );
                CONSOLE::displayf( NULL, "  CFAM Register              : %s",
                                   str ? str : "Unknown" );
                CONSOLE::displayf( NULL, "    %08X", val32 );
                buf += sizeof(uint32_t);
                size -= sizeof(uint32_t);
            }
            else if( type == fapi2::HBFW_FFDC_TYPE_SCOM_REG
                && (size >= sizeof(uint64_t)) )
            {
                uint64_t val64 = be64toh( *reinterpret_cast<uint64_t*>( buf ) );
                CONSOLE::displayf( NULL, "  SCOM Register              : %s",
                                   str ? str : "Unknown" );
                CONSOLE::displayf( NULL, "    %08llX %08llX",
                                   (val64 >> 32) & 0xffffffff,
                                   (val64 & 0xffffffff) );
                buf += sizeof(uint64_t);
                size -= sizeof(uint64_t);
            }
            index++;
        }
        break;
    }
    }
#endif
}

//
// Display a human-readable form of an error.
void ErrLogDisplay::msgDisplay (const errlHndl_t &i_err,
                                compId_t i_committerComp)
{
    TRACDCOMP( g_trac_errldisp, ENTER_MRK "ErrLogDisplay::msgDisplay" );

    do
    {
        // Decide whether or not to skip the error log
        if( i_err->getSkipShowingLog() )
        {
            TRACDCOMP( g_trac_errldisp, INFO_MRK"msgDisplay: %.8X is INFORMATIONAL/RECOVERED; skipping...", i_err->eid());
            break;
        }
        const errLogInfo *info = findErrLogInfo ( i_err->moduleId(),
                                              i_err->reasonCode());

        CONSOLE::displayf(NULL,
                          "================================================");
        CONSOLE::displayf(NULL, "Error reported by %s (0x%04X) PLID 0x%08X",
                         findComponentName( i_committerComp ),
                         i_committerComp, i_err->plid() );

        //PRD doesn't follow the rest of the HB conventions
        // Handle them special
        if(i_committerComp == PRDF_COMP_ID)
        {
            displayPrdf(i_err->getUserData1(), i_err->getUserData2());
        }
        else
        {
            CONSOLE::displayf(NULL, "  %s", info->descriptString);
            CONSOLE::displayf(NULL, "  ModuleId   0x%02x %s",
                          i_err->moduleId(), info->moduleName);
            CONSOLE::displayf(NULL, "  ReasonCode 0x%04x %s",
                          i_err->reasonCode(), info->reasonString);
        }

        CONSOLE::displayf(NULL, "  UserData1  %s : 0x%016lx",
                          info->userData1String, i_err->getUserData1());
        CONSOLE::displayf(NULL, "  UserData2  %s : 0x%016lx",
                          info->userData2String, i_err->getUserData2());

        // Loop through and print interesting  user data sections.
        for ( size_t i = 0; i < i_err->iv_SectionVector.size(); ++i )
        {
            ERRORLOG::ErrlUD *user_data = i_err->iv_SectionVector[i];
            //HWPF subsections abuse the rules... handle it special
            if(user_data->iv_header.iv_compId == HWPF_COMP_ID)
            {
                displayHwpf( user_data->iv_pData, user_data->iv_Size,
                             user_data->iv_header.iv_sst);
            }
            else if(user_data->iv_header.iv_compId == ERRL_COMP_ID)
{'fraction_non_alphanumeric': 0.1030436823167446, 'fraction_numerical': 0.00823932277633889, 'mean_word_length': 1.5445619001282676, 'pattern_counts': {'":': 0, '<': 95, '<?xml version=': 0, '>': 222, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 154, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5088378', 'n_tokens_mistral': 17234, 'n_tokens_neox': 16292, 'n_words': 3493}