alder_lake_bios/Oem/L05/FeatureCommon/InsydeL05ModulePkg/LegacyToEfiDxe/LegacyToEfiDxe.c

434 lines
12 KiB
C

/** @file
This driver is for providing the Legacy To Efi Services routines.
;******************************************************************************
;* Copyright (c) 2012 - 2018, 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 "LegacyToEfiDxe.h"
EFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS mOrgShadowAllLegacyOproms;
/**
Erase L"LegacyToEfi" Variable during Ready To Boot Event
@param Event ReadyToBootEvent
@param Context Context
**/
VOID
EFIAPI
EraseLegacyToEfiVariable (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT8 LegacyToEfi;
UINTN BufferSize;
Status = EFI_SUCCESS;
LegacyToEfi = 0;
BufferSize = sizeof (UINT8);
Status = gRT->GetVariable (
L"LegacyToEfi",
&gEfiGenericVariableGuid,
NULL,
&BufferSize,
&LegacyToEfi
);
if (!EFI_ERROR (Status) && LegacyToEfi == 1) {
//
// Clear the "LegacyToEfi" variable first
//
Status = gRT->SetVariable (
L"LegacyToEfi",
&gEfiGenericVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
0,
NULL
);
}
}
/**
Replace the LegacyBios->ShadowAllLegacyOproms function to hook Int10 that make sure No any display during LegacyToEfi boot
@param This Points to Legacy BIOS protocol
@param Context Context
@retval EFI_SUCCESS Dispatch LegacyRom success
@retval EFI_LOAD_ERROR Dispatch LegacyRom failure
**/
EFI_STATUS
BypassInt10 (
IN EFI_LEGACY_BIOS_PROTOCOL *This
)
{
EFI_STATUS Status;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
UINT8 *DummyRetOpCode;
UINT8 OpCode;
UINT32 *IdtArray;
UINT32 OrgInt10;
Status = EFI_LOAD_ERROR;
//
// Locate LegacyBios Protocol
//
Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios);
if (!EFI_ERROR (Status)) {
Status = LegacyBios->GetLegacyRegion (
LegacyBios,
1,
0,
1,
&DummyRetOpCode
);
if (!EFI_ERROR (Status)) {
//
// Fill in machine code for iret
//
OpCode = 0x0cf;
Status = LegacyBios->CopyLegacyRegion (
LegacyBios,
1,
DummyRetOpCode,
&OpCode
);
if (!EFI_ERROR (Status)) {
IdtArray = (UINT32 *) 0;
OrgInt10 = IdtArray[0x10];
//
// Hook Int10h
//
IdtArray[0x10] = (EFI_SEGMENT ((UINTN) DummyRetOpCode) << 16) | EFI_OFFSET ((UINTN) DummyRetOpCode);
Status = mOrgShadowAllLegacyOproms (LegacyBios);
LegacyBios->ShadowAllLegacyOproms = mOrgShadowAllLegacyOproms;
//
// Restore Int10h
//
IdtArray[0x10] = OrgInt10;
Status = EFI_SUCCESS;
}
}
}
return Status;
}
/**
This function is invoked when gEfiLegacyBiosProtocolGuid is installed
@retval EFI_SUCCESS Shadow All Legac OpRoms success
@retval Others An unexpected error occurred after locating gEfiLegacyBiosProtocolGuid Protocol
**/
EFI_STATUS
ShadowAllLegacyOpRomsCore (
)
{
EFI_STATUS Status;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios);
if (!EFI_ERROR (Status)) {
//
// Replace the LegacyBios->ShadowAllLegacyOproms function
//
mOrgShadowAllLegacyOproms = LegacyBios->ShadowAllLegacyOproms;
LegacyBios->ShadowAllLegacyOproms = BypassInt10;
}
return Status;
}
/**
This function is invoked when gEfiLegacyBiosProtocolGuid is installed
@param Event The triggered event.
@param Context Context for this event.
**/
VOID
EFIAPI
HookShadowAllLegacyOproms (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
Status = ShadowAllLegacyOpRomsCore ();
if (!EFI_ERROR (Status)) {
gBS->CloseEvent (Event);
}
}
/**
This function is invoked when gH2OBdsCpReadyToBootBeforeGuid is triggered
@param Event A pointer to the Event that triggered the callback.
@param Handle Checkpoint handle.
**/
STATIC
VOID
EFIAPI
LegacyToEfiCpHandler (
IN EFI_EVENT Event,
IN H2O_CP_HANDLE Handle
)
{
EFI_STATUS Status;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
BBS_TABLE *LocalBbsTable;
EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication;
UINT8 SmmCommBuffer[SMM_COMMUNICATE_HEADER_SIZE + sizeof (UINTN)];
EFI_SMM_COMMUNICATE_HEADER *SmmCommHeader;
UINTN *LegacyToEfiSmmData;
UINTN CommBufferSize;
LegacyBios = NULL;
LocalBbsTable = NULL;
SmmCommunication = NULL;
SmmCommHeader = NULL;
LegacyToEfiSmmData = NULL;
CommBufferSize = 0;
H2OCpUnregisterHandler (Handle);
Status = gBS->LocateProtocol (
&gEfiLegacyBiosProtocolGuid,
NULL,
&LegacyBios
);
if (EFI_ERROR (Status)) {
return;
}
LegacyBios->GetBbsInfo (
LegacyBios,
NULL,
NULL,
NULL,
&LocalBbsTable
);
//
// Trigger SMI for pass data to SMM instance
//
Status = gBS->LocateProtocol (
&gEfiSmmCommunicationProtocolGuid,
NULL,
(VOID **)&SmmCommunication
);
if (EFI_ERROR (Status)) {
return;
}
SmmCommHeader = (EFI_SMM_COMMUNICATE_HEADER *) SmmCommBuffer;
CommBufferSize = SMM_COMMUNICATE_HEADER_SIZE + sizeof (UINTN);
ZeroMem (SmmCommHeader, CommBufferSize);
CopyGuid (&SmmCommHeader->HeaderGuid , &gEfiL05LegacyToEfiCommunicationGuid);
LegacyToEfiSmmData = (UINTN *) SmmCommHeader->Data;
*LegacyToEfiSmmData = (UINTN) LocalBbsTable;
Status = SmmCommunication->Communicate (
SmmCommunication,
SmmCommHeader,
&CommBufferSize
);
return;
}
/**
This is the declaration of an EFI image entry point. This entry point is
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
both device drivers and bus drivers.
@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
EFIAPI
LegacyToEfiDxeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINT8 LegacyToEfi;
UINTN BufferSize;
VOID *HobPtr;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
EFI_EVENT LegacyBiosEvent;
VOID *Registration;
EFI_EVENT ReadyToBootEvent;
BOOLEAN IsLegacyToEfi;
H2O_CP_HANDLE CpHandle;
Registration = NULL;
IsLegacyToEfi = TRUE;
HobPtr = NULL;
LegacyBios = NULL;
CpHandle = NULL;
//
// Get Current Status of Legacy To EFI function
//
BufferSize = sizeof (UINT8);
Status = gRT->GetVariable (
L"LegacyToEfi",
&gEfiGenericVariableGuid,
NULL,
&BufferSize,
&LegacyToEfi
);
if (EFI_ERROR (Status) || LegacyToEfi != 1) {
return EFI_SUCCESS;
}
//
// Stop process of Legacy To EFI by Project decide in PEI or DXE phase
// Project neeed check System not Wake from cold boot(ex: power button, WOL, RTC wake..., etc).
//
HobPtr = GetNextGuidHob ((CONST EFI_GUID *) &gL05StopLegacyToEfiProcessGuid, GetHobList ());
Status = OemSvcStopLegacyToEfiProcess ();
if (HobPtr != NULL || Status == EFI_MEDIA_CHANGED) {
//
// Delete L"LegacyToEfi" & L"BootNext" variable to stop process of Legacy To EFI
//
Status = gRT->SetVariable (
L"LegacyToEfi",
&gEfiGenericVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
0,
NULL
);
Status = gRT->SetVariable (
L"BootNext",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
0,
NULL
);
return EFI_UNSUPPORTED;
}
//
// Replace the ShadowAllLegacyOproms function
//
Status = gBS->LocateProtocol (
&gEfiLegacyBiosProtocolGuid,
NULL,
(VOID **) &LegacyBios
);
if (!EFI_ERROR (Status)) {
ShadowAllLegacyOpRomsCore ();
} else {
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
HookShadowAllLegacyOproms,
NULL,
&LegacyBiosEvent
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->RegisterProtocolNotify (
&gEfiLegacyBiosProtocolGuid,
LegacyBiosEvent,
&Registration
);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Create ReadyToBoot to make sure the "LegacyToEfi" variable be erase
//
Status = EfiCreateEventReadyToBootEx (
TPL_CALLBACK,
EraseLegacyToEfiVariable,
NULL,
&ReadyToBootEvent
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Register notification on H2O_CP_LOW of gH2OBdsCpReadyToBootBeforeGuid event for pass BbsTable pointer to SMM instance
//
Status = H2OCpRegisterHandler (
&gH2OBdsCpReadyToBootBeforeGuid,
LegacyToEfiCpHandler,
H2O_CP_MEDIUM,
&CpHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// For HddPassword and OemBadgingSupportDxe module to check status of Legacy To EFI function
//
Status = gRT->SetVariable (
L"IsLegacyToEfi",
&gEfiGenericVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS,
sizeof (IsLegacyToEfi),
&IsLegacyToEfi
);
return EFI_SUCCESS;
}