IntelFrameworkModulePkg: Add Compatibility Support Module (CSM) drivers

Added these drivers:
* LegacyBiosDxe
* BlockIoDxe
* KeyboardDxe
* Snp16Dxe
* VideoDxe

Signed-off-by: jljusten
Reviewed-by: mdkinney
Reviewed-by: geekboy15a

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11905 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jljusten
2011-06-27 23:32:56 +00:00
parent a7a0f78bd6
commit bcecde140a
46 changed files with 30571 additions and 1 deletions

View File

@@ -0,0 +1,67 @@
## @file
# Interrupt Redirection Template
#
# 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.
#
##
ASM_GLOBAL ASM_PFX(InterruptRedirectionTemplate)
#----------------------------------------------------------------------------
# Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F
#
# Input: None
#
# Output: None
#
# Prototype: VOID
# InterruptRedirectionTemplate (
# VOID
# );
#
# Saves: None
#
# Modified: None
#
# Description: Contains the code that is copied into low memory (below 640K).
# This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.
# This template must be copied into low memory, and the IDT entries
# 0x68-0x6F must be point to the low memory copy of this code. Each
# entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily
# computed.
#
#----------------------------------------------------------------------------
ASM_PFX(InterruptRedirectionTemplate):
int $0x8
.byte 0xcf
nop
int $0x9
.byte 0xcf
nop
int $0xa
.byte 0xcf
nop
int $0xb
.byte 0xcf
nop
int $0xc
.byte 0xcf
nop
int $0xd
.byte 0xcf
nop
int $0xe
.byte 0xcf
nop
int $0xf
.byte 0xcf
nop

View File

@@ -0,0 +1,73 @@
;; @file
; Interrupt Redirection Template
;
; 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.
;
;;
.686P
.MODEL FLAT, C
.CODE
;----------------------------------------------------------------------------
; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F
;
; Input: None
;
; Output: None
;
; Prototype: VOID
; InterruptRedirectionTemplate (
; VOID
; );
;
; Saves: None
;
; Modified: None
;
; Description: Contains the code that is copied into low memory (below 640K).
; This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.
; This template must be copied into low memory, and the IDT entries
; 0x68-0x6F must be point to the low memory copy of this code. Each
; entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily
; computed.
;
;----------------------------------------------------------------------------
InterruptRedirectionTemplate PROC C
int 08h
DB 0cfh ; IRET
nop
int 09h
DB 0cfh ; IRET
nop
int 0ah
DB 0cfh ; IRET
nop
int 0bh
DB 0cfh ; IRET
nop
int 0ch
DB 0cfh ; IRET
nop
int 0dh
DB 0cfh ; IRET
nop
int 0eh
DB 0cfh ; IRET
nop
int 0fh
DB 0cfh ; IRET
nop
InterruptRedirectionTemplate ENDP
END

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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::

View File

@@ -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);
}

View File

@@ -0,0 +1,384 @@
/** @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"
#include <IndustryStandard/Pci.h>
// Give floppy 3 states
// FLOPPY_PRESENT_WITH_MEDIA = Floppy controller present and media is inserted
// FLOPPY_NOT_PRESENT = No floppy controller present
// FLOPPY_PRESENT_NO_MEDIA = Floppy controller present but no media inserted
//
#define FLOPPY_NOT_PRESENT 0
#define FLOPPY_PRESENT_WITH_MEDIA 1
#define FLOPPY_PRESENT_NO_MEDIA 2
BBS_TABLE *mBbsTable;
BOOLEAN mBbsTableDoneFlag = FALSE;
BOOLEAN IsHaveMediaInFloppy = TRUE;
/**
Checks the state of the floppy and if media is inserted.
This routine checks the state of the floppy and if media is inserted.
There are 3 cases:
No floppy present - Set BBS entry to ignore
Floppy present & no media - Set BBS entry to lowest priority. We cannot
set it to ignore since 16-bit CSM will
indicate no floppy and thus drive A: is
unusable. CSM-16 will not try floppy since
lowest priority and thus not incur boot
time penality.
Floppy present & media - Set BBS entry to some priority.
@return State of floppy media
**/
UINT8
HasMediaInFloppy (
VOID
)
{
EFI_STATUS Status;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN Index;
EFI_ISA_IO_PROTOCOL *IsaIo;
EFI_BLOCK_IO_PROTOCOL *BlkIo;
HandleBuffer = NULL;
HandleCount = 0;
gBS->LocateHandleBuffer (
ByProtocol,
&gEfiIsaIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
//
// If don't find any ISA/IO protocol assume no floppy. Need for floppy
// free system
//
if (HandleCount == 0) {
return FLOPPY_NOT_PRESENT;
}
ASSERT (HandleBuffer != NULL);
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiIsaIoProtocolGuid,
(VOID **) &IsaIo
);
if (EFI_ERROR (Status)) {
continue;
}
if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
continue;
}
//
// Update blockio in case the floppy is inserted in during BdsTimeout
//
Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
if (EFI_ERROR (Status)) {
continue;
}
Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
if (EFI_ERROR (Status)) {
continue;
}
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiBlockIoProtocolGuid,
(VOID **) &BlkIo
);
if (EFI_ERROR (Status)) {
continue;
}
if (BlkIo->Media->MediaPresent) {
FreePool (HandleBuffer);
return FLOPPY_PRESENT_WITH_MEDIA;
} else {
FreePool (HandleBuffer);
return FLOPPY_PRESENT_NO_MEDIA;
}
}
FreePool (HandleBuffer);
return FLOPPY_NOT_PRESENT;
}
/**
Complete build of BBS TABLE.
@param Private Legacy BIOS Instance data
@param BbsTable BBS Table passed to 16-bit code
@retval EFI_SUCCESS Removable media not present
**/
EFI_STATUS
LegacyBiosBuildBbs (
IN LEGACY_BIOS_INSTANCE *Private,
IN BBS_TABLE *BbsTable
)
{
UINTN BbsIndex;
HDD_INFO *HddInfo;
UINTN HddIndex;
UINTN Index;
//
// First entry is floppy.
// Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE.
// Next n entries are filled in after each ROM is dispatched.
// Entry filled in if follow BBS spec. See LegacyPci.c
// Next entries are for non-BBS compliant ROMS. They are filled in by
// 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority
// occurs after that invocation.
//
// Floppy
// Set default state.
//
IsHaveMediaInFloppy = HasMediaInFloppy ();
if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) {
BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY;
} else {
if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) {
BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY;
} else {
BbsTable[0].BootPriority = BBS_IGNORE_ENTRY;
}
}
BbsTable[0].Bus = 0xff;
BbsTable[0].Device = 0xff;
BbsTable[0].Function = 0xff;
BbsTable[0].DeviceType = BBS_FLOPPY;
BbsTable[0].Class = 01;
BbsTable[0].SubClass = 02;
BbsTable[0].StatusFlags.OldPosition = 0;
BbsTable[0].StatusFlags.Reserved1 = 0;
BbsTable[0].StatusFlags.Enabled = 0;
BbsTable[0].StatusFlags.Failed = 0;
BbsTable[0].StatusFlags.MediaPresent = 0;
BbsTable[0].StatusFlags.Reserved2 = 0;
//
// Onboard HDD - Note Each HDD controller controls 2 drives
// Master & Slave
//
HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];
//
// Get IDE Drive Info
//
LegacyBiosBuildIdeData (Private, &HddInfo, 0);
for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) {
BbsIndex = HddIndex * 2 + 1;
for (Index = 0; Index < 2; ++Index) {
BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus;
BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device;
BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function;
BbsTable[BbsIndex + Index].Class = 01;
BbsTable[BbsIndex + Index].SubClass = 01;
BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0;
BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0;
BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0;
BbsTable[BbsIndex + Index].StatusFlags.Failed = 0;
BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0;
BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0;
//
// If no controller found or no device found set to ignore
// else set to unprioritized and set device type
//
if (HddInfo[HddIndex].CommandBaseAddress == 0) {
BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
} else {
if (Index == 0) {
if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) {
BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) {
BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
} else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) {
BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
} else {
//
// for ZIPDISK
//
BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
}
} else {
BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
}
} else {
if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) {
BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) {
BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
} else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) {
BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
} else {
//
// for ZIPDISK
//
BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
}
} else {
BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
}
}
}
}
}
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
)
{
LEGACY_BIOS_INSTANCE *Private;
EFI_IA32_REGISTER_SET Regs;
EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
// HDD_INFO *LocalHddInfo;
// IN BBS_TABLE *LocalBbsTable;
UINTN NumHandles;
EFI_HANDLE *HandleBuffer;
UINTN Index;
UINTN TempData;
UINT32 Granularity;
HandleBuffer = NULL;
Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;
// LocalHddInfo = EfiToLegacy16BootTable->HddInfo;
// LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
if (!mBbsTableDoneFlag) {
mBbsTable = Private->BbsTablePtr;
//
// Always enable disk controllers so 16-bit CSM code has valid information for all
// drives.
//
//
// Get PciRootBridgeIO protocol
//
gBS->LocateHandleBuffer (
ByProtocol,
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
&NumHandles,
&HandleBuffer
);
if (NumHandles == 0) {
return EFI_NOT_FOUND;
}
mBbsTableDoneFlag = TRUE;
for (Index = 0; Index < NumHandles; Index++) {
//
// Connect PciRootBridgeIO protocol handle with FALSE parameter to let
// PCI bus driver enumerate all subsequent handles
//
gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);
}
LegacyBiosBuildBbs (Private, mBbsTable);
Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
//
// Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs.
//
ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
Regs.X.AX = Legacy16UpdateBbs;
//
// Pass in handoff data
//
TempData = (UINTN) EfiToLegacy16BootTable;
Regs.X.ES = EFI_SEGMENT ((UINT32) TempData);
Regs.X.BX = EFI_OFFSET ((UINT32) TempData);
Private->LegacyBios.FarCall86 (
This,
Private->Legacy16CallSegment,
Private->Legacy16CallOffset,
&Regs,
NULL,
0
);
Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
if (Regs.X.AX != 0) {
return EFI_DEVICE_ERROR;
}
}
if (HandleBuffer != NULL) {
FreePool (HandleBuffer);
}
*HddCount = MAX_IDE_CONTROLLER;
*HddInfo = EfiToLegacy16BootTable->HddInfo;
*BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
*BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,66 @@
/** @file
This code fills in BDA (0x400) and EBDA (pointed to by 0x4xx)
information. There is support for doing initializeation before
Legacy16 is loaded and before a legacy boot is attempted.
Copyright (c) 2006 - 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"
/**
Fill in the standard BDA and EBDA stuff before Legacy16 load
@param Private Legacy BIOS Instance data
@retval EFI_SUCCESS It should always work.
**/
EFI_STATUS
LegacyBiosInitBda (
IN LEGACY_BIOS_INSTANCE *Private
)
{
BDA_STRUC *Bda;
UINT8 *Ebda;
Bda = (BDA_STRUC *) ((UINTN) 0x400);
Ebda = (UINT8 *) ((UINTN) 0x9fc00);
ZeroMem (Bda, 0x100);
ZeroMem (Ebda, 0x400);
//
// 640k-1k for EBDA
//
Bda->MemSize = 0x27f;
Bda->KeyHead = 0x1e;
Bda->KeyTail = 0x1e;
Bda->FloppyData = 0x00;
Bda->FloppyTimeout = 0xff;
Bda->KeyStart = 0x001E;
Bda->KeyEnd = 0x003E;
Bda->KeyboardStatus = 0x10;
Bda->Ebda = 0x9fc0;
//
// Move LPT time out here and zero out LPT4 since some SCSI OPROMS
// use this as scratch pad (LPT4 is Reserved)
//
Bda->Lpt1_2Timeout = 0x1414;
Bda->Lpt3_4Timeout = 0x1400;
*Ebda = 0x01;
return EFI_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
## @file
# Legacy Bios Module to support CSM.
#
# This driver installs Legacy Bios Protocol to support CSM module work in EFI system.
#
# 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.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = LegacyBiosDxe
FILE_GUID = F122A15C-C10B-4d54-8F48-60F4F06DD1AD
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = LegacyBiosInstall
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
LegacyCmos.c
LegacyIde.c
LegacyBios.c
LegacyBda.c
LegacyBiosInterface.h
LegacyPci.c
[Sources.Ia32]
IA32/InterruptTable.S
IA32/InterruptTable.asm
Thunk.c
LegacyBootSupport.c
LegacyBbs.c
LegacySio.c
[Sources.X64]
X64/InterruptTable.asm
X64/InterruptTable.S
Thunk.c
LegacyBootSupport.c
LegacyBbs.c
LegacySio.c
[Sources.IPF]
Ipf/IpfThunk.s
Ipf/Thunk.c
Ipf/IpfThunk.i
Ipf/IpfBootSupport.c
Ipf/IpfThunk.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
[LibraryClasses]
DevicePathLib
UefiBootServicesTableLib
MemoryAllocationLib
UefiDriverEntryPoint
BaseMemoryLib
UefiLib
DebugLib
DxeServicesTableLib
PcdLib
ReportStatusCodeLib
PeCoffLib
CacheMaintenanceLib
DebugAgentLib
[LibraryClasses.IA32]
IoLib
HobLib
UefiRuntimeServicesTableLib
BaseLib
[LibraryClasses.X64]
IoLib
HobLib
UefiRuntimeServicesTableLib
BaseLib
[LibraryClasses.IPF]
IoLib
UefiRuntimeServicesTableLib
[Guids]
gEfiDiskInfoIdeInterfaceGuid # ALWAYS_CONSUMED
gEfiLegacyBiosGuid # ALWAYS_PRODUCED
[Guids.IA32]
gEfiSmbiosTableGuid # ALWAYS_CONSUMED
gEfiAcpi20TableGuid # ALWAYS_CONSUMED
gEfiAcpi10TableGuid # ALWAYS_CONSUMED
[Guids.X64]
gEfiSmbiosTableGuid # ALWAYS_CONSUMED
gEfiAcpi20TableGuid # ALWAYS_CONSUMED
gEfiAcpi10TableGuid # ALWAYS_CONSUMED
[Protocols]
gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiPciRootBridgeIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiCpuArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiIsaIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiGenericMemTestProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDiskInfoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLegacy8259ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLegacyBiosPlatformProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLegacyInterruptProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLegacyRegion2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_PRODUCED
gEfiTimerArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED
[Pcd]
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize
[Depex]
gEfiLegacyRegion2ProtocolGuid AND gEfiLegacyInterruptProtocolGuid AND gEfiLegacyBiosPlatformProtocolGuid AND gEfiLegacy8259ProtocolGuid AND gEfiGenericMemTestProtocolGuid AND gEfiCpuArchProtocolGuid

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,124 @@
/** @file
This code fills in standard CMOS values and updates the standard CMOS
checksum. The Legacy16 code or LegacyBiosPlatform.c is responsible for
non-standard CMOS locations and non-standard checksums.
Copyright (c) 2006 - 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"
/**
Read CMOS register through index/data port.
@param[in] Index The index of the CMOS register to read.
@return The data value from the CMOS register specified by Index.
**/
UINT8
LegacyReadStandardCmos (
IN UINT8 Index
)
{
IoWrite8 (PORT_70, Index);
return IoRead8 (PORT_71);
}
/**
Write CMOS register through index/data port.
@param[in] Index The index of the CMOS register to write.
@param[in] Value The value of CMOS register to write.
@return The value written to the CMOS register specified by Index.
**/
UINT8
LegacyWriteStandardCmos (
IN UINT8 Index,
IN UINT8 Value
)
{
IoWrite8 (PORT_70, Index);
return IoWrite8 (PORT_71, Value);
}
/**
Calculate the new standard CMOS checksum and write it.
@param Private Legacy BIOS Instance data
@retval EFI_SUCCESS Calculate 16-bit checksum successfully
**/
EFI_STATUS
LegacyCalculateWriteStandardCmosChecksum (
VOID
)
{
UINT8 Register;
UINT16 Checksum;
for (Checksum = 0, Register = 0x10; Register < 0x2e; Register++) {
Checksum = (UINT16)(Checksum + LegacyReadStandardCmos (Register));
}
LegacyWriteStandardCmos (CMOS_2E, (UINT8)(Checksum >> 8));
LegacyWriteStandardCmos (CMOS_2F, (UINT8)(Checksum & 0xff));
return EFI_SUCCESS;
}
/**
Fill in the standard CMOS stuff before Legacy16 load
@param Private Legacy BIOS Instance data
@retval EFI_SUCCESS It should always work.
**/
EFI_STATUS
LegacyBiosInitCmos (
IN LEGACY_BIOS_INSTANCE *Private
)
{
UINT32 Size;
//
// Clear all errors except RTC lost power
//
LegacyWriteStandardCmos (CMOS_0E, (UINT8)(LegacyReadStandardCmos (CMOS_0E) & BIT7));
//
// Update CMOS locations 15,16,17,18,30,31 and 32
// CMOS 16,15 = 640Kb = 0x280
// CMOS 18,17 = 31,30 = 15Mb max in 1Kb increments =0x3C00 max
// CMOS 32 = 0x20
//
LegacyWriteStandardCmos (CMOS_15, 0x80);
LegacyWriteStandardCmos (CMOS_16, 0x02);
Size = 15 * SIZE_1MB;
if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) {
Size = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10;
}
LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF));
LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF));
LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8));
LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8));
LegacyCalculateWriteStandardCmosChecksum ();
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,300 @@
/** @file
Collect IDE information from Native EFI Driver
Copyright (c) 2006 - 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"
BOOLEAN mIdeDataBuiltFlag = FALSE;
/**
Collect IDE Inquiry data from the IDE disks
@param Private Legacy BIOS Instance data
@param HddInfo Hdd Information
@param Flag Reconnect IdeController or not
@retval EFI_SUCCESS It should always work.
**/
EFI_STATUS
LegacyBiosBuildIdeData (
IN LEGACY_BIOS_INSTANCE *Private,
IN HDD_INFO **HddInfo,
IN UINT16 Flag
)
{
EFI_STATUS Status;
EFI_HANDLE IdeController;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN Index;
EFI_DISK_INFO_PROTOCOL *DiskInfo;
UINT32 IdeChannel;
UINT32 IdeDevice;
UINT32 Size;
UINT8 *InquiryData;
UINT32 InquiryDataSize;
HDD_INFO *LocalHddInfo;
UINT32 PciIndex;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode;
PCI_DEVICE_PATH *PciDevicePath;
//
// Only build data once
// We have a problem with GetBbsInfo in that it can be invoked two
// places. Once in BDS, when all EFI drivers are connected and once in
// LegacyBoot after all EFI drivers are disconnected causing this routine
// to hang. In LegacyBoot this function is also called before EFI drivers
// are disconnected.
// Cases covered
// GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored.
// GetBbsInfo not invoked in BDS. First invocation of this function
// proceeds normally and second via GetBbsInfo ignored.
//
PciDevicePath = NULL;
LocalHddInfo = *HddInfo;
Status = Private->LegacyBiosPlatform->GetPlatformHandle (
Private->LegacyBiosPlatform,
EfiGetPlatformIdeHandle,
0,
&HandleBuffer,
&HandleCount,
(VOID *) &LocalHddInfo
);
if (!EFI_ERROR (Status)) {
IdeController = HandleBuffer[0];
//
// Force IDE drive spin up!
//
if (Flag != 0) {
gBS->DisconnectController (
IdeController,
NULL,
NULL
);
}
gBS->ConnectController (IdeController, NULL, NULL, FALSE);
//
// Do GetIdeHandle twice since disconnect/reconnect will switch to native mode
// And GetIdeHandle will switch to Legacy mode, if required.
//
Private->LegacyBiosPlatform->GetPlatformHandle (
Private->LegacyBiosPlatform,
EfiGetPlatformIdeHandle,
0,
&HandleBuffer,
&HandleCount,
(VOID *) &LocalHddInfo
);
}
mIdeDataBuiltFlag = TRUE;
//
// Get Identity command from all drives
//
gBS->LocateHandleBuffer (
ByProtocol,
&gEfiDiskInfoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
Private->IdeDriveCount = (UINT8) HandleCount;
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiDiskInfoProtocolGuid,
(VOID **) &DiskInfo
);
ASSERT_EFI_ERROR (Status);
if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {
//
// Locate which PCI device
//
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiDevicePathProtocolGuid,
(VOID *) &DevicePath
);
ASSERT_EFI_ERROR (Status);
DevicePathNode = DevicePath;
while (!IsDevicePathEnd (DevicePathNode)) {
TempDevicePathNode = NextDevicePathNode (DevicePathNode);
if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) &&
( DevicePathSubType (DevicePathNode) == HW_PCI_DP) &&
( DevicePathType(TempDevicePathNode) == MESSAGING_DEVICE_PATH) &&
( DevicePathSubType(TempDevicePathNode) == MSG_ATAPI_DP) ) {
PciDevicePath = (PCI_DEVICE_PATH *) DevicePathNode;
break;
}
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
if (PciDevicePath == NULL) {
continue;
}
//
// Find start of PCI device in HddInfo. The assumption of the data
// structure is 2 controllers(channels) per PCI device and each
// controller can have 2 drives(devices).
// HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master
// HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave
// HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master
// HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave
// @bug eventually need to pass in max number of entries
// for end of for loop
//
for (PciIndex = 0; PciIndex < 8; PciIndex++) {
if ((PciDevicePath->Device == LocalHddInfo[PciIndex].Device) &&
(PciDevicePath->Function == LocalHddInfo[PciIndex].Function)
) {
break;
}
}
if (PciIndex == 8) {
continue;
}
Status = DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice);
if (!EFI_ERROR (Status)) {
Size = sizeof (ATAPI_IDENTIFY);
DiskInfo->Identify (
DiskInfo,
&LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[IdeDevice],
&Size
);
if (IdeChannel == 0) {
LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_PRIMARY;
} else if (IdeChannel == 1) {
LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SECONDARY;
}
InquiryData = NULL;
InquiryDataSize = 0;
Status = DiskInfo->Inquiry (
DiskInfo,
NULL,
&InquiryDataSize
);
if (Status == EFI_BUFFER_TOO_SMALL) {
InquiryData = (UINT8 *) AllocatePool (
InquiryDataSize
);
if (InquiryData != NULL) {
Status = DiskInfo->Inquiry (
DiskInfo,
InquiryData,
&InquiryDataSize
);
}
} else {
Status = EFI_DEVICE_ERROR;
}
//
// If ATAPI device then Inquiry will pass and ATA fail.
//
if (!EFI_ERROR (Status)) {
ASSERT (InquiryData != NULL);
//
// If IdeDevice = 0 then set master bit, else slave bit
//
if (IdeDevice == 0) {
if ((InquiryData[0] & 0x1f) == 0x05) {
LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_CDROM;
} else if ((InquiryData[0] & 0x1f) == 0x00) {
LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_ZIPDISK;
}
} else {
if ((InquiryData[0] & 0x1f) == 0x05) {
LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_CDROM;
} else if ((InquiryData[0] & 0x1f) == 0x00) {
LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_ZIPDISK;
}
}
FreePool (InquiryData);
} else {
if (IdeDevice == 0) {
LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_IDE;
} else {
LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_IDE;
}
}
}
}
}
if (HandleBuffer != NULL) {
FreePool (HandleBuffer);
}
return EFI_SUCCESS;
}
/**
If the IDE channel is in compatibility (legacy) mode, remove all
PCI I/O BAR addresses from the controller.
@param IdeController The handle of target IDE controller
**/
VOID
InitLegacyIdeController (
IN EFI_HANDLE IdeController
)
{
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 Pi;
UINT32 IOBarClear;
EFI_STATUS Status;
//
// If the IDE channel is in compatibility (legacy) mode, remove all
// PCI I/O BAR addresses from the controller. Some software gets
// confused if an IDE controller is in compatibility (legacy) mode
// and has PCI I/O resources allocated
//
Status = gBS->HandleProtocol (
IdeController,
&gEfiPciIoProtocolGuid,
(VOID **) &PciIo
);
if (!EFI_ERROR (Status)) {
IOBarClear = 0x00;
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 1, &Pi);
if ((Pi & 0x01) == 0) {
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear);
}
if ((Pi & 0x04) == 0) {
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear);
}
}
return ;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
/** @file
Collect Sio information from Native EFI Drivers.
Sio is floppy, parallel, serial, ... hardware
Copyright (c) 2006 - 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"
/**
Collect EFI Info about legacy devices.
@param Private Legacy BIOS Instance data
@retval EFI_SUCCESS It should always work.
**/
EFI_STATUS
LegacyBiosBuildSioData (
IN LEGACY_BIOS_INSTANCE *Private
)
{
EFI_STATUS Status;
DEVICE_PRODUCER_DATA_HEADER *SioPtr;
DEVICE_PRODUCER_SERIAL *Sio1Ptr;
DEVICE_PRODUCER_PARALLEL *Sio2Ptr;
DEVICE_PRODUCER_FLOPPY *Sio3Ptr;
EFI_HANDLE IsaBusController;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN Index;
UINTN ResourceIndex;
UINTN ChildIndex;
EFI_ISA_IO_PROTOCOL *IsaIo;
EFI_ISA_ACPI_RESOURCE_LIST *ResourceList;
EFI_ISA_ACPI_RESOURCE *IoResource;
EFI_ISA_ACPI_RESOURCE *DmaResource;
EFI_ISA_ACPI_RESOURCE *InterruptResource;
UINTN EntryCount;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
//
// Get the pointer to the SIO data structure
//
SioPtr = &Private->IntThunk->EfiToLegacy16BootTable.SioData;
//
// Zero the data in the SIO data structure
//
gBS->SetMem (SioPtr, sizeof (DEVICE_PRODUCER_DATA_HEADER), 0);
//
// Find the ISA Bus Controller used for legacy
//
Status = Private->LegacyBiosPlatform->GetPlatformHandle (
Private->LegacyBiosPlatform,
EfiGetPlatformIsaBusHandle,
0,
&HandleBuffer,
&HandleCount,
NULL
);
IsaBusController = HandleBuffer[0];
if (!EFI_ERROR (Status)) {
//
// Force ISA Bus Controller to produce all ISA devices
//
gBS->ConnectController (IsaBusController, NULL, NULL, TRUE);
}
//
// Get the list of ISA controllers in the system
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiIsaIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
//
// Collect legacy information from each of the ISA controllers in the system
//
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo);
if (EFI_ERROR (Status)) {
continue;
}
ResourceList = IsaIo->ResourceList;
if (ResourceList == NULL) {
continue;
}
//
// Collect the resource types neededto fill in the SIO data structure
//
IoResource = NULL;
DmaResource = NULL;
InterruptResource = NULL;
for (ResourceIndex = 0;
ResourceList->ResourceItem[ResourceIndex].Type != EfiIsaAcpiResourceEndOfList;
ResourceIndex++
) {
switch (ResourceList->ResourceItem[ResourceIndex].Type) {
case EfiIsaAcpiResourceIo:
IoResource = &ResourceList->ResourceItem[ResourceIndex];
break;
case EfiIsaAcpiResourceMemory:
break;
case EfiIsaAcpiResourceDma:
DmaResource = &ResourceList->ResourceItem[ResourceIndex];
break;
case EfiIsaAcpiResourceInterrupt:
InterruptResource = &ResourceList->ResourceItem[ResourceIndex];
break;
default:
break;
}
}
//
// See if this is an ISA serial port
//
// Ignore DMA resource since it is always returned NULL
//
if (ResourceList->Device.HID == EISA_PNP_ID (0x500) || ResourceList->Device.HID == EISA_PNP_ID (0x501)) {
if (ResourceList->Device.UID <= 3 &&
IoResource != NULL &&
InterruptResource != NULL
) {
//
// Get the handle of the child device that has opened the ISA I/O Protocol
//
Status = gBS->OpenProtocolInformation (
HandleBuffer[Index],
&gEfiIsaIoProtocolGuid,
&OpenInfoBuffer,
&EntryCount
);
if (EFI_ERROR (Status)) {
continue;
}
//
// We want resource for legacy even if no 32-bit driver installed
//
for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) {
Sio1Ptr = &SioPtr->Serial[ResourceList->Device.UID];
Sio1Ptr->Address = (UINT16) IoResource->StartRange;
Sio1Ptr->Irq = (UINT8) InterruptResource->StartRange;
Sio1Ptr->Mode = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF;
}
FreePool (OpenInfoBuffer);
}
}
//
// See if this is an ISA parallel port
//
// Ignore DMA resource since it is always returned NULL, port
// only used in output mode.
//
if (ResourceList->Device.HID == EISA_PNP_ID (0x400) || ResourceList->Device.HID == EISA_PNP_ID (0x401)) {
if (ResourceList->Device.UID <= 2 &&
IoResource != NULL &&
InterruptResource != NULL &&
DmaResource != NULL
) {
Sio2Ptr = &SioPtr->Parallel[ResourceList->Device.UID];
Sio2Ptr->Address = (UINT16) IoResource->StartRange;
Sio2Ptr->Irq = (UINT8) InterruptResource->StartRange;
Sio2Ptr->Dma = (UINT8) DmaResource->StartRange;
Sio2Ptr->Mode = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY;
}
}
//
// See if this is an ISA floppy controller
//
if (ResourceList->Device.HID == EISA_PNP_ID (0x604)) {
if (IoResource != NULL && InterruptResource != NULL && DmaResource != NULL) {
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
if (!EFI_ERROR (Status)) {
Sio3Ptr = &SioPtr->Floppy;
Sio3Ptr->Address = (UINT16) IoResource->StartRange;
Sio3Ptr->Irq = (UINT8) InterruptResource->StartRange;
Sio3Ptr->Dma = (UINT8) DmaResource->StartRange;
Sio3Ptr->NumberOfFloppy++;
}
}
}
//
// See if this is a mouse
// Always set mouse found so USB hot plug will work
//
// Ignore lower byte of HID. Pnp0fxx is any type of mouse.
//
// Hid = ResourceList->Device.HID & 0xff00ffff;
// PnpId = EISA_PNP_ID(0x0f00);
// if (Hid == PnpId) {
// if (ResourceList->Device.UID == 1) {
// Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
// if (!EFI_ERROR (Status)) {
//
SioPtr->MousePresent = 0x01;
//
// }
// }
// }
//
}
FreePool (HandleBuffer);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,284 @@
/** @file
Call into 16-bit BIOS code, Use AsmThunk16 function of BaseLib.
Copyright (c) 2006 - 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"
THUNK_CONTEXT mThunkContext;
/**
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
)
{
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 = 0;
Regs->X.Flags.TF = 0;
Regs->X.Flags.CF = 0;
return InternalLegacyBiosFarCall (
This,
(UINT16) (((UINT32 *)NULL)[BiosInt] >> 16),
(UINT16) ((UINT32 *)NULL)[BiosInt],
Regs,
&Regs->X.Flags,
sizeof (Regs->X.Flags)
);
}
/**
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
)
{
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;
return InternalLegacyBiosFarCall (This, Segment, Offset, Regs, Stack, StackSize);
}
/**
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
InternalLegacyBiosFarCall (
IN EFI_LEGACY_BIOS_PROTOCOL *This,
IN UINT16 Segment,
IN UINT16 Offset,
IN EFI_IA32_REGISTER_SET *Regs,
IN VOID *Stack,
IN UINTN StackSize
)
{
UINTN Status;
LEGACY_BIOS_INSTANCE *Private;
UINT16 *Stack16;
EFI_TPL OriginalTpl;
IA32_REGISTER_SET ThunkRegSet;
BOOLEAN InterruptState;
Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));
ThunkRegSet.X.DI = Regs->X.DI;
ThunkRegSet.X.SI = Regs->X.SI;
ThunkRegSet.X.BP = Regs->X.BP;
ThunkRegSet.X.BX = Regs->X.BX;
ThunkRegSet.X.DX = Regs->X.DX;
//
// 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.
//
ThunkRegSet.E.ECX = Regs->E.ECX;
ThunkRegSet.X.AX = Regs->X.AX;
ThunkRegSet.E.DS = Regs->X.DS;
ThunkRegSet.E.ES = Regs->X.ES;
CopyMem (&(ThunkRegSet.E.EFLAGS.UintN), &(Regs->X.Flags), sizeof (Regs->X.Flags));
//
// Clear the error flag; thunk code may set it. Stack16 should be the high address
// Make Statk16 address the low 16 bit must be not zero.
//
Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16));
//
// Save and disable interrutp of debug timer
//
InterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
//
// The call to Legacy16 is a critical section to EFI
//
OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
if (Stack != NULL && StackSize != 0) {
//
// Copy Stack to low memory stack
//
Stack16 -= StackSize / sizeof (UINT16);
CopyMem (Stack16, Stack, StackSize);
}
ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12);
ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16;
ThunkRegSet.E.CS = Segment;
ThunkRegSet.E.Eip = Offset;
mThunkContext.RealModeState = &ThunkRegSet;
//
// Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
//
Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL);
ASSERT_EFI_ERROR (Status);
AsmThunk16 (&mThunkContext);
//
// OPROM may allocate EBDA range by itself and change EBDA base and EBDA size.
// Get the current EBDA base address, and compared with pre-allocate minimum
// EBDA base address, if the current EBDA base address is smaller, it indicates
// PcdEbdaReservedMemorySize should be adjusted to larger for more OPROMs.
//
DEBUG_CODE (
{
UINTN EbdaBaseAddress;
UINTN ReservedEbdaBaseAddress;
EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4;
ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize);
ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress);
}
);
if (Stack != NULL && StackSize != 0) {
//
// Copy low memory stack to Stack
//
CopyMem (Stack, Stack16, StackSize);
}
//
// Restore protected mode interrupt state
//
Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL);
ASSERT_EFI_ERROR (Status);
mThunkContext.RealModeState = NULL;
//
// End critical section
//
gBS->RestoreTPL (OriginalTpl);
//
// Restore interrutp of debug timer
//
SaveAndSetDebugTimerInterrupt (InterruptState);
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->X.SS = ThunkRegSet.E.SS;
Regs->X.CS = ThunkRegSet.E.CS;
Regs->X.DS = ThunkRegSet.E.DS;
Regs->X.ES = ThunkRegSet.E.ES;
CopyMem (&(Regs->X.Flags), &(ThunkRegSet.E.EFLAGS.UintN), sizeof (Regs->X.Flags));
return (BOOLEAN) (Regs->X.Flags.CF == 1);
}
/**
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
)
{
EFI_PHYSICAL_ADDRESS MemoryAddress;
MemoryAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->IntThunk;
mThunkContext.RealModeBuffer = (VOID *) (UINTN) (MemoryAddress + ((sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE);
mThunkContext.RealModeBufferSize = EFI_PAGE_SIZE;
mThunkContext.ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE | THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15;
AsmPrepareThunk16 (&mThunkContext);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,72 @@
## @file
# Interrupt Redirection Template
#
# 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.
#
##
#text SEGMENT
#----------------------------------------------------------------------------
# Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F
#
# Input: None
#
# Output: None
#
# Prototype: VOID
# InterruptRedirectionTemplate (
# VOID
# );
#
# Saves: None
#
# Modified: None
#
# Description: Contains the code that is copied into low memory (below 640K).
# This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.
# This template must be copied into low memory, and the IDT entries
# 0x68-0x6F must be point to the low memory copy of this code. Each
# entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily
# computed.
#
#----------------------------------------------------------------------------
ASM_GLOBAL ASM_PFX(InterruptRedirectionTemplate)
ASM_PFX(InterruptRedirectionTemplate):
int $0x08
.byte 0x0cf # IRET
nop
int $0x09
.byte 0x0cf # IRET
nop
int $0x0a
.byte 0x0cf # IRET
nop
int $0x0b
.byte 0x0cf # IRET
nop
int $0x0c
.byte 0x0cf # IRET
nop
int $0x0d
.byte 0x0cf # IRET
nop
int $0x0e
.byte 0x0cf # IRET
nop
int $0x0f
.byte 0x0cf # IRET
nop
#END

View File

@@ -0,0 +1,71 @@
;; @file
; Interrupt Redirection Template
;
; 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.
;
;;
text SEGMENT
;----------------------------------------------------------------------------
; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F
;
; Input: None
;
; Output: None
;
; Prototype: VOID
; InterruptRedirectionTemplate (
; VOID
; );
;
; Saves: None
;
; Modified: None
;
; Description: Contains the code that is copied into low memory (below 640K).
; This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.
; This template must be copied into low memory, and the IDT entries
; 0x68-0x6F must be point to the low memory copy of this code. Each
; entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily
; computed.
;
;----------------------------------------------------------------------------
InterruptRedirectionTemplate PROC
int 08h
DB 0cfh ; IRET
nop
int 09h
DB 0cfh ; IRET
nop
int 0ah
DB 0cfh ; IRET
nop
int 0bh
DB 0cfh ; IRET
nop
int 0ch
DB 0cfh ; IRET
nop
int 0dh
DB 0cfh ; IRET
nop
int 0eh
DB 0cfh ; IRET
nop
int 0fh
DB 0cfh ; IRET
nop
InterruptRedirectionTemplate ENDP
END