summaryrefslogtreecommitdiff
path: root/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf
diff options
context:
space:
mode:
Diffstat (limited to 'IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf')
-rw-r--r--IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c277
-rw-r--r--IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h102
-rw-r--r--IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i89
-rw-r--r--IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s524
-rw-r--r--IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c550
5 files changed, 1542 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c
new file mode 100644
index 0000000000..b6787ae0e7
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c
@@ -0,0 +1,277 @@
+/** @file
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+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.
+
+**/
+
+#include "LegacyBiosInterface.h"
+
+/**
+ Assign drive number to legacy HDD drives prior to booting an EFI
+ aware OS so the OS can access drives without an EFI driver.
+ Note: BBS compliant drives ARE NOT available until this call by
+ either shell or EFI.
+
+ @param This Protocol instance pointer.
+ @param BbsCount Number of BBS_TABLE structures
+ @param BbsTable List BBS entries
+
+ @retval EFI_SUCCESS Drive numbers assigned
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyBiosPrepareToBootEfi (
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ OUT UINT16 *BbsCount,
+ OUT BBS_TABLE **BbsTable
+ )
+{
+ //
+ // Shadow All Opion ROM
+ //
+ LegacyBiosShadowAllLegacyOproms (This);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ To boot from an unconventional device like parties and/or execute
+ HDD diagnostics.
+
+ @param This Protocol instance pointer.
+ @param Attributes How to interpret the other input parameters
+ @param BbsEntry The 0-based index into the BbsTable for the
+ parent device.
+ @param BeerData Pointer to the 128 bytes of ram BEER data.
+ @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data.
+ The caller must provide a pointer to the specific
+ Service Area and not the start all Service Areas.
+ EFI_INVALID_PARAMETER if error. Does NOT return if no error.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyBiosBootUnconventionalDevice (
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UDC_ATTRIBUTES Attributes,
+ IN UINTN BbsEntry,
+ IN VOID *BeerData,
+ IN VOID *ServiceAreaData
+ )
+{
+ return EFI_INVALID_PARAMETER;
+}
+
+
+/**
+ Attempt to legacy boot the BootOption. If the EFI contexted has been
+ compromised this function will not return.
+
+ @param This Protocol instance pointer.
+ @param BbsDevicePath EFI Device Path from BootXXXX variable.
+ @param LoadOptionsSize Size of LoadOption in size.
+ @param LoadOptions LoadOption from BootXXXX variable
+
+ @retval EFI_SUCCESS Removable media not present
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyBiosLegacyBoot (
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN BBS_BBS_DEVICE_PATH *BbsDevicePath,
+ IN UINT32 LoadOptionsSize,
+ IN VOID *LoadOptions
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Build the E820 table.
+
+ @param Private Legacy BIOS Instance data
+ @param Size Size of E820 Table
+
+ @retval EFI_SUCCESS It should always work.
+
+**/
+EFI_STATUS
+LegacyBiosBuildE820 (
+ IN LEGACY_BIOS_INSTANCE *Private,
+ OUT UINTN *Size
+ )
+{
+ *Size = 0;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get all BBS info
+
+ @param This Protocol instance pointer.
+ @param HddCount Number of HDD_INFO structures
+ @param HddInfo Onboard IDE controller information
+ @param BbsCount Number of BBS_TABLE structures
+ @param BbsTable List BBS entries
+
+ @retval EFI_SUCCESS Tables returned
+ @retval EFI_NOT_FOUND resource not found
+ @retval EFI_DEVICE_ERROR can not get BBS table
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyBiosGetBbsInfo (
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ OUT UINT16 *HddCount,
+ OUT HDD_INFO **HddInfo,
+ OUT UINT16 *BbsCount,
+ OUT BBS_TABLE **BbsTable
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Fill in the standard BDA for Keyboard LEDs
+
+ @param This Protocol instance pointer.
+ @param Leds Current LED status
+
+ @retval EFI_SUCCESS It should always work.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyBiosUpdateKeyboardLedStatus (
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT8 Leds
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Relocate this image under 4G memory for IPF.
+
+ @param ImageHandle Handle of driver image.
+ @param SystemTable Pointer to system table.
+
+ @retval EFI_SUCCESS Image successfully relocated.
+ @retval EFI_ABORTED Failed to relocate image.
+
+**/
+EFI_STATUS
+RelocateImageUnder4GIfNeeded (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ UINTN NumberOfPages;
+ EFI_PHYSICAL_ADDRESS LoadedImageBase;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ EFI_PHYSICAL_ADDRESS MemoryAddress;
+ EFI_HANDLE NewImageHandle;
+
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID *) &LoadedImage
+ );
+
+ if (!EFI_ERROR (Status)) {
+ LoadedImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImage->ImageBase;
+ if (LoadedImageBase > 0xffffffff) {
+ NumberOfPages = (UINTN) (DivU64x32(LoadedImage->ImageSize, EFI_PAGE_SIZE) + 1);
+
+ //
+ // Allocate buffer below 4GB here
+ //
+ Status = AllocateLegacyMemory (
+ AllocateMaxAddress,
+ 0x7FFFFFFF,
+ NumberOfPages, // do we have to convert this to pages??
+ &MemoryAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+ ImageContext.Handle = (VOID *)(UINTN)LoadedImageBase;
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+
+ //
+ // Get information about the image being loaded
+ //
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)MemoryAddress;
+ //
+ // Align buffer on section boundry
+ //
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+ ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
+
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (MemoryAddress, NumberOfPages);
+ return Status;
+ }
+
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (MemoryAddress, NumberOfPages);
+ return Status;
+ }
+
+ //
+ // Create a new handle with gEfiCallerIdGuid to be used as the ImageHandle fore the reloaded image
+ //
+ NewImageHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewImageHandle,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+
+ //
+ // Flush the instruction cache so the image data is written before we execute it
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+
+ Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (MemoryAddress, NumberOfPages);
+ return Status;
+ }
+ //
+ // return error directly the BS will unload this image
+ //
+ return EFI_ABORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h
new file mode 100644
index 0000000000..26aa3a694b
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h
@@ -0,0 +1,102 @@
+/** @file
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+
+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.
+
+**/
+
+#ifndef _IPF_THUNK_H_
+#define _IPF_THUNK_H_
+
+#include "LegacyBiosInterface.h"
+#include <IndustryStandard/Sal.h>
+
+/**
+ Template of real mode code.
+
+ @param CodeStart Start address of code.
+ @param CodeEnd End address of code
+ @param ReverseThunkStart Start of reverse thunk.
+ @param IntThunk Low memory thunk.
+
+**/
+VOID
+RealModeTemplate (
+ OUT UINTN *CodeStart,
+ OUT UINTN *CodeEnd,
+ OUT UINTN *ReverseThunkStart,
+ LOW_MEMORY_THUNK *IntThunk
+ );
+
+/**
+ Register physical address of Esal Data Area
+
+ @param ReverseThunkCodeAddress Reverse Thunk Address
+ @param IntThunkAddress IntThunk Address
+
+ @retval EFI_SUCCESS ESAL data area set successfully.
+
+**/
+EFI_STATUS
+EsalSetSalDataArea (
+ IN UINTN ReverseThunkCodeAddress,
+ IN UINTN IntThunkAddress
+ );
+
+/**
+ Get address of reverse thunk.
+
+ @retval EFI_SAL_SUCCESS Address of reverse thunk returned successfully.
+
+**/
+SAL_RETURN_REGS
+EsalGetReverseThunkAddress (
+ VOID
+ );
+
+typedef struct {
+ UINT32 Eax; // 0
+ UINT32 Ecx; // 4
+ UINT32 Edx; // 8
+ UINT32 Ebx; // 12
+ UINT32 Esp; // 16
+ UINT32 Ebp; // 20
+ UINT32 Esi; // 24
+ UINT32 Edi; // 28
+ UINT32 Eflag; // 32
+ UINT32 Eip; // 36
+ UINT16 Cs; // 40
+ UINT16 Ds; // 42
+ UINT16 Es; // 44
+ UINT16 Fs; // 46
+ UINT16 Gs; // 48
+ UINT16 Ss; // 50
+} IPF_DWORD_REGS;
+
+/**
+ Entrypoint of IA32 code.
+
+ @param CallTypeData Data of call type
+ @param DwordRegister Register set of IA32 general registers
+ and segment registers
+ @param StackPointer Stack pointer.
+ @param StackSize Size of stack.
+
+**/
+VOID
+EfiIaEntryPoint (
+ UINT64 CallTypeData,
+ IPF_DWORD_REGS *DwordRegister,
+ UINT64 StackPointer,
+ UINT64 StackSize
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i
new file mode 100644
index 0000000000..441bb25e3d
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i
@@ -0,0 +1,89 @@
+//// @file
+//
+// Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+//
+// 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.
+//
+////
+
+#define NUM_REAL_GDT_ENTRIES 3
+#define LOW_STACK_SIZE (8*1024) // 8k?
+
+//
+// Low memory Thunk Structure
+//
+#define Code 0
+#define LowReverseThunkStart Code + 4096
+#define GdtDesc LowReverseThunkStart + 4
+#define IdtDesc GdtDesc + 6
+#define FlatSs IdtDesc + 6
+#define FlatEsp FlatSs + 4
+#define LowCodeSelector FlatEsp + 4
+#define LowDataSelector LowCodeSelector + 4
+#define LowStack LowDataSelector + 4
+#define RealModeIdtDesc LowStack + 4
+#define RealModeGdt RealModeIdtDesc + 6
+#define RealModeGdtDesc RealModeGdt + (8 * NUM_REAL_GDT_ENTRIES)
+#define RevRealDs RealModeGdtDesc + 6
+#define RevRealSs RevRealDs + 2
+#define RevRealEsp RevRealSs + 2
+#define RevRealIdtDesc RevRealEsp + 4
+#define RevFlatDataSelector RevRealIdtDesc + 6
+#define RevFlatStack RevFlatDataSelector + 2
+#define Stack RevFlatStack + 4
+#define RevThunkStack Stack + LOW_STACK_SIZE
+
+#define EfiToLegacy16InitTable RevThunkStack + LOW_STACK_SIZE
+#define InitTableBiosLessThan1MB EfiToLegacy16InitTable
+#define InitTableHiPmmMemory InitTableBiosLessThan1MB + 4
+#define InitTablePmmMemorySizeInBytes InitTableHiPmmMemory + 4
+#define InitTableReverseThunkCallSegment InitTablePmmMemorySizeInBytes + 4
+#define InitTableReverseThunkCallOffset InitTableReverseThunkCallSegment + 2
+#define InitTableNumberE820Entries InitTableReverseThunkCallOffset + 2
+#define InitTableOsMemoryAbove1Mb InitTableNumberE820Entries + 4
+#define InitTableThunkStart InitTableOsMemoryAbove1Mb + 4
+#define InitTableThunkSizeInBytes InitTableThunkStart + 4
+#define InitTable16InitTableEnd InitTableThunkSizeInBytes + 4
+
+#define EfiToLegacy16BootTable InitTable16InitTableEnd
+#define BootTableBiosLessThan1MB EfiToLegacy16BootTable
+#define BootTableHiPmmMemory BootTableBiosLessThan1MB + 4
+#define BootTablePmmMemorySizeInBytes BootTableHiPmmMemory + 4
+#define BootTableReverseThunkCallSegment BootTablePmmMemorySizeInBytes + 4
+#define BootTableReverseThunkCallOffset BootTableReverseThunkCallSegment + 2
+#define BootTableNumberE820Entries BootTableReverseThunkCallOffset + 2
+#define BootTableOsMemoryAbove1Mb BootTableNumberE820Entries + 4
+#define BootTableThunkStart BootTableOsMemoryAbove1Mb + 4
+#define BootTableThunkSizeInBytes BootTableThunkStart + 4
+#define EfiToLegacy16BootTableEnd BootTableThunkSizeInBytes + 4
+
+#define InterruptRedirectionCode EfiToLegacy16BootTableEnd
+#define PciHandler InterruptRedirectionCode + 32
+
+
+//
+// Register Sets (16 Bit)
+//
+
+#define AX 0
+#define BX 2
+#define CX 4
+#define DX 6
+#define SI 8
+#define DI 10
+#define Flags 12
+#define ES 14
+#define CS 16
+#define SS 18
+#define DS 20
+#define BP 22
+
+
+
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s
new file mode 100644
index 0000000000..d08f781319
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s
@@ -0,0 +1,524 @@
+//// @file
+//
+// Copyright (c) 1999 - 2008, Intel Corporation. All rights reserved.<BR>
+//
+// 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.
+//
+////
+
+.file "IpfThunk.s"
+
+#include "IpfMacro.i"
+#include "Ipf/IpfThunk.i"
+
+.align 0x10
+//-----------------------------------------------------------------------------
+//++
+// EfiIaEntryPoint
+//
+// Register physical address of Esal Data Area
+//
+// On Entry :
+// in1 = ptr to legacy bios reg
+// in2 = ptr to Call Stack
+// in3 = Call Stack Size
+//
+// Return Value:
+// r8 = SAL_SUCCESS
+//
+// As per static calling conventions.
+//
+//--
+//---------------------------------------------------------------------------
+PROCEDURE_ENTRY(EfiIaEntryPoint)
+
+ alloc loc0 = 8,10,8,0;;
+
+ mov out0 = r0;;
+ mov out1 = r0;;
+ mov out2 = r0;;
+ mov out3 = r0;;
+ mov out4 = r0;;
+ mov out5 = r0;;
+ mov out6 = r0;;
+ mov out7 = r0;;
+
+ mov loc1 = b0;; // save efi (b0)
+ mov loc2 = psr;; // save efi (PSR)
+ mov loc3 = gp;; // save efi (GP)
+ mov loc4 = pr;; // save efi (PR)
+ mov loc5 = sp;; // save efi (SP)
+ mov loc6 = r13;; // save efi (TP)
+ mov loc7 = ar.lc;; // save efi (LC)
+ mov loc8 = ar.fpsr;; // save efi (FPSR)
+
+ mov r8 = r0;; // return status
+ mov r9 = r0;; // return value
+ mov r10 = r0;; // return value
+ mov r11 = r0;; // return value
+
+bios_int_func::
+ rsm 0x4000;; // i(14)=0, disable interrupt
+ srlz.d;;
+ srlz.i;;
+
+//---------------------//
+// save fp registers //
+//---------------------//
+
+ dep sp = 0,sp,0,4;; // align 16
+ add sp = -16,sp;; // post decrement
+
+int_ip_1x::
+ mov r2 = ip;;
+ add r2 = (int_ip_1y - int_ip_1x),r2;;
+ mov b7 = r2;;
+ br save_fp_registers;;
+
+int_ip_1y::
+ add sp = 16,sp;; // adjust (SP)
+ mov loc9 = sp;; // save (SP)
+ adds sp = 0x10,in1;; // in1 + 0x10 = SP
+ ld4 sp = [sp];; // SP
+ adds r17 = 0x32,in1;; // in1 + 0x32 = SS
+ ld2 r17 = [r17];; // SS
+ movl r2 = 0xffffffff;; // if no SS:SP, then define new SS:SP
+ cmp.ne p6,p0 = sp,r2;;
+ movl r2 = 0xffff;;
+ cmp.ne.or p6,p0 = r17,r2;;
+ (p6) br.sptk bif_1;;
+
+ mov sp = in3;; // 16-bit stack pointer
+ mov r2 = psr;;
+ tbit.z p6,p7 = r2,17;; // psr.dt (Physical OR Virtual)
+
+bif_ip1x::
+ mov r2 = in2;; // ia32 callback stack top
+ mov r3 = in3;; // 16-bit stack pointer
+ sub r2 = r2,r3;;
+ shr.u r17 = r2,4;; // 16-bit stack segment
+
+bif_1::
+ extr.u sp = sp,0,16;; // SP (16-bit sp for legacy code)
+ dep sp = 0,sp,0,3;; // align 8
+ cmp.eq p6,p0 = 0,sp;; // if SP=0000 then wrap to 0x10000
+ (p6) dep sp = -1,sp,16,1;;
+ shladd r2 = r17,4,sp;; // ESP = SS<<4+SP
+ add r2 = -8,r2;; // post decrement 64 bit pointer
+ add sp = -8,sp;; // post decrement SP
+
+sale_ip1x::
+ mov r18 = ip;;
+ adds r18 = (sale_ip1y - sale_ip1x),r18;;
+ sub r18 = r18,r2;; // return address - CS base
+ add r18 = r18,sp;; // adjustment for stack
+ shl r18 = r18,32;;
+ movl r19 = 0xb80f66fa;; // CLI, JMPE xxxxxxxx
+ or r18 = r18,r19;;
+ st8 [r2] = r18;; // (FA,66,0F,B8,xx,xx,xx,xx)
+
+ cmp.eq p6,p0 = 0,sp;; // if SP=0000 then wrap to 0x10000
+ (p6) dep sp = -1,sp,16,1;;
+ shladd r2 = r17,4,sp;; // ESP=SS<<4+SP
+ add r2 = -2,r2;; // post decrement 64 bit pointer
+ add sp = -2,sp;; // post decrement SP
+
+ movl r18 = 0x8000000000000100;; // CALL FAR function
+ cmp.eq p6,p7 = in0,r18;;
+ (p6) add r19 = 0x28,in1;; // in1 + 0x28 = CS
+ (p6) ld2 r18 = [r19],-4;; // CS
+ (p6) st2 [r2] = r18,-2;; // in1 + 0x24 = EIP
+ (p6) ld2 r18 = [r19];; // EIP
+ (p6) st2 [r2] = r18,-2;; //
+ (p6) movl r18 = 0x9a90;; // nop, CALLFAR xxxx:yyyy
+
+ (p7) movl r18 = 0xcd;; // INT xx
+ (p7) dep r18 = in0,r18,8,8;;
+ st2 [r2] = r18;; // (CD,xx)
+
+ mov r18 = r2;; // EIP for legacy execution
+
+//------------------------------//
+// flush 32 bytes legacy code //
+//------------------------------//
+
+ dep r2 = 0,r2,0,5;; // align to 32
+ fc r2;;
+ sync.i;;
+ srlz.i;;
+ srlz.d;;
+
+//------------------------------//
+// load legacy registers //
+//------------------------------//
+ mov r2 = in1;; // IA32 BIOS register state
+ ld4 r8 = [r2],4;; // in1 + 0 = EAX
+ ld4 r9 = [r2],4;; // in1 + 4 = ECX
+ ld4 r10 = [r2],4;; // in1 + 8 = EDX
+ ld4 r11 = [r2],4;; // in1 + 12 = EBX
+
+ add r2 = 4,r2;; // in1 + 16 = ESP (skip)
+
+ ld4 r13 = [r2],4;; // in1 + 20 = EBP
+ ld4 r14 = [r2],4;; // in1 + 24 = ESI
+ ld4 r15 = [r2],4;; // in1 + 28 = EDI
+ ld4 r3 = [r2],4;; // in1 + 32 = EFLAGS
+ mov ar.eflag = r3;;
+
+ add r2 = 4,r2;; // in1 + 36 = EIP (skip)
+ add r2 = 2,r2;; // in1 + 40 = CS (skip)
+
+ ld2 r16 = [r2],2;; // in1 + 42 = DS, (r16 = GS,FS,ES,DS)
+ movl r27 = 0xc93fffff00000000;;
+ dep r27 = r16,r27,4,16;; // r27 = DSD
+
+ ld2 r19 = [r2],2;; // in1 + 44 = ES
+ dep r16 = r19,r16,16,16;;
+ movl r24 = 0xc93fffff00000000;;
+ dep r24 = r19,r24,4,16;; // r24 = ESD
+
+ ld2 r19 = [r2],2;; // in1 + 46 = FS
+ dep r16 = r19,r16,32,16;;
+ movl r28 = 0xc93fffff00000000;;
+ dep r28 = r19,r28,4,16;; // r28 = FSD
+
+ ld2 r19 = [r2],2;; // in1 + 48 = GS
+ dep r16 = r19,r16,48,16;;
+ movl r29 = 0xc93fffff00000000;;
+ dep r29 = r19,r29,4,16;; // r29 = GSD
+
+ mov r30 = r0;; // r30 = LDTD, clear NaT
+ mov r31 = r0;; // r31 = GDTD, clear NaT
+
+ dep r17 = r17,r17,16,16;; // CS = SS, (r17 = TSS,LDT,SS,CS)
+
+ movl r3 = 0x0930ffff00000000;;
+ dep r3 = r17,r3,4,16;;
+ mov ar.csd = r3;; // ar25 = CSD
+ mov ar.ssd = r3;; // ar26 = SSD
+
+//------------------------------//
+// give control to INT function //
+//------------------------------//
+
+ br.call.sptk b0 = execute_int_function;;
+
+//------------------------------//
+// store legacy registers //
+//------------------------------//
+
+ mov r2 = in1;;
+ st4 [r2] = r8,4;; // EAX
+ st4 [r2] = r9,4;; // ECX
+ st4 [r2] = r10,4;; // EDX
+ st4 [r2] = r11,4;; // EBX
+
+ add r2 = 4,r2;; // ESP (skip)
+
+ st4 [r2] = r13,4;; // EBP
+ st4 [r2] = r14,4;; // ESI
+ st4 [r2] = r15,4;; // EDI
+
+ mov r3 = ar.eflag;;
+ st4 [r2] = r3,4;; // EFLAGS
+
+ add r2 = 4,r2;; // EIP (skip)
+ add r2 = 2,r2;; // CS (skip)
+
+ st2 [r2] = r16,2;; // DS, (r16 = GS,FS,ES,DS)
+
+ extr.u r3 = r16,16,16;;
+ st2 [r2] = r3,2;; // ES
+
+ extr.u r3 = r16,32,16;;
+ st2 [r2] = r3,2;; // FS
+
+ extr.u r3 = r16,48,16;;
+ st2 [r2] = r3,2;; // GS
+
+//------------------------------//
+// restore fp registers //
+//------------------------------//
+ mov sp = loc9;; // restore (SP)
+int_ip_2x::
+ mov r2 = ip;;
+ add r2 = (int_ip_2y - int_ip_2x),r2;;
+ mov b7 = r2;;
+ br restore_fp_registers;;
+
+int_ip_2y::
+ mov r8 = r0;; // return status
+ mov r9 = r0;; // return value
+ mov r10 = r0;; // return value
+ mov r11 = r0;; // return value
+
+ mov ar.fpsr = loc8;; // restore efi (FPSR)
+ mov ar.lc = loc7;; // restore efi (LC)
+ mov r13 = loc6;; // restore efi (TP)
+ mov sp = loc5;; // restore efi (SP)
+ mov pr = loc4;; // restore efi (PR)
+ mov gp = loc3;; // restore efi (GP)
+ mov psr.l = loc2;; // restore efi (PSR)
+ srlz.d;;
+ srlz.i;;
+ mov b0 = loc1;; // restore efi (b0)
+ mov ar.pfs = loc0;;
+ br.ret.sptk b0;; // return to efi
+
+PROCEDURE_EXIT (EfiIaEntryPoint)
+
+//==============================//
+// EXECUTE_INT_FUNCTION //
+//==============================//
+// switch to virtual address //
+//------------------------------//
+
+execute_int_function::
+
+ alloc r2 = 0,0,0,0;; // cfm.sof=0
+ flushrs;;
+
+ rsm 0x2000;; // ic(13)=0 for control register programming
+ srlz.d;;
+ srlz.i;;
+
+ mov r2 = psr;;
+ dep r2 = -1,r2,34,1;; // set is(34)
+ dep r2 = -1,r2,44,1;; // set bn(44)
+ dep r2 = -1,r2,36,1;; // set it(36)
+ dep r2 = -1,r2,27,1;; // set rt(27)
+ dep r2 = -1,r2,17,1;; // set dt(17)
+ dep r2 = 0,r2,3,1;; // reset ac(3)
+ dep r2 = -1,r2,13,1;; // set ic(13)
+
+ mov cr.ipsr = r2;;
+ mov cr.ifs = r0;; // clear interruption function state register
+ mov cr.iip = r18;;
+
+ rfi;; // go to legacy code execution
+
+//------------------------------//
+// back from legacy code //
+//------------------------------//
+// switch to physical address //
+//------------------------------//
+
+sale_ip1y::
+ rsm 0x6000;; // i(14)=0,ic(13)=0 for control reg programming
+ srlz.d;;
+ srlz.i;;
+
+ mov r2 = psr;;
+ dep r2 = -1,r2,44,1;; // set bn(44)
+ dep r2 = 0,r2,36,1;; // reset it(36)
+ dep r2 = 0,r2,27,1;; // reset rt(27)
+ dep r2 = 0,r2,17,1;; // reset dt(17)
+ dep r2 = -1,r2,13,1;; // set ic(13)
+ mov cr.ipsr = r2;;
+
+sale_ip2x::
+ mov r2 = ip;;
+ add r2 = (sale_ip2y - sale_ip2x),r2;;
+ mov cr.ifs = r0;; // clear interruption function state register
+ mov cr.iip = r2;;
+ rfi;;
+
+sale_ip2y::
+ br.ret.sptk b0;; // return to SAL
+
+//------------------------------//
+// store fp registers //
+//------------------------------//
+save_fp_registers::
+ stf.spill [sp]=f2,-16;; stf.spill [sp]=f3,-16;;
+ stf.spill [sp]=f4,-16;; stf.spill [sp]=f5,-16;; stf.spill [sp]=f6,-16;; stf.spill [sp]=f7,-16;;
+ stf.spill [sp]=f8,-16;; stf.spill [sp]=f9,-16;; stf.spill [sp]=f10,-16;; stf.spill [sp]=f11,-16;;
+ stf.spill [sp]=f12,-16;; stf.spill [sp]=f13,-16;; stf.spill [sp]=f14,-16;; stf.spill [sp]=f15,-16;;
+ stf.spill [sp]=f16,-16;; stf.spill [sp]=f17,-16;; stf.spill [sp]=f18,-16;; stf.spill [sp]=f19,-16;;
+ stf.spill [sp]=f20,-16;; stf.spill [sp]=f21,-16;; stf.spill [sp]=f22,-16;; stf.spill [sp]=f23,-16;;
+ stf.spill [sp]=f24,-16;; stf.spill [sp]=f25,-16;; stf.spill [sp]=f26,-16;; stf.spill [sp]=f27,-16;;
+ stf.spill [sp]=f28,-16;; stf.spill [sp]=f29,-16;; stf.spill [sp]=f30,-16;; stf.spill [sp]=f31,-16;;
+ stf.spill [sp]=f32,-16;; stf.spill [sp]=f33,-16;; stf.spill [sp]=f34,-16;; stf.spill [sp]=f35,-16;;
+ stf.spill [sp]=f36,-16;; stf.spill [sp]=f37,-16;; stf.spill [sp]=f38,-16;; stf.spill [sp]=f39,-16;;
+ stf.spill [sp]=f40,-16;; stf.spill [sp]=f41,-16;; stf.spill [sp]=f42,-16;; stf.spill [sp]=f43,-16;;
+ stf.spill [sp]=f44,-16;; stf.spill [sp]=f45,-16;; stf.spill [sp]=f46,-16;; stf.spill [sp]=f47,-16;;
+ stf.spill [sp]=f48,-16;; stf.spill [sp]=f49,-16;; stf.spill [sp]=f50,-16;; stf.spill [sp]=f51,-16;;
+ stf.spill [sp]=f52,-16;; stf.spill [sp]=f53,-16;; stf.spill [sp]=f54,-16;; stf.spill [sp]=f55,-16;;
+ stf.spill [sp]=f56,-16;; stf.spill [sp]=f57,-16;; stf.spill [sp]=f58,-16;; stf.spill [sp]=f59,-16;;
+ stf.spill [sp]=f60,-16;; stf.spill [sp]=f61,-16;; stf.spill [sp]=f62,-16;; stf.spill [sp]=f63,-16;;
+ stf.spill [sp]=f64,-16;; stf.spill [sp]=f65,-16;; stf.spill [sp]=f66,-16;; stf.spill [sp]=f67,-16;;
+ stf.spill [sp]=f68,-16;; stf.spill [sp]=f69,-16;; stf.spill [sp]=f70,-16;; stf.spill [sp]=f71,-16;;
+ stf.spill [sp]=f72,-16;; stf.spill [sp]=f73,-16;; stf.spill [sp]=f74,-16;; stf.spill [sp]=f75,-16;;
+ stf.spill [sp]=f76,-16;; stf.spill [sp]=f77,-16;; stf.spill [sp]=f78,-16;; stf.spill [sp]=f79,-16;;
+ stf.spill [sp]=f80,-16;; stf.spill [sp]=f81,-16;; stf.spill [sp]=f82,-16;; stf.spill [sp]=f83,-16;;
+ stf.spill [sp]=f84,-16;; stf.spill [sp]=f85,-16;; stf.spill [sp]=f86,-16;; stf.spill [sp]=f87,-16;;
+ stf.spill [sp]=f88,-16;; stf.spill [sp]=f89,-16;; stf.spill [sp]=f90,-16;; stf.spill [sp]=f91,-16;;
+ stf.spill [sp]=f92,-16;; stf.spill [sp]=f93,-16;; stf.spill [sp]=f94,-16;; stf.spill [sp]=f95,-16;;
+ stf.spill [sp]=f96,-16;; stf.spill [sp]=f97,-16;; stf.spill [sp]=f98,-16;; stf.spill [sp]=f99,-16;;
+ stf.spill [sp]=f100,-16;;stf.spill [sp]=f101,-16;;stf.spill [sp]=f102,-16;;stf.spill [sp]=f103,-16;;
+ stf.spill [sp]=f104,-16;;stf.spill [sp]=f105,-16;;stf.spill [sp]=f106,-16;;stf.spill [sp]=f107,-16;;
+ stf.spill [sp]=f108,-16;;stf.spill [sp]=f109,-16;;stf.spill [sp]=f110,-16;;stf.spill [sp]=f111,-16;;
+ stf.spill [sp]=f112,-16;;stf.spill [sp]=f113,-16;;stf.spill [sp]=f114,-16;;stf.spill [sp]=f115,-16;;
+ stf.spill [sp]=f116,-16;;stf.spill [sp]=f117,-16;;stf.spill [sp]=f118,-16;;stf.spill [sp]=f119,-16;;
+ stf.spill [sp]=f120,-16;;stf.spill [sp]=f121,-16;;stf.spill [sp]=f122,-16;;stf.spill [sp]=f123,-16;;
+ stf.spill [sp]=f124,-16;;stf.spill [sp]=f125,-16;;stf.spill [sp]=f126,-16;;stf.spill [sp]=f127,-16;;
+ invala;;
+ br b7;;
+
+//------------------------------//
+// restore fp registers //
+//------------------------------//
+restore_fp_registers::
+ ldf.fill f127=[sp],16;;ldf.fill f126=[sp],16;;ldf.fill f125=[sp],16;;ldf.fill f124=[sp],16;;
+ ldf.fill f123=[sp],16;;ldf.fill f122=[sp],16;;ldf.fill f121=[sp],16;;ldf.fill f120=[sp],16;;
+ ldf.fill f119=[sp],16;;ldf.fill f118=[sp],16;;ldf.fill f117=[sp],16;;ldf.fill f116=[sp],16;;
+ ldf.fill f115=[sp],16;;ldf.fill f114=[sp],16;;ldf.fill f113=[sp],16;;ldf.fill f112=[sp],16;;
+ ldf.fill f111=[sp],16;;ldf.fill f110=[sp],16;;ldf.fill f109=[sp],16;;ldf.fill f108=[sp],16;;
+ ldf.fill f107=[sp],16;;ldf.fill f106=[sp],16;;ldf.fill f105=[sp],16;;ldf.fill f104=[sp],16;;
+ ldf.fill f103=[sp],16;;ldf.fill f102=[sp],16;;ldf.fill f101=[sp],16;;ldf.fill f100=[sp],16;;
+ ldf.fill f99=[sp],16;; ldf.fill f98=[sp],16;; ldf.fill f97=[sp],16;; ldf.fill f96=[sp],16;;
+ ldf.fill f95=[sp],16;; ldf.fill f94=[sp],16;; ldf.fill f93=[sp],16;; ldf.fill f92=[sp],16;;
+ ldf.fill f91=[sp],16;; ldf.fill f90=[sp],16;; ldf.fill f89=[sp],16;; ldf.fill f88=[sp],16;;
+ ldf.fill f87=[sp],16;; ldf.fill f86=[sp],16;; ldf.fill f85=[sp],16;; ldf.fill f84=[sp],16;;
+ ldf.fill f83=[sp],16;; ldf.fill f82=[sp],16;; ldf.fill f81=[sp],16;; ldf.fill f80=[sp],16;;
+ ldf.fill f79=[sp],16;; ldf.fill f78=[sp],16;; ldf.fill f77=[sp],16;; ldf.fill f76=[sp],16;;
+ ldf.fill f75=[sp],16;; ldf.fill f74=[sp],16;; ldf.fill f73=[sp],16;; ldf.fill f72=[sp],16;;
+ ldf.fill f71=[sp],16;; ldf.fill f70=[sp],16;; ldf.fill f69=[sp],16;; ldf.fill f68=[sp],16;;
+ ldf.fill f67=[sp],16;; ldf.fill f66=[sp],16;; ldf.fill f65=[sp],16;; ldf.fill f64=[sp],16;;
+ ldf.fill f63=[sp],16;; ldf.fill f62=[sp],16;; ldf.fill f61=[sp],16;; ldf.fill f60=[sp],16;;
+ ldf.fill f59=[sp],16;; ldf.fill f58=[sp],16;; ldf.fill f57=[sp],16;; ldf.fill f56=[sp],16;;
+ ldf.fill f55=[sp],16;; ldf.fill f54=[sp],16;; ldf.fill f53=[sp],16;; ldf.fill f52=[sp],16;;
+ ldf.fill f51=[sp],16;; ldf.fill f50=[sp],16;; ldf.fill f49=[sp],16;; ldf.fill f48=[sp],16;;
+ ldf.fill f47=[sp],16;; ldf.fill f46=[sp],16;; ldf.fill f45=[sp],16;; ldf.fill f44=[sp],16;;
+ ldf.fill f43=[sp],16;; ldf.fill f42=[sp],16;; ldf.fill f41=[sp],16;; ldf.fill f40=[sp],16;;
+ ldf.fill f39=[sp],16;; ldf.fill f38=[sp],16;; ldf.fill f37=[sp],16;; ldf.fill f36=[sp],16;;
+ ldf.fill f35=[sp],16;; ldf.fill f34=[sp],16;; ldf.fill f33=[sp],16;; ldf.fill f32=[sp],16;;
+ ldf.fill f31=[sp],16;; ldf.fill f30=[sp],16;; ldf.fill f29=[sp],16;; ldf.fill f28=[sp],16;;
+ ldf.fill f27=[sp],16;; ldf.fill f26=[sp],16;; ldf.fill f25=[sp],16;; ldf.fill f24=[sp],16;;
+ ldf.fill f23=[sp],16;; ldf.fill f22=[sp],16;; ldf.fill f21=[sp],16;; ldf.fill f20=[sp],16;;
+ ldf.fill f19=[sp],16;; ldf.fill f18=[sp],16;; ldf.fill f17=[sp],16;; ldf.fill f16=[sp],16;;
+ ldf.fill f15=[sp],16;; ldf.fill f14=[sp],16;; ldf.fill f13=[sp],16;; ldf.fill f12=[sp],16;;
+ ldf.fill f11=[sp],16;; ldf.fill f10=[sp],16;; ldf.fill f9=[sp],16;; ldf.fill f8=[sp],16;;
+ ldf.fill f7=[sp],16;; ldf.fill f6=[sp],16;; ldf.fill f5=[sp],16;; ldf.fill f4=[sp],16;;
+ ldf.fill f3=[sp],16;; ldf.fill f2=[sp],16;;
+ invala;;
+ br b7;;
+
+//-----------------------------------------------------------------------------
+//++
+// EsalSetSalDataArea
+//
+// Register physical address of Esal Data Area
+//
+// On Entry :
+// in0 = Reverse Thunk Address
+// in1 = IntThunk Address
+//
+// Return Value:
+// r8 = SAL_SUCCESS
+//
+// As per static calling conventions.
+//
+//--
+//---------------------------------------------------------------------------
+
+PROCEDURE_ENTRY (EsalSetSalDataArea)
+
+ NESTED_SETUP (4,8,0,0)
+
+EsalCalcStart1_3::
+ mov r8 = ip;;
+ add r8 = (ReverseThunkAddress - EsalCalcStart1_3), r8;;
+ st8 [r8] = in0;;
+
+EsalCalcStart1_4::
+ mov r8 = ip;;
+ add r8 = (IntThunkAddress - EsalCalcStart1_4), r8;;
+ st8 [r8] = in1;;
+
+ mov r8 = r0;;
+
+ NESTED_RETURN
+
+PROCEDURE_EXIT (EsalSetSalDataArea)
+
+//-----------------------------------------------------------------------------
+//++
+// EsagGetReverseThunkAddress
+//
+// Register physical address of Esal Data Area
+//
+// On Entry :
+// out0 = CodeStart
+// out1 = CodeEnd
+// out1 = ReverseThunkCode
+//
+// Return Value:
+// r8 = SAL_SUCCESS
+//
+// As per static calling conventions.
+//
+//--
+//---------------------------------------------------------------------------
+
+PROCEDURE_ENTRY (EsalGetReverseThunkAddress)
+
+ NESTED_SETUP (4,8,0,0)
+
+EsalCalcStart1_31::
+ mov r8 = ip;;
+ add r8 = (Ia32CodeStart - EsalCalcStart1_31), r8;;
+ mov r9 = r8;;
+
+EsalCalcStart1_41::
+ mov r8 = ip;;
+ add r8 = (Ia32CodeEnd - EsalCalcStart1_41), r8;;
+ mov r10 = r8;;
+
+EsalCalcStart1_51::
+ mov r8 = ip;;
+ add r8 = (ReverseThunkAddress - EsalCalcStart1_51), r8;;
+ mov r11 = r8;;
+ mov r8 = r0;;
+
+ NESTED_RETURN
+
+PROCEDURE_EXIT (EsalGetReverseThunkAddress)
+
+
+.align 16
+PROCEDURE_ENTRY (InterruptRedirectionTemplate)
+ data8 0x90CFCD08
+ data8 0x90CFCD09
+ data8 0x90CFCD0A
+ data8 0x90CFCD0B
+ data8 0x90CFCD0C
+ data8 0x90CFCD0D
+ data8 0x90CFCD0E
+ data8 0x90CFCD0F
+PROCEDURE_EXIT (InterruptRedirectionTemplate)
+
+//------------------------------//
+// Reverse Thunk Code //
+//------------------------------//
+
+Ia32CodeStart::
+ br.sptk.few Ia32CodeStart;; // IPF CSM integration -Bug (Write This Code)
+ReverseThunkCode::
+ data8 0xb80f66fa // CLI, JMPE xxxx
+ReverseThunkAddress::
+ data8 0 // Return Address
+IntThunkAddress::
+ data8 0 // IntThunk Address
+Ia32CodeEnd::
+
+
+
+
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c
new file mode 100644
index 0000000000..ca59b97ec4
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c
@@ -0,0 +1,550 @@
+/** @file
+ Call into 16-bit BIOS code
+
+ BugBug: Thunker does A20 gate. Can we get rid of this code or
+ put it into Legacy16 code.
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+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.
+
+**/
+
+#include "LegacyBiosInterface.h"
+#include "IpfThunk.h"
+
+/**
+ Gets the current flat GDT and IDT descriptors and store them in
+ Private->IntThunk. These values are used by the Thunk code.
+ This method must be called before every thunk in order to assure
+ that the correct GDT and IDT are restored after the thunk.
+
+ @param Private Private context for Legacy BIOS
+
+ @retval EFI_SUCCESS Should only pass.
+
+**/
+EFI_STATUS
+LegacyBiosGetFlatDescs (
+ IN LEGACY_BIOS_INSTANCE *Private
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ BIOS interrupt call function.
+
+ @param BiosInt Int number of BIOS call
+ @param Segment Segment number
+ @param Offset Offset in segment
+ @param Regs IA32 Register set.
+ @param Stack Base address of stack
+ @param StackSize Size of stack
+
+ @retval EFI_SUCCESS BIOS interrupt call succeeds.
+
+**/
+EFI_STATUS
+BiosIntCall (
+ IN UINT16 BiosInt,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN EFI_IA32_REGISTER_SET *Regs,
+ IN VOID *Stack,
+ IN UINTN StackSize
+ )
+{
+ IPF_DWORD_REGS DwordRegs;
+ UINT64 IntTypeVariable;
+
+ IntTypeVariable = 0x8000000000000000;
+ IntTypeVariable |= BiosInt;
+
+ DwordRegs.Cs = Segment;
+ DwordRegs.Eip = Offset;
+
+ DwordRegs.Ds = Regs->X.DS;
+ DwordRegs.Es = Regs->X.ES;
+ DwordRegs.Fs = Regs->X.ES;
+ DwordRegs.Gs = Regs->X.ES;
+ DwordRegs.Ss = 0xFFFF;
+
+ DwordRegs.Eax = Regs->X.AX;
+ DwordRegs.Ebx = Regs->X.BX;
+ //
+ // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, AX = B10Dh is
+ // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to write.
+ //
+ DwordRegs.Ecx = Regs->E.ECX;
+ DwordRegs.Edx = Regs->X.DX;
+
+ DwordRegs.Ebp = Regs->X.BP;
+ DwordRegs.Eflag = *((UINT16 *) &Regs->X.Flags);
+
+ DwordRegs.Edi = Regs->X.DI;
+ DwordRegs.Esi = Regs->X.SI;
+ DwordRegs.Esp = 0xFFFFFFFF;
+
+ EfiIaEntryPoint (IntTypeVariable, &DwordRegs, ((UINTN) Stack + StackSize), StackSize);
+
+ Regs->X.CS = DwordRegs.Cs;
+
+ Regs->X.DS = (UINT16) DwordRegs.Ds;
+ Regs->X.SS = (UINT16) DwordRegs.Ss;
+
+ Regs->E.EAX = DwordRegs.Eax;
+ Regs->E.EBX = DwordRegs.Ebx;
+ Regs->E.ECX = DwordRegs.Ecx;
+ Regs->E.EDX = DwordRegs.Edx;
+
+ Regs->E.EBP = DwordRegs.Ebp;
+ CopyMem (&Regs->X.Flags, &DwordRegs.Eflag, sizeof (EFI_FLAGS_REG));
+
+ Regs->E.EDI = DwordRegs.Edi;
+ Regs->E.ESI = DwordRegs.Esi;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Template of real mode code.
+
+ @param CodeStart Start address of code.
+ @param CodeEnd End address of code
+ @param ReverseThunkStart Start of reverse thunk.
+ @param IntThunk Low memory thunk.
+
+**/
+VOID
+RealModeTemplate (
+ OUT UINTN *CodeStart,
+ OUT UINTN *CodeEnd,
+ OUT UINTN *ReverseThunkStart,
+ LOW_MEMORY_THUNK *IntThunk
+ )
+{
+ SAL_RETURN_REGS SalStatus;
+
+ SalStatus = EsalGetReverseThunkAddress ();
+
+ *CodeStart = SalStatus.r9;
+ *CodeEnd = SalStatus.r10;
+ *ReverseThunkStart = SalStatus.r11;
+
+}
+
+
+/**
+ Allocate memory < 1 MB and copy the thunker code into low memory. Se up
+ all the descriptors.
+
+ @param Private Private context for Legacy BIOS
+
+ @retval EFI_SUCCESS Should only pass.
+
+**/
+EFI_STATUS
+LegacyBiosInitializeThunk (
+ IN LEGACY_BIOS_INSTANCE *Private
+ )
+{
+ GDT32 *CodeGdt;
+ GDT32 *DataGdt;
+ UINTN CodeStart;
+ UINTN CodeEnd;
+ UINTN ReverseThunkStart;
+ UINT32 Base;
+ LOW_MEMORY_THUNK *IntThunk;
+ UINTN TempData;
+
+ ASSERT (Private);
+
+ IntThunk = Private->IntThunk;
+
+ //
+ // Clear the reserved descriptor
+ //
+ ZeroMem (&(IntThunk->RealModeGdt[0]), sizeof (GDT32));
+
+ //
+ // Setup a descriptor for real-mode code
+ //
+ CodeGdt = &(IntThunk->RealModeGdt[1]);
+
+ //
+ // Fill in the descriptor with our real-mode segment value
+ //
+ CodeGdt->Type = 0xA;
+ //
+ // code/read
+ //
+ CodeGdt->System = 1;
+ CodeGdt->Dpl = 0;
+ CodeGdt->Present = 1;
+ CodeGdt->Software = 0;
+ CodeGdt->Reserved = 0;
+ CodeGdt->DefaultSize = 0;
+ //
+ // 16 bit operands
+ //
+ CodeGdt->Granularity = 0;
+
+ CodeGdt->LimitHi = 0;
+ CodeGdt->LimitLo = 0xffff;
+
+ Base = (*((UINT32 *) &IntThunk->Code));
+ CodeGdt->BaseHi = (Base >> 24) & 0xFF;
+ CodeGdt->BaseMid = (Base >> 16) & 0xFF;
+ CodeGdt->BaseLo = Base & 0xFFFF;
+
+ //
+ // Setup a descriptor for read-mode data
+ //
+ DataGdt = &(IntThunk->RealModeGdt[2]);
+ CopyMem (DataGdt, CodeGdt, sizeof (GDT32));
+
+ DataGdt->Type = 0x2;
+ //
+ // read/write data
+ //
+ DataGdt->BaseHi = 0x0;
+ //
+ // Base = 0
+ //
+ DataGdt->BaseMid = 0x0;
+ //
+ DataGdt->BaseLo = 0x0;
+ //
+ DataGdt->LimitHi = 0x0F;
+ //
+ // Limit = 4Gb
+ //
+ DataGdt->LimitLo = 0xFFFF;
+ //
+ DataGdt->Granularity = 0x1;
+ //
+ //
+ // Compute selector value
+ //
+ IntThunk->RealModeGdtDesc.Limit = (UINT16) (sizeof (IntThunk->RealModeGdt) - 1);
+ CopyMem (&IntThunk->RealModeGdtDesc.Base, (UINT32 *) &IntThunk->RealModeGdt, sizeof (UINT32));
+ //
+ // IntThunk->RealModeGdtDesc.Base = *((UINT32*) &IntThunk->RealModeGdt);
+ //
+ IntThunk->RealModeIdtDesc.Limit = 0xFFFF;
+ IntThunk->RealModeIdtDesc.Base = 0;
+ IntThunk->LowCodeSelector = (UINT32) ((UINTN) CodeGdt - IntThunk->RealModeGdtDesc.Base);
+ IntThunk->LowDataSelector = (UINT32) ((UINTN) DataGdt - IntThunk->RealModeGdtDesc.Base);
+
+ //
+ // Initialize low real-mode code thunk
+ //
+ RealModeTemplate (&CodeStart, &CodeEnd, &ReverseThunkStart, IntThunk);
+
+ TempData = (UINTN) &(IntThunk->Code);
+ IntThunk->LowReverseThunkStart = ((UINT32) TempData + (UINT32) (ReverseThunkStart - CodeStart));
+
+ EsalSetSalDataArea (TempData, (UINTN) IntThunk);
+ CopyMem (IntThunk->Code, (VOID *) CodeStart, CodeEnd - CodeStart);
+
+ IntThunk->EfiToLegacy16InitTable.ReverseThunkCallSegment = EFI_SEGMENT (*((UINT32 *) &IntThunk->LowReverseThunkStart));
+ IntThunk->EfiToLegacy16InitTable.ReverseThunkCallOffset = EFI_OFFSET (*((UINT32 *) &IntThunk->LowReverseThunkStart));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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.
+
+ @param This Protocol instance pointer.
+ @param BiosInt Processor interrupt vector to invoke
+ @param Regs Register contexted passed into (and returned) from
+ thunk to 16-bit mode
+
+ @retval FALSE Thunk completed, and there were no BIOS errors in the
+ target code. See Regs for status.
+ @retval TRUE There was a BIOS erro in the target code.
+
+**/
+BOOLEAN
+EFIAPI
+LegacyBiosInt86 (
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT8 BiosInt,
+ IN EFI_IA32_REGISTER_SET *Regs
+ )
+{
+ EFI_STATUS Status;
+ LEGACY_BIOS_INSTANCE *Private;
+ LOW_MEMORY_THUNK *IntThunk;
+ UINT16 *Stack16;
+ EFI_TPL OriginalTpl;
+ UINTN IaSegment;
+ UINTN IaOffset;
+ UINTN *Address;
+ UINTN TempData;
+
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
+ IntThunk = Private->IntThunk;
+
+ //
+ // Get the current flat GDT, IDT, and SS and store them in Private->IntThunk.
+ //
+ Status = LegacyBiosGetFlatDescs (Private);
+ ASSERT_EFI_ERROR (Status);
+
+ 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;
+ //
+ // Clear the error flag; thunk code may set it.
+ //
+ Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE);
+
+ //
+ // Copy regs to low memory stack
+ //
+ Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16);
+ CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ //
+ // Provide low stack esp
+ //
+ TempData = ((UINTN) Stack16) - ((UINTN) IntThunk);
+ IntThunk->LowStack = *((UINT32 *) &TempData);
+
+ //
+ // Stack for reverse thunk flat mode.
+ // It must point to top of stack (end of stack space).
+ //
+ TempData = ((UINTN) IntThunk->RevThunkStack) + LOW_STACK_SIZE;
+ IntThunk->RevFlatStack = *((UINT32 *) &TempData);
+
+ //
+ // The call to Legacy16 is a critical section to EFI
+ //
+ OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ //
+ // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
+ //
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Call the real mode thunk code
+ //
+ TempData = BiosInt * 4;
+ Address = (UINTN *) TempData;
+ IaOffset = 0xFFFF & (*Address);
+ IaSegment = 0xFFFF & ((*Address) >> 16);
+
+ Status = BiosIntCall (
+ BiosInt,
+ (UINT16) IaSegment,
+ (UINT16) IaOffset,
+ (EFI_IA32_REGISTER_SET *) Stack16,
+ IntThunk,
+ IntThunk->LowStack
+ );
+
+ //
+ // Check for errors with the thunk
+ //
+ switch (Status) {
+ case THUNK_OK:
+ break;
+
+ case THUNK_ERR_A20_UNSUP:
+ case THUNK_ERR_A20_FAILED:
+ default:
+ //
+ // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error).
+ //
+ Regs->X.Flags.CF = 1;
+ break;
+ }
+
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // End critical section
+ //
+ gBS->RestoreTPL (OriginalTpl);
+
+ //
+ // Return the resulting registers
+ //
+ CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET));
+
+ return (BOOLEAN) (Regs->X.Flags.CF != 0);
+}
+
+
+/**
+ Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the
+ 16-bit register context on entry and exit. Arguments can be passed on
+ the Stack argument
+
+ @param This Protocol instance pointer.
+ @param Segment Segemnt of 16-bit mode call
+ @param Offset Offset of 16-bit mdoe call
+ @param Regs Register contexted passed into (and returned) from
+ thunk to 16-bit mode
+ @param Stack Caller allocated stack used to pass arguments
+ @param StackSize Size of Stack in bytes
+
+ @retval FALSE Thunk completed, and there were no BIOS errors in the
+ target code. See Regs for status.
+ @retval TRUE There was a BIOS erro in the target code.
+
+**/
+BOOLEAN
+EFIAPI
+LegacyBiosFarCall86 (
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN EFI_IA32_REGISTER_SET *Regs,
+ IN VOID *Stack,
+ IN UINTN StackSize
+ )
+{
+ EFI_STATUS Status;
+ LEGACY_BIOS_INSTANCE *Private;
+ LOW_MEMORY_THUNK *IntThunk;
+ UINT16 *Stack16;
+ EFI_TPL OriginalTpl;
+ UINTN IaSegment;
+ UINTN IaOffset;
+ UINTN TempData;
+
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
+ IntThunk = Private->IntThunk;
+ IaSegment = Segment;
+ IaOffset = Offset;
+
+ //
+ // Get the current flat GDT and IDT and store them in Private->IntThunk.
+ //
+ Status = LegacyBiosGetFlatDescs (Private);
+ ASSERT_EFI_ERROR (Status);
+
+ 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;
+ //
+ // Clear the error flag; thunk code may set it.
+ //
+ Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE);
+ if (Stack != NULL && StackSize != 0) {
+ //
+ // Copy Stack to low memory stack
+ //
+ Stack16 -= StackSize / sizeof (UINT16);
+ CopyMem (Stack16, Stack, StackSize);
+ }
+ //
+ // Copy regs to low memory stack
+ //
+ Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16);
+ CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ //
+ // Provide low stack esp
+ //
+ TempData = ((UINTN) Stack16) - ((UINTN) IntThunk);
+ IntThunk->LowStack = *((UINT32 *) &TempData);
+
+ //
+ // The call to Legacy16 is a critical section to EFI
+ //
+ OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ //
+ // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
+ //
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Call the real mode thunk code
+ //
+ Status = BiosIntCall (
+ 0x100,
+ (UINT16) IaSegment,
+ (UINT16) IaOffset,
+ (EFI_IA32_REGISTER_SET *) Stack16,
+ IntThunk,
+ IntThunk->LowStack
+ );
+
+ //
+ // Check for errors with the thunk
+ //
+ switch (Status) {
+ case THUNK_OK:
+ break;
+
+ case THUNK_ERR_A20_UNSUP:
+ case THUNK_ERR_A20_FAILED:
+ default:
+ //
+ // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error).
+ //
+ Regs->X.Flags.CF = 1;
+ break;
+ }
+ //
+ // Restore protected mode interrupt state
+ //
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // End critical section
+ //
+ gBS->RestoreTPL (OriginalTpl);
+
+ //
+ // Return the resulting registers
+ //
+ CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET));
+ Stack16 += sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16);
+
+ if (Stack != NULL && StackSize != 0) {
+ //
+ // Copy low memory stack to Stack
+ //
+ CopyMem (Stack, Stack16, StackSize);
+ Stack16 += StackSize / sizeof (UINT16);
+ }
+
+ return (BOOLEAN) (Regs->X.Flags.CF != 0);
+}