654 lines
20 KiB
C
654 lines
20 KiB
C
/** @file
|
|
BIOS Self-Healing SMM Driver.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2020, Insyde Software Corporation. 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 "BiosSelfHealingSmm.h"
|
|
|
|
EFI_SMM_CPU_PROTOCOL *mSmmCpu = NULL;
|
|
H2O_IHISI_PROTOCOL *mH2OIhisi = NULL;
|
|
|
|
STATIC IHISI_REGISTER_TABLE mFeatureFbtsRegisterTable[] = {
|
|
//
|
|
// AH=1Fh
|
|
//
|
|
{ FBTSApHookPoint, "S1FL05ApHookForBios", FbtsApHookForBios}
|
|
};
|
|
|
|
/**
|
|
Read information from the CPU save state.
|
|
|
|
@param Register Specifies the CPU register to read form the save state.
|
|
@param Width The number of bytes to read from the CPU save state.
|
|
@param CpuNum Specifies the zero-based index of the CPU save state.
|
|
@param RegisterData Upon return, this holds the CPU register value read from the save state.
|
|
|
|
@retval EFI_SUCCESS The register was read from Save State
|
|
@retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
|
|
@retval EFI_INVALID_PARAMTER This or Buffer is NULL.
|
|
**/
|
|
EFI_STATUS
|
|
ReadDwordRegister (
|
|
IN EFI_SMM_SAVE_STATE_REGISTER RegisterNum,
|
|
IN UINTN Width,
|
|
IN UINTN CpuNum,
|
|
OUT VOID *RegisterData
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = mSmmCpu->ReadSaveState (
|
|
mSmmCpu,
|
|
Width,
|
|
RegisterNum,
|
|
CpuNum,
|
|
RegisterData
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Write value to a CPU Save State register on the target processor.
|
|
|
|
This function abstracts the differences that whether the CPU Save State register is in the
|
|
IA32 CPU Save State Map or X64 CPU Save State Map.
|
|
|
|
This function supports writing a CPU Save State register in SMBase relocation handler.
|
|
|
|
@param RegisterNum Specifies the CPU register to write to the save state.
|
|
@param Width The number of bytes to read from the CPU save state.
|
|
@param CpuNum Specifies the zero-based index of the CPU save state.
|
|
@param RegisterData Upon entry, this holds the new CPU register value.
|
|
|
|
@retval EFI_SUCCESS The register was written to Save State.
|
|
@retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
|
|
@retval EFI_INVALID_PARAMTER ProcessorIndex or Width is not correct.
|
|
**/
|
|
EFI_STATUS
|
|
WriteDwordRegister (
|
|
IN EFI_SMM_SAVE_STATE_REGISTER RegisterNum,
|
|
IN UINTN Width,
|
|
IN UINTN CpuNum,
|
|
IN VOID *RegisterData
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = mSmmCpu->WriteSaveState (
|
|
mSmmCpu,
|
|
Width,
|
|
RegisterNum,
|
|
CpuNum,
|
|
RegisterData
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Check current BIOS capability of BIOS Self-Healing.
|
|
|
|
@param None
|
|
|
|
@retval ReturnStatus Current support capabilities.
|
|
**/
|
|
UINT32
|
|
CheckCapability (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 ReturnStatus;
|
|
|
|
ReturnStatus = L05_BIOS_SELF_HEALING_FUNCTION_SUPPORTED;
|
|
ReturnStatus |= (PcdGetBool (PcdL05BiosSelfHealingEnable)) ? L05_BIOS_SELF_HEALING_FUNCTION_ENABLED : L05_BIOS_SELF_HEALING_FUNCTION_DISABLED;
|
|
|
|
return ReturnStatus;
|
|
}
|
|
|
|
/**
|
|
Set specific destruction flag.
|
|
|
|
@param None
|
|
|
|
@retval L05_BIOS_SELF_HEALING_FUNCTION_SUCCESSFUL Setup successful.
|
|
@retval L05_BIOS_SELF_HEALING_FUNCTION_FAILED Setup failed.
|
|
**/
|
|
UINT32
|
|
SetDestructionFlag (
|
|
IN UINT8 Flag
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 BiosSelfHealingFlag;
|
|
|
|
Status = EFI_SUCCESS;
|
|
BiosSelfHealingFlag = 0;
|
|
|
|
//
|
|
// Check destruction flag
|
|
//
|
|
Status = GetBiosSelfHealingFlag (&BiosSelfHealingFlag);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return L05_BIOS_SELF_HEALING_FUNCTION_FAILED;
|
|
}
|
|
|
|
if ((BiosSelfHealingFlag & Flag) == Flag) {
|
|
return L05_BIOS_SELF_HEALING_FUNCTION_SUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Set destruction flag
|
|
//
|
|
BiosSelfHealingFlag |= Flag;
|
|
|
|
Status = SetBiosSelfHealingFlag (BiosSelfHealingFlag);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return L05_BIOS_SELF_HEALING_FUNCTION_FAILED;
|
|
}
|
|
|
|
return L05_BIOS_SELF_HEALING_FUNCTION_SUCCESSFUL;
|
|
}
|
|
|
|
/**
|
|
Software SMI callback for verification tool.
|
|
|
|
@param CpuNum CPU number.
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BiosSelfHealingSmmCallback (
|
|
IN UINTN CpuNum
|
|
)
|
|
{
|
|
UINT32 ReturnStatus;
|
|
UINT32 Eax;
|
|
UINT32 Ebx;
|
|
|
|
ReturnStatus = L05_BIOS_SELF_HEALING_FUNCTION_FAILED;
|
|
Eax = 0;
|
|
Ebx = 0;
|
|
|
|
//
|
|
// Check function signature is valid or not
|
|
//
|
|
ReadDwordRegister (EFI_SMM_SAVE_STATE_REGISTER_RAX, sizeof (UINT32), CpuNum, &Eax);
|
|
|
|
if (Eax != L05_BIOS_SELF_HEALING_FUNCTION) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
ReadDwordRegister (EFI_SMM_SAVE_STATE_REGISTER_RBX, sizeof (UINT32), CpuNum, &Ebx);
|
|
|
|
switch (Ebx) {
|
|
|
|
case L05_BIOS_SELF_HEALING_CHECK_CAPABILITY:
|
|
ReturnStatus = CheckCapability ();
|
|
break;
|
|
|
|
case L05_BIOS_SELF_HEALING_DESTROY_BOOT_BLOCK:
|
|
//
|
|
// Can only be executed in manufacturing mode and function is enabled
|
|
//
|
|
if (IsManufacturingMode () && PcdGetBool (PcdL05BiosSelfHealingEnable)) {
|
|
ReturnStatus = SetDestructionFlag (L05_BIOS_SELF_HEALING_FLAG_DESTROY_BOOT_BLOCK);
|
|
}
|
|
break;
|
|
|
|
case L05_BIOS_SELF_HEALING_DESTROY_FVMAIN:
|
|
//
|
|
// Can only be executed in manufacturing mode and function is enabled
|
|
//
|
|
if (IsManufacturingMode () && PcdGetBool (PcdL05BiosSelfHealingEnable)) {
|
|
ReturnStatus = SetDestructionFlag (L05_BIOS_SELF_HEALING_FLAG_DESTROY_FVMAIN);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ReturnStatus = L05_BIOS_SELF_HEALING_FUNCTION_FAILED;
|
|
break;
|
|
}
|
|
|
|
WriteDwordRegister (EFI_SMM_SAVE_STATE_REGISTER_RAX, sizeof (UINT32), CpuNum, &ReturnStatus);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Check pending flags during POST and perform related actions.
|
|
|
|
@param None
|
|
|
|
@retval EFI_SUCCESS Successful operation.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
CheckPendingFlag (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SMM_FW_BLOCK_SERVICE_PROTOCOL *SmmFwb;
|
|
UINT8 BiosSelfHealingFlag;
|
|
BOOLEAN DestroyBootBlock;
|
|
BOOLEAN DestroyFvMain;
|
|
UINTN EraseBase;
|
|
UINTN EraseSize;
|
|
|
|
Status = EFI_SUCCESS;
|
|
SmmFwb = NULL;
|
|
BiosSelfHealingFlag = 0;
|
|
DestroyBootBlock = FALSE;
|
|
DestroyFvMain = FALSE;
|
|
EraseBase = 0;
|
|
EraseSize = 0;
|
|
|
|
Status = gSmst->SmmLocateProtocol (
|
|
&gEfiSmmFwBlockServiceProtocolGuid,
|
|
NULL,
|
|
&SmmFwb
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check destruction flag
|
|
//
|
|
Status = GetBiosSelfHealingFlag (&BiosSelfHealingFlag);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
DestroyBootBlock = ((BiosSelfHealingFlag & L05_BIOS_SELF_HEALING_FLAG_DESTROY_BOOT_BLOCK) == L05_BIOS_SELF_HEALING_FLAG_DESTROY_BOOT_BLOCK) ? TRUE : FALSE;
|
|
DestroyFvMain = ((BiosSelfHealingFlag & L05_BIOS_SELF_HEALING_FLAG_DESTROY_FVMAIN) == L05_BIOS_SELF_HEALING_FLAG_DESTROY_FVMAIN) ? TRUE : FALSE;
|
|
|
|
if (!DestroyBootBlock && !DestroyFvMain) {
|
|
//
|
|
// Flags are not set, just skip
|
|
//
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (DestroyBootBlock && IsManufacturingMode ()) {
|
|
#if (FixedPcdGet32 (PcdL05ChipsetName) == L05_CHIPSET_NAME_TIGERLAKE)
|
|
EraseBase = (UINTN) PcdGet32 (PcdFlashFvFspmBase);
|
|
EraseSize = (UINTN) (PcdGet32 (PcdFlashFvFspmSize) +
|
|
PcdGet32 (PcdFlashFvFsptSize) +
|
|
(UINT32)(PcdGet64 (PcdH2OFlashDeviceMapSize)) +
|
|
PcdGet32 (PcdFlashFvRecovery0Size));
|
|
#endif
|
|
#if (FixedPcdGet32 (PcdL05ChipsetName) == L05_CHIPSET_NAME_ALDERLAKE)
|
|
EraseBase = (UINTN) PcdGet32 (PcdFlashFvFspMBase);
|
|
EraseSize = (UINTN) (PcdGet32 (PcdFlashFvFspMSize) +
|
|
PcdGet32 (PcdFlashFvFspTSize) +
|
|
(UINT32)(PcdGet64 (PcdH2OFlashDeviceMapSize)) +
|
|
PcdGet32 (PcdFlashFvRecovery0Size));
|
|
#endif
|
|
#if (FixedPcdGet32 (PcdL05ChipsetName) == L05_CHIPSET_NAME_CEZANNE)
|
|
EraseBase = (UINTN) PcdGet32 (PcdFlashFvRecovery2PadBase);
|
|
EraseSize = (UINTN) PcdGet32 (PcdFlashFvRecovery2PadSize);
|
|
#endif
|
|
#if (FixedPcdGet32 (PcdL05ChipsetName) == L05_CHIPSET_NAME_REMBRANDT)
|
|
EraseBase = (UINTN) PcdGet32 (PcdFlashFvRecoveryBase);
|
|
EraseSize = (UINTN) PcdGet32 (PcdFlashFvRecoverySize);
|
|
#endif
|
|
Status = SmmFwb->EraseBlocks (
|
|
SmmFwb,
|
|
EraseBase,
|
|
&EraseSize
|
|
);
|
|
}
|
|
|
|
if (DestroyFvMain && IsManufacturingMode ()) {
|
|
EraseBase = (UINTN) PcdGet32 (PcdFlashFvMainBase);
|
|
EraseSize = (UINTN) PcdGet32 (PcdFlashFvMainSize);
|
|
Status = SmmFwb->EraseBlocks (
|
|
SmmFwb,
|
|
EraseBase,
|
|
&EraseSize
|
|
);
|
|
}
|
|
|
|
//
|
|
// Clear flags
|
|
//
|
|
if (DestroyBootBlock) {
|
|
BiosSelfHealingFlag &= ~L05_BIOS_SELF_HEALING_FLAG_DESTROY_BOOT_BLOCK;
|
|
}
|
|
|
|
if (DestroyFvMain) {
|
|
BiosSelfHealingFlag &= ~L05_BIOS_SELF_HEALING_FLAG_DESTROY_FVMAIN;
|
|
}
|
|
|
|
if (IsManufacturingMode ()) {
|
|
BiosSelfHealingFlag &= ~L05_BIOS_SELF_HEALING_FLAG_BACKUP_BLOCK_SYNCED;
|
|
}
|
|
|
|
Status = SetBiosSelfHealingFlag (BiosSelfHealingFlag);
|
|
|
|
if (!IsManufacturingMode ()) {
|
|
//
|
|
// Only clear flags if not in manufacturing mode to avoid false triggering
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// BIOS should notify EC to set WDT flag when using tool to simulate BootBlock crash
|
|
//
|
|
OemSvcNotifyEcToSetWdtFlag ();
|
|
|
|
#ifdef L05_BIOS_SELF_HEALING_TEST_ON_CRB
|
|
TopSwapSet (TRUE);
|
|
#endif
|
|
|
|
DEBUG ((DEBUG_INFO, "cold reset from %a()\n", __FUNCTION__));
|
|
|
|
ResetCold ();
|
|
|
|
//
|
|
// Waiting for reset
|
|
//
|
|
CpuDeadLoop ();
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Software SMI callback to clear Top Swap bit.
|
|
|
|
@param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
|
@param DispatchContext Points to an optional handler context which was specified when the
|
|
handler was registered.
|
|
@param CommBuffer A pointer to a collection of data in memory that will
|
|
be conveyed from a non-SMM environment into an SMM environment.
|
|
@param CommBufferSize The size of the CommBuffer.
|
|
|
|
@retval EFI_SUCCESS The interrupt was handled successfully.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisableTopSwapCallback (
|
|
IN EFI_HANDLE DispatchHandle,
|
|
IN CONST VOID *DispatchContext,
|
|
IN OUT VOID *CommBuffer OPTIONAL,
|
|
IN OUT UINTN *CommBufferSize OPTIONAL
|
|
)
|
|
{
|
|
TopSwapSet (FALSE);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
AH=1Fh Fbts Ap Hook For BIOS.
|
|
This callback function will be invoked several times during flash process.
|
|
|
|
@retval EFI_SUCCESS Success returns.
|
|
**/
|
|
EFI_STATUS
|
|
FbtsApHookForBios (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 BiosSelfHealingFlag;
|
|
UINT8 ApState;
|
|
|
|
Status = EFI_SUCCESS;
|
|
BiosSelfHealingFlag = 0;
|
|
ApState = (UINT8) mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX);
|
|
|
|
if (ApState == BeforeWriteRom) {
|
|
//
|
|
// [Lenovo BIOS Self-Healing Design Guidance Specification v1.9]
|
|
// 2.2 Detect
|
|
// When BIOS flash happened, before erase/write BIOS should notify EC to set flag (Wdt Flag should be keeped
|
|
// even EC power lost, such as stored in the EC EEPROM) to enable WDT.
|
|
//
|
|
DEBUG ((DEBUG_INFO, "BiosSelfHealingSmm: FbtsApHookForBios => Before write ROM\n"));
|
|
OemSvcNotifyEcToSetWdtFlag ();
|
|
|
|
#if (FixedPcdGet32 (PcdL05ChipsetName) != L05_CHIPSET_NAME_ALDERLAKE)
|
|
//
|
|
// Clear BackupBlockSynced Flag
|
|
//
|
|
Status = GetBiosSelfHealingFlag (&BiosSelfHealingFlag);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "BiosSelfHealingSmm: Clear BackupBlockSynced Flag\n"));
|
|
BiosSelfHealingFlag &= ~L05_BIOS_SELF_HEALING_FLAG_BACKUP_BLOCK_SYNCED;
|
|
Status = SetBiosSelfHealingFlag (BiosSelfHealingFlag);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Register IHISI sub function if SubFuncTable CmdNumber/AsciiFuncGuid define in PcdIhisiRegisterTable list.
|
|
|
|
@param SubFuncTable Pointer to ihisi register table.
|
|
@param TableCount SubFuncTable count
|
|
|
|
@retval EFI_SUCCESS Function succeeded.
|
|
@return Other Error occurred in this function.
|
|
**/
|
|
EFI_STATUS
|
|
RegisterIhisiSubFunction (
|
|
IN IHISI_REGISTER_TABLE *SubFuncTable,
|
|
IN UINT16 TableCount
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *PcdTable;
|
|
UINT8 PcdPriority;
|
|
UINT8 EndChar;
|
|
UINTN Index;
|
|
UINTN PcdCount;
|
|
UINTN PcdMaxCount;
|
|
UINTN SignatureSize;
|
|
BOOLEAN PcdFoundRegistered;
|
|
|
|
Status = EFI_SUCCESS;
|
|
PcdTable = NULL;
|
|
PcdPriority = 0;
|
|
EndChar = 0;
|
|
Index = 0;
|
|
PcdCount = 0;
|
|
PcdMaxCount = 0;
|
|
SignatureSize = 0;
|
|
PcdFoundRegistered = FALSE;
|
|
|
|
PcdTable = (UINT8 *) PcdGetPtr (PcdIhisiRegisterTable);
|
|
PcdMaxCount = FixedPcdGetPtrSize (PcdIhisiRegisterTable) / sizeof (UINT8);
|
|
|
|
if ((FixedPcdGetPtrSize (PcdIhisiRegisterTable) % sizeof (PCD_IHISI_REGISTER_TABLE)) != 0) {
|
|
DEBUG ((EFI_D_ERROR, "PcdIhisiRegisterTable of description not follow PCD_IHISI_REGISTER_TABLE definition, \
|
|
it may cause some of IHISI function register fail \n"));
|
|
}
|
|
|
|
for (Index = 0; Index < TableCount; Index ++) {
|
|
PcdCount = 0;
|
|
PcdPriority = 0x80;
|
|
PcdFoundRegistered = FALSE;
|
|
SignatureSize = AsciiStrLen (SubFuncTable[Index].FuncSignature);
|
|
|
|
//
|
|
// Calculate PCD of address to find 1. CmdNumber 2. FuncSignature 3. Priority
|
|
//
|
|
do {
|
|
if (SubFuncTable[Index].CmdNumber == *(PcdTable + PcdCount)) {
|
|
PcdCount++;
|
|
if (AsciiStrnCmp (SubFuncTable[Index].FuncSignature, (CHAR8 *) (PcdTable + PcdCount), SignatureSize) == 0) {
|
|
if (EndChar == *(PcdTable + PcdCount + SignatureSize)) {
|
|
PcdPriority = *(PcdTable + PcdCount + SignatureSize + 1);
|
|
PcdFoundRegistered = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
PcdCount++;
|
|
} while (PcdCount < PcdMaxCount);
|
|
|
|
if (PcdFoundRegistered) {
|
|
Status = mH2OIhisi->RegisterCommand (
|
|
SubFuncTable[Index].CmdNumber,
|
|
SubFuncTable[Index].IhisiFunction,
|
|
PcdPriority
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "IHISI command :0x%X, priority : 0x%X, that already has a registered function\n", SubFuncTable[Index].CmdNumber, PcdPriority));
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
BIOS Self-Healing SMM entry.
|
|
|
|
@param ImageHandle The firmware allocated handle for the UEFI image.
|
|
@param SystemTable A pointer to the EFI System Table.
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
BiosSelfHealingSmmEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_L05_SMM_SW_SMI_INTERFACE_PROTOCOL *L05SwSmiPtr;
|
|
EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
|
|
EFI_SMM_SW_REGISTER_CONTEXT SwContext;
|
|
EFI_HANDLE SwHandle;
|
|
IHISI_REGISTER_TABLE *SubFuncTable;
|
|
UINT16 TableCount;
|
|
|
|
Status = EFI_SUCCESS;
|
|
L05SwSmiPtr = NULL;
|
|
SwDispatch = NULL;
|
|
SwContext.SwSmiInputValue = 0;
|
|
SwHandle = NULL;
|
|
SubFuncTable = NULL;
|
|
TableCount = 0;
|
|
|
|
Status = gSmst->SmmLocateProtocol (
|
|
&gEfiSmmCpuProtocolGuid,
|
|
NULL,
|
|
&mSmmCpu
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gSmst->SmmLocateProtocol (
|
|
&gH2OIhisiProtocolGuid,
|
|
NULL,
|
|
&mH2OIhisi
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gSmst->SmmLocateProtocol (
|
|
&gEfiL05SmmSwSmiInterfaceProtocolGuid,
|
|
NULL,
|
|
&L05SwSmiPtr
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gSmst->SmmLocateProtocol (
|
|
&gEfiSmmSwDispatch2ProtocolGuid,
|
|
NULL,
|
|
&SwDispatch
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Register BIOS Self-Healing Software SMI callback
|
|
//
|
|
Status = L05SwSmiPtr->RegisterCallbackFunction (
|
|
L05SwSmiPtr,
|
|
L05_SECURITY_SW_SMI,
|
|
FeatureCallbackType,
|
|
BiosSelfHealingSmmCallback
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check if BIOS Self-Healing function is enabled or not
|
|
//
|
|
if (!PcdGetBool (PcdL05BiosSelfHealingEnable)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Check pending flags during POST and perform related actions
|
|
//
|
|
CheckPendingFlag ();
|
|
|
|
#ifdef L05_BIOS_SELF_HEALING_TEST_ON_CRB
|
|
//
|
|
// Register disable Top Swap Software SMI callback
|
|
//
|
|
SwContext.SwSmiInputValue = (UINTN) -1;
|
|
Status = SwDispatch->Register (
|
|
SwDispatch,
|
|
DisableTopSwapCallback,
|
|
&SwContext,
|
|
&SwHandle
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
PcdSet8S (PcdL05TopSwapDisableSwSmi, (UINT8) SwContext.SwSmiInputValue);
|
|
DEBUG ((DEBUG_INFO, "PcdL05TopSwapDisableSwSmi value: %x\n", PcdGet8 (PcdL05TopSwapDisableSwSmi)));
|
|
#endif
|
|
|
|
//
|
|
// Register IHISI Sub Function
|
|
//
|
|
SubFuncTable = mFeatureFbtsRegisterTable;
|
|
TableCount = sizeof (mFeatureFbtsRegisterTable) / sizeof (mFeatureFbtsRegisterTable[0]);
|
|
|
|
Status = RegisterIhisiSubFunction (SubFuncTable, TableCount);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|