// // This file contains 'Framework Code' and is licensed as such // under the terms of your license agreement with Intel or your // vendor. This file may not be modified, except as allowed by // additional terms of your license agreement. // /** @file TraceHub status code reporting worker. INTEL CONFIDENTIAL Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.
This software and associated documentation (if any) is furnished under a license and may only be used or copied in accordance with the terms of the license. Except as permitted by such license, no part of this software or documentation may be reproduced, stored in a retrieval system, or transmitted in any form or by any means without the express written consent of Intel Corporation. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include EFI_RSC_HANDLER_PROTOCOL *mTraceHubRscHandlerProtocol = NULL; BOOLEAN mTraceHubRegistered = FALSE; /** Convert status code value and extended data to readable ASCII string, send string to TraceHub device. @param CodeType Indicates the type of status code being reported. @param Value Describes the current status of a hardware or software entity. This included information about the class and subclass that is used to classify the entity as well as an operation. @param Instance The enumeration of a hardware or software entity within the system. Valid instance numbers start with 1. @param CallerId This optional parameter may be used to identify the caller. This parameter allows the status code driver to apply different rules to different callers. @param Data This optional parameter may be used to pass additional data. @retval EFI_SUCCESS Status code reported to TraceHub successfully. @retval EFI_DEVICE_ERROR EFI TraceHub device cannot work after ExitBootService() is called. @retval EFI_DEVICE_ERROR EFI TraceHub device cannot work with TPL higher than TPL_CALLBACK. **/ EFI_STATUS EFIAPI TraceHubStatusCodeReportWorker ( IN EFI_STATUS_CODE_TYPE CodeType, IN EFI_STATUS_CODE_VALUE Value, IN UINT32 Instance, IN EFI_GUID *CallerId, IN EFI_STATUS_CODE_DATA *Data OPTIONAL ) { CHAR8 *Filename; CHAR8 *Description; CHAR8 *Format; CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; UINT32 ErrorLevel; UINT32 LineNumber; UINTN CharCount; BASE_LIST Marker; UINT32 DebugPrintErrorLevel; TRACE_HUB_SEVERITY_TYPE TraceHubSeverityLevel; Buffer[0] = '\0'; DebugPrintErrorLevel = GetDebugPrintErrorLevel (); if (Data != NULL && CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeStringGuid) && ((EFI_STATUS_CODE_STRING_DATA *) Data)->StringType == EfiStringAscii) { if ((Instance & DebugPrintErrorLevel) == 0) { return EFI_SUCCESS; } // // Print String Data. // TraceHubSeverityLevel = SeverityNormal; TraceHubDebugWrite ( TraceHubSeverityLevel, (UINT8 *) (((EFI_STATUS_CODE_STRING_DATA *) Data)->String.Ascii), ((EFI_STATUS_CODE_STRING_DATA *) Data)->DataHeader.Size ); return EFI_SUCCESS; } else if (Data != NULL && ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) { if ((EFI_D_ERROR & DebugPrintErrorLevel) == 0) { return EFI_SUCCESS; } // // Print ASSERT() information into output buffer. // CharCount = AsciiSPrint ( Buffer, sizeof (Buffer), "\n\rDXE_ASSERT!: %a (%d): %a\n\r", Filename, LineNumber, Description ); TraceHubSeverityLevel = SeverityFatal; } else if (Data != NULL && ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { if ((ErrorLevel & DebugPrintErrorLevel) == 0) { return EFI_SUCCESS; } // // Print DEBUG() information into output buffer. // CharCount = AsciiBSPrint ( Buffer, sizeof (Buffer), Format, Marker ); if (ErrorLevel == EFI_D_WARN) { TraceHubSeverityLevel = SeverityNormal; } else if (ErrorLevel == EFI_D_ERROR) { TraceHubSeverityLevel = SeverityError; } else { TraceHubSeverityLevel = SeverityNormal; } } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { if ((EFI_D_ERROR & DebugPrintErrorLevel) == 0) { return EFI_SUCCESS; } // // Print ERROR information into output buffer. // CharCount = AsciiSPrint ( Buffer, sizeof (Buffer), "ERROR: C%08x:V%08x I%x", CodeType, Value, Instance ); ASSERT (CharCount > 0); if (CallerId != NULL) { CharCount += AsciiSPrint ( &Buffer[CharCount], (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)), " %g", CallerId ); } if (Data != NULL) { CharCount += AsciiSPrint ( &Buffer[CharCount], (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)), " %x", Data ); } CharCount += AsciiSPrint ( &Buffer[CharCount], (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)), "\n\r" ); TraceHubSeverityLevel = SeverityError; } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { if ((EFI_D_INFO & DebugPrintErrorLevel) == 0) { return EFI_SUCCESS; } // // Print PROGRESS information into output buffer. // CharCount = AsciiSPrint ( Buffer, sizeof (Buffer), "PROGRESS CODE: V%08x I%x\n\r", Value, Instance ); TraceHubSeverityLevel = SeverityNormal; #if FixedPcdGetBool (PcdTraceHubCatalogEnable) == 1 TraceHubWriteCataLog64_0 (TraceHubSeverityLevel, Value); #endif } else { if ((EFI_D_INFO & DebugPrintErrorLevel) == 0) { return EFI_SUCCESS; } // // Code type is not defined. // CharCount = AsciiSPrint ( Buffer, sizeof (Buffer), "Undefined: C%08x:V%08x I%x\n\r", CodeType, Value, Instance ); TraceHubSeverityLevel = SeverityNone; } // // Call TraceHub Lib function to do print. // #if FixedPcdGetBool (PcdTraceHubCatalogEnable) == 0 TraceHubDebugWrite (TraceHubSeverityLevel, (UINT8 *) Buffer, CharCount); #endif // // If register an unregister function of gEfiEventExitBootServicesGuid, // then some log called in ExitBootServices() will be lost, // so unregister the handler after receive the value of exit boot service. // if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE && Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) { if (mTraceHubRegistered) { mTraceHubRscHandlerProtocol->Unregister (TraceHubStatusCodeReportWorker); } } return EFI_SUCCESS; } /** Register status code callback function only when Report Status Code protocol is installed. @param Event Event whose notification function is being invoked. @param Context Pointer to the notification function's context, which is always zero in current implementation. **/ VOID EFIAPI RegisterTraceHubBootTimeHandlers ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; Status = gBS->LocateProtocol ( &gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mTraceHubRscHandlerProtocol ); ASSERT_EFI_ERROR (Status); mTraceHubRscHandlerProtocol->Register (TraceHubStatusCodeReportWorker, TPL_HIGH_LEVEL); ASSERT_EFI_ERROR (Status); mTraceHubRegistered = TRUE; } /** Constructor function of RuntimeDxeTraceHubStatusCodeHandlerLib. This function allocates memory for extended status code data, caches the report status code service, and registers events. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. **/ EFI_STATUS EFIAPI RuntimeDxeTraceHubStatusCodeHandlerLibConstructor ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_EVENT RegisterStatusCodeHandlerEvent; VOID *Registration; if (!PcdGetBool (PcdStatusCodeUseTraceHub)) { return EFI_SUCCESS; } Status = gBS->LocateProtocol ( &gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mTraceHubRscHandlerProtocol ); if (!EFI_ERROR (Status)) { RegisterTraceHubBootTimeHandlers (NULL, NULL); } else { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RegisterTraceHubBootTimeHandlers, NULL, &RegisterStatusCodeHandlerEvent ); ASSERT_EFI_ERROR (Status); // // Register for protocol notifications on this event // Status = gBS->RegisterProtocolNotify ( &gEfiRscHandlerProtocolGuid, RegisterStatusCodeHandlerEvent, &Registration ); ASSERT_EFI_ERROR (Status); } return EFI_SUCCESS; }