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:
@@ -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
|
@@ -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
|
277
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c
Normal file
277
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c
Normal 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;
|
||||
}
|
102
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h
Normal file
102
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.h
Normal 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
|
89
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i
Normal file
89
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.i
Normal 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
|
||||
|
||||
|
||||
|
524
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s
Normal file
524
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfThunk.s
Normal 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::
|
||||
|
||||
|
||||
|
||||
|
550
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c
Normal file
550
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/Thunk.c
Normal 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);
|
||||
}
|
384
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c
Normal file
384
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c
Normal 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;
|
||||
}
|
66
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
Normal file
66
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
Normal 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;
|
||||
}
|
1007
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
Normal file
1007
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
Normal file
File diff suppressed because it is too large
Load Diff
143
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
Normal file
143
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
Normal 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
|
||||
|
1501
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
Normal file
1501
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
Normal file
File diff suppressed because it is too large
Load Diff
2032
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c
Normal file
2032
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c
Normal file
File diff suppressed because it is too large
Load Diff
124
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c
Normal file
124
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyCmos.c
Normal 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;
|
||||
}
|
300
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c
Normal file
300
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyIde.c
Normal 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 ;
|
||||
}
|
2901
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
Normal file
2901
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
Normal file
File diff suppressed because it is too large
Load Diff
234
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c
Normal file
234
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c
Normal 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;
|
||||
}
|
284
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c
Normal file
284
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c
Normal 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;
|
||||
}
|
@@ -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
|
@@ -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
|
Reference in New Issue
Block a user