UINTN mTimerVector = 0;\r
volatile EFI_CPU_INTERRUPT_HANDLER mTimerHandler = NULL;\r
EFI_LEGACY_8259_PROTOCOL *gLegacy8259 = NULL;\r
+THUNK_CONTEXT mThunkContext;\r
+#define EFI_CPU_EFLAGS_IF 0x200\r
\r
+VOID\r
+InitializeBiosIntCaller (\r
+ VOID\r
+ );\r
+ \r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosInt86 (\r
+ IN UINT8 BiosInt,\r
+ IN EFI_IA32_REGISTER_SET *Regs\r
+ );\r
+ \r
//\r
// The Cpu Architectural Protocol that this Driver produces\r
//\r
EFI_IA32_REGISTER_SET Regs;\r
UINT16 OriginalVideoMode = (UINT16) -1;\r
\r
- //\r
- // See if the Legacy BIOS Protocol is available\r
- //\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosThunkProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- return OriginalVideoMode;\r
- }\r
\r
//\r
// VESA SuperVGA BIOS - GET CURRENT VIDEO MODE\r
//\r
gBS->SetMem (&Regs, sizeof (Regs), 0);\r
Regs.X.AX = 0x4F03;\r
- LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ LegacyBiosInt86 (0x10, &Regs);\r
if (Regs.X.AX == 0x004F) {\r
OriginalVideoMode = Regs.X.BX;\r
} else {\r
//\r
gBS->SetMem (&Regs, sizeof (Regs), 0);\r
Regs.H.AH = 0x0F;\r
- LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ LegacyBiosInt86 (0x10, &Regs);\r
OriginalVideoMode = Regs.H.AL;\r
}\r
\r
gBS->SetMem (&Regs, sizeof (Regs), 0);\r
Regs.H.AH = 0x00;\r
Regs.H.AL = (UINT8) NewVideoMode;\r
- LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ LegacyBiosInt86 (0x10, &Regs);\r
\r
//\r
// VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA)\r
Regs.H.AH = 0x11;\r
Regs.H.AL = 0x14;\r
Regs.H.BL = 0;\r
- LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ LegacyBiosInt86 (0x10, &Regs);\r
} else {\r
//\r
// VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE\r
gBS->SetMem (&Regs, sizeof (Regs), 0);\r
Regs.X.AX = 0x4F02;\r
Regs.X.BX = NewVideoMode;\r
- LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ LegacyBiosInt86 (0x10, &Regs);\r
if (Regs.X.AX != 0x004F) {\r
DEBUG ((EFI_D_ERROR, "SORRY: Cannot set to video mode: 0x%04X!\n", NewVideoMode));\r
return (UINT16) -1;\r
InstallInterruptHandler (InterruptVector, SystemTimerHandler);\r
}\r
\r
+ InitializeBiosIntCaller();\r
+ \r
//\r
// Install CPU Architectural Protocol and the thunk protocol\r
//\r
return EFI_SUCCESS;\r
}\r
\r
+VOID\r
+InitializeBiosIntCaller (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 RealModeBufferSize;\r
+ UINT32 ExtraStackSize;\r
+ EFI_PHYSICAL_ADDRESS LegacyRegionBase;\r
+ \r
+ //\r
+ // Get LegacyRegion\r
+ //\r
+ AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize);\r
+\r
+ LegacyRegionBase = 0x100000;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES(RealModeBufferSize + ExtraStackSize + 200),\r
+ &LegacyRegionBase\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ mThunkContext.RealModeBuffer = (VOID*)(UINTN)LegacyRegionBase;\r
+ mThunkContext.RealModeBufferSize = EFI_PAGES_TO_SIZE (RealModeBufferSize);\r
+ mThunkContext.ThunkAttributes = 3;\r
+ AsmPrepareThunk16(&mThunkContext);\r
+ \r
+}\r
+\r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosInt86 (\r
+ IN UINT8 BiosInt,\r
+ IN EFI_IA32_REGISTER_SET *Regs\r
+ )\r
+{\r
+ UINTN Status;\r
+ UINTN Eflags;\r
+ IA32_REGISTER_SET ThunkRegSet;\r
+ BOOLEAN Ret;\r
+ UINT16 *Stack16;\r
+ \r
+ Regs->X.Flags.Reserved1 = 1;\r
+ Regs->X.Flags.Reserved2 = 0;\r
+ Regs->X.Flags.Reserved3 = 0;\r
+ Regs->X.Flags.Reserved4 = 0;\r
+ Regs->X.Flags.IOPL = 3;\r
+ Regs->X.Flags.NT = 0;\r
+ Regs->X.Flags.IF = 1;\r
+ Regs->X.Flags.TF = 0;\r
+ Regs->X.Flags.CF = 0;\r
+\r
+ ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));\r
+ ThunkRegSet.E.EDI = Regs->E.EDI;\r
+ ThunkRegSet.E.ESI = Regs->E.ESI;\r
+ ThunkRegSet.E.EBP = Regs->E.EBP;\r
+ ThunkRegSet.E.EBX = Regs->E.EBX;\r
+ ThunkRegSet.E.EDX = Regs->E.EDX;\r
+ ThunkRegSet.E.ECX = Regs->E.ECX;\r
+ ThunkRegSet.E.EAX = Regs->E.EAX;\r
+ ThunkRegSet.E.DS = Regs->E.DS;\r
+ ThunkRegSet.E.ES = Regs->E.ES;\r
+\r
+ CopyMem (&(ThunkRegSet.E.EFLAGS), &(Regs->E.EFlags), sizeof (UINT32));\r
+ \r
+ //\r
+ // The call to Legacy16 is a critical section to EFI\r
+ //\r
+ Eflags = AsmReadEflags ();\r
+ if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {\r
+ DisableInterrupts ();\r
+ }\r
+\r
+ //\r
+ // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.\r
+ //\r
+ Status = gLegacy8259->SetMode (gLegacy8259, Efi8259LegacyMode, NULL, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16));\r
+ Stack16 -= sizeof (ThunkRegSet.E.EFLAGS) / sizeof (UINT16);\r
+ CopyMem (Stack16, &ThunkRegSet.E.EFLAGS, sizeof (ThunkRegSet.E.EFLAGS));\r
+\r
+ ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12);\r
+ ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16;\r
+ ThunkRegSet.E.Eip = (UINT16)((UINT32 *)NULL)[BiosInt];\r
+ ThunkRegSet.E.CS = (UINT16)(((UINT32 *)NULL)[BiosInt] >> 16);\r
+ mThunkContext.RealModeState = &ThunkRegSet;\r
+ AsmThunk16 (&mThunkContext);\r
+\r
+ //\r
+ // Restore protected mode interrupt state\r
+ //\r
+ Status = gLegacy8259->SetMode (gLegacy8259, Efi8259ProtectedMode, NULL, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // End critical section\r
+ //\r
+ if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {\r
+ EnableInterrupts ();\r
+ }\r
+\r
+ Regs->E.EDI = ThunkRegSet.E.EDI; \r
+ Regs->E.ESI = ThunkRegSet.E.ESI; \r
+ Regs->E.EBP = ThunkRegSet.E.EBP; \r
+ Regs->E.EBX = ThunkRegSet.E.EBX; \r
+ Regs->E.EDX = ThunkRegSet.E.EDX; \r
+ Regs->E.ECX = ThunkRegSet.E.ECX; \r
+ Regs->E.EAX = ThunkRegSet.E.EAX;\r
+ Regs->E.SS = ThunkRegSet.E.SS;\r
+ Regs->E.CS = ThunkRegSet.E.CS; \r
+ Regs->E.DS = ThunkRegSet.E.DS; \r
+ Regs->E.ES = ThunkRegSet.E.ES;\r
+\r
+ CopyMem (&(Regs->E.EFlags), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));\r
+\r
+ Ret = (BOOLEAN) (Regs->E.EFlags.CF == 1);\r
+\r
+ return Ret;\r
+}\r