alder_lake_bios/Insyde/InsydeModulePkg/Universal/StatusCode/CmosStatusCodePei/CmosStatusCodePei.c

303 lines
9.0 KiB
C

/** @file
PEIM for Cmos Report Status Code
;******************************************************************************
;* Copyright (c) 2012, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "CmosStatusCodePei.h"
//
// module variables
//
EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnRscHandlerPpiList = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiRscHandlerPpiGuid,
RscHandlerPpiNotifyCallback
};
/**
Entry point of Cmos Status Code PEIM.
This function is the entry point of this DXE Status Code Driver.
It registers notify event for EFI_RSC_HANDLER_PROTOCOL installed.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
**/
EFI_STATUS
EFIAPI
CmosStatusCodePeiEntry (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
EFI_PEI_RSC_HANDLER_PPI *RscHandlerPpi;
//
// Shift Status Code saved in Cmos during the last time boot
//
ShiftDebugCodeInCmos ();
Status = PeiServicesLocatePpi (
&gEfiPeiRscHandlerPpiGuid,
0,
NULL,
(VOID **) &RscHandlerPpi
);
if (EFI_ERROR(Status)) {
//
// Notified when ReportStatusCodeRouter is ready.
//
return (*PeiServices)->NotifyPpi (PeiServices, &mNotifyOnRscHandlerPpiList);
}
//
// LocatePpi success, register StatusCodeReportWorker now
//
Status = RscHandlerPpi->Register (CmosStatusCodeReportWorker);
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
Decode status code value, and write to Cmos.
@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 is written to Cmos successfully.
**/
EFI_STATUS
EFIAPI
CmosStatusCodeReportWorker (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
IN CONST EFI_GUID *CallerId,
IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
)
{
EFI_STATUS Status;
UINT8 CodeValue;
UINT8 GroupValue;
if (Data == NULL) {
//
// The DebugInfo was not sent by PeiCore Dispatcher.
//
return EFI_SUCCESS;
}
//
// Progress or error code, Output to CMOS Offset 0x38 and 0x39
//
if (Value == (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN)) {
//
// Search in KernelDebugCodeTbl and ChipsetDebugCodeTbl
//
Status = SearchDebugCodeValue (Data, &CodeValue, &GroupValue);
if (!EFI_ERROR (Status)) {
WriteCmos8 (CurrentDebugGroup, GroupValue);
WriteCmos8 (CurrentDebugCode, CodeValue);
} else {
//
// Driver GUID is not found.
//
WriteCmos8 (CurrentDebugGroup, 0xFF);
WriteCmos8 (CurrentDebugCode, 0xFF);
}
} else if (Value == (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END)) {
//
// Reserve for expand.
//
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}
/**
Notification function for ReportStatusCode handler Protocol
This routine is the notification function for EFI_RSC_HANDLER_PROTOCOL
@param EFI_EVENT Event of the notification
@param Context not used in this function
@retval none
**/
EFI_STATUS
EFIAPI
RscHandlerPpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
EFI_STATUS Status;
EFI_PEI_RSC_HANDLER_PPI *RscHandlerPpi;
Status = PeiServicesLocatePpi (
&gEfiPeiRscHandlerPpiGuid,
0,
NULL,
(VOID **) &RscHandlerPpi
);
if (!EFI_ERROR(Status)) {
//
// Register the worker function to ReportStatusCodeRouter
//
Status = RscHandlerPpi->Register (CmosStatusCodeReportWorker);
}
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
Helper function to search the module guid in KernelDebugCodeTable and ChipsetDebugCodeTable.
The FileGuid of module is embedded in Data.
@param Data The ExtendedData sent by REPORT_STATUS_CODE_WITH_EXTENDED_DATA.
@param DebugCodeValue The pointer to the value of the DebugCode found.
@param DebugGroupValue The pointer to the value of the DebugGroup found.
@retval EFI_INVALID_PARAMETER Invalid file guid value.
@retval EFI_NOT_FOUND The module is not in the DebugCode tables.
@retval EFI_SUCCESS The module is found in the DebugCode table,
the DebugCode/DebugGroup values outputed successfully.
**/
EFI_STATUS
EFIAPI
SearchDebugCodeValue (
IN CONST EFI_STATUS_CODE_DATA *Data,
OUT UINT8 *DebugCodeValue,
OUT UINT8 *DebugGroupValue
)
{
EFI_DEVICE_HANDLE_EXTENDED_DATA *ExtendedDataPtr;
EFI_DEVICE_HANDLE_EXTENDED_DATA *DataPtr;
EFI_PEI_FILE_HANDLE FileHandle;
EFI_FV_FILE_INFO FvFileInfo;
UINT32 Index;
EFI_STATUS Status;
DEBUG_CODE_DATA *KernelDebugCodeTbl = NULL; //retrieved from Pcd
DEBUG_CODE_DATA *ChipsetDebugCodeTbl = NULL; //retrieved from Pcd
DEBUG_CODE_DATA EndEntry;
ZeroMem (&EndEntry, sizeof (DEBUG_CODE_DATA));
//
// The ExtendedData was sent by Dispatcher of PeiCore
//
ExtendedDataPtr = (EFI_DEVICE_HANDLE_EXTENDED_DATA *)Data;
DataPtr = (EFI_DEVICE_HANDLE_EXTENDED_DATA *)(&ExtendedDataPtr->Handle);
FileHandle = DataPtr->Handle;
//
// Use PeiServicesLib to get file info.
//
Status = PeiServicesFfsGetFileInfo (
FileHandle,
&FvFileInfo
);
if (EFI_ERROR (Status)) {
return Status;
}
KernelDebugCodeTbl = (DEBUG_CODE_DATA *)PcdGetPtr (PcdPeiKernelDebugCodeTable);
ChipsetDebugCodeTbl = (DEBUG_CODE_DATA *)PcdGetPtr (PcdPeiChipsetDebugCodeTable);
//
// Search the FileGuid in KernelDebugCodeTable and ChipsetDebugCodeTable
//
Status = EFI_NOT_FOUND;
//
// Search in KernelDebugCodeTbl
//
Index = 0;
while (CompareMem (&EndEntry, &KernelDebugCodeTbl[Index], sizeof (DEBUG_CODE_DATA)) != 0) {
if (CompareGuid (&FvFileInfo.FileName, (EFI_GUID *)&KernelDebugCodeTbl[Index].NameGuid)) {
*DebugCodeValue = KernelDebugCodeTbl[Index].DebugCode;
*DebugGroupValue = KernelDebugCodeTbl[Index].DebugGroup;
Status = EFI_SUCCESS;
return Status;
}
Index++;
}
//
// Search in ChipsetDebugCodeTbl
//
Index = 0;
while (CompareMem (&EndEntry, &ChipsetDebugCodeTbl[Index], sizeof (DEBUG_CODE_DATA)) != 0) {
if (CompareGuid (&FvFileInfo.FileName, (EFI_GUID *)&ChipsetDebugCodeTbl[Index].NameGuid)) {
*DebugCodeValue = ChipsetDebugCodeTbl[Index].DebugCode;
*DebugGroupValue = ChipsetDebugCodeTbl[Index].DebugGroup;
Status = EFI_SUCCESS;
return Status;
}
Index++;
}
return Status;
}
/**
Helper function to shift the DebugCode/DebugGroup written in Cmos during the last time boot.
@param none
@retval none
**/
VOID
ShiftDebugCodeInCmos (
VOID
)
{
//
// Shift the last Status Code written to Cmos in the last time boot.
// There are 8 bytes (0x38~0x3F) used to save the Status Code.
// Please refer to CmosLib.h.
//
WriteCmos8 (BackupDebugGroup3, ReadCmos8 (BackupDebugGroup2));
WriteCmos8 (BackupDebugCode3, ReadCmos8 (BackupDebugCode2));
WriteCmos8 (BackupDebugGroup2, ReadCmos8 (BackupDebugGroup1));
WriteCmos8 (BackupDebugCode2, ReadCmos8 (BackupDebugCode1));
WriteCmos8 (BackupDebugGroup1, ReadCmos8 (CurrentDebugGroup));
WriteCmos8 (BackupDebugCode1, ReadCmos8 (CurrentDebugCode));
}