alder_lake_bios/Insyde/InsydeModulePkg/Universal/CommonPolicy/CommonSmiCallBackSmm/CommonSmiCallBackSmm.c

255 lines
7.4 KiB
C

/** @file
It register callbacks for common Sw or Sx(s3/S4).
;******************************************************************************
;* Copyright (c) 2012 - 2018, 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 "CommonSmiCallBackSmm.h"
BOOLEAN mLegacyBoot = FALSE;
/**
SMM Legacy boot callback to indicate gLegacyBootProtocolGuid event is signaled
@retval EFI_SUCCESS: Locate EFI_SMM_SW_DISPATCH2_PROTOCOL success
@retval Others EFI_SMM_SW_DISPATCH2_PROTOCOL not installed
**/
STATIC
EFI_STATUS
EFIAPI
SmmLegacyBootCallback (
IN CONST EFI_GUID *Protocol,
IN VOID *Interface,
IN EFI_HANDLE Handle
)
{
mLegacyBoot = TRUE;
return EFI_SUCCESS;
}
/**
The driver's entry point.
It register callbacks for common Sw or Sx(s3/S4).
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
@retval Others Some error occurs when executing this entry point.
**/
EFI_STATUS
EFIAPI
CommonSmiInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE WakeOnAcLossHandle;
EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch2;
EFI_SMM_SX_REGISTER_CONTEXT EntryDispatchContext2;
VOID *LegacyBootRegistration;
//
// Get the Sx dispatch2 protocol
//
Status = gSmst->SmmLocateProtocol (&gEfiSmmSxDispatch2ProtocolGuid, NULL, (VOID **)&SxDispatch2);
if (!EFI_ERROR(Status)) {
EntryDispatchContext2.Type = SxS4;
EntryDispatchContext2.Phase = SxEntry;
Status = SxDispatch2->Register (
SxDispatch2,
S4SleepEntryCallBack2,
&EntryDispatchContext2,
&WakeOnAcLossHandle
);
if (EFI_ERROR(Status)) {
return Status;
}
}
Status = gSmst->SmmRegisterProtocolNotify (
&gEdkiiSmmLegacyBootProtocolGuid,
SmmLegacyBootCallback,
&LegacyBootRegistration
);
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
Change the BBS index to Boot current when legacy boot
@retval 0xff Failed
@retval Others Boot current value
**/
UINT8
GetBootCurrent (
VOID
)
{
UINTN OptionOrderSize;
UINT16 *OptionOrder;
UINT16 PriorityIndex;
CHAR16 BootOption[10];
UINT8 *Ptr;
UINT8 *BootOptionVar;
UINT8 CmosData;
UINT16 DevPathSize;
CHAR16 *BootDesc;
UINT8 BootCurrentValue;
UINT16 BbsIndex;
OptionOrderSize = 0;
OptionOrder = NULL;
CommonGetVariableDataAndSize (
L"BootOrder",
&gEfiGlobalVariableGuid,
&OptionOrderSize,
(VOID **) &OptionOrder
);
if (OptionOrder == NULL) {
return INVALID;
}
BootCurrentValue = INVALID;
//
// Set BBS priority according OptionOrder variable
//
for (PriorityIndex = 0; PriorityIndex < OptionOrderSize / sizeof (UINT16); PriorityIndex++) {
UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionOrder[PriorityIndex]);
BootOptionVar = CommonGetVariableData (BootOption, &gEfiGlobalVariableGuid);
if (BootOptionVar == NULL) {
break;
}
//
// Skip the native boot options(EFI shell...)
//
Ptr = BootOptionVar + sizeof(UINT32) + sizeof(UINT16) + StrSize ((CHAR16 *)(BootOptionVar + 6));
if (*Ptr != BBS_DEVICE_PATH) {
FreePool (BootOptionVar);
continue;
}
Ptr = BootOptionVar;
Ptr += sizeof (UINT32);
DevPathSize = *((UINT16 *) Ptr);
Ptr += sizeof (UINT16);
BootDesc = (CHAR16*) Ptr;
Ptr += StrSize (BootDesc);
Ptr += DevPathSize;
Ptr += sizeof (BBS_TABLE);
BbsIndex = *((UINT16 *) Ptr);
FreePool (BootOptionVar);
//
// Change BBS index to boot current
//
CmosData = ReadCmos8 (LastBootDevice);
if (CmosData == (UINT8) BbsIndex) {
//
// Save boot current to CMOS
//
BootCurrentValue = (UINT8) OptionOrder[PriorityIndex];
break;
}
}
FreePool (OptionOrder);
return BootCurrentValue;
}
/**
Check whether is Legacy boot
@retval VALUE Legacy boot
@retval 0xFF UEFI boot or invalid's boot option
**/
UINT8
SaveLastBootDevice (
VOID
)
{
UINT32 *BootTablePtr;
//
// If legacy boot event isn't signaled, it indicates system boots from UEFI boot option.
// In this case, return INVALID directly.
// This check condition can prevent from accessing EfiConventionalMemory type memory in
// SMM and cause CPU exception if copper point feature is enabled.
//
if (!mLegacyBoot) {
return INVALID;
}
if ((BDA(BDA_MEMORY_SIZE_OFFSET) == 0xFFFF) || (BDA(BDA_MEMORY_SIZE_OFFSET) == 0)) {
//
// Class 3 Bios
//
return INVALID;
}
//
// Check whether BDA is valid (BDA offset 0x13(40:13) * 0x400 is equal EBDA address)
//
if ((BOOLEAN)((BDA(BDA_MEMORY_SIZE_OFFSET) * 0x400) == (BDA(EXT_DATA_SEG_OFFSET) << 4))) {
//
// Check whether Boot table is valid
//
if ((EBDA(LEGACY_BOOT_TABLE_OFFSET) != 0xFFFF) &&
(EBDA(LEGACY_BOOT_TABLE_OFFSET) != 0) &&
(EBDA(LEGACY_BOOT_TABLE_OFFSET) >= EBDA_DEFAULT_SIZE)) {
BootTablePtr = (UINT32 *)(UINTN)((BDA(EXT_DATA_SEG_OFFSET) << 4) + EBDA(LEGACY_BOOT_TABLE_OFFSET));
if ((*BootTablePtr != 0xFFFFFFFF) && (*BootTablePtr != 0)) {
return GetBootCurrent();
}
}
}
return INVALID;
}
/**
S4 sleep entry callback for save boot current to CMOS using gEfiSmmSxDispatch2ProtocolGuid
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param[in] Context Points to an optional handler context which was specified when the
handler was registered.
@param[in, out] CommBuffer A pointer to a collection of data in memory that will
be conveyed from a non-SMM environment into an SMM environment.
@param[in, out] CommBufferSize The size of the CommBuffer.
@retval EFI_SUCCESS The S4 sleep entry callabck was handled successfully.
**/
EFI_STATUS
EFIAPI
S4SleepEntryCallBack2 (
IN EFI_HANDLE DispatchHandle,
IN CONST VOID *Context OPTIONAL,
IN OUT VOID *CommBuffer OPTIONAL,
IN OUT UINTN *CommBufferSize OPTIONAL
)
{
//
// Save Boot Current into offset 0x5f of CMOS if Legacy boot,
// else if UEFI boot then save value to 0xFF(that mean is invalid).
//
WriteCmos8 (LastBootDevice, SaveLastBootDevice());
return EFI_SUCCESS;
}