legacybiosthunk.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 360 行
C
360 行
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
LegacyBiosThunk.c
Abstract:
--*/
#include "LegacyBiosThunk.h"
#include "CpuIa32.h"
#define EFI_CPU_EFLAGS_IF 0x200
EFI_LEGACY_8259_PROTOCOL *gLegacy8259 = NULL;
THUNK_CONTEXT mThunkContext;
EFI_LEGACY_BIOS_THUNK_PROTOCOL mLegacyBiosThunk = {
LegacyBiosInt86,
LegacyBiosFarCall86
};
EFI_DRIVER_ENTRY_POINT (InitializeLegacyBiosThunk)
EFI_STATUS
EFIAPI
InitializeLegacyBiosThunk (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Initialize the state information for the Simple CSM driver
Arguments:
ImageHandle of the loaded driver
Pointer to the System Table
Returns:
EFI_SUCCESS - thread can be successfully created
EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
EFI_DEVICE_ERROR - cannot create the thread
--*/
{
EFI_STATUS Status;
EFI_HANDLE Handle;
EfiInitializeDriverLib (ImageHandle, SystemTable);
//
// Find the Legacy8259 protocol.
//
Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &gLegacy8259);
ASSERT_EFI_ERROR (Status);
InitializeBiosIntCaller ();
//
// Install thunk protocol
//
Handle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiLegacyBiosThunkProtocolGuid,
&mLegacyBiosThunk,
NULL
);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
EFI_STATUS
GetFreeLegacyRegion (
IN OUT UINTN *LegacyRegionBase,
IN OUT UINTN *LegacyRegionLength
)
/*++
Routine Description:
Get a free Legacy Region.
Arguments:
LegacyRegionBase - return free legacy region base
LegacyRegionLength - on input, it means the minimal length request,
on output, it means the length required.
Returns:
EFI_SUCCESS - Find a free legacy region and return.
EFI_NOT_FOUND - Can not find a free legacy region.
--*/
{
EFI_PHYSICAL_ADDRESS PhysicalBase;
EFI_STATUS Status;
PhysicalBase = 0x100000;
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiACPIMemoryNVS,
EFI_SIZE_TO_PAGES(*LegacyRegionLength),
&PhysicalBase
);
if (EFI_ERROR(Status)) {
return Status;
}
*LegacyRegionBase = (UINTN)PhysicalBase;
return EFI_SUCCESS;
}
VOID
InitializeBiosIntCaller (
VOID
)
/*++
Routine Description:
Initialize call infrastructure to 16-bit BIOS code
Arguments:
NONE
Returns:
NONE
--*/
{
UINTN LegacyRegionBase;
UINTN LegacyRegionLength;
UINTN LegacyStackSize;
EFI_STATUS Status;
//
// Get LegacyRegion
//
LegacyRegionLength = AsmThunk16GetProperties (&LegacyStackSize);
LegacyRegionLength += LegacyStackSize;
Status = GetFreeLegacyRegion (&LegacyRegionBase, &LegacyRegionLength);
ASSERT_EFI_ERROR (Status);
//
// Prepare environment
//
AsmThunk16SetProperties (
&mThunkContext,
(VOID*)LegacyRegionBase,
LegacyRegionLength
);
return;
}
BOOLEAN
EFIAPI
LegacyBiosInt86 (
IN EFI_LEGACY_BIOS_THUNK_PROTOCOL *This,
IN UINT8 BiosInt,
IN EFI_IA32_REGISTER_SET *Regs
)
/*++
Routine Description:
Thunk to 16-bit real mode and execute a software interrupt with a vector
of BiosInt. Regs will contain the 16-bit register context on entry and
exit.
Arguments:
This - Protocol instance pointer.
BiosInt - Processor interrupt vector to invoke
Reg - Register contexted passed into (and returned) from thunk to
16-bit mode
Returns:
FALSE - Thunk completed, and there were no BIOS errors in the target code.
See Regs for status.
TRUE - There was a BIOS erro in the target code.
--*/
{
UINTN Status;
UINT32 Eflags;
IA32_REGISTER_SET ThunkRegSet;
BOOLEAN Ret;
Regs->X.Flags.Reserved1 = 1;
Regs->X.Flags.Reserved2 = 0;
Regs->X.Flags.Reserved3 = 0;
Regs->X.Flags.Reserved4 = 0;
Regs->X.Flags.IOPL = 3;
Regs->X.Flags.NT = 0;
Regs->X.Flags.IF = 1;
Regs->X.Flags.TF = 0;
Regs->X.Flags.CF = 0;
EfiCommonLibZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));
ThunkRegSet.E.EDI = Regs->E.EDI;
ThunkRegSet.E.ESI = Regs->E.ESI;
ThunkRegSet.E.EBP = Regs->E.EBP;
ThunkRegSet.E.EBX = Regs->E.EBX;
ThunkRegSet.E.EDX = Regs->E.EDX;
ThunkRegSet.E.ECX = Regs->E.ECX;
ThunkRegSet.E.EAX = Regs->E.EAX;
ThunkRegSet.E.DS = Regs->E.DS;
ThunkRegSet.E.ES = Regs->E.ES;
EfiCommonLibCopyMem (&(ThunkRegSet.E.EFLAGS), &(Regs->E.EFlags), sizeof (UINT32));
//
// The call to Legacy16 is a critical section to EFI
//
Eflags = EfiGetEflags ();
if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {
EfiDisableInterrupts ();
}
//
// Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
//
Status = gLegacy8259->SetMode (gLegacy8259, Efi8259LegacyMode, NULL, NULL);
ASSERT_EFI_ERROR (Status);
AsmThunk16Int86 (&mThunkContext, BiosInt, &ThunkRegSet, 0);
//
// Restore protected mode interrupt state
//
Status = gLegacy8259->SetMode (gLegacy8259, Efi8259ProtectedMode, NULL, NULL);
ASSERT_EFI_ERROR (Status);
//
// End critical section
//
if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {
EfiEnableInterrupts ();
}
Regs->E.EDI = ThunkRegSet.E.EDI;
Regs->E.ESI = ThunkRegSet.E.ESI;
Regs->E.EBP = ThunkRegSet.E.EBP;
Regs->E.EBX = ThunkRegSet.E.EBX;
Regs->E.EDX = ThunkRegSet.E.EDX;
Regs->E.ECX = ThunkRegSet.E.ECX;
Regs->E.EAX = ThunkRegSet.E.EAX;
Regs->E.SS = ThunkRegSet.E.SS;
Regs->E.CS = ThunkRegSet.E.CS;
Regs->E.DS = ThunkRegSet.E.DS;
Regs->E.ES = ThunkRegSet.E.ES;
EfiCommonLibCopyMem (&(Regs->E.EFlags), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));
Ret = (BOOLEAN) (Regs->E.EFlags.CF == 1);
return Ret;
}
BOOLEAN
EFIAPI
LegacyBiosFarCall86 (
IN EFI_LEGACY_BIOS_THUNK_PROTOCOL *This,
IN UINT16 Segment,
IN UINT16 Offset,
IN EFI_IA32_REGISTER_SET *Regs,
IN VOID *Stack,
IN UINTN StackSize
)
{
UINTN Status;
UINT32 Eflags;
IA32_REGISTER_SET ThunkRegSet;
BOOLEAN Ret;
Regs->X.Flags.Reserved1 = 1;
Regs->X.Flags.Reserved2 = 0;
Regs->X.Flags.Reserved3 = 0;
Regs->X.Flags.Reserved4 = 0;
Regs->X.Flags.IOPL = 3;
Regs->X.Flags.NT = 0;
Regs->X.Flags.IF = 1;
Regs->X.Flags.TF = 0;
Regs->X.Flags.CF = 0;
EfiCommonLibZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));
ThunkRegSet.E.EDI = Regs->E.EDI;
ThunkRegSet.E.ESI = Regs->E.ESI;
ThunkRegSet.E.EBP = Regs->E.EBP;
ThunkRegSet.E.EBX = Regs->E.EBX;
ThunkRegSet.E.EDX = Regs->E.EDX;
ThunkRegSet.E.ECX = Regs->E.ECX;
ThunkRegSet.E.EAX = Regs->E.EAX;
ThunkRegSet.E.DS = Regs->E.DS;
ThunkRegSet.E.ES = Regs->E.ES;
EfiCommonLibCopyMem (&(ThunkRegSet.E.EFLAGS), &(Regs->E.EFlags), sizeof (UINT32));
//
// The call to Legacy16 is a critical section to EFI
//
Eflags = EfiGetEflags ();
if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {
EfiDisableInterrupts ();
}
ThunkRegSet.E.CS = Segment;
ThunkRegSet.E.EIP = Offset;
//
// Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
//
Status = gLegacy8259->SetMode (gLegacy8259, Efi8259LegacyMode, NULL, NULL);
ASSERT_EFI_ERROR (Status);
AsmThunk16FarCall86 (&mThunkContext, &ThunkRegSet, 0);
//
// Restore protected mode interrupt state
//
Status = gLegacy8259->SetMode (gLegacy8259, Efi8259ProtectedMode, NULL, NULL);
ASSERT_EFI_ERROR (Status);
//
// End critical section
//
if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {
EfiEnableInterrupts ();
}
Regs->E.EDI = ThunkRegSet.E.EDI;
Regs->E.ESI = ThunkRegSet.E.ESI;
Regs->E.EBP = ThunkRegSet.E.EBP;
Regs->E.EBX = ThunkRegSet.E.EBX;
Regs->E.EDX = ThunkRegSet.E.EDX;
Regs->E.ECX = ThunkRegSet.E.ECX;
Regs->E.EAX = ThunkRegSet.E.EAX;
Regs->E.SS = ThunkRegSet.E.SS;
Regs->E.CS = ThunkRegSet.E.CS;
Regs->E.DS = ThunkRegSet.E.DS;
Regs->E.ES = ThunkRegSet.E.ES;
EfiCommonLibCopyMem (&(Regs->E.EFlags), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));
Ret = (BOOLEAN) (Regs->E.EFlags.CF == 1);
return Ret;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?