832 lines
23 KiB
C
832 lines
23 KiB
C
/** @file
|
|
This driver is for providing the Legacy To Efi Services routines.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2019, 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 "LegacyToEfiSmm.h"
|
|
|
|
EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;
|
|
EFI_PHYSICAL_ADDRESS *mBootOrderBuffer;
|
|
EFI_PHYSICAL_ADDRESS *mBootOptionBuffer;
|
|
UINT8 mBBSIndex;
|
|
BOOLEAN mAllbootFailed = FALSE;
|
|
BBS_TABLE *mLocalBbsTable = NULL;
|
|
|
|
/**
|
|
This function is for getting variable data and size in SMM mode
|
|
|
|
@param Name Point to variable string name
|
|
@param VendorGuid Point to variable guid
|
|
@param VariableSize Point to Variable data size
|
|
|
|
@retval VOID Return point of variable data
|
|
**/
|
|
VOID *
|
|
SmmGetVariableAndSize (
|
|
IN CHAR16 *Name,
|
|
IN EFI_GUID *VendorGuid,
|
|
OUT UINTN *VariableSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN BufferSize;
|
|
VOID *Buffer;
|
|
|
|
Buffer = NULL;
|
|
|
|
//
|
|
// Pass in a zero size buffer to find the required buffer size.
|
|
//
|
|
BufferSize = 0;
|
|
Status = mSmmVariable->SmmGetVariable (
|
|
Name,
|
|
VendorGuid,
|
|
NULL,
|
|
&BufferSize,
|
|
Buffer
|
|
);
|
|
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
|
|
//
|
|
// Allocate the buffer to return
|
|
//
|
|
Status = gSmst->SmmAllocatePool (
|
|
EfiRuntimeServicesData,
|
|
BufferSize,
|
|
&Buffer
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return NULL;
|
|
}
|
|
|
|
ZeroMem (Buffer, BufferSize);
|
|
|
|
//
|
|
// Read variable into the allocated buffer.
|
|
//
|
|
Status = mSmmVariable->SmmGetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
BufferSize = 0;
|
|
gSmst->SmmFreePool (Buffer);
|
|
Buffer = NULL;
|
|
}
|
|
}
|
|
|
|
*VariableSize = BufferSize;
|
|
|
|
return Buffer;
|
|
}
|
|
|
|
/**
|
|
Check the Boot#### number of device is vaild or not
|
|
|
|
@param BootOptionNum The Boot device number in BootOrder variable
|
|
|
|
@retval TRUE This is valid EFI Boot Option.
|
|
@retval FALSE This is not valid EFI Boot Option (Legacy, Recovery, ...etc.).
|
|
**/
|
|
BOOLEAN
|
|
IsValidEfiBootOption (
|
|
IN UINT16 BootOptionNum
|
|
)
|
|
{
|
|
UINT16 BootOption[10];
|
|
UINT8 *BootOptionVar;
|
|
UINTN BootOptionSize;
|
|
UINT8 *BootOptionPtr;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
BOOLEAN IsValid;
|
|
CHAR16 *RecoverySystemNameString = L05_NOVO_RECOVERY_SYSTEM_NAME;
|
|
|
|
UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOptionNum);
|
|
|
|
BootOptionVar = SmmGetVariableAndSize (
|
|
BootOption,
|
|
&gEfiGlobalVariableGuid,
|
|
&BootOptionSize
|
|
);
|
|
|
|
if (BootOptionVar == NULL) {
|
|
|
|
//
|
|
// Boot Option is not exist
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
IsValid = TRUE;
|
|
|
|
BootOptionPtr = BootOptionVar;
|
|
BootOptionPtr += sizeof (UINT32);
|
|
BootOptionPtr += sizeof (UINT16);
|
|
|
|
//
|
|
// Check device name in Boot#### variable
|
|
//
|
|
if (StrSize (RecoverySystemNameString) == StrSize ((UINT16 *) BootOptionPtr) &&
|
|
CompareMem (RecoverySystemNameString, BootOptionPtr, StrSize (RecoverySystemNameString)) == 0x0) {
|
|
|
|
IsValid = FALSE;
|
|
}
|
|
|
|
BootOptionPtr += (UINTN) StrSize ((UINT16 *) BootOptionPtr);
|
|
|
|
//
|
|
// Check device path in Boot#### variable
|
|
//
|
|
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) BootOptionPtr;
|
|
|
|
if ((DevicePath->Type == BBS_DEVICE_PATH) && (DevicePath->SubType == BBS_BBS_DP)) {
|
|
|
|
IsValid = FALSE;
|
|
}
|
|
|
|
gSmst->SmmFreePool (BootOptionVar);
|
|
|
|
return IsValid;
|
|
}
|
|
|
|
/**
|
|
Find the next boot EFI Boot Option and set L"BootNext" variable
|
|
|
|
@retval TRUE Do LegacyToEfi feature that meaning is the next boot is EFI boot.
|
|
@retval FALSE Next boot is Legacy boot or this is last boot OS.
|
|
**/
|
|
BOOLEAN
|
|
IsSetBootNextVariable (
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN OptionOrderSize;
|
|
UINT16 *OptionOrder;
|
|
UINT16 PriorityIndex;
|
|
UINT16 BootOption[10];
|
|
UINT16 BootOrderNumber[10];
|
|
UINTN BootOptionSize;
|
|
UINT8 *BootOptionVar;
|
|
UINT8 *Ptr;
|
|
UINT16 DevPathSize;
|
|
CHAR16 *BootDesc;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevPath;
|
|
UINT16 BbsIndex;
|
|
UINT32 Attributes;
|
|
UINT16 BootNext;
|
|
UINT8 LegacyToEfi;
|
|
|
|
OptionOrderSize = 0x400;
|
|
OptionOrder = NULL;
|
|
BootOptionSize = 0x1000;
|
|
BootOptionVar = NULL;
|
|
Ptr = NULL;
|
|
DevPathSize = 0;
|
|
BootDesc = NULL;
|
|
DevPath = NULL;
|
|
BbsIndex = 0;
|
|
|
|
OptionOrder = (UINT16 *) (mBootOrderBuffer);
|
|
|
|
Status = mSmmVariable->SmmGetVariable (
|
|
L"BootOrder",
|
|
&gEfiGlobalVariableGuid,
|
|
&Attributes,
|
|
&OptionOrderSize,
|
|
(VOID *) OptionOrder
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Skip to set BootNext if only one boot option exist.
|
|
//
|
|
if ((OptionOrderSize / sizeof (UINT16)) == 1) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BootNext = 0xFFFF;
|
|
|
|
//
|
|
// Set BBS priority according OptionOrder variable
|
|
//
|
|
for (PriorityIndex = 0; PriorityIndex < OptionOrderSize / sizeof (UINT16); PriorityIndex++) {
|
|
|
|
ZeroMem ((VOID *) BootOption, sizeof (BootOption));
|
|
ZeroMem ((VOID *) BootOrderNumber, sizeof (BootOrderNumber));
|
|
StrCpyS (BootOption, (sizeof (BootOption) / sizeof (UINT16)), L"Boot");
|
|
UnicodeValueToStringS (BootOrderNumber, sizeof (BootOrderNumber), (PREFIX_ZERO | RADIX_HEX), OptionOrder[PriorityIndex], 4);
|
|
StrCatS (BootOption, (sizeof (BootOption) / sizeof (UINT16)), BootOrderNumber);
|
|
|
|
BootOptionVar = (UINT8 *) (mBootOptionBuffer);
|
|
BootOptionSize = 0x1000;
|
|
|
|
Status = mSmmVariable->SmmGetVariable (
|
|
BootOption,
|
|
&gEfiGlobalVariableGuid,
|
|
&Attributes,
|
|
&BootOptionSize,
|
|
(VOID *) BootOptionVar
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Ptr = BootOptionVar;
|
|
Ptr += sizeof (UINT32);
|
|
DevPathSize = *(UINT16 *) Ptr;
|
|
Ptr += sizeof (UINT16);
|
|
BootDesc = (CHAR16 *) Ptr;
|
|
Ptr += StrSize (BootDesc);
|
|
DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
|
|
|
|
//
|
|
// Skip the native boot options(EFI shell, Win8..)
|
|
//
|
|
if (DevPath->Type != BBS_DEVICE_PATH) {
|
|
continue;
|
|
}
|
|
|
|
Ptr += DevPathSize;
|
|
Ptr += sizeof (BBS_TABLE);
|
|
BbsIndex = *(UINT16 *) Ptr;
|
|
|
|
if (mBBSIndex == BbsIndex) {
|
|
BootNext = OptionOrder[PriorityIndex + 1];
|
|
|
|
if ((PriorityIndex + 1) >= (OptionOrderSize / sizeof (UINT16))) {
|
|
BootNext = OptionOrder[0];
|
|
}
|
|
|
|
if (IsValidEfiBootOption (BootNext)) {
|
|
|
|
//
|
|
// Boot next is valid EFI Boot Option
|
|
//
|
|
break;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Boot next is not valid EFI Boot Option
|
|
//
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (BootNext != 0xFFFF) {
|
|
|
|
Status = mSmmVariable->SmmSetVariable (
|
|
L"BootNext",
|
|
&gEfiGlobalVariableGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
sizeof (UINT16),
|
|
&BootNext
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// Set "LegacyToEfi" variable and do reset for boot next
|
|
//
|
|
LegacyToEfi = 1;
|
|
Status = mSmmVariable->SmmSetVariable (
|
|
L"LegacyToEfi",
|
|
&gEfiGenericVariableGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
sizeof (UINT8),
|
|
&LegacyToEfi
|
|
);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Update Legacy BBS Table
|
|
|
|
@param EfiToLegacy Next Legacy BootXXXX
|
|
**/
|
|
VOID
|
|
SetBootTableAttribute (
|
|
IN UINT16 *EfiToLegacy
|
|
)
|
|
{
|
|
UINTN OptionOrderSize;
|
|
UINT16 *OptionOrder;
|
|
UINT16 PriorityIndex;
|
|
UINT16 BootOption[10];
|
|
UINT16 BootOrderNumber[10];
|
|
UINTN BootOptionSize;
|
|
UINT8 *BootOptionVar;
|
|
UINT8 *Ptr;
|
|
UINT16 DevPathSize;
|
|
CHAR16 *BootDesc;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevPath;
|
|
UINT16 BbsIndex;
|
|
UINT8 *BootTablePtr;
|
|
UINT16 BootPriority;
|
|
|
|
OptionOrder = NULL;
|
|
BootOptionVar = NULL;
|
|
Ptr = NULL;
|
|
DevPathSize = 0;
|
|
BootDesc = NULL;
|
|
DevPath = NULL;
|
|
BbsIndex = 0;
|
|
BootPriority = 0;
|
|
|
|
if (mLocalBbsTable == NULL) {
|
|
return;
|
|
}
|
|
|
|
OptionOrder = SmmGetVariableAndSize (
|
|
L"BootOrder",
|
|
&gEfiGlobalVariableGuid,
|
|
&OptionOrderSize
|
|
);
|
|
|
|
//
|
|
// Set BBS priority according OptionOrder variable
|
|
//
|
|
for (PriorityIndex = 0; PriorityIndex < OptionOrderSize / sizeof (UINT16); PriorityIndex++) {
|
|
|
|
ZeroMem ((VOID *) BootOption, sizeof (BootOption));
|
|
ZeroMem ((VOID *) BootOrderNumber, sizeof (BootOrderNumber));
|
|
StrCpyS (BootOption, (sizeof (BootOption) / sizeof (UINT16)), L"Boot");
|
|
UnicodeValueToStringS (BootOrderNumber, sizeof (BootOrderNumber), (PREFIX_ZERO | RADIX_HEX), OptionOrder[PriorityIndex], 4);
|
|
StrCatS (BootOption, (sizeof (BootOption) / sizeof (UINT16)), BootOrderNumber);
|
|
|
|
BootOptionVar = NULL;
|
|
BootOptionVar = SmmGetVariableAndSize (
|
|
BootOption,
|
|
&gEfiGlobalVariableGuid,
|
|
&BootOptionSize
|
|
);
|
|
|
|
if (BootOptionVar == NULL) {
|
|
continue;
|
|
}
|
|
|
|
Ptr = BootOptionVar;
|
|
Ptr += sizeof (UINT32);
|
|
DevPathSize = *(UINT16 *) Ptr;
|
|
Ptr += sizeof (UINT16);
|
|
BootDesc = (CHAR16 *) Ptr;
|
|
Ptr += StrSize (BootDesc);
|
|
DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
|
|
|
|
//
|
|
// Skip the native boot options(EFI shell, Win8..)
|
|
//
|
|
if (DevPath->Type != BBS_DEVICE_PATH) {
|
|
gSmst->SmmFreePool (BootOptionVar);
|
|
continue;
|
|
}
|
|
|
|
Ptr += DevPathSize;
|
|
Ptr += sizeof (BBS_TABLE);
|
|
BbsIndex = *(UINT16 *) Ptr;
|
|
|
|
if (OptionOrder[PriorityIndex] != *EfiToLegacy) {
|
|
BootPriority = mLocalBbsTable[BbsIndex].BootPriority;
|
|
|
|
}
|
|
|
|
if (OptionOrder[PriorityIndex] == *EfiToLegacy) {
|
|
|
|
gSmst->SmmFreePool (BootOptionVar);
|
|
break;
|
|
}
|
|
|
|
if (BootPriority != 0) {
|
|
|
|
//
|
|
// Update Boot table attribute
|
|
//
|
|
BootTablePtr = (UINT8 *) (UINTN) ((BDA (0xe) << 4) + EBDA (0x180));
|
|
BootTablePtr = BootTablePtr + (BootPriority * 0x20);
|
|
*BootTablePtr |= ATTEMPED_BOOT;
|
|
}
|
|
|
|
gSmst->SmmFreePool (BootOptionVar);
|
|
}
|
|
|
|
gSmst->SmmFreePool (OptionOrder);
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Clear variable of EfiToLegacyBootNext, if varaible existed.
|
|
**/
|
|
VOID
|
|
EfiToLegacy (
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN OptionOrderSize;
|
|
UINT16 *EfiToLegacy;
|
|
|
|
EfiToLegacy = SmmGetVariableAndSize (
|
|
L"EfiToLegacyBootNext",
|
|
&gEfiGenericVariableGuid,
|
|
&OptionOrderSize
|
|
);
|
|
|
|
if (EfiToLegacy != NULL) {
|
|
|
|
SetBootTableAttribute (EfiToLegacy);
|
|
|
|
//
|
|
// Erase "EfiToLegacyBootNext" variable
|
|
//
|
|
Status = mSmmVariable->SmmSetVariable (
|
|
L"EfiToLegacyBootNext",
|
|
&gEfiGenericVariableGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
0,
|
|
EfiToLegacy
|
|
);
|
|
|
|
gSmst->SmmFreePool (EfiToLegacy);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Execute STANDBY_IMMEDIATE command by AtaPassThru protocol
|
|
|
|
@param None
|
|
|
|
@retval EFI_SUCCESS Success to finish hard disk spin down function
|
|
@retval Others Fail to execute hard disk spin down function
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HddSpinDownFunc (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_L05_HDD_SPINDOWN_PROTOCOL *L05HddSpindownProtocol;
|
|
|
|
L05HddSpindownProtocol = NULL;
|
|
|
|
Status = gSmst->SmmLocateProtocol (
|
|
&gEfiL05HddSpindownProtocolGuid,
|
|
NULL,
|
|
(VOID **) &L05HddSpindownProtocol
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = L05HddSpindownProtocol->HddSpinDownAllPort ();
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Calling this function causes a system-wide reset. This sets
|
|
all circuitry within the system to its initial state. This type of reset
|
|
is asynchronous to system operation and operates without regard to
|
|
cycle boundaries.
|
|
|
|
System reset should not return, if it returns, it means the system does
|
|
not support cold reset.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
ResetCold (
|
|
VOID
|
|
)
|
|
{
|
|
IoWrite8 (IO_RST_CNT, IO_RST_CNT_HARDRESET);
|
|
}
|
|
|
|
/**
|
|
INT15 Callback Routine. It contains several INT15 Services corresponding
|
|
to specific Function Number such as 0x5F49 for Backlight Brightness.
|
|
|
|
@param CpuRegs The structure containing CPU Registers (AX, BX, CX, DX etc.)
|
|
@param Context Context
|
|
**/
|
|
VOID
|
|
LegacyToEfiInt15HookCore (
|
|
IN OUT EFI_IA32_REGISTER_SET *CpuRegs,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
UINT32 Int15FunNum;
|
|
|
|
//
|
|
// GET THE INT15 FUNCTION NUMBER
|
|
//
|
|
Int15FunNum = (CpuRegs->X.AX & 0xFFFF);
|
|
|
|
if (!Int15FunNum) {
|
|
return;
|
|
}
|
|
|
|
if (Int15FunNum == INT19_HOOK_POINTS) {
|
|
|
|
//
|
|
// SWITCH CASE Used For Applying Different HOOK corresponding to the Function Number
|
|
//
|
|
switch (CpuRegs->X.BX) {
|
|
|
|
case INT19_ENTRY:
|
|
|
|
//
|
|
// wait check plicy......
|
|
//
|
|
if (mAllbootFailed) {
|
|
|
|
//
|
|
// To do : retry all boot devices (maybe set "L05Legacy2EFIEntry" to bypass display...)
|
|
//
|
|
//Status = gRT->SetVariable (
|
|
// L"L05Legacy2EFIEntry",
|
|
// &gL05UefiBootEntryListGuid,
|
|
// EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS |
|
|
// EFI_VARIABLE_NON_VOLATILE,
|
|
// 0,
|
|
// NULL
|
|
// );
|
|
HddSpinDownFunc ();
|
|
ResetCold ();
|
|
}
|
|
|
|
//
|
|
// Int19 entry
|
|
//
|
|
EfiToLegacy ();
|
|
break;
|
|
|
|
case BEFORE_BOOT_ENTRY:
|
|
|
|
//
|
|
// Before Boot entry
|
|
// AX = 9998h, BX= 1h, DL=Drive number (floppy:00, 01,... / HDD: 80h, 81h, .../ ODD: A0h, A1h,.../ BEV: 0FFh),DI = BBS index
|
|
//
|
|
mBBSIndex = (UINT8) CpuRegs->X.DI;
|
|
break;
|
|
|
|
case LEGACY_BOOT_FAILURE:
|
|
|
|
//
|
|
// Single Legacy Boot failure
|
|
// AX = 9998h, BX= 2h
|
|
//
|
|
if (IsSetBootNextVariable ()) {
|
|
HddSpinDownFunc ();
|
|
ResetCold ();
|
|
}
|
|
|
|
break;
|
|
|
|
case ALL_LEGACY_BOOT_FAILURE:
|
|
|
|
//
|
|
// All Legacy Boot failure
|
|
// AX = 9998h, BX= 3h
|
|
//
|
|
mAllbootFailed = TRUE;
|
|
break;
|
|
|
|
case BEFORE_BOOT_TO_OS:
|
|
|
|
//
|
|
// Before boot to OS (0x7c00)
|
|
// AX = 9998h, BX= 4h, DL=Drive number (floppy:00, 01,... / HDD: 80h, 81h, .../ ODD: A0h, A1h,.../ BEV: 0FFh),DI = BBS index
|
|
//
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
LegacyToEfi INT 15 Hook Core
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
SmmInt15ServiceCallbackCore (
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SMM_INT15_SERVICE_PROTOCOL *SmmInt15Service;
|
|
|
|
SmmInt15Service = NULL;
|
|
|
|
Status = gSmst->SmmLocateProtocol (&gEfiSmmInt15ServiceProtocolGuid, NULL, &SmmInt15Service);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Register the 0x9998 function for INT19 callback
|
|
//
|
|
Status = SmmInt15Service->InstallInt15ProtocolInterface (
|
|
SmmInt15Service,
|
|
INT19_HOOK_POINTS,
|
|
LegacyToEfiInt15HookCore,
|
|
NULL
|
|
);
|
|
|
|
if (Status == EFI_ALREADY_STARTED) {
|
|
|
|
//
|
|
// use new callback function to replace original one
|
|
//
|
|
Status = SmmInt15Service->ReinstallInt15ProtocolInterface (
|
|
SmmInt15Service,
|
|
INT19_HOOK_POINTS,
|
|
LegacyToEfiInt15HookCore,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Protocol notify function for gEfiSmmInt15ServiceProtocolGuid protocol
|
|
|
|
@param Protocol Points to the protocol's unique identifier.
|
|
@param Interface Points to the interface instance.
|
|
@param Handle The handle on which the interface was installed.
|
|
|
|
@return Status Code
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SmmInt15ServiceCallback (
|
|
IN CONST EFI_GUID *Protocol,
|
|
IN VOID *Interface,
|
|
IN EFI_HANDLE Handle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = SmmInt15ServiceCallbackCore ();
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
SMM communication handler.
|
|
This function is used to get some initial data from non-SMM environment.
|
|
|
|
@param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
|
@param RegisterContext 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 and quiesced. No other handlers
|
|
should still be called.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LegacyToEfiSmiHandler (
|
|
IN EFI_HANDLE DispatchHandle,
|
|
IN CONST VOID *RegisterContext,
|
|
IN OUT VOID *CommBuffer,
|
|
IN OUT UINTN *CommBufferSize
|
|
)
|
|
{
|
|
//
|
|
// If input is invalid, stop processing this SMI
|
|
//
|
|
if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
mLocalBbsTable = *((BBS_TABLE **) CommBuffer);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
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
|
|
LegacyToEfiSmmEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SMM_INT15_SERVICE_PROTOCOL *SmmInt15Service;
|
|
EFI_EVENT InstallLegacyToEfiSmmCallBackFunctionEvent;
|
|
EFI_HANDLE DispatchHandle;
|
|
|
|
SmmInt15Service = NULL;
|
|
|
|
Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **) &mSmmVariable);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Allocate the buffer for BootOrder Variable
|
|
//
|
|
Status = gSmst->SmmAllocatePool (
|
|
EfiRuntimeServicesData,
|
|
0x400,
|
|
&mBootOrderBuffer
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
ZeroMem ((VOID *) mBootOrderBuffer, 0x400);
|
|
|
|
//
|
|
// Allocate the buffer for Boot Option Variable
|
|
//
|
|
Status = gSmst->SmmAllocatePool (
|
|
EfiRuntimeServicesData,
|
|
EFI_PAGE_SIZE,
|
|
&mBootOptionBuffer
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
ZeroMem ((VOID *) mBootOptionBuffer, EFI_PAGE_SIZE);
|
|
|
|
Status = gSmst->SmmLocateProtocol (&gEfiSmmInt15ServiceProtocolGuid, NULL, &SmmInt15Service);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
|
|
Status = SmmInt15ServiceCallbackCore ();
|
|
|
|
} else {
|
|
|
|
Status = gSmst->SmmRegisterProtocolNotify (
|
|
&gEfiSmmInt15ServiceProtocolGuid,
|
|
SmmInt15ServiceCallback,
|
|
&InstallLegacyToEfiSmmCallBackFunctionEvent
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Register SMM communication handler
|
|
//
|
|
DispatchHandle = NULL;
|
|
Status = gSmst->SmiHandlerRegister (
|
|
LegacyToEfiSmiHandler,
|
|
&gEfiL05LegacyToEfiCommunicationGuid,
|
|
&DispatchHandle
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|