summaryrefslogtreecommitdiff
path: root/Core/EM/CSM/thunk
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/CSM/thunk
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/CSM/thunk')
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c260
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c1076
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h277
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl25
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmEdd.h407
-rw-r--r--Core/EM/CSM/thunk/BlockIo/CsmInt13.c1525
-rw-r--r--Core/EM/CSM/thunk/BlockIo/biosblkio.dxs46
-rw-r--r--Core/EM/CSM/thunk/BlockIo/biosblkio.mak63
-rw-r--r--Core/EM/CSM/thunk/BlockIo/int13thunk.cif15
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/AmiMapping.c162
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/AmiMapping.h153
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/ComponentName.c324
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/CsmVideo.cif20
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/CsmVideo.dxs46
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/CsmVideo.mak66
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/CsmVideo.sdl58
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.c3886
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.h597
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/VesaBiosExtensions.h463
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/VgaClass.c1349
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/VgaClass.h418
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/VgaMiniPort.h78
-rw-r--r--Core/EM/CSM/thunk/CsmVideo/pci22.h621
-rw-r--r--Core/EM/CSM/thunk/Snp16/snp16.cif8
-rw-r--r--Core/EM/CSM/thunk/thunk.cif11
-rw-r--r--Core/EM/CSM/thunk/x86/thunk.c793
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.asm828
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.cif10
-rw-r--r--Core/EM/CSM/thunk/x86/x86thunk.mak67
29 files changed, 13652 insertions, 0 deletions
diff --git a/Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c b/Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c
new file mode 100644
index 0000000..6807d3e
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c
@@ -0,0 +1,260 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlkIoComponentName.c 6 12/23/13 3:38p Olegi $
+//
+// $Revision: 6 $
+//
+// $Date: 12/23/13 3:38p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlkIoComponentName.c $
+//
+// 6 12/23/13 3:38p Olegi
+// EIP128504: implement EFI_COMPONENT2_NAME_PROTOCOL for CsmBlockIo driver
+//
+// 5 1/12/10 11:50a Olegi
+// Copyright message updated.
+//
+// 4 10/03/07 4:41p Yakovlevs
+// Removed Component Name Protocol and its Strings in NO DEBUG mode to
+// save some space.
+//
+// 3 4/27/07 5:14p Olegi
+// CSM.CHM file preparation.
+//
+// 2 3/04/05 1:43p Mandal
+//
+// 1 2/15/05 10:59a Olegi
+// Initial VSS check-in.
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: CsmBlkIoComponentName.c
+//
+// Description: Set of functions that implement Component Name protocol
+// for the CSM BlockIO driver.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include "CsmBlockIo.h"
+
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#define LANGUAGE_CODE_ENGLISH "eng"
+#define EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL
+#endif
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+CsmBlockIoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+CsmBlockIoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+CHAR16 *gCsmBlockIoDriverName = L"AMI CSM Block I/O Driver";
+CHAR16 gCsmBlockIoControllerName[256];
+
+EFI_COMPONENT_NAME2_PROTOCOL gCsmBlockIoComponentName = {
+ CsmBlockIoComponentNameGetDriverName,
+ CsmBlockIoComponentNameGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: CsmBlockIoComponentNameGetDriverName
+//
+// DESCRIPTION: Retrieves a Unicode string that is the user readable name of
+// the EFI Driver.
+//
+//
+// PARAMETERS:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// Language - A pointer to a three character ISO 639-2 language identifier.
+// This is the language of the driver name that that the caller
+// is requesting, and it must match one of the languages specified
+// in SupportedLanguages. The number of languages supported by a
+// driver is up to the driver writer.
+// DriverName - A pointer to the Unicode string to return. This Unicode string
+// is the name of the driver specified by This in the language
+// specified by Language.
+//
+// RETURN:
+// EFI_SUCCES - The Unicode string for the Driver specified by This
+// and the language specified by Language was returned
+// in DriverName.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - DriverName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CsmBlockIoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ //
+ //Supports only English
+ //
+ if (!Language || !DriverName) return EFI_INVALID_PARAMETER;
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) return EFI_UNSUPPORTED;
+ *DriverName = gCsmBlockIoDriverName;
+ return EFI_SUCCESS;
+}
+
+//---------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// FUNCTION: CsmBlockIoComponentNameGetControllerName
+//
+// DESCRIPTION: Retrieves a Unicode string that is the user readable name of
+// the controller that is being managed by an EFI Driver.
+//
+// PARAMETERS:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// ControllerHandle - The handle of a controller that the driver specified by
+// This is managing. This handle specifies the controller
+// whose name is to be returned.
+// ChildHandle - The handle of the child controller to retrieve the name
+// of. This is an optional parameter that may be NULL. It
+// will be NULL for device drivers. It will also be NULL
+// for a bus drivers that wish to retrieve the name of the
+// bus controller. It will not be NULL for a bus driver
+// that wishes to retrieve the name of a child controller.
+// Language - A pointer to a three character ISO 639-2 language
+// identifier. This is the language of the controller name
+// that that the caller is requesting, and it must match one
+// of the languages specified in SupportedLanguages. The
+// number of languages supported by a driver is up to the
+// driver writer.
+// ControllerName - A pointer to the Unicode string to return. This Unicode
+// string is the name of the controller specified by
+// ControllerHandle and ChildHandle in the language
+// specified by Language from the point of view of the
+// driver specified by This.
+//
+// RETURNS:
+// EFI_SUCCESS - The Unicode string for the user readable name in the
+// language specified by Language for the driver
+// specified by This was returned in DriverName.
+// EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+// EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
+// EFI_HANDLE.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - ControllerName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This is not currently
+// managing the controller specified by
+// ControllerHandle and ChildHandle.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//<AMI_PHDR_END>
+//---------------------------------------------------------------------------
+
+EFI_STATUS
+CsmBlockIoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_EXT_PROTOCOL *LegacyBiosExt;
+ UINT8 BbsCount;
+ BBS_TABLE *BbsEntry;
+ UINT32 i;
+ EFI_HANDLE Handle;
+ CHAR8 *Str;
+ UINT8 Index = 0;
+
+ //
+ //Supports only "eng"
+ //
+ if (!Language || !ControllerName) return EFI_INVALID_PARAMETER;
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) return EFI_UNSUPPORTED;
+ if (ChildHandle == NULL) return EFI_UNSUPPORTED;
+
+ Status = pBS->LocateProtocol(&gEfiLegacyBiosExtProtocolGuid, NULL, (VOID**)&LegacyBiosExt);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = LegacyBiosExt->GetBbsTable(&BbsEntry, &BbsCount);
+ if (EFI_ERROR(Status)) return Status;
+
+ ZeroMemory(gCsmBlockIoControllerName, sizeof(gCsmBlockIoControllerName));
+
+ for (i = 0; i < MAX_BBS_ENTRIES_NO; i++, BbsEntry++) {
+ Handle = *(VOID**)(&BbsEntry->IBV1);
+ if (Handle == ChildHandle) {
+ Str = (CHAR8*)(UINTN)((BbsEntry->DescStringSegment<<4) + BbsEntry->DescStringOffset);
+ if (Str == NULL) return EFI_UNSUPPORTED;
+ //
+ // Transfer Ascii code to Unicode
+ //
+ while (Str[Index] != 0) {
+ gCsmBlockIoControllerName[Index] = (CHAR16)Str[Index];
+ Index++;
+ }
+
+ *ControllerName = gCsmBlockIoControllerName;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c
new file mode 100644
index 0000000..14438f5
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c
@@ -0,0 +1,1076 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlockIo.c 49 8/06/14 1:20p Fasihm $
+//
+// $Revision: 49 $
+//
+// $Date: 8/06/14 1:20p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlockIo.c $
+//
+// 49 8/06/14 1:20p Fasihm
+// [TAG] EIP180668
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Aptio 4 CSM: CsmBlkIO: Start function might incorrectly
+// initialize IBV fields in BBS table.
+// [Solution] Maintain the number of newly created BBS entries;
+// initialize IBV fields only for those entries created by the Option ROM.
+// [Files]
+// Core\EM\CSM\thunk\BlockIo\CsmBlockIo.c
+//
+// 48 12/23/13 3:38p Olegi
+// EIP128504: implement EFI_COMPONENT_NAME2_PROTOCOL for CsmBlockIo driver
+//
+// 47 12/23/13 3:14p Olegi
+// EIP148138: use AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL instead of
+// EFI_MBR_WRITE_PROTECTION_PROTOCOL
+//
+// 46 12/23/13 10:22a Olegi
+// EIP148123: CSM includes file which name has been changed
+//
+// 45 12/06/13 12:07a Rameshr
+// [TAG] EIP143793
+// [Category] Improvement
+// [Description] For onboard Raid controller, consumed
+// DevicePathProtocol - By driver and as a child controller, instead of
+// the PciIo Protocol. Because PciIo protocol us already consumed by
+// SataController driver.
+// [Files] CsmBlockIo.c
+//
+// 44 7/01/13 5:56a Kapilporwal
+// [TAG] EIP125560
+// [Category] Improvement
+// [Description] Please support Boot Sector Virus Protection for CSM
+// Disabled Mode
+// [Files] VirusProtect.c, VirusProtect.dxs, AhciBus.c,
+// AhciController.c, CsmBlockIo.c, CsmInt13.c, Ata.c, IdeBus.c,
+// SdioBlkIo.c, SdioDriver.c, efiusbmass.c
+//
+// 43 3/07/13 10:47p Olegi
+// [TAG] EIP117323
+// [Category] New Feature
+// [Description] Fiber Channel controllers support in CsmBlockIo
+//
+// 42 12/14/12 3:29p Olegi
+//
+// 41 12/23/11 2:12p Olegi
+// [TAG] EIP78921
+// [Category] Improvement
+// [Description] CsmBlockIo should create device handle in BBS table
+// [Files] CsmBlockIo.c
+// CsmBlockIo.h
+//
+// 39 11/10/11 7:15p Olegi
+// Installed thunk driver GUID
+//
+// 38 11/04/11 12:41p Olegi
+//
+// 37 8/15/11 9:45a Olegi
+//
+// 36 8/12/11 3:05p Olegi
+// Correction to the previous check-in: in Supported function some
+// protocols can not be open BY_DRIVER for the onboard RAID. Changed the
+// OpenProtocol attributes.
+//
+// 35 8/10/11 11:48a Olegi
+// GUID and variable names are corrected; Supported function modified to
+// close PciIo protocol right after it is used. EIP49352.
+//
+// 34 7/20/11 12:21p Olegi
+// Added dependency on the HDD security SDL token.
+//
+// 33 6/27/11 4:50p Olegi
+// Cleaning the headers and the comments. Change in Supported function
+// that partially undoing EIP39017 and allows non-Intel RAID option ROMs
+// produce BlkIo.
+//
+// 32 4/27/11 6:47p Olegi
+// [TAG] EIP54911
+// [Category] Improvement
+// [Description] Start function modified to return the proper value.
+// [Files] CsmBlockIo.c
+//
+// 31 1/19/11 10:19a Olegi
+//
+// 29 12/14/10 12:08p Olegi
+// [TAG] EIP48212
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Some controllers are not enabled before executing their
+// Option ROM
+// [RootCause] There is no code that enable a device in CsmBlockIo start
+// function.
+// [Solution] Added a call that enables device to the CsmBlockIo start
+// function.
+// [Files] CsmBlockIo.c, PciInterrupts.c
+//
+// 28 7/29/10 3:20p Olegi
+// EIP39017:: Added code in Supported function to prevent BlockIo from
+// binding prematurely.
+//
+// 27 3/12/10 9:49a Olegi
+// Onboard RAID option ROM related changes. EIP34602.
+//
+// 26 1/12/10 11:50a Olegi
+// Copyright message updated.
+//
+// 25 8/07/09 2:46p Rameshr
+// SD boot support Added.
+//
+// 24 10/04/07 3:04p Olegi
+// Bugfix in CsmBlockIoStart for HW interrupt save/restore in case of
+// multiple drives connected.
+//
+// 23 10/03/07 4:41p Yakovlevs
+// Removed Component Name Protocol and its Strings in NO DEBUG mode to
+// save some space.
+//
+// 22 4/27/07 5:14p Olegi
+// CSM.CHM file preparation.
+//
+// 21 4/13/07 9:37a Olegi
+//
+// 20 3/29/07 5:51p Olegi
+//
+// 19 3/29/07 1:37p Felixp
+// Bug fix in BuildDevicePath: properly initialize device path for unknown
+// devices
+//
+// 18 12/07/06 3:13p Olegi
+// Support for embedded OpROMs added.
+//
+// 17 7/31/06 4:11p Olegi
+//
+// 16 5/19/06 11:25p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 15 5/01/06 3:57p Olegi
+// CheckPciRom will be called from LegacyBios.InstallPciRom, no need to
+// call it again.
+//
+// 14 3/13/06 4:15p Felixp
+//
+// 13 3/13/06 2:38p Felixp
+//
+// 12 10/13/05 6:21p Olegi
+// Added HW interrupt handling
+//
+// 11 8/30/05 9:06a Olegi
+// BuildDevicePath correction.
+//
+// 10 7/26/05 2:51p Olegi
+//
+// 9 6/23/05 5:26p Olegi
+//
+// 8 6/22/05 8:34a Olegi
+//
+// 7 4/20/05 4:16p Olegi
+// INT 13 vector maintenance has been moved to the main CSM module.
+//
+// 6 4/12/05 12:21p Olegi
+//
+// 5 3/16/05 11:05a Olegi
+//
+// 4 3/04/05 1:45p Mandal
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: CsmBlockIo.c
+//
+// Description: CSM Block I/O Module. Main module, containing entry,
+// supported, start, and stop functions.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include "CsmBlockIo.h"
+#include <Protocol\Legacy8259.h>
+#include <Protocol\IdeControllerInit.h>
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+#include <Protocol\AmiBlockIoWriteProtection.h>
+AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL *gBlockIoWriteProtectionProtocol = NULL;
+#endif
+
+// EFI Driver Binding Protocol Instance
+EFI_DRIVER_BINDING_PROTOCOL gCsmBlockIoDriverBinding = {
+ CsmBlockIoSupported,
+ CsmBlockIoStart,
+ CsmBlockIoStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+EFI_GUID gComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+extern EFI_COMPONENT_NAME_PROTOCOL gCsmBlockIoComponentName;
+#else
+EFI_GUID gComponentNameProtocolGuid = EFI_COMPONENT_NAME2_PROTOCOL_GUID;
+extern EFI_COMPONENT_NAME2_PROTOCOL gCsmBlockIoComponentName;
+#endif
+
+// Number of current users of this driver
+UINTN mCurrentUsers = 0;
+
+// Real mode buffer to contain the buffers below
+EFI_PHYSICAL_ADDRESS mRealModeBuffer = 0;
+
+// Packet buffer under 1 MB for all version EDD calls
+EDD_DEVICE_ADDRESS_PACKET *mEDDPacketBuffer;
+
+// EDD 1.1 transfer buffer
+VOID *mEDDTransferBuffer;
+
+// This is a buffer for INT 13h func 48 information
+CSM_LEGACY_DRIVE *mDriveParameterBuffer;
+
+// The following variables will track the onboard mass storage controller
+// in RAID mode with the Option ROM that can not handle ATAPI devices:
+//
+// - gOnboardRaidGuid is GUID installed on such controller in SBDXE
+// - gOnboardRaid is the switch indicating the requested controller
+// has gOnboardRaidGuid installed on it
+//
+#define ONBOARD_RAID_GUID \
+ { 0x5d206dd3, 0x516a, 0x47dc, 0xa1, 0xbc, 0x6d, 0xa2, 0x4, 0xaa, 0xbe, 0x8};
+EFI_GUID gOnboardRaidGuid = ONBOARD_RAID_GUID;
+
+// The following GUID is used to ensure the Start function is executed after all
+// individual drives in RAID are unlocked before RAID Option ROM is executed
+//
+#define HDD_UNLOCKED_GUID \
+ { 0x1fd29be6, 0x70d0, 0x42a4, 0xa6, 0xe7, 0xe5, 0xd1, 0xe, 0x6a, 0xc3, 0x76};
+EFI_GUID gHddUnlockedGuid = HDD_UNLOCKED_GUID;
+
+
+//<AMI_PHDR_START>
+//**********************************************************************
+//
+// Procedure: CsmBlockIoEntryPoint
+//
+// Description:
+// This is the CsmBlockIo driver entry point. It installs
+// gCsmBlockIoDriverBinding protocol
+//
+//**********************************************************************
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CsmBlockIoEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+
+{
+ static EFI_GUID gCsmThunkDriverGuid =
+ { 0x2362ea9c, 0x84e5, 0x4dff, 0x83, 0xbc, 0xb5, 0xac, 0xec, 0xb5, 0x7c, 0xbb };
+
+ gCsmBlockIoDriverBinding.DriverBindingHandle = ImageHandle;
+ gCsmBlockIoDriverBinding.ImageHandle = ImageHandle;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ return pBS->InstallMultipleProtocolInterfaces(
+ &gCsmBlockIoDriverBinding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, &gCsmBlockIoDriverBinding,
+ &gComponentNameProtocolGuid, &gCsmBlockIoComponentName,
+ &gCsmThunkDriverGuid, NULL,
+ NULL
+ );
+}
+
+//<AMI_PHDR_START>
+//**********************************************************************
+//
+// Procedure: CsmBlockIoSupported
+//
+// Description:
+// This is a binding protocol function. It checks whether or not this
+// driver supports the given controller
+//
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller,
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+//
+//**********************************************************************
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CsmBlockIoSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_STD_DEVICE Pci;
+ VOID *IdeControllerInterface;
+
+ // See if the Legacy BIOS Protocol is available
+ Status = pBS->LocateProtocol( &gEfiLegacyBiosProtocolGuid,
+ NULL, (VOID**)&LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Check whether DevicePath Protocol has been installed on this controller
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ pBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+
+ // Check whether this is Onboard RAID
+ Status = pBS->OpenProtocol( Controller,
+ &gOnboardRaidGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ // Do the checkings/manipulations with the onboard RAID
+ if(!EFI_ERROR(Status))
+ {
+ // Make sure drives are unlocked
+#if defined SETUP_IDE_SECURITY_SUPPORT && SETUP_IDE_SECURITY_SUPPORT == 1
+ Status = pBS->OpenProtocol( Controller,
+ &gHddUnlockedGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+#endif
+ if(EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Make sure IDE_CONTROLLER_PROTOCOL is installed; this ensures the
+ // controller is initialized
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ // Check whether PCI Protocol has been installed on this controller
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID**)&PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if (EFI_ERROR(Status)) return Status;
+
+ // Read PCI configuration
+ Status = PciIo->Pci.Read (PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci);
+ if (EFI_ERROR(Status)) return Status;
+
+ pBS->CloseProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller );
+
+
+ // Status is EFI_SUCCESS here
+
+ if ( Pci.Header.ClassCode[2] != PCI_CL_MASS_STOR && \
+ (Pci.Header.ClassCode[2] != PCI_BASE_CLASS_INTELLIGENT || \
+ Pci.Header.ClassCode[1] != PCI_SUB_CLASS_INTELLIGENT) )
+ {
+ Status = EFI_UNSUPPORTED;
+ }
+ if ( Pci.Header.ClassCode[1] == PCI_CL_SYSTEM_PERIPHERALS_SCL_SD && \
+ Pci.Header.ClassCode[2] == PCI_CL_SYSTEM_PERIPHERALS )
+ {
+ Status = EFI_SUCCESS;
+ }
+ if ( Pci.Header.ClassCode[1] == PCI_CL_SER_BUS_SCL_FIBCHAN &&
+ Pci.Header.ClassCode[2] == PCI_CL_SER_BUS )
+ {
+ Status = EFI_SUCCESS;
+ }
+
+// TRACE((-1, "\nCsmBlockIo.Supported: called for VID/DID: %x %x, CL %x SCL %x; Status = %r\n",
+// Pci.Header.VendorId, Pci.Header.DeviceId, Pci.Header.ClassCode[2], Pci.Header.ClassCode[1], Status));
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//**********************************************************************
+//
+// Procedure: CsmBlockIoStart
+//
+// Description:
+// Installs BlockIoProtocol using INT13 services produced by Option ROM
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller,
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Open PCI and Devicepath protocol
+// 2. Enable the device
+// 3. Post the option rom
+// 4. If first time, allocate buffer for real mode thunk code
+// 5. For each disk...
+// a. Allocate and initialize a private structure
+// b. Install block I/O protocol on a new child device
+// c. Open the child device
+// 6. Increment user counter
+//
+//**********************************************************************
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CsmBlockIoStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_PCI_IO_PROTOCOL *PciIo = NULL;
+ UINT8 FirstDisk;
+ UINT8 LastDisk;
+ UINT8 x = 0;
+ CSM_BLOCK_IO_DEV *PrivateBlockIoStruc = NULL;
+ EFI_DEVICE_PATH_PROTOCOL *PciDevPath;
+ UINTN i = 0;
+ UINTN Flags;
+ UINTN TempAddress = 0;
+ UINT8 irq = 0;
+ EFI_LEGACY_8259_PROTOCOL *i8259;
+ UINT32 *ivt = (UINT32*)0;
+ UINT32 TempInt;
+ UINT32 HwInterruptHandler;
+ UINT64 Capabilities;
+ UINT8 j = 0;
+ UINT8 BbsCount;
+ BBS_TABLE* BbsEntry = NULL;
+ BBS_TABLE* BbsTable = NULL;
+ BOOLEAN BbsEntryPresent[MAX_BBS_ENTRIES_NO] = {0};
+ UINTN FirstNewBbsEntry = 0;
+ EFI_LEGACY_BIOS_EXT_PROTOCOL *LegacyBiosExt;
+ BOOLEAN OnboardRaidController=FALSE;
+ EFI_DEVICE_PATH_PROTOCOL *ChildPciDevPath;
+ UINT8 NumberOfBbsEntriesBeforeOprom = 0;
+ UINT8 NumberOfBbsEntriesAfterOprom = 0;
+ UINT8 NewBbsEntries;
+
+ // See if the Legacy BIOS Protocol is available
+ Status = pBS->LocateProtocol( &gEfiLegacyBiosProtocolGuid,
+ NULL, (VOID **)&LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // See if the Legacy BIOS Ext Protocol is available
+ Status = pBS->LocateProtocol ( &gEfiLegacyBiosExtProtocolGuid,
+ NULL, (VOID**)&LegacyBiosExt);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+ if(gBlockIoWriteProtectionProtocol == NULL)
+ pBS->LocateProtocol(&gAmiBlockIoWriteProtectionProtocolGuid, NULL, &gBlockIoWriteProtectionProtocol);
+#endif
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&PciDevPath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Check whether this is Onboard RAID
+ Status = pBS->OpenProtocol( Controller,
+ &gOnboardRaidGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if (!EFI_ERROR (Status)) {
+ OnboardRaidController=TRUE;
+ }
+
+ // Open PCI I/O Protocol
+ if (OnboardRaidController) {
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+
+ } else {
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ }
+
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+
+ // Get the hardware interrupt vector and its handler pointer
+ Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint8, 0x3C, 1, &irq);
+ ASSERT_EFI_ERROR(Status);
+ if (irq > 0 && irq < 0xF) {
+ Status = pBS->LocateProtocol(&gEfiLegacy8259ProtocolGuid, NULL, &i8259);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = i8259->GetVector (i8259, irq, &irq); // irq has INT number
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ // Store HW interrupt vector, to be restored for PnP ROMs
+ TempInt = ivt[irq];
+
+ // Enable the device
+ Status = PciIo->Attributes (PciIo,
+ EfiPciIoAttributeOperationSupported, 0,
+ &Capabilities); // Get device capabilities
+
+ ASSERT_EFI_ERROR(Status);
+
+ Status = PciIo->Attributes (PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Capabilities & EFI_PCI_DEVICE_ENABLE,
+ NULL); // Enable device
+ ASSERT_EFI_ERROR(Status);
+
+ // Check to see if there is a legacy option ROM image associated with this PCI device
+ Status = LegacyBios->CheckPciRom (LegacyBios,
+ Controller,
+ NULL,
+ NULL,
+ &Flags
+ );
+
+ if ( EFI_ERROR(Status) ) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ // Get BBS table
+ Status = LegacyBiosExt->GetBbsTable(
+ &BbsEntry,
+ &BbsCount);
+ ASSERT_EFI_ERROR(Status);
+ BbsTable = BbsEntry;
+
+ // Loop through table and note entries which are populated
+ for (i = 0; i < MAX_BBS_ENTRIES_NO; i++, BbsEntry++) {
+
+ if (BbsEntry->BootPriority == BBS_IGNORE_ENTRY)
+ continue;
+
+ BbsEntryPresent[i] = TRUE;
+ NumberOfBbsEntriesBeforeOprom++;
+ }
+
+ // Post the legacy option ROM if it is available.
+ Status = LegacyBios->InstallPciRom( LegacyBios,
+ Controller,
+ NULL,
+ &Flags,
+ &FirstDisk,
+ &LastDisk,
+ NULL,
+ NULL );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ BbsEntry = BbsTable;
+
+ // Loop through BBS table and find first new entry, added due to OpROM execution
+ for (i = 0; i < MAX_BBS_ENTRIES_NO; i++, BbsEntry++) {
+ if (BbsEntry->BootPriority == BBS_IGNORE_ENTRY)
+ continue;
+ if ((BbsEntryPresent[i] == FALSE) && (FirstNewBbsEntry == 0)) {
+ FirstNewBbsEntry = i;
+ }
+ NumberOfBbsEntriesAfterOprom++;
+ }
+
+ ASSERT(NumberOfBbsEntriesAfterOprom >= NumberOfBbsEntriesBeforeOprom);
+ NewBbsEntries = NumberOfBbsEntriesAfterOprom - NumberOfBbsEntriesBeforeOprom;
+
+ HwInterruptHandler = ivt[irq];
+
+ // All users share a buffer under 1MB to put real mode thunk code in
+ // If it has not been allocated, then we allocate it.
+ if (mRealModeBuffer == 0) {
+ // Allocate below 1MB
+ mRealModeBuffer = 0x00000000000FFFFF;
+ Status = pBS->AllocatePages( AllocateMaxAddress,
+ EfiBootServicesData,
+ BLOCK_IO_BUFFER_PAGE_SIZE,
+ &mRealModeBuffer );
+
+ // Check memory allocation success
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ mRealModeBuffer = 0;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ // Set up real mode memory for Thunk
+ TempAddress = (UINTN)mRealModeBuffer;
+ // Setup the EDD 1.1 transfer buffer
+ TempAddress += AlignAddress(TempAddress);
+ mEDDTransferBuffer = (VOID *)(TempAddress);
+ // Setup the Legacy Drive buffer
+ TempAddress += MAX_EDD11_XFER;
+ TempAddress += AlignAddress(TempAddress);
+ mDriveParameterBuffer = (CSM_LEGACY_DRIVE *)(TempAddress);
+ // Setup the EDD Packet buffer
+ TempAddress += sizeof (CSM_LEGACY_DRIVE);
+ TempAddress += AlignAddress(TempAddress);
+ mEDDPacketBuffer = (EDD_DEVICE_ADDRESS_PACKET *)TempAddress;
+ }
+
+ // Allocate the private device structure for each disk
+ for (i = FirstDisk, j = 0; i < LastDisk; i++, j++) {
+
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ sizeof (CSM_BLOCK_IO_DEV),
+ &PrivateBlockIoStruc );
+
+ if (EFI_ERROR(Status)) {
+ pBS->CloseProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller );
+
+ pBS->CloseProtocol( Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller );
+
+ if (mRealModeBuffer != 0 && mCurrentUsers == 0) {
+ pBS->FreePages (mRealModeBuffer, BLOCK_IO_BUFFER_PAGE_SIZE);
+ mRealModeBuffer = 0;
+ }
+
+ return Status;
+ }
+
+ // Zero the private device structure
+ ZeroMemory (PrivateBlockIoStruc, sizeof (CSM_BLOCK_IO_DEV));
+
+ // Initialize the private device structure
+ PrivateBlockIoStruc->ControllerHandle = Controller;
+ PrivateBlockIoStruc->LegacyBios = LegacyBios;
+ PrivateBlockIoStruc->PciIo = PciIo;
+
+ PrivateBlockIoStruc->Drive.Floppy = FALSE;
+ x = (i & 0x40)? 0x40 : 0;
+ if (x) {
+ PrivateBlockIoStruc->HwInt = irq;
+ PrivateBlockIoStruc->HwIntHandler = HwInterruptHandler;
+ ivt[irq] = TempInt; // Restore HW interrupt
+ }
+ PrivateBlockIoStruc->Drive.Number = (UINT8) i - x;
+ PrivateBlockIoStruc->Drive.Letter = (UINT8)(i - x - 0x80 + 'C');
+ PrivateBlockIoStruc->BlockMedia.RemovableMedia = FALSE;
+
+ if (InitBlockIo (PrivateBlockIoStruc)) {
+ BuildDevicePath( PciDevPath,
+ &PrivateBlockIoStruc->Drive,
+ &PrivateBlockIoStruc->DevicePath);
+
+ // Install the Block Io Protocol onto a new child handle
+ Status = pBS->InstallMultipleProtocolInterfaces( &PrivateBlockIoStruc->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &PrivateBlockIoStruc->BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ PrivateBlockIoStruc->DevicePath,
+ NULL );
+ if (EFI_ERROR (Status)) {
+ pBS->FreePool (PrivateBlockIoStruc);
+ }
+
+ // Set handle to which BlockIO has been installed
+ if (j < NewBbsEntries)
+ {
+ *(UINTN*)(&(BbsTable[FirstNewBbsEntry + j].IBV1)) = (UINTN)(PrivateBlockIoStruc->Handle);
+ }
+ if(OnboardRaidController) {
+ // Open For Child Device
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&ChildPciDevPath,
+ This->DriverBindingHandle,
+ PrivateBlockIoStruc->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER );
+
+ } else {
+
+ // Open For Child Device
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID**)&PrivateBlockIoStruc->PciIo,
+ This->DriverBindingHandle,
+ PrivateBlockIoStruc->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER );
+ }
+ } else {
+ pBS->FreePool (PrivateBlockIoStruc);
+ }
+ } // end for loop
+
+ mCurrentUsers++;
+
+ return Status;
+
+Done:
+ pBS->CloseProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller );
+ pBS->CloseProtocol( Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller );
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//**********************************************************************
+//
+// Procedure: CsmBlockIoStop
+//
+// Description: Installs IdeControllerProtocol
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller,
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Decrement user counter
+// 2. Free global buffer
+// 3. Release PCI I/O protocol and Block I/O protocol for each child handle.
+// 4. Shut down the hardware for each child handle.
+//
+//**********************************************************************
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CsmBlockIoStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+)
+{
+ EFI_STATUS Status;
+ BOOLEAN AllChildrenStopped;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ CSM_BLOCK_IO_DEV *PrivateBlockIoStruc;
+ UINTN i;
+ BOOLEAN OnboardRaidController=FALSE;
+
+ // Decrement the number of current users
+ mCurrentUsers--;
+
+ if (mCurrentUsers == 0) {
+ // Free our global buffer
+ Status = pBS->FreePages (mRealModeBuffer, BLOCK_IO_BUFFER_PAGE_SIZE);
+ ASSERT_EFI_ERROR (Status);
+ mRealModeBuffer = 0;
+ }
+
+ // Check whether this is Onboard RAID
+ Status = pBS->OpenProtocol( Controller,
+ &gOnboardRaidGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if (!EFI_ERROR (Status)) {
+ OnboardRaidController=TRUE;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ // Close protocols and shut down hardware for each child handle.
+ for (i = 0; i < NumberOfChildren; i++) {
+
+ Status = pBS->OpenProtocol( ChildHandleBuffer[i],
+ &gEfiBlockIoProtocolGuid,
+ (VOID**)&BlockIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PrivateBlockIoStruc = (CSM_BLOCK_IO_DEV *) BlockIo;
+
+ if(OnboardRaidController) {
+ pBS->CloseProtocol( Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[i] );
+ }
+
+ // Release PCI I/O and Block IO Protocols on the clild handle.
+ Status = pBS->UninstallMultipleProtocolInterfaces( ChildHandleBuffer[i],
+ &gEfiBlockIoProtocolGuid,
+ &PrivateBlockIoStruc->BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ PrivateBlockIoStruc->DevicePath,
+ NULL );
+
+ if (EFI_ERROR(Status)) {
+ AllChildrenStopped = FALSE;
+ }
+
+ // Shutdown the hardware
+ PrivateBlockIoStruc->PciIo->Attributes (
+ PrivateBlockIoStruc->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL);
+
+
+ if(!OnboardRaidController) {
+ pBS->CloseProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[i] );
+ }
+
+ pBS->FreePool (PrivateBlockIoStruc);
+ } // end for loop
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = pBS->CloseProtocol( Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller );
+
+ if(!OnboardRaidController) {
+ Status = pBS->CloseProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+// LOCAL FUNCTIONS
+//**********************************************************************
+
+//<AMI_PHDR_START>
+//**********************************************************************
+//
+// Procedure: BuildDevicePath
+//
+// Description: Builds device path for this device
+//
+// Input:
+// IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+// IN CSM_LEGACY_DRIVE *Drive,
+// OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Decrement user counter
+// 2. Free global buffer
+// 3. Release PCI I/O protocol and Block I/O protocol for each child handle.
+// 4. Shut down the hardware for each child handle.
+//
+//**********************************************************************
+//<AMI_PHDR_END>
+
+VOID
+BuildDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN CSM_LEGACY_DRIVE *Drive,
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+)
+{
+ EFI_GUID UnknownDevGuid = UNKNOWN_DEVICE_GUID; // ditto
+ EFI_DEV_PATH Node;
+ UINT32 Controller;
+
+ Node.DevPath.Type = 0;
+ if (Drive->EddVersion == EDD_VERSION_30 &&
+ Drive->Parameters.StructureSize > 0x1A &&
+ *(UINT32*)Drive->Parameters.InterfaceType != 0) {
+ // Build device path for EDD 3.0 device
+ Controller = (UINT32)Drive->Parameters.InterfacePath.Pci.Controller;
+ if ((MemCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) ||
+ (MemCmp ("ATA", Drive->Parameters.InterfaceType, 3) == 0)) {
+ // ATA or ATAPI drive found
+ Node.Atapi.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.Atapi.Header.SubType = MSG_ATAPI_DP;
+ SET_NODE_LENGTH(&Node.Atapi.Header,sizeof(ATAPI_DEVICE_PATH));
+ Node.Atapi.SlaveMaster = Drive->Parameters.DevicePath.Atapi.Master;
+ Node.Atapi.Lun = Drive->Parameters.DevicePath.Atapi.Lun;
+ Node.Atapi.PrimarySecondary = (UINT8)Controller;
+ } else {
+ // Not an ATA/ATAPI drive
+ if (Controller != 0) {
+ Node.Controller.Header.Type = HARDWARE_DEVICE_PATH;
+ Node.Controller.Header.SubType = HW_CONTROLLER_DP;
+ SET_NODE_LENGTH(&Node.Controller.Header,sizeof(CONTROLLER_DEVICE_PATH));
+ Node.Controller.Controller = Controller;
+ *DevicePath = DPAddNode (BaseDevicePath, &Node.DevPath);
+ Node.DevPath.Type = 0;
+ }
+ // Since it's not ATA/ATAPI, find out what kind it is
+ if (MemCmp("SCSI", Drive->Parameters.InterfaceType, 4) == 0 ) {
+ // SCSI drive
+ Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.Scsi.Header.SubType = MSG_SCSI_DP;
+ SET_NODE_LENGTH(&Node.Scsi.Header,sizeof(SCSI_DEVICE_PATH));
+ Node.Scsi.Lun = (UINT16)Drive->Parameters.DevicePath.Scsi.Lun;
+ Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.TargetId;
+ } else if (MemCmp("USB", Drive->Parameters.InterfaceType, 3) == 0 ) {
+ // USB drive
+ Node.Usb.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.Usb.Header.SubType = MSG_USB_DP;
+ SET_NODE_LENGTH(&Node.Usb.Header,sizeof(USB_DEVICE_PATH));
+ Node.Usb.ParentPortNumber = (UINT8)Drive->Parameters.DevicePath.Usb.Reserved;
+ } else if (MemCmp("1394", Drive->Parameters.InterfaceType, 4) == 0 ) {
+ // 1394 drive
+ Node.F1394.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.F1394.Header.SubType = MSG_1394_DP;
+ SET_NODE_LENGTH(&Node.F1394.Header,sizeof(F1394_DEVICE_PATH));
+ Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid;
+ } else if (MemCmp("FIBRE", Drive->Parameters.InterfaceType, 5) == 0 ) {
+ // Fibre Channel drive
+ Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP;
+ SET_NODE_LENGTH(&Node.FibreChannel.Header,sizeof(FIBRECHANNEL_DEVICE_PATH));
+ Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn;
+ Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun;
+ }
+ }
+ }
+ // If Device Path Type is still zero, it means this is either EDD 1.1 device
+ // or unreconized EDD 3.0 device. Add vendor HW device node for such devices
+ if (Node.DevPath.Type == 0) {
+ Node.UnknownVendor.DevicePath.Header.Type = HARDWARE_DEVICE_PATH;
+ Node.UnknownVendor.DevicePath.Header.SubType = HW_VENDOR_DP;
+ SET_NODE_LENGTH(&Node.UnknownVendor.DevicePath.Header,sizeof(UNKNOWN_DEVICE_VENDOR_DEVICE_PATH));
+ Node.UnknownVendor.DevicePath.Guid = UnknownDevGuid;
+ Node.UnknownVendor.LegacyDriveLetter = Drive->Number;
+ }
+ *DevicePath = DPAddNode (BaseDevicePath, &Node.DevPath);
+}
+
+// Align address on boundary of UINTN for this compiler
+UINTN AlignAddress (UINTN Address)
+{
+ if((UINTN)Address % sizeof(UINTN)) {
+ return sizeof(UINTN) - ((UINTN)Address % sizeof(UINTN));
+ } else {
+ return 0;
+ }
+}
+
+// Zero memory
+VOID ZeroMemory (
+ VOID *Buffer,
+ UINTN Size
+)
+{
+ UINT8 *Ptr;
+ Ptr = Buffer;
+ while (Size--) {
+ *(Ptr++) = 0;
+ }
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h
new file mode 100644
index 0000000..59ce30b
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h
@@ -0,0 +1,277 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlockIo.h 10 12/23/11 2:12p Olegi $
+//
+// $Revision: 10 $
+//
+// $Date: 12/23/11 2:12p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmBlockIo.h $
+//
+// 10 12/23/11 2:12p Olegi
+// [TAG] EIP78921
+// [Category] Improvement
+// [Description] CsmBlockIo should create device handle in BBS table
+// [Files] CsmBlockIo.c
+// CsmBlockIo.h
+//
+// 9 6/27/11 4:50p Olegi
+//
+// 8 1/12/10 11:50a Olegi
+// Copyright message updated.
+//
+// 7 9/23/09 11:18a Olegi
+//
+// 6 8/07/09 2:46p Rameshr
+// SD boot support Added.
+//
+// 5 10/03/07 4:42p Yakovlevs
+// Removed Component Name Protocol and its Strings in NO DEBUG mode to
+// save some space.
+//
+// 4 4/27/07 5:14p Olegi
+// CSM.CHM file preparation.
+//
+// 3 3/13/06 2:38p Felixp
+//
+// 2 3/04/05 1:45p Mandal
+//
+// 1 2/15/05 11:00a Olegi
+// Initial VSS check-in.
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: CsmBlockIo.h
+//
+// Description: CSM BlockIO driver header file.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifndef _CsmBlockIo_
+#define _CsmBlockIo_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Efi.h>
+#include <Token.h>
+#include <Dxe.h>
+#include <PCI.h>
+#include <AmiDxeLib.h>
+#include <Protocol\PciIo.h>
+#include <Protocol\DevicePath.h>
+#include <Protocol\LegacyBios.h>
+#include <Protocol\LegacyBiosExt.h>
+#include <protocol\DriverBinding.h>
+#include <Protocol\ComponentName.h>
+#include <protocol\BlockIo.h>
+
+#include "CsmEdd.h"
+
+
+// Global Variables
+#if EFI_DEBUG
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName;
+#endif
+
+
+// Define the I2O class code
+
+#define PCI_BASE_CLASS_INTELLIGENT 0x0e
+#define PCI_SUB_CLASS_INTELLIGENT 0x00
+
+// SD class/subclass defined in PCI.H in 4.6.3.7
+#ifndef PCI_CL_SYSTEM_PERIPHERALS
+#define PCI_CL_SYSTEM_PERIPHERALS 0x08
+#endif
+#ifndef PCI_CL_SYSTEM_PERIPHERALS_SCL_SD
+#define PCI_CL_SYSTEM_PERIPHERALS_SCL_SD 0x05
+#endif
+
+
+// Number of pages needed for our buffer under 1MB
+
+#define BLOCK_IO_BUFFER_PAGE_SIZE (((sizeof (EDD_DEVICE_ADDRESS_PACKET) + sizeof (CSM_LEGACY_DRIVE) + MAX_EDD11_XFER) / EFI_PAGE_SIZE) + 1)
+
+
+// PROTOTYPES
+
+// Driver Binding Protocol functions
+
+EFI_STATUS
+CsmBlockIoSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+CsmBlockIoStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+CsmBlockIoStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+// Block I/O functions
+
+EFI_STATUS
+CsmBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+EFI_STATUS
+CsmBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+// These prototypes aren't actually used -- they are the generic for the specific
+// functions below
+EFI_STATUS
+CsmBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+CsmBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+// Specific read/write function prototypes
+EFI_STATUS
+Edd30CsmReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+Edd30CsmWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+Edd11CsmReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+Edd11CsmWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+LegacyCsmReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+LegacyCsmWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+// Local support function prototypes
+BOOLEAN
+InitBlockIo (
+ IN CSM_BLOCK_IO_DEV *Dev
+ );
+
+// Local function prototypes
+VOID
+BuildDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN CSM_LEGACY_DRIVE *Drive,
+ IN EFI_DEVICE_PATH_PROTOCOL **DevPath
+ );
+
+EFI_DEVICE_PATH_PROTOCOL *
+AppendDevicePathNode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath,
+ IN EFI_DEVICE_PATH_PROTOCOL *Node
+ );
+
+UINTN AlignAddress (
+ UINTN Address
+ );
+
+VOID ZeroMemory (
+ VOID *Buffer,
+ UINTN Size
+);
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl
new file mode 100644
index 0000000..ac17f94
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = "CsmBlockIo_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable CsmBlockIo support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "CSMBLOCKIO_DIR"
+ Help = "CSM BLOCK I/O source directory"
+End
+
+MODULE
+ Help = "Includes CsmBlockIo.mak to Project"
+ File = "biosblkio.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\biosblkio.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/EM/CSM/thunk/BlockIo/CsmEdd.h b/Core/EM/CSM/thunk/BlockIo/CsmEdd.h
new file mode 100644
index 0000000..0c9ff4c
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/CsmEdd.h
@@ -0,0 +1,407 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmEdd.h 7 1/12/10 11:50a Olegi $
+//
+// $Revision: 7 $
+//
+// $Date: 1/12/10 11:50a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmEdd.h $
+//
+// 7 1/12/10 11:50a Olegi
+// Copyright message updated.
+//
+// 6 4/27/07 5:14p Olegi
+// CSM.CHM file preparation.
+//
+// 5 3/13/06 2:38p Felixp
+//
+// 4 10/13/05 6:21p Olegi
+//
+// 3 4/20/05 4:54p Andriyn
+// USB_DEVICE_PATH is in core now
+//
+// 2 3/04/05 1:45p Mandal
+//
+// 1 2/15/05 11:00a Olegi
+// Initial VSS check-in.
+//
+//
+//**********************************************************************
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: CsmEdd.h
+//
+// Description: EDD support definitions file
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifndef _CSM_EDD_H_
+#define _CSM_EDD_H_
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 Controller;
+ UINT32 Reserved;
+} EDD_PCI;
+
+typedef struct {
+ UINT16 Base;
+ UINT16 Reserved;
+ UINT32 Reserved2;
+} EDD_LEGACY;
+
+typedef union {
+ EDD_PCI Pci;
+ EDD_LEGACY Legacy;
+} EDD_INTERFACE_PATH;
+
+typedef struct {
+ UINT8 Master;
+ UINT8 Reserved[15];
+} EDD_ATA;
+
+typedef struct {
+ UINT8 Master;
+ UINT8 Lun;
+ UINT8 Reserved[14];
+} EDD_ATAPI;
+
+typedef struct {
+ UINT16 TargetId;
+ UINT64 Lun;
+ UINT8 Reserved[6];
+} EDD_SCSI;
+
+typedef struct {
+ UINT64 SerialNumber;
+ UINT64 Reserved;
+} EDD_USB;
+
+typedef struct {
+ UINT64 Guid;
+ UINT64 Reserved;
+} EDD_1394;
+
+typedef struct {
+ UINT64 Wwn;
+ UINT64 Lun;
+} EDD_FIBRE;
+
+typedef union {
+ EDD_ATA Ata;
+ EDD_ATAPI Atapi;
+ EDD_SCSI Scsi;
+ EDD_USB Usb;
+ EDD_1394 FireWire;
+ EDD_FIBRE FibreChannel;
+} EDD_DEVICE_PATH;
+
+typedef struct _UNKNOWN_VENDOR_DEVICE_PATH {
+ VENDOR_DEVICE_PATH DevicePath;
+ UINT8 LegacyDriveLetter;
+} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH;
+
+//typedef struct _CONTROLLER_DEVICE_PATH {
+// EFI_DEVICE_PATH_PROTOCOL Header;
+// UINT32 Controller;
+//} CONTROLLER_DEVICE_PATH;
+
+//typedef struct _ATAPI_DEVICE_PATH {
+// EFI_DEVICE_PATH_PROTOCOL Header;
+// UINT8 Channel;
+// UINT8 Device;
+// UINT16 Lun;
+//} ATAPI_DEVICE_PATH;
+
+//typedef struct _SCSI_DEVICE_PATH {
+// EFI_DEVICE_PATH_PROTOCOL Header;
+// UINT16 TargetId;
+// UINT16 Lun;
+//} SCSI_DEVICE_PATH;
+
+//typedef struct _FIBRE_CHANNEL_DEVICE_PATH {
+// EFI_DEVICE_PATH_PROTOCOL Header;
+// UINT32 Reserved;
+// UINT64 WorldWideNumber;
+// UINT64 Lun;
+//} FIBRECHANNEL_DEVICE_PATH;
+
+//typedef struct _F1394_DEVICE_PATH {
+// EFI_DEVICE_PATH_PROTOCOL Header;
+// UINT32 Reserved;
+// UINT64 _1394Guid;
+//} F1394_DEVICE_PATH;
+/* AndriyN : must belong to DevicePath.h
+typedef struct _USB_DEVICE_PATH {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ UINT8 ParentPortNumber;
+ UINT8 InterfaceNumber;
+} USB_DEVICE_PATH;
+*/
+
+// Union of all possible device paths
+typedef union {
+ EFI_DEVICE_PATH_PROTOCOL DevPath;
+ PCI_DEVICE_PATH Pci;
+// PCCARD_DEVICE_PATH PcCard;
+// MEMMAP_DEVICE_PATH MemMap;
+ VENDOR_DEVICE_PATH Vendor;
+ UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UnknownVendor;
+ CONTROLLER_DEVICE_PATH Controller;
+// ACPI_HID_DEVICE_PATH Acpi;
+ ACPI_HID_DEVICE_PATH Acpi;
+ ATAPI_DEVICE_PATH Atapi;
+ SCSI_DEVICE_PATH Scsi;
+ FIBRECHANNEL_DEVICE_PATH FibreChannel;
+ F1394_DEVICE_PATH F1394;
+ USB_DEVICE_PATH Usb;
+ USB_CLASS_DEVICE_PATH UsbClass;
+ I20_DEVICE_PATH I20;
+// MAC_ADDR_DEVICE_PATH MacAddr;
+ IPv4_DEVICE_PATH Ipv4;
+ IPv6_DEVICE_PATH Ipv6;
+ INFINIBAND_DEVICE_PATH InfiniBand;
+ UART_DEVICE_PATH Uart;
+ HARDDRIVE_DEVICE_PATH HardDrive;
+ CDROM_DEVICE_PATH CD;
+// FILEPATH_DEVICE_PATH FilePath;
+// MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol;
+// BBS_BBS_DEVICE_PATH Bbs;
+} EFI_DEV_PATH;
+
+#define HARDWARE_DEVICE_PATH 0x01
+#define HW_VENDOR_DP 0x04
+#define MESSAGING_DEVICE_PATH 0x03
+#define MSG_ATAPI_DP 0x01
+#define HW_CONTROLLER_DP 0x05
+#define MSG_SCSI_DP 0x02
+#define MSG_1394_DP 0x04
+#define MSG_FIBRECHANNEL_DP 0x03
+
+typedef struct {
+ UINT16 StructureSize;
+ UINT16 Flags;
+ UINT32 MaxCylinders;
+ UINT32 MaxHeads;
+ UINT32 SectorsPerTrack;
+ UINT64 PhysicalSectors;
+ UINT16 BytesPerSector;
+ UINT32 FDPT;
+ UINT16 Key;
+ UINT8 DevicePathLength;
+ UINT8 Reserved1;
+ UINT16 Reserved2;
+ CHAR8 HostBusType[4];
+ CHAR8 InterfaceType[8];
+ EDD_INTERFACE_PATH InterfacePath;
+ EDD_DEVICE_PATH DevicePath;
+ UINT8 Reserved3;
+ UINT8 Checksum;
+} EDD_DRIVE_PARAMETERS;
+
+// Flag definitions for above
+#define EDD_GEOMETRY_VALID 0x02
+#define EDD_DEVICE_REMOVABLE 0x04
+#define EDD_WRITE_VERIFY_SUPPORTED 0x08
+#define EDD_DEVICE_CHANGE 0x10
+#define EDD_DEVICE_LOCKABLE 0x20
+
+// For WIN98 limitation
+#define EDD_DEVICE_GEOMETRY_MAX 0x40
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: EDD_DEVICE_ADDRESS_PACKET
+//
+// Description: Device address packet used during EDD data transfers
+//
+// Fields:
+// PacketSizeInBytes UINT8 Packet size in bytes
+// Zero UINT8
+// NumberOfBlocks UINT8 # of blocks to transfer
+// Zero2 UINT8
+// SegOffset UINT32 Data address below 1MB
+// LBA UINT64 Device Logical Block Address
+// TransferBuffer UINT64 Transfer Buffer
+// ExtendedBlockCount UINT32 Transferred blocks counter
+// Zero3 UINT32
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ UINT8 PacketSizeInBytes; // 0x18
+ UINT8 Zero;
+ UINT8 NumberOfBlocks; // Max 0x7f
+ UINT8 Zero2;
+ UINT32 SegOffset;
+ UINT64 LBA;
+ UINT64 TransferBuffer;
+ UINT32 ExtendedBlockCount; // Max 0xffffffff
+ UINT32 Zero3;
+} EDD_DEVICE_ADDRESS_PACKET;
+
+#define UNKNOWN_DEVICE_GUID \
+ { 0xcf31fac5, 0xc24e, 0x11d2, 0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b }
+
+#define EDD_VERSION_30 0x30
+
+// Int 13 Error Messages
+#define ERR_PASS 0x00
+#define ERR_WRITE_PROTECTED 0x03
+#define ERR_SECTOR_NOT_FOUND 0x04
+#define ERR_RESET_FAILED 0x05
+#define ERR_DISK_CHANGED 0x06
+#define ERR_DRIVE_DOES_NOT_EXIST 0x07
+#define ERR_DMA_ERROR 0x08
+#define ERR_DATA_BOUNADRY_ERROR 0x09
+#define ERR_BAD_SECTOR 0x0a
+#define ERR_BAD_TRACK 0x0b
+#define ERR_MEDIA_TYPE_NOT_FOUND 0x0c
+#define ERR_INVALID_FORMAT 0x0d
+#define ERR_ECC_ERROR 0x10
+#define ERR_ECC_CORRECTED_ERROR 0x11
+#define ERR_HARD_DRIVE_FAILURE 0x20
+#define ERR_SEEK_FAILED 0x40
+#define ERR_DRIVE_TIMEOUT 0x80
+#define ERR_DRIVE_NOT_READY 0xaa
+#define ERR_UNDEFINED_ERROR 0xbb
+#define ERR_WRITE_FAULT 0xcc
+#define ERR_SENSE_FAILED 0xff
+
+#define MAX_EDD11_XFER 0xfe00
+
+// PCI classes not defined in PCI.h
+#define PCI_BASE_CLASS_INTELLIGENT 0x0e
+#define PCI_SUB_CLASS_INTELLIGENT 0x00
+
+#define EFI_SEGMENT(_Adr) (UINT16)((UINT16) (((UINTN)(_Adr)) >> 4) & 0xf000)
+#define EFI_OFFSET(_Adr) (UINT16)(((UINT16)((UINTN)_Adr)) & 0xffff)
+
+#pragma pack()
+
+// Local data structures
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: CSM_LEGACY_DRIVE
+//
+// Description: Hard drive data structure
+//
+// Fields:
+// Letter CHAR8 Drive letter
+// Number UINT8 INT13 drive handle
+// EddVersion UINT8 EDD version supported by the drive
+// ExtendedInt13 BOOLEAN Extended INT13 support status
+// DriveLockingAndEjecting BOOLEAN Locking/Ejecting support
+// Edd BOOLEAN EDD support status
+// Extensions64Bit BOOLEAN 64 bit extension support
+// ParametersValid BOOLEAN Valid parameters (Parameters field) indicator
+// ErrorCode UINT8 Error code field
+// FdptPointer VOID* Pointer to FDPT
+// Floppy BOOLEAN Device-is-a-floppy indicator
+// AtapiFloppy BOOLEAN Device-is-an-ATAPI-floppy indicator
+// MaxHead UINT8 Number of heads
+// MaxSector UINT8 Number of sectors
+// MaxCylinder UINT16 Number of cylinders
+// Pad UINT16
+// Parameters EDD_DRIVE_PARAMETERS EDD drive parameters
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ CHAR8 Letter;
+ UINT8 Number;
+ UINT8 EddVersion;
+ BOOLEAN ExtendedInt13;
+ BOOLEAN DriveLockingAndEjecting;
+ BOOLEAN Edd;
+ BOOLEAN Extensions64Bit;
+ BOOLEAN ParametersValid;
+ UINT8 ErrorCode;
+ VOID *FdptPointer;
+ BOOLEAN Floppy;
+ BOOLEAN AtapiFloppy;
+ UINT8 MaxHead;
+ UINT8 MaxSector;
+ UINT16 MaxCylinder;
+ UINT16 Pad;
+ EDD_DRIVE_PARAMETERS Parameters;
+} CSM_LEGACY_DRIVE;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: CSM_BLOCK_IO_DEV
+//
+// Description: CSM BlockIo device properies
+//
+// Fields:
+// BlockIo EFI_BLOCK_IO_PROTOCOL BlockIo protocol instance
+// Handle EFI_HANDLE EFI device handle
+// ControllerHandle EFI_HANDLE EFI controller handle
+// BlockMedia EFI_BLOCK_IO_MEDIA BlockIo device media
+// DevicePath EFI_DEVICE_PATH_PROTOCOL* Device path
+// PciIo EFI_PCI_IO_PROTOCOL* Device PciIo
+// LegacyBios EFI_LEGACY_BIOS_PROTOCOL* Legacy Bios instance pointer
+// Drive CSM_LEGACY_DRIVE Drive data pointer
+// HwInt UINT8 Hardware interrupt used by this device
+// HwIntHandler UINT32 Storage for the original HW interrupt
+//
+// Referrals: CSM_LEGACY_DRIVE
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ EFI_HANDLE Handle;
+ EFI_HANDLE ControllerHandle;
+ EFI_BLOCK_IO_MEDIA BlockMedia;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ CSM_LEGACY_DRIVE Drive;
+ UINT8 HwInt;
+ UINT32 HwIntHandler;
+} CSM_BLOCK_IO_DEV;
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/BlockIo/CsmInt13.c b/Core/EM/CSM/thunk/BlockIo/CsmInt13.c
new file mode 100644
index 0000000..8e3195e
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/CsmInt13.c
@@ -0,0 +1,1525 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmInt13.c 17 12/23/13 3:14p Olegi $
+//
+// $Revision: 17 $
+//
+// $Date: 12/23/13 3:14p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/CsmInt13.c $
+//
+// 17 12/23/13 3:14p Olegi
+// EIP148138: use AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL instead of
+// EFI_MBR_WRITE_PROTECTION_PROTOCOL
+//
+// 16 12/23/13 10:22a Olegi
+// EIP148123: CSM includes file which name has been changed
+//
+// 15 7/01/13 5:56a Kapilporwal
+// [TAG] EIP125560
+// [Category] Improvement
+// [Description] Please support Boot Sector Virus Protection for CSM
+// Disabled Mode
+// [Files] VirusProtect.c, VirusProtect.dxs, AhciBus.c,
+// AhciController.c, CsmBlockIo.c, CsmInt13.c, Ata.c, IdeBus.c,
+// SdioBlkIo.c, SdioDriver.c, efiusbmass.c
+//
+// 14 3/09/12 3:22a Deepthins
+// [TAG] EIP73940
+// [Category] Improvement
+// [Description] CSM BlockIo functions, ReadBlock and WriteBlock should
+// return EFI_INVALID_PARAMETER if alignment is not proper.
+// [Files] CsmInt13.c
+//
+// 13 5/27/11 5:47a Rameshr
+// [TAG]- EIP 58687
+// [Category]-IMPROVEMENT
+// [Description]- Update implementation of EFI_BLOCK_IO_PROTOCOL as
+// described in UEFI specification v 2.3.1, page 12.8
+// [Files]- CsmInt13.c
+//
+// 12 1/12/10 11:50a Olegi
+// Copyright message updated.
+//
+// 11 5/09/08 10:37a Olegi
+// Low memory segment is normalized before INT13 execution.
+//
+// 10 4/27/07 5:14p Olegi
+// CSM.CHM file preparation.
+//
+// 9 12/07/06 4:00p Olegi
+//
+// 8 3/13/06 2:38p Felixp
+//
+// 7 10/13/05 6:20p Olegi
+// Added HW interrupt handling.
+//
+// 6 9/06/05 11:55a Olegi
+//
+// 5 6/26/05 7:19a Olegi
+// Actual drive parameters size is used while copying extended drive
+// parameters data.
+//
+// 4 3/04/05 1:43p Mandal
+//
+// 3 3/02/05 8:24a Olegi
+//
+// 2 2/21/05 9:33a Olegi
+//
+// 1 2/15/05 10:59a Olegi
+// Initial VSS check-in.
+//
+//
+//**********************************************************************
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: CsmInt13.c
+//
+// Description: CSM Block I/O module. Support module containing reset,
+// flush, read and write functions.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include "CsmBlockIo.h"
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+#include <Protocol\AmiBlockIoWriteProtection.h>
+extern AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL *gBlockIoWriteProtectionProtocol;
+#endif
+
+//extern EFI_BOOT_SERVICES *pBS;
+extern EFI_GUID gEfiBlockIoProtocolGuid;
+
+// Global variables
+
+// Packet buffer under 1 MB for all version EDD calls
+extern EDD_DEVICE_ADDRESS_PACKET *mEDDPacketBuffer;
+
+// This is a buffer for INT 13h func 48 information
+extern CSM_LEGACY_DRIVE *mDriveParameterBuffer;
+
+// EDD 1.1 transfer buffer
+extern VOID *mEDDTransferBuffer;
+
+// Local function prototypes
+BOOLEAN
+GetInt13DeviceParameters (
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev,
+ IN CSM_LEGACY_DRIVE *Drive
+);
+
+BOOLEAN
+GetInt13Extensions (
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev,
+ IN CSM_LEGACY_DRIVE *Drive
+);
+
+BOOLEAN
+GetDriveParameters (
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev,
+ IN CSM_LEGACY_DRIVE *Drive
+);
+
+VOID
+PatchHwInterrupt(
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev
+);
+
+VOID
+RestoreHwInterrupt(
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev
+);
+
+UINT32 gTempHwIntSav;
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: InitBlockIo
+//
+// Description: Initializes BlockIo protocol for a given device
+//
+// Input: Device to initialize
+//
+// Output: TRUE initialization succeeded, FALSE otherwise
+//
+// Referrals: CSM_BLOCK_IO_DEV, GetInt13DeviceParameters, GetInt13Extensions
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+InitBlockIo (
+ IN CSM_BLOCK_IO_DEV *Dev
+)
+{
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_BLOCK_IO_MEDIA *BlockMedia;
+ CSM_LEGACY_DRIVE *Drive;
+
+ BlockIo = &Dev->BlockIo;
+ BlockIo->Media = &Dev->BlockMedia;
+ BlockMedia = BlockIo->Media;
+ Drive = &Dev->Drive;
+
+#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+ } else {
+ BlockIo->Revision = 1;
+ }
+#else
+ BlockIo->Revision = 1;
+#endif
+
+ if (GetInt13DeviceParameters (Dev, Drive)) {
+ if (GetInt13Extensions (Dev, Drive)) {
+ BlockMedia->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1;
+ BlockMedia->BlockSize = (UINT32)Drive->Parameters.BytesPerSector;
+
+ if ((Drive->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) {
+ BlockMedia->RemovableMedia = TRUE;
+ }
+
+ } else {
+ // No extensions, use Legacy parameters.
+ BlockMedia->BlockSize = 512;
+ BlockMedia->LastBlock = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1) - 1;
+ }
+
+// TRACE((-1," BlockSize = %d LastBlock = %d\n", BlockMedia->BlockSize, BlockMedia->LastBlock));
+
+ BlockMedia->LogicalPartition = FALSE;
+ BlockMedia->WriteCaching = FALSE;
+
+ BlockMedia->ReadOnly = FALSE; // Set for removable media in case no media present
+ BlockMedia->MediaPresent = TRUE; // ditto
+
+ BlockIo->Reset = CsmBlockIoReset;
+ BlockIo->FlushBlocks = CsmBlockIoFlushBlocks;
+
+ // Need logic here to test for EDD and set read/write functions if so
+ if (!Drive->ExtendedInt13) {
+ // No Int 13 extensions, use Legacy functions
+ BlockIo->ReadBlocks = LegacyCsmReadBlocks;
+ BlockIo->WriteBlocks = LegacyCsmWriteBlocks;
+/* } else if ((Drive->EddVersion == EDD_VERSION_30) && (Drive->Extensions64Bit)) {
+ // Use EDD 3.0 functions
+ BlockIo->ReadBlocks = Edd30CsmReadBlocks;
+ BlockIo->WriteBlocks = Edd30CsmWriteBlocks;
+*/
+ } else {
+ // Assume EDD 1.1 Read and Write functions.
+ BlockIo->ReadBlocks = Edd11CsmReadBlocks;
+ BlockIo->WriteBlocks = Edd11CsmWriteBlocks;
+ }
+
+ BlockMedia->LogicalPartition = FALSE;
+ BlockMedia->WriteCaching = FALSE;
+
+ //
+ // Check for Core Version > 4.6.5.0
+ //
+#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a
+
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ //
+ // Default value set to 1 logical blocks per PhysicalBlock
+ //
+ BlockMedia->LogicalBlocksPerPhysicalBlock=1;
+
+ //
+ // Default value set to 0 for Lowest Aligned LBA
+ //
+ BlockMedia->LowestAlignedLba=0;
+
+ BlockMedia->OptimalTransferLengthGranularity=BlockMedia->BlockSize;
+ }
+
+#endif
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: GetInt13DeviceParameters
+//
+// Description: Get hard drive parameters using INT13 function 8
+//
+// Input: BlockIo device, Drive
+//
+// Output: TRUE if operation is successful, FALSE otherwise
+//
+// Referrals: CSM_BLOCK_IO_DEV, CSM_LEGACY_DRIVE
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+GetInt13DeviceParameters (
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev,
+ IN CSM_LEGACY_DRIVE *Drive
+)
+{
+ BOOLEAN CarryFlag;
+ UINT16 Cylinder;
+ EFI_IA32_REGISTER_SET Regs;
+
+ Regs.H.AH = 0x08;
+ Regs.H.DL = Drive->Number;
+ PatchHwInterrupt(CsmBlockIoDev);
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ RestoreHwInterrupt(CsmBlockIoDev);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+// TRACE((-1," GetInt13DeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH));
+
+ if (CarryFlag || Regs.H.AH != 0x00) {
+ Drive->ErrorCode = Regs.H.AH;
+ return FALSE;
+ }
+
+ if (Drive->Floppy) {
+ if (Regs.H.BL == 0x10) {
+ Drive->AtapiFloppy = TRUE;
+ } else {
+ Drive->MaxHead = Regs.H.DH;
+ Drive->MaxSector = Regs.H.CL;
+ Drive->MaxCylinder = Regs.H.CH;
+ if (Drive->MaxSector == 0) {
+ return FALSE;
+ }
+ }
+ } else {
+ Drive->MaxHead = (UINT8)(Regs.H.DH & 0x3f);
+ Cylinder = (UINT16)(((UINT16)Regs.H.DH & 0xc0) << 4);
+ Cylinder |= (UINT16)(((UINT16)Regs.H.CL & 0xc0) << 2);
+ Drive->MaxCylinder = (UINT16)(Cylinder + Regs.H.CH);
+ Drive->MaxSector = (UINT8)(Regs.H.CL & 0x3f);
+ }
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: GetInt13Extensions
+//
+// Description: Executes INT13 func 41 to check EDD extensions
+//
+// Input: BlockIo device, Drive
+//
+// Output: TRUE if operation is successful, FALSE otherwise
+//
+// Referrals: CSM_BLOCK_IO_DEV, CSM_LEGACY_DRIVE
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+GetInt13Extensions(
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev,
+ IN CSM_LEGACY_DRIVE *Drive
+)
+{
+ BOOLEAN CarryFlag;
+ EFI_IA32_REGISTER_SET Regs;
+
+ Regs.H.AH = 0x41;
+ Regs.X.BX = 0x55aa;
+ Regs.H.DL = Drive->Number;
+ PatchHwInterrupt(CsmBlockIoDev);
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ RestoreHwInterrupt(CsmBlockIoDev);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+// TRACE((-1, " GetInt13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX));
+
+ if (CarryFlag || Regs.X.BX != 0xaa55) {
+ Drive->ExtendedInt13 = FALSE;
+ Drive->DriveLockingAndEjecting = FALSE;
+ Drive->Edd = FALSE;
+ return(FALSE);
+ }
+ Drive->EddVersion = Regs.H.AH;
+ Drive->ExtendedInt13 = (BOOLEAN)((Regs.X.CX & 0x01) == 0x01);
+ Drive->DriveLockingAndEjecting = (BOOLEAN)((Regs.X.CX & 0x02) == 0x02);
+ Drive->Edd = (BOOLEAN)((Regs.X.CX & 0x04) == 0x04);
+ Drive->Extensions64Bit = (BOOLEAN)(Regs.X.CX & 0x08);
+
+ Drive->ParametersValid = (UINT8)GetDriveParameters(CsmBlockIoDev, Drive);
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: GetDriveParameters
+//
+// Description: Executes INT13 function 48 to get hard disk parameters
+//
+// Input: BlockIo device, Drive
+//
+// Output: TRUE if operation is successful, FALSE otherwise
+//
+// Referrals: CSM_BLOCK_IO_DEV, CSM_LEGACY_DRIVE
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+GetDriveParameters(
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev,
+ IN CSM_LEGACY_DRIVE *Drive
+)
+{
+ BOOLEAN CarryFlag;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN PointerMath;
+ UINT8 Temp;
+ UINT8 FloppyTable [] = {
+ 1, 9, 79, // Type 3 -- 720 Kb
+ 1, 18, 79, // Type 4 -- 1.44 Mb
+ 0, 1, 0, // No type 5
+ 1, 36, 79, // Type 6 -- 2.88 Mb
+ 0, 1, 0,
+ 0, 1, 0,
+ 0, 1, 0,
+ 0, 1, 0,
+ 0, 1, 0,
+ 1, 9, 39, // Type C -- 360 Kb
+ 1, 15, 79 // Type D -- 1.2 Mb
+ };
+
+ Regs.H.AH = 0x48;
+ Regs.H.DL = Drive->Number;
+
+ // Get Int13 Parameters
+ mDriveParameterBuffer->Parameters.StructureSize = sizeof(EDD_DRIVE_PARAMETERS);
+ Regs.X.DS = EFI_SEGMENT(&mDriveParameterBuffer->Parameters);
+ Regs.X.SI = EFI_OFFSET(&mDriveParameterBuffer->Parameters);
+
+ PatchHwInterrupt(CsmBlockIoDev);
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+ if (CarryFlag || Regs.H.AH != 0x00) {
+ RestoreHwInterrupt(CsmBlockIoDev);
+ Drive->ErrorCode = Regs.H.AH;
+ pBS->SetMem(&Drive->Parameters, sizeof(Drive->Parameters), 0xaf);
+ return FALSE;
+ }
+
+// Copy parameters into real mode buffer
+ pBS->SetMem (&Drive->Parameters, sizeof(Drive->Parameters), 0);
+ pBS->CopyMem (
+ &Drive->Parameters,
+ &mDriveParameterBuffer->Parameters,
+ mDriveParameterBuffer->Parameters.StructureSize // updated by int 13 call
+ );
+
+ if (Drive->AtapiFloppy) {
+
+ // Get Media type
+ Regs.H.AH = 0x20;
+ Regs.H.DL = Drive->Number;
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+ if (CarryFlag) {
+
+ // Unknown or no media present
+ if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) {
+ Drive->MaxHead = (UINT8)(Drive->Parameters.MaxHeads - 1);
+ Drive->MaxSector = (UINT8)Drive->Parameters.SectorsPerTrack;
+ ASSERT(Drive->MaxSector != 0);
+ Drive->MaxCylinder = (UINT16)(Drive->Parameters.MaxCylinders - 1);
+ } else {
+ Drive->MaxHead = 0;
+ Drive->MaxSector = 1;
+ Drive->MaxCylinder = 0;
+ }
+
+ } else {
+
+ // Media present -- get parameters
+ Drive->MaxHead = 0;
+ Drive->MaxSector = 1;
+ Drive->MaxCylinder = 0; // Assume unknown media
+ if(Regs.H.AL != 10) {
+ if((Regs.H.AL >= 3) && (Regs.H.AL <= 0xd)) {
+ Temp = (Regs.H.AL - 3) * 3; // First drive type is 3
+ Drive->MaxHead = FloppyTable[Temp];
+ Drive->MaxSector = FloppyTable[Temp+1];
+ Drive->MaxCylinder = FloppyTable[Temp+2];
+ }
+ } else {
+ if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) {
+ Drive->MaxHead = (UINT8)(Drive->Parameters.MaxHeads - 1);
+ Drive->MaxSector = (UINT8)Drive->Parameters.SectorsPerTrack;
+ ASSERT(Drive->MaxSector != 0);
+ Drive->MaxCylinder = (UINT16)(Drive->Parameters.MaxCylinders - 1);
+ } else {
+ Drive->MaxHead = 0;
+ Drive->MaxSector = 1;
+ Drive->MaxCylinder = 0;
+ }
+ }
+ }
+ Drive->Parameters.PhysicalSectors = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1);
+ Drive->Parameters.BytesPerSector = 512;
+ }
+
+ // This data comes from the BIOS so it may not allways be valid
+ // since the BIOS may reuse this buffer for future accesses
+ PointerMath = EFI_SEGMENT(Drive->Parameters.FDPT) << 4;
+ PointerMath += EFI_OFFSET(Drive->Parameters.FDPT);
+ Drive->FdptPointer = (VOID *)PointerMath;
+
+ RestoreHwInterrupt(CsmBlockIoDev);
+
+ return TRUE;
+}
+
+// BLOCK I/O FUNCTIONS
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: CsmBlockIoFlushBlocks
+//
+// Description: BlockIo protocol function that flushes data onto the device
+//
+// Input: Instance of the EFI_BLOCK_IO_PROTOCOL
+//
+// Output: Status of the operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CsmBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: CsmBlockIoFlushBlocks
+//
+// Description: BlockIo protocol function that resets the device
+//
+// Input:
+// Instance of the EFI_BLOCK_IO_PROTOCOL
+// ExtendedVerification request
+//
+// Output: Status of the operation
+//
+// Referrals: CSM_BLOCK_IO_DEV, EFI_IA32_REGISTER_SET
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CsmBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ BOOLEAN CarryFlag;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This;
+
+ PatchHwInterrupt(CsmBlockIoDev);
+
+ Regs.H.AH = 0x00;
+ Regs.H.DL = CsmBlockIoDev->Drive.Number;
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+// TRACE((-1, " CsmBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH));
+
+ if (CarryFlag) {
+ if (Regs.H.AL == ERR_RESET_FAILED) {
+ Regs.H.AH = 0x00;
+ Regs.H.DL = CsmBlockIoDev->Drive.Number;
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+// TRACE((-1, "CsmBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH));
+
+ if (CarryFlag) {
+ CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH;
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+ }
+
+ RestoreHwInterrupt(CsmBlockIoDev);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: Edd30CsmReadBlocks
+//
+// Description: Read device using EDD3.0 read function
+//
+// Input: BlockIo protocol instance, Media ID, read data buffer
+//
+// Output: Status of the operation
+//
+// Referrals: EFI_LBA
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+Edd30CsmReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket; // I exist only for readability
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ CSM_LEGACY_DRIVE *Drive;
+ BOOLEAN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+// Check for error conditions
+ if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED;
+ if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE;
+ if (Buffer == NULL) return EFI_INVALID_PARAMETER;
+ if (BufferSize == 0) return EFI_SUCCESS;
+
+// CsmBlockIoDev = ((CSM_BLOCK_IO_DEV *) ((CHAR8 *)(This) - (CHAR8 *) &(((CSM_BLOCK_IO_DEV *) 0)->BlockIo)));
+ CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This;
+ AddressPacket = mEDDPacketBuffer;
+
+ MaxTransferBlocks = MAX_EDD11_XFER/BlockSize;
+
+ TransferBuffer = (UINT64)Buffer;
+
+ PatchHwInterrupt(CsmBlockIoDev);
+
+ while (BufferSize) {
+ NumberOfBlocks = BufferSize/BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks
+
+ AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+ AddressPacket->SegOffset = 0xffffffff;
+ AddressPacket->LBA = (UINT64)LBA;
+ AddressPacket->TransferBuffer = TransferBuffer;
+
+ Regs.H.AH = 0x42;
+ Regs.H.DL = CsmBlockIoDev->Drive.Number;
+ Regs.X.SI = EFI_OFFSET(AddressPacket);
+ Regs.X.DS = EFI_SEGMENT(AddressPacket);
+
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+// TRACE((-1, " Edd30CsmReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH));
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag) {
+ // If we have a carry, figure out the error.
+ CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH;
+ if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) {
+ Media->MediaId++;
+ Drive = &CsmBlockIoDev->Drive;
+ if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) {
+ if (GetInt13Extensions (CsmBlockIoDev, Drive)) {
+ Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector;
+ } else {
+ ASSERT(FALSE);
+ }
+ Media->ReadOnly = FALSE;
+ pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+ pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ Status = EFI_MEDIA_CHANGED;
+ goto Exit;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ BufferSize = BufferSize - TransferByteSize;
+ TransferBuffer += TransferByteSize;
+ LBA += NumberOfBlocks;
+ }
+Exit:
+ RestoreHwInterrupt(CsmBlockIoDev);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: Edd30CsmWriteBlocks
+//
+// Description: Write device using EDD3.0 write function
+//
+// Input: BlockIo protocol instance, Media ID, write data buffer
+//
+// Output: Status of the operation
+//
+// Referrals: EFI_LBA
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+Edd30CsmWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ CSM_LEGACY_DRIVE *Drive;
+ BOOLEAN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED;
+ if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE;
+ if (Buffer == NULL) return EFI_INVALID_PARAMETER;
+ if (BufferSize == 0) return EFI_SUCCESS;
+
+ CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This;
+ AddressPacket = mEDDPacketBuffer;
+
+ MaxTransferBlocks = MAX_EDD11_XFER/BlockSize;
+
+ PatchHwInterrupt(CsmBlockIoDev);
+
+ TransferBuffer = (UINT64)Buffer;
+ while (BufferSize) {
+ NumberOfBlocks = BufferSize/BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks
+ AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+ AddressPacket->SegOffset = 0xffffffff;
+ AddressPacket->LBA = (UINT64)LBA;
+ AddressPacket->TransferBuffer = TransferBuffer;
+
+ Regs.H.AH = 0x43;
+ Regs.H.AL = 0x00; // Write Verify Off
+ Regs.H.DL = (UINT8)(CsmBlockIoDev->Drive.Number);
+ Regs.X.SI = EFI_OFFSET(AddressPacket);
+ Regs.X.DS = EFI_SEGMENT(AddressPacket);
+
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+// TRACE((-1, " Edd30CsmWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH));
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag) {
+ // If we have a carry, figure out the error.
+ CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH;
+ if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) {
+ Media->MediaId++;
+ Drive = &CsmBlockIoDev->Drive;
+ if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) {
+ if (GetInt13Extensions (CsmBlockIoDev, Drive)) {
+ Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector;
+ } else {
+ ASSERT(FALSE);
+ }
+ Media->ReadOnly = FALSE;
+ pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+ pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ Status = EFI_MEDIA_CHANGED;
+ goto Exit;
+ }
+ } else if (CsmBlockIoDev->Drive.ErrorCode == ERR_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Media->ReadOnly = FALSE;
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ BufferSize = BufferSize - TransferByteSize;
+ TransferBuffer += TransferByteSize;
+ LBA += NumberOfBlocks;
+ }
+Exit:
+ RestoreHwInterrupt(CsmBlockIoDev);
+ return Status;
+}
+
+
+// Older read/write methods
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: Edd11CsmReadBlocks
+//
+// Description: Read device using EDD1.1 read function
+//
+// Input: BlockIo protocol instance, Media ID, read data buffer
+//
+// Output: Status of the operation
+//
+// Referrals: EFI_LBA
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+Edd11CsmReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ CSM_LEGACY_DRIVE *Drive;
+ BOOLEAN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT16 AlignedOffset;
+ UINT16 AlignedSegment;
+ UINTN BufferAddress;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED;
+ if (BufferSize == 0) return EFI_SUCCESS;
+ if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE;
+ if (Buffer == NULL) return EFI_INVALID_PARAMETER;
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((Media->IoAlign > 1 ) && (BufferAddress % Media->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This;
+ AddressPacket = mEDDPacketBuffer;
+
+ MaxTransferBlocks = MAX_EDD11_XFER/BlockSize;
+
+ PatchHwInterrupt(CsmBlockIoDev);
+
+ TransferBuffer = (UINT64)mEDDTransferBuffer;
+ while (BufferSize) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks
+ AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+
+ //
+ // Normalize TransferBuffer address if needed
+ //
+ AlignedOffset = EFI_OFFSET(TransferBuffer);
+ AlignedSegment = EFI_SEGMENT(TransferBuffer);
+ if(AlignedOffset != 0) {
+ AlignedSegment = AlignedSegment + (AlignedOffset >> 4);
+ AlignedOffset = 0;
+ }
+
+ AddressPacket->SegOffset = AlignedSegment << 16;
+ AddressPacket->SegOffset |= AlignedOffset;
+
+ AddressPacket->LBA = (UINT64)LBA;
+
+ Regs.H.AH = 0x42;
+ Regs.H.DL = CsmBlockIoDev->Drive.Number;
+ Regs.X.SI = EFI_OFFSET(AddressPacket);
+ Regs.X.DS = EFI_SEGMENT(AddressPacket);
+
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+// TRACE((-1, "Edd11CsmReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH, LBA, NumberOfBlocks));
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag) {
+ // If we have a carry, figure out the error.
+ CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH;
+ if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) {
+ Media->MediaId++;
+ Drive = &CsmBlockIoDev->Drive;
+ if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) {
+ if (GetInt13Extensions (CsmBlockIoDev, Drive)) {
+ Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector;
+ } else {
+ ASSERT(FALSE);
+ }
+ // The media has changed.
+ Media->ReadOnly = FALSE;
+ pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+ pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ Status = EFI_MEDIA_CHANGED;
+ goto Exit;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ pBS->CopyMem (Buffer, (VOID *)(UINTN)TransferBuffer, TransferByteSize);
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize);
+ LBA += NumberOfBlocks;
+ }
+Exit:
+ RestoreHwInterrupt(CsmBlockIoDev);
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: Edd11CsmWriteBlocks
+//
+// Description: Write device using EDD1.1 write function
+//
+// Input: BlockIo protocol instance, Media ID, write data buffer
+//
+// Output: Status of the operation
+//
+// Referrals: EFI_LBA
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+Edd11CsmWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket; // I exist only for readability
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ CSM_LEGACY_DRIVE *Drive;
+ BOOLEAN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT16 AlignedOffset;
+ UINT16 AlignedSegment;
+ UINTN BufferAddress;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED;
+ if (BufferSize == 0) return EFI_SUCCESS;
+ if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE;
+ if (Buffer == NULL) return EFI_INVALID_PARAMETER;
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((Media->IoAlign > 1 ) && (BufferAddress % Media->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This;
+ AddressPacket = mEDDPacketBuffer;
+
+ MaxTransferBlocks = MAX_EDD11_XFER/BlockSize;
+
+ PatchHwInterrupt(CsmBlockIoDev);
+
+ TransferBuffer = (UINT64)mEDDTransferBuffer;
+ while (BufferSize) {
+ NumberOfBlocks = BufferSize/BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; // Max transfer MaxTransferBlocks
+ AddressPacket->PacketSizeInBytes = sizeof(EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8)NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+
+ //
+ // Normalize TransferBuffer address if needed
+ //
+ AlignedOffset = EFI_OFFSET(TransferBuffer);
+ AlignedSegment = EFI_SEGMENT(TransferBuffer);
+
+ if (AlignedOffset != 0) {
+ AlignedSegment = AlignedSegment + (AlignedOffset >> 4);
+ AlignedOffset = 0;
+ }
+
+ AddressPacket->SegOffset = AlignedSegment << 16;
+ AddressPacket->SegOffset |= AlignedOffset;
+
+ AddressPacket->LBA = (UINT64)LBA;
+
+ Regs.H.AH = 0x43;
+ Regs.H.AL = 0x00; // Write Verify disable
+ Regs.H.DL = CsmBlockIoDev->Drive.Number;
+ Regs.X.SI = EFI_OFFSET(AddressPacket);
+ Regs.X.DS = EFI_SEGMENT(AddressPacket);
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ pBS->CopyMem ((VOID *)(UINTN)TransferBuffer, Buffer, TransferByteSize);
+
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+// TRACE((-1, "Edd11CsmWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH, LBA, NumberOfBlocks));
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag) {
+ // If we have a carry, figure out the error.
+ CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH;
+ if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) {
+ Media->MediaId++;
+ Drive = &CsmBlockIoDev->Drive;
+ if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) {
+ if (GetInt13Extensions (CsmBlockIoDev, Drive)) {
+ Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector;
+ } else {
+ ASSERT(FALSE);
+ }
+ // The media has changed.
+ Media->ReadOnly = FALSE;
+ pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+ pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ Status = EFI_MEDIA_CHANGED;
+ goto Exit;
+ }
+ } else if (CsmBlockIoDev->Drive.ErrorCode == ERR_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ Status = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Media->ReadOnly = FALSE;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize);
+ LBA += NumberOfBlocks;
+ }
+Exit:
+ RestoreHwInterrupt(CsmBlockIoDev);
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: LegacyCsmReadBlocks
+//
+// Description: Read device using INT13 function 2
+//
+// Input: BlockIo protocol instance, Media ID, read data buffer
+//
+// Output: Status of the operation
+//
+// Referrals: EFI_LBA
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+LegacyCsmReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN UpperCylinder, Temp;
+ UINTN Cylinder, Head, Sector;
+ UINTN NumberOfBlocks, TransferByteSize;
+ UINTN ShortLba, CheckLba;
+ UINTN BlockSize;
+ CSM_LEGACY_DRIVE *Drive;
+ BOOLEAN CarryFlag;
+ UINTN Retry;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN BufferAddress;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED;
+ if (BufferSize == 0) return EFI_SUCCESS;
+ if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE;
+ if (Buffer == NULL) return EFI_INVALID_PARAMETER;
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((Media->IoAlign > 1 ) && (BufferAddress % Media->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This;
+ ShortLba = (UINTN) LBA;
+
+ PatchHwInterrupt(CsmBlockIoDev);
+
+ while (BufferSize) {
+ // Convert LBA to CHS.
+ Sector = (ShortLba % CsmBlockIoDev->Drive.MaxSector) + 1;
+ Temp = ShortLba / CsmBlockIoDev->Drive.MaxSector;
+ Head = Temp % (CsmBlockIoDev->Drive.MaxHead + 1);
+ Cylinder = Temp / (CsmBlockIoDev->Drive.MaxHead + 1);
+ // Limit number of blocks to one head and cylindar
+ NumberOfBlocks = BufferSize/BlockSize;
+ Temp = CsmBlockIoDev->Drive.MaxSector - Sector + 1;
+ NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;
+
+ Retry = 3;
+ // Loop to perform the read
+ do {
+ Regs.H.AH = 2;
+ Regs.H.AL = (UINT8) NumberOfBlocks;
+ Regs.H.DL = CsmBlockIoDev->Drive.Number;
+
+ UpperCylinder = (Cylinder & 0x0f00) >> 2;
+
+ CheckLba = Cylinder*(CsmBlockIoDev->Drive.MaxHead + 1) + Head;
+ CheckLba = CheckLba*CsmBlockIoDev->Drive.MaxSector + Sector - 1;
+
+// ASSERT(CheckLba == ShortLba);
+
+ Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff));
+ Regs.H.DH = (UINT8) (Head & 0x3f);
+ Regs.H.CH = (UINT8) (Cylinder & 0xff);
+
+ Regs.X.BX = EFI_OFFSET(mEDDTransferBuffer);
+ Regs.X.ES = EFI_SEGMENT(mEDDTransferBuffer);
+
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+// TRACE((-1, "LegacyCsmReadBlocks: INT 13 02 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH));
+
+ Retry--;
+ } while (CarryFlag && Retry !=0 && Regs.H.AH != ERR_DISK_CHANGED);
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag) {
+ // If we have a carry, figure out the error.
+ CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH;
+ if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) {
+ Media->MediaId++;
+ Drive = &CsmBlockIoDev->Drive;
+ if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) {
+ // The media has changed
+ if (GetInt13Extensions (CsmBlockIoDev, Drive)) {
+ Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector;
+ } else {
+ Media->LastBlock = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1) - 1;
+ Media->BlockSize = 512;
+ }
+ Media->ReadOnly = FALSE;
+ pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+ pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ Status = EFI_MEDIA_CHANGED;
+ goto Exit;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ pBS->CopyMem (Buffer, mEDDTransferBuffer, TransferByteSize);
+
+ ShortLba = ShortLba + NumberOfBlocks;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize);
+ }
+Exit:
+ RestoreHwInterrupt(CsmBlockIoDev);
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: LegacyCsmWriteBlocks
+//
+// Description: Write device using INT13 function 3
+//
+// Input: BlockIo protocol instance, Media ID, write data buffer
+//
+// Output: Status of the operation
+//
+// Referrals: EFI_LBA
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+LegacyCsmWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN UpperCylinder, Temp;
+ UINTN Cylinder, Head, Sector;
+ UINTN NumberOfBlocks, TransferByteSize;
+ UINTN ShortLba, CheckLba;
+ UINTN BlockSize;
+ CSM_LEGACY_DRIVE *Drive;
+ BOOLEAN CarryFlag;
+ UINTN Retry;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN BufferAddress;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ if (MediaId != Media->MediaId) return EFI_MEDIA_CHANGED;
+ if (BufferSize == 0) return EFI_SUCCESS;
+ if (LBA > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if ((LBA + (BufferSize / BlockSize) - 1) > Media->LastBlock) return EFI_INVALID_PARAMETER;
+ if (BufferSize % BlockSize != 0) return EFI_BAD_BUFFER_SIZE;
+ if (Buffer == NULL) return EFI_INVALID_PARAMETER;
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((Media->IoAlign > 1 ) && (BufferAddress % Media->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+ // Verify if write is allowed
+ if(gBlockIoWriteProtectionProtocol != NULL) {
+ Status = gBlockIoWriteProtectionProtocol->BlockIoWriteProtectionCheck(
+ gBlockIoWriteProtectionProtocol,
+ This,
+ LBA,
+ BufferSize
+ );
+
+ // Abort operation if denied
+ if(Status == EFI_ACCESS_DENIED) {
+ return Status;
+ }
+ }
+#endif
+
+ CsmBlockIoDev = (CSM_BLOCK_IO_DEV *) This;
+ ShortLba = (UINTN) LBA;
+
+ PatchHwInterrupt(CsmBlockIoDev);
+
+ while(BufferSize) {
+ // Convert LBA to CHS
+ Sector = (ShortLba % CsmBlockIoDev->Drive.MaxSector) + 1;
+ Temp = ShortLba / CsmBlockIoDev->Drive.MaxSector;
+ Head = Temp % (CsmBlockIoDev->Drive.MaxHead + 1);
+ Cylinder = Temp / (CsmBlockIoDev->Drive.MaxHead + 1);
+
+ // Limit number of blocks to one head and cylindar
+ NumberOfBlocks = BufferSize/BlockSize;
+ Temp = CsmBlockIoDev->Drive.MaxSector - Sector + 1;
+ NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;
+
+
+ Retry = 3;
+ // Loop to perform the write.
+ do {
+ Regs.H.AH = 3;
+ Regs.H.AL = (UINT8) NumberOfBlocks;
+ Regs.H.DL = CsmBlockIoDev->Drive.Number;
+
+ UpperCylinder = (Cylinder & 0x0f00) >> 2;
+
+ CheckLba = Cylinder*(CsmBlockIoDev->Drive.MaxHead + 1) + Head;
+ CheckLba = CheckLba*CsmBlockIoDev->Drive.MaxSector + Sector - 1;
+
+// ASSERT(CheckLba == ShortLba);
+
+ Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff));
+ Regs.H.DH = (UINT8) (Head & 0x3f);
+ Regs.H.CH = (UINT8) (Cylinder & 0xff);
+
+ Regs.X.BX = EFI_OFFSET(mEDDTransferBuffer);
+ Regs.X.ES = EFI_SEGMENT(mEDDTransferBuffer);
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ pBS->CopyMem (mEDDTransferBuffer, Buffer, TransferByteSize);
+
+ CsmBlockIoDev->LegacyBios->Int86 (CsmBlockIoDev->LegacyBios, 0x13, &Regs);
+ CarryFlag = (BOOLEAN)Regs.X.Flags.CF;
+
+// TRACE((-1, "LegacyCsmWriteBlocks: INT 13 03 DL=%02x : CF=%d AH=%02x\n", CsmBlockIoDev->Drive.Number, CarryFlag, Regs.H.AH));
+
+ Retry--;
+ } while (CarryFlag && Retry !=0 && Regs.H.AH != ERR_DISK_CHANGED);
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag) {
+ // If we have a carry, figure out the error.
+ CsmBlockIoDev->Drive.ErrorCode = Regs.H.AH;
+ if (CsmBlockIoDev->Drive.ErrorCode == ERR_DISK_CHANGED) {
+ Media->MediaId++;
+ Drive = &CsmBlockIoDev->Drive;
+ if (GetInt13DeviceParameters(CsmBlockIoDev, Drive)) {
+ if (GetInt13Extensions (CsmBlockIoDev, Drive)) {
+ Media->LastBlock = (EFI_LBA)Drive->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32)Drive->Parameters.BytesPerSector;
+ } else {
+ Media->LastBlock = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1) - 1;
+ Media->BlockSize = 512;
+ }
+ // The media has changed.
+ Media->ReadOnly = FALSE;
+ pBS->HandleProtocol(CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+ pBS->ReinstallProtocolInterface (CsmBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ Status = EFI_MEDIA_CHANGED;
+ goto Exit;
+ }
+ } else if (CsmBlockIoDev->Drive.ErrorCode == ERR_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ Status = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ Media->ReadOnly = FALSE;
+ ShortLba = ShortLba + NumberOfBlocks;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *)((UINT8 *)Buffer + TransferByteSize);
+ }
+
+Exit:
+ RestoreHwInterrupt(CsmBlockIoDev);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: PatchHwInterrupt
+//
+// Description: Saves HW interrupt vector used by this device
+//
+// Input: BlockIo device
+//
+// Output: None
+//
+// Referrals: CSM_BLOCK_IO_DEV
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+PatchHwInterrupt(
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev
+)
+{
+ UINT32 *ivt = (UINT32*)0;
+ if (CsmBlockIoDev->HwInt) {
+ gTempHwIntSav = ivt[CsmBlockIoDev->HwInt];
+ ivt[CsmBlockIoDev->HwInt] = CsmBlockIoDev->HwIntHandler;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: RestoreHwInterrupt
+//
+// Description: Restores HW interrupt saved by PatchHwInterrupt
+//
+// Input: BlockIo device
+//
+// Output: None
+//
+// Referrals: CSM_BLOCK_IO_DEV, PatchHwInterrupt
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+RestoreHwInterrupt(
+ CSM_BLOCK_IO_DEV *CsmBlockIoDev
+)
+{
+ UINT32 *ivt = (UINT32*)0;
+ if (CsmBlockIoDev->HwInt) {
+ ivt[CsmBlockIoDev->HwInt] = gTempHwIntSav;
+ }
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/BlockIo/biosblkio.dxs b/Core/EM/CSM/thunk/BlockIo/biosblkio.dxs
new file mode 100644
index 0000000..8a863fa
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/biosblkio.dxs
@@ -0,0 +1,46 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/biosblkio.dxs 1 10/03/11 3:38p Olegi $
+//
+// $Revision: 1 $
+//
+// $Date: 10/03/11 3:38p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/biosblkio.dxs $
+//
+// 1 10/03/11 3:38p Olegi
+//
+//**********************************************************************
+
+#include <Protocol\LegacyBios.h>
+
+DEPENDENCY_START
+ EFI_LEGACY_BIOS_PROTOCOL_GUID
+DEPENDENCY_END
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/BlockIo/biosblkio.mak b/Core/EM/CSM/thunk/BlockIo/biosblkio.mak
new file mode 100644
index 0000000..879933f
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/biosblkio.mak
@@ -0,0 +1,63 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#************************************************************************//
+# $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/biosblkio.mak 3 1/12/10 11:50a Olegi $
+#
+# $Revision: 3 $
+#
+# $Date: 1/12/10 11:50a $
+#************************************************************************//
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/INT13/biosblkio.mak $
+#
+# 3 1/12/10 11:50a Olegi
+# Copyright message updated.
+#
+# 2 12/02/05 11:44a Felixp
+#
+# 1 2/15/05 11:00a Olegi
+# Initial VSS check-in.
+#
+#
+#************************************************************************//
+all : CsmBlockIo
+
+CsmBlockIo : $(BUILD_DIR)\biosblkio.mak CsmBlockIoBin
+
+$(BUILD_DIR)\biosblkio.mak : $(CSMBLOCKIO_DIR)\int13thunk.cif $(CSMBLOCKIO_DIR)\biosblkio.mak $(BUILD_RULES)
+ $(CIF2MAK) $(CSMBLOCKIO_DIR)\int13thunk.cif $(CIF2MAK_DEFAULTS)
+
+CsmBlockIoBin: $(AMIDXELIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\biosblkio.mak all\
+ GUID=25ACF158-DD61-4e64-9A49-55851E9A26C7\
+ ENTRY_POINT=CsmBlockIoEntryPoint \
+ TYPE=BS_DRIVER \
+ COMPRESS=1\
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/Core/EM/CSM/thunk/BlockIo/int13thunk.cif b/Core/EM/CSM/thunk/BlockIo/int13thunk.cif
new file mode 100644
index 0000000..24c82f3
--- /dev/null
+++ b/Core/EM/CSM/thunk/BlockIo/int13thunk.cif
@@ -0,0 +1,15 @@
+<component>
+ name = "INT13"
+ category = ModulePart
+ LocalRoot = "core\em\csm\thunk\BlockIo"
+ RefName = "BIOSBLKIO"
+[files]
+"CsmInt13.c"
+"CsmBlkIoComponentName.c"
+"CsmBlockIo.c"
+"CsmBlockIo.h"
+"CsmBlockIo.sdl"
+"CsmEdd.h"
+"biosblkio.mak"
+"biosblkio.dxs"
+<endComponent>
diff --git a/Core/EM/CSM/thunk/CsmVideo/AmiMapping.c b/Core/EM/CSM/thunk/CsmVideo/AmiMapping.c
new file mode 100644
index 0000000..88c165b
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/AmiMapping.c
@@ -0,0 +1,162 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/AmiMapping.c 2 3/04/11 2:28p Olegi $
+//
+// $Revision: 2 $
+//
+// $Date: 3/04/11 2:28p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/AmiMapping.c $
+//
+// 2 3/04/11 2:28p Olegi
+// [TAG] EIP55098
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] UefiBiosVideo.h
+// UefiBiosVideo.c
+// ComponentName.c
+// AmiMapping.h
+// AmiMapping.c
+//
+// 1 12/29/06 3:33p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AmiMapping.c
+//
+// Description: Mapping from EDK to AMI definitions
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include "AmiMapping.h"
+#include "VgaMiniPort.h"
+
+EFI_GUID gEfiVgaMiniPortProtocolGuid = EFI_VGA_MINI_PORT_PROTOCOL_GUID;
+
+EFI_STATUS EfiLibInstallAllDriverProtocols (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
+ IN EFI_HANDLE DriverBindingHandle,
+#if EFI_SPECIFICATION_VERSION <= 0x20000
+ IN EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL
+#else
+ IN EFI_COMPONENT_NAME2_PROTOCOL *ComponentName, OPTIONAL
+#endif
+ IN VOID/*EFI_DRIVER_CONFIGURATION_PROTOCOL*/ *DriverConfiguration, OPTIONAL
+ IN VOID/*EFI_DRIVER_DIAGNOSTICS_PROTOCOL*/ *DriverDiagnostics OPTIONAL
+)
+{
+ EFI_STATUS Status;
+ InitAmiLib (ImageHandle, SystemTable);
+ DriverBinding->ImageHandle = ImageHandle;
+ DriverBinding->DriverBindingHandle = DriverBindingHandle;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &DriverBinding->DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, DriverBinding,
+ NULL
+ );
+ if (EFI_ERROR(Status)) return Status;
+ if (ComponentName)
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &DriverBinding->DriverBindingHandle,
+#if EFI_SPECIFICATION_VERSION <= 0x20000
+ &gEfiComponentNameProtocolGuid, ComponentName,
+#else
+ &gEfiComponentName2ProtocolGuid,ComponentName,
+#endif
+ NULL
+ );
+ return Status;
+}
+
+BOOLEAN
+EfiLibCompareLanguage (
+ CHAR8 *Language1,
+ CHAR8 *Language2
+ )
+
+{
+ return *(UINT16*)Language1==*(UINT16*)Language2
+ && Language1[2]==Language2[2];
+}
+
+EFI_STATUS EfiLibLookupUnicodeString (
+ CHAR8 *Language,
+ CHAR8 *SupportedLanguages,
+ EFI_UNICODE_STRING_TABLE *UnicodeStringTable,
+ CHAR16 **UnicodeString
+ )
+{
+ //
+ // Make sure the parameters are valid
+ //
+ if (Language == NULL || UnicodeString == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If there are no supported languages, or the Unicode String Table is empty, then the
+ // Unicode String specified by Language is not supported by this Unicode String Table
+ //
+ if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure Language is in the set of Supported Languages
+ //
+ while (*SupportedLanguages != 0) {
+ if (EfiLibCompareLanguage (Language, SupportedLanguages)) {
+
+ //
+ // Search the Unicode String Table for the matching Language specifier
+ //
+ while (UnicodeStringTable->Language != NULL) {
+ if (EfiLibCompareLanguage (Language, UnicodeStringTable->Language)) {
+
+ //
+ // A matching string was found, so return it
+ //
+ *UnicodeString = UnicodeStringTable->UnicodeString;
+ return EFI_SUCCESS;
+ }
+ UnicodeStringTable++;
+ }
+ return EFI_UNSUPPORTED;
+ }
+ SupportedLanguages += 3;
+ }
+ return EFI_UNSUPPORTED;
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/CSM/thunk/CsmVideo/AmiMapping.h b/Core/EM/CSM/thunk/CsmVideo/AmiMapping.h
new file mode 100644
index 0000000..9c92d54
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/AmiMapping.h
@@ -0,0 +1,153 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/AmiMapping.h 3 12/23/13 10:21a Olegi $
+//
+// $Revision: 3 $
+//
+// $Date: 12/23/13 10:21a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/AmiMapping.h $
+//
+// 3 12/23/13 10:21a Olegi
+// [TAG] EIP148123
+// [Description] CSM includes file which name has been changed
+//
+// 2 3/04/11 2:28p Olegi
+// [TAG] EIP55098
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI
+// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode.
+// [Files] UefiBiosVideo.h
+// UefiBiosVideo.c
+// ComponentName.c
+// AmiMapping.h
+// AmiMapping.c
+//
+// 1 12/29/06 3:33p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AmiMapping.h
+//
+// Description: Mapping from EDK to AMI definitions
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef __AMI_MAPPING__H__
+#define __AMI_MAPPING__H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName.h>
+#include <AmiDxeLib.h>
+#include <Token.h>
+
+#define STATIC static
+#define EFI_GUID_DEFINITION(a)
+#define EFI_PROTOCOL_DEFINITION(a) CONVERT_TO_STRING(Protocol/a.h)
+#define EFI_DRIVER_ENTRY_POINT(a)
+#define EFI_TPL_NOTIFY TPL_NOTIFY
+#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
+
+#define EfiZeroMem(Address, Length) gBS->SetMem ((Address), (Length), 0)
+#define gBS pBS
+#define ReportStatusCodeWithDevicePath(a,b,c,d,e)
+
+#define ACPI_ADR_DISPLAY_TYPE_VGA 1
+#define ACPI_DISPLAY_ADR(_DeviceIdScheme, _HeadId, _NonVgaOutput, _BiosCanDetect, _VendorInfo, _Type, _Port, _Index) \
+ ((UINT32) ( (((_DeviceIdScheme) & 0x1) << 31) | \
+ (((_HeadId) & 0x7) << 18) | \
+ (((_NonVgaOutput) & 0x1) << 17) | \
+ (((_BiosCanDetect) & 0x1) << 16) | \
+ (((_VendorInfo) & 0xf) << 12) | \
+ (((_Type) & 0xf) << 8) | \
+ (((_Port) & 0xf) << 4) | \
+ ((_Index) & 0xf) ))
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION < 0x4028F)
+#define SetDevicePathNodeLength SET_NODE_LENGTH
+#endif
+
+#define EfiAppendDevicePathNode DPAddNode
+#define CR(pField, OutterType, Field, Signature) OUTTER(pField, Field, OutterType)
+#define EFI_SEGMENT(_Adr) (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) & 0xf000)
+#define EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xffff)
+#define EFI_SIMPLE_TEXT_OUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+#define EFI_SIMPLE_TEXT_OUTPUT_MODE SIMPLE_TEXT_OUTPUT_MODE
+#define CHAR_NULL 0x0000
+#define CHAR_BACKSPACE 0x0008
+#define CHAR_TAB 0x0009
+#define CHAR_LINEFEED 0x000A
+#define CHAR_CARRIAGE_RETURN 0x000D
+
+typedef struct {
+ CHAR8 *Language;
+ CHAR16 *UnicodeString;
+} EFI_UNICODE_STRING_TABLE;
+
+#define INSTALL_ALL_DRIVER_PROTOCOLS EfiLibInstallAllDriverProtocols
+EFI_STATUS
+EfiLibInstallAllDriverProtocols (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
+ IN EFI_HANDLE DriverBindingHandle,
+#if EFI_SPECIFICATION_VERSION <= 0x20000
+ IN EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL
+#else
+ IN EFI_COMPONENT_NAME2_PROTOCOL *ComponentName, OPTIONAL
+#endif
+ IN VOID/*EFI_DRIVER_CONFIGURATION_PROTOCOL*/ *DriverConfiguration, OPTIONAL
+ IN VOID/*EFI_DRIVER_DIAGNOSTICS_PROTOCOL*/ *DriverDiagnostics OPTIONAL
+ );
+
+EFI_STATUS
+EfiLibLookupUnicodeString (
+ CHAR8 *Language,
+ CHAR8 *SupportedLanguages,
+ EFI_UNICODE_STRING_TABLE *UnicodeStringTable,
+ CHAR16 **UnicodeString
+ );
+
+EFI_STATUS
+EFIAPI
+VgaClassDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2006, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/CSM/thunk/CsmVideo/ComponentName.c b/Core/EM/CSM/thunk/CsmVideo/ComponentName.c
new file mode 100644
index 0000000..786cec4
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/ComponentName.c
@@ -0,0 +1,324 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+--*/
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+//*** AMI PORTING BEGIN ***//
+//This file is not part of the component.
+//#include "BiosVideo.h"
+#include "UefiBiosVideo.h"
+//*** AMI PORTING END *****//
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+BiosVideoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+BiosVideoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+EFI_STATUS
+
+EFIAPI
+BiosVideoComponentName2GetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+EFI_STATUS
+EFIAPI
+BiosVideoComponentName2GetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = {
+ BiosVideoComponentName2GetDriverName,
+ BiosVideoComponentName2GetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+
+EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName = {
+ BiosVideoComponentNameGetDriverName,
+ BiosVideoComponentNameGetControllerName,
+ "eng"
+};
+
+static EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = {
+ {
+ "eng",
+ L"BIOS[INT10] Video Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+static EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable2[] = {
+ {
+ LANGUAGE_CODE_ENGLISH,
+ L"BIOS[INT10] Video Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+EFI_STATUS
+EFIAPI
+BiosVideoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+
+ return EfiLibLookupUnicodeString (
+ Language,
+ gBiosVideoComponentName.SupportedLanguages,
+ mBiosVideoDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+BiosVideoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+BiosVideoComponentName2GetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+
+ return EfiLibLookupUnicodeString (
+ Language,
+ gBiosVideoComponentName2.SupportedLanguages,
+ mBiosVideoDriverNameTable2,
+ DriverName
+ );
+}
+
+
+EFI_STATUS
+EFIAPI
+BiosVideoComponentName2GetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/Core/EM/CSM/thunk/CsmVideo/CsmVideo.cif b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.cif
new file mode 100644
index 0000000..e357445
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.cif
@@ -0,0 +1,20 @@
+<component>
+ name = "CsmVideo"
+ category = ModulePart
+ LocalRoot = "Core\EM\CSM\Thunk\CsmVideo\"
+ RefName = "CsmVideo"
+[files]
+"CsmVideo.sdl"
+"CsmVideo.mak"
+"UefiBiosVideo.h"
+"UefiBiosVideo.c"
+"ComponentName.c"
+"VesaBiosExtensions.h"
+"pci22.h"
+"AmiMapping.h"
+"AmiMapping.c"
+"VgaMiniPort.h"
+"VgaClass.h"
+"VgaClass.c"
+"CsmVideo.dxs"
+<endComponent>
diff --git a/Core/EM/CSM/thunk/CsmVideo/CsmVideo.dxs b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.dxs
new file mode 100644
index 0000000..2f961f5
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.dxs
@@ -0,0 +1,46 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/CsmVideo.dxs 1 11/10/11 6:34p Olegi $
+//
+// $Revision: 1 $
+//
+// $Date: 11/10/11 6:34p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/CsmVideo.dxs $
+//
+// 1 11/10/11 6:34p Olegi
+//
+//**********************************************************************
+
+#include <Protocol\LegacyBios.h>
+
+DEPENDENCY_START
+ EFI_LEGACY_BIOS_PROTOCOL_GUID
+DEPENDENCY_END
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/CsmVideo/CsmVideo.mak b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.mak
new file mode 100644
index 0000000..4d59620
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.mak
@@ -0,0 +1,66 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2006, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/CsmVideo.mak 2 4/27/07 5:18p Olegi $
+#
+# $Revision: 2 $
+#
+# $Date: 4/27/07 5:18p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/CsmVideo/CsmVideo.mak $
+#
+# 2 4/27/07 5:18p Olegi
+#
+# 1 12/29/06 3:33p Felixp
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: CsmVideo.mak
+#
+# Description: CSM Video make file
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : CsmVideo
+
+CsmVideo : $(BUILD_DIR)\CsmVideo.mak CsmVideoBin
+
+$(BUILD_DIR)\CsmVideo.mak : $(CsmVideo_DIR)\$(@B).cif $(CsmVideo_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CsmVideo_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+CsmVideoBin : $(AMIDXELIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\CsmVideo.mak all\
+ GUID=29CF55F8-B675-4f5d-8F2F-B87A3ECFD063\
+ ENTRY_POINT=BiosVideoDriverEntryPoint\
+ EXT_HEADERS=$(BUILD_DIR)\Token.h\
+ TYPE=BS_DRIVER \
+ COMPRESS=1
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2006, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/Core/EM/CSM/thunk/CsmVideo/CsmVideo.sdl b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.sdl
new file mode 100644
index 0000000..19768e8
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/CsmVideo.sdl
@@ -0,0 +1,58 @@
+TOKEN
+ Name = "CsmVideo_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable CsmVideo support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "INT10_VESA_GO_SUPPORT"
+ Value = "1"
+ Help = "Enables/Disables support of the Graphics Output protocol using VESA INT10 extensions"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "INT10_VGA_GO_SUPPORT"
+ Value = "0"
+ Help = "Enables/Disables support of the Graphics Output protocol using standard VGA INT10 calls in 640x480 16 color mode.\If both VGA_GO_SUPPORT and VESA_GO_SUPPORT enabled, VGA calls will only be used if VESA extensions are not supported by the video card."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "INT10_SIMPLE_TEXT_SUPPORT"
+ Value = "1"
+ Help = "Enables/Disables support of the Simple Text Output protocol using text mode.\If VGA_GO_SUPPORT or VESA_GO_SUPPORT or both enabled, text mode will will only be used if neither VESA nor standard VGA graphical modes are supported"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "INT10_TRUST_EDID_INFORMATION"
+ Value = "1"
+ Help = "Some SSUs(Server Switch Units) return invalid EDID information, for these turn this switch off."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+
+PATH
+ Name = "CsmVideo_DIR"
+End
+
+MODULE
+ Help = "Includes CsmVideo.mak to Project"
+ File = "CsmVideo.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CsmVideo.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.c b/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.c
new file mode 100644
index 0000000..ddbe46c
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.c
@@ -0,0 +1,3886 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+--*/
+/*++
+
+Copyright (c) 2006 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ BiosVideo.c
+
+Abstract:
+
+ ConsoleOut Routines that speak VGA.
+
+Revision History
+
+--*/
+
+//*** AMI PORTING BEGIN ***//
+#include "AcpiRes.h"
+//*** AMI PORTING END *****//
+#include "UefiBiosVideo.h"
+
+#define TRACE_BIOS_VIDEO TRACE_ALWAYS
+//#define TRACE_BIOS_VIDEO TRACE_NEVER
+
+//
+// EFI Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {
+ BiosVideoDriverBindingSupported,
+ BiosVideoDriverBindingStart,
+ BiosVideoDriverBindingStop,
+ 0x00000024,
+ NULL,
+ NULL
+};
+
+typedef struct _TEXT_MODE {
+ INT32 ModeNum;
+ INT32 Col;
+ INT32 Row;
+ UINT32 VideoCol; // horizontal pixels
+ UINT32 VideoRow; // vertical pixels
+} TEXT_MODE;
+
+#if CORE_COMBINED_VERSION < 0x4028e
+const TEXT_MODE TextModeArray[] = {GC_MODE_LIST};
+const INT32 MaxTextMode=(sizeof(TextModeArray)/sizeof(TEXT_MODE));
+#else
+extern TEXT_MODE TextModeArray[];
+extern INT32 MaxTextMode;
+#endif
+
+// remove the following line when Protocol/EdidOverride.h becomes available
+EFI_GUID gEfiEdidOverrideProtocolGuid = EFI_EDID_OVERRIDE_PROTOCOL_GUID;
+
+//*** AMI PORTING BEGIN ***//
+#if INT10_VGA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+//
+// Global lookup tables for VGA graphics modes
+//
+UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
+
+UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
+
+UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = {
+ { 0x00, 0x00, 0x00, 0x00 },
+ { 0x98, 0x00, 0x00, 0x00 },
+ { 0x00, 0x98, 0x00, 0x00 },
+ { 0x98, 0x98, 0x00, 0x00 },
+ { 0x00, 0x00, 0x98, 0x00 },
+ { 0x98, 0x00, 0x98, 0x00 },
+ { 0x00, 0x98, 0x98, 0x00 },
+ { 0x98, 0x98, 0x98, 0x00 },
+ { 0x10, 0x10, 0x10, 0x00 },
+ { 0xff, 0x10, 0x10, 0x00 },
+ { 0x10, 0xff, 0x10, 0x00 },
+ { 0xff, 0xff, 0x10, 0x00 },
+ { 0x10, 0x10, 0xff, 0x00 },
+ { 0xf0, 0x10, 0xff, 0x00 },
+ { 0x10, 0xff, 0xff, 0x00 },
+ { 0xff, 0xff, 0xff, 0x00 }
+};
+
+//*** AMI PORTING BEGIN ***//
+#endif //if INT10_VGA_GO_SUPPORT==1
+#if INT10_VESA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+
+//
+// Standard timing defined by VESA EDID
+//
+VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = {
+ //
+ // Established Timing I
+ //
+ {800, 600, 60},
+ {800, 600, 56},
+ {640, 480, 75},
+ {640, 480, 72},
+ {640, 480, 67},
+ {640, 480, 60},
+ {720, 400, 88},
+ {720, 400, 70},
+ //
+ // Established Timing II
+ //
+ {1280, 1024, 75},
+ {1024, 768, 75},
+ {1024, 768, 70},
+ {1024, 768, 60},
+ {1024, 768, 87},
+ {832, 624, 75},
+ {800, 600, 75},
+ {800, 600, 72},
+ //
+ // Established Timing III
+ //
+ {1152, 870, 75}
+};
+//*** AMI PORTING BEGIN ***//
+#endif //if INT10_VESA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+
+UINT32 SupportedResolutions[29] = { 0 };
+
+EFI_STATUS
+BiosVideoChildHandleInstall (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ParentHandle,
+ IN EFI_PCI_IO_PROTOCOL *ParentPciIo,
+ IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+EFI_STATUS
+BiosVideoChildHandleUninstall (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_HANDLE Handle
+ )
+;
+
+VOID
+BiosVideoDeviceReleaseResource (
+ BIOS_VIDEO_DEV *BiosVideoPrivate
+ )
+;
+
+//*** AMI PORTING BEGIN ***//
+//CsmVideo Policy Protocol support
+//The protocol can be used to set the driver policy.
+// The two supported policies are:
+// SimpleTextOut over the text mode 3 (TextMode=TRUE)
+// GOP over graphical mode (TextMode=FALSE)
+EFI_HANDLE VgaControllerHandle = NULL;
+BOOLEAN TextModePolicy = FALSE;
+
+EFI_STATUS CsmVideoPolicySetMode(
+ IN CSM_VIDEO_POLICY_PROTOCOL *This,
+ IN BOOLEAN TextMode, IN BOOLEAN ForceModeChange
+){
+#if INT10_SIMPLE_TEXT_SUPPORT==0
+ return (TextMode) ? EFI_UNSUPPORTED : EFI_SUCCESS;
+#else
+ EFI_STATUS Status;
+ BOOLEAN OriginalPolicy=TextModePolicy;
+ EFI_HANDLE Handle;
+
+ TextModePolicy = TextMode;
+ if ( VgaControllerHandle == NULL
+ || OriginalPolicy==TextModePolicy && !ForceModeChange
+ ) return EFI_SUCCESS;
+
+ // save the VGA handle
+ // the global variable VgaControllerHandle will be nullified
+ // by the Stop function during Disconnect.
+ Handle = VgaControllerHandle;
+ Status = pBS->DisconnectController( Handle, NULL, NULL );
+ if (!EFI_ERROR(Status))
+ Status = pBS->ConnectController( Handle, NULL, NULL, TRUE );
+ else
+ TextModePolicy = OriginalPolicy;
+ if (EFI_ERROR(Status)) return Status;
+ return (TextModePolicy==TextMode) ? EFI_SUCCESS : EFI_UNSUPPORTED;
+#endif
+}
+
+EFI_STATUS CsmVideoPolicyGetMode(
+ IN CSM_VIDEO_POLICY_PROTOCOL *This,IN BOOLEAN *IsTextMode
+){
+ if (IsTextMode!=NULL) *IsTextMode = TextModePolicy;
+ return (VgaControllerHandle == NULL) ? EFI_NOT_STARTED : EFI_SUCCESS;
+}
+
+CSM_VIDEO_POLICY_PROTOCOL CsmVideoPolicyProtocol = {
+ CsmVideoPolicyGetMode, CsmVideoPolicySetMode
+};
+//*** AMI PORTING END *****//
+
+EFI_STATUS GetBadEdid (
+ IN EFI_EDID_OVERRIDE_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle,
+ OUT UINT32 *Attributes,
+ IN OUT UINTN *EdidSize,
+ IN OUT UINT8 **Edid
+ )
+{
+ static UINT8 EdidData[0x80] = {0};
+ EdidData[0x7f] = 1; // invalid checksum
+
+ *Edid = EdidData;
+ *EdidSize = 0x80;
+ *Attributes = 0;
+
+ return EFI_SUCCESS;
+}
+
+
+//
+// Driver Entry Point
+//
+EFI_DRIVER_ENTRY_POINT (BiosVideoDriverEntryPoint)
+
+EFI_STATUS
+EFIAPI
+BiosVideoDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+ Routine Description:
+
+ Driver Entry Point.
+
+ Arguments:
+
+ ImageHandle - Handle of driver image.
+ SystemTable - Pointer to system table.
+
+ Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ static EFI_GUID gCsmThunkDriverGuid =
+ { 0x2362ea9c, 0x84e5, 0x4dff, 0x83, 0xbc, 0xb5, 0xac, 0xec, 0xb5, 0x7c, 0xbb };
+
+ Status = EfiLibInstallAllDriverProtocols (
+ ImageHandle,
+ SystemTable,
+ &gBiosVideoDriverBinding,
+ ImageHandle,
+#if EFI_SPECIFICATION_VERSION <= 0x20000
+ &gBiosVideoComponentName,
+#else
+ &gBiosVideoComponentName2,
+#endif
+ NULL,
+ NULL
+ );
+//*** AMI PORTING BEGIN ***//
+#if INT10_SIMPLE_TEXT_SUPPORT==1
+{
+//create new handle
+ EFI_HANDLE Handle = NULL;
+ VgaClassDriverEntryPoint(Handle,SystemTable);
+}
+#endif
+
+#if INT10_TRUST_EDID_INFORMATION == 0
+{
+ // Install EdidOverride with the dummy EDID information; this is needed to ignore
+ // bad EDID information
+ EFI_STATUS Status;
+ static EFI_EDID_OVERRIDE_PROTOCOL EdidOverride = { GetBadEdid };
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle,
+ &gEfiEdidOverrideProtocolGuid, &EdidOverride,
+ NULL
+ );
+}
+#endif
+
+// Install CsmVideoPolicy protocol
+ gBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle,
+ &gCsmVideoPolicyProtocolGuid, &CsmVideoPolicyProtocol,
+ &gCsmThunkDriverGuid, NULL,
+ NULL
+ );
+
+//AMI CSM Core does not need Legacy BIOS GUID
+//Just return the status
+ return Status;
+/*
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver
+ //
+ return gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiLegacyBiosGuid,
+ NULL,
+ NULL
+ );
+*/
+//*** AMI PORTING END *****//
+}
+//*** AMI PORTING BEGIN ***//
+//Exit Boot Services callback is not needed.
+/*
+VOID
+BiosVideoExitBootServices (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+*/
+/*++
+
+Routine Description:
+
+ Callback function for exit boot service event
+
+Arguments:
+
+ Event - EFI_EVENT structure
+ Context - Event context
+
+Returns:
+
+ None
+
+--*/
+/*{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_IA32_REGISTER_SET Regs;
+
+ //
+ // Get our context
+ //
+ BiosVideoPrivate = (BIOS_VIDEO_DEV *) Context;
+
+ //
+ // Set the 80x25 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x83;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x14;
+ Regs.H.BL = 0;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+}
+*/
+//*** AMI PORTING END *****//
+
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+
+ Supported.
+
+ Arguments:
+
+ This - Pointer to driver binding protocol
+ Controller - Controller handle to connect
+ RemainingDevicePath - A pointer to the remaining portion of a device path
+
+
+ Returns:
+
+ EFI_STATUS - EFI_SUCCESS:This controller can be managed by this driver,
+ Otherwise, this controller cannot be managed by this driver
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // See if this is a PCI Graphics Controller by looking at the Command register and
+ // Class Code Register
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+
+ Install Graphics Output Protocol onto VGA device handles
+
+ Arguments:
+
+ This - Pointer to driver binding protocol
+ Controller - Controller handle to connect
+ RemainingDevicePath - A pointer to the remaining portion of a device path
+
+ Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Flags;
+//*** AMI PORTING BEGIN ***//
+// See comments below regarding the Capabilities usage
+ UINT64 Capabilities = 0;
+//*** AMI PORTING END *****//
+
+ PciIo = NULL;
+ //
+ // Prepare for status code
+ //
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Open the IO Abstraction(s) needed
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ReportStatusCodeWithDevicePath (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_ENABLE,
+ 0,
+ &gEfiCallerIdGuid,
+ ParentDevicePath
+ );
+ //
+ // Enable the device and make sure VGA cycles are being forwarded to this VGA device
+ //
+//*** AMI PORTING BEGIN ***//
+// We need to check what is supported by the hardware before enabling attributes
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Capabilities
+ );
+
+ if ( EFI_ERROR(Status) ) {
+ goto Done;
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Capabilities & EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+ NULL
+ );
+/*
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+ NULL
+ );
+*/
+//*** AMI PORTING END *****//
+ if (EFI_ERROR (Status)) {
+ ReportStatusCodeWithDevicePath (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,
+ 0,
+ &gEfiCallerIdGuid,
+ ParentDevicePath
+ );
+ goto Done;
+ }
+ //
+ // Check to see if there is a legacy option ROM image associated with this PCI device
+ //
+ Status = LegacyBios->CheckPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ NULL,
+ &Flags
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Post the legacy option ROM if it is available.
+ //
+ ReportStatusCodeWithDevicePath (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_RESET,
+ 0,
+ &gEfiCallerIdGuid,
+ ParentDevicePath
+ );
+ Status = LegacyBios->InstallPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ &Flags,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ReportStatusCodeWithDevicePath (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
+ 0,
+ &gEfiCallerIdGuid,
+ ParentDevicePath
+ );
+ goto Done;
+ }
+
+ //
+ // Create child handle and install GraphicsOutputProtocol on it
+ //
+ Status = BiosVideoChildHandleInstall (
+ This,
+ Controller,
+ PciIo,
+ LegacyBios,
+ ParentDevicePath,
+ RemainingDevicePath
+ );
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if (PciIo != NULL) {
+ ReportStatusCodeWithDevicePath (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_DISABLE,
+ 0,
+ &gEfiCallerIdGuid,
+ ParentDevicePath
+ );
+ //
+ // Turn off the PCI device and disable forwarding of VGA cycles to this device
+ //
+ if (Capabilities != 0)
+ {
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+//*** AMI PORTING BEGIN ***//
+ Capabilities & EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+// EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+//*** AMI PORTING END *****//
+ NULL
+ );
+ }
+ //
+ // Release PCI I/O Protocols on the controller handle.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+
+ Stop.
+
+ Arguments:
+
+ This - Pointer to driver binding protocol
+ Controller - Controller handle to connect
+ NumberOfChilren - Number of children handle created by this driver
+ ChildHandleBuffer - Buffer containing child handle created
+
+ Returns:
+
+ EFI_SUCCESS - Driver disconnected successfully from controller
+ EFI_UNSUPPORTED - Cannot find BIOS_VIDEO_DEV structure
+
+--*/
+{
+ EFI_STATUS Status;
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Capabilities;
+
+ BiosVideoPrivate = NULL;
+
+ if (NumberOfChildren == 0) {
+//*** AMI PORTING BEGIN ***//
+//In text mode, the child handle is not created
+//and the mini port protocol is installed on the PciIo handle.
+//Original implementation does not stop controller in this case
+//Here is the fix:
+#if INT10_SIMPLE_TEXT_SUPPORT==1
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiVgaMiniPortProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR(Status)){
+ return BiosVideoChildHandleUninstall (This, Controller, Controller);
+ }
+#endif
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Capabilities
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ Capabilities & EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+ NULL
+ );
+
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+//*** AMI PORTING END *****//
+ //
+ // Close PCI I/O protocol on the controller handle
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+BiosVideoChildHandleInstall (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ParentHandle,
+ IN EFI_PCI_IO_PROTOCOL *ParentPciIo,
+ IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+ Install child handles if the Handle supports MBR format.
+
+Arguments:
+ This - Calling context.
+ Handle - Parent Handle
+ PciIo - Parent PciIo interface
+ LegacyBios - Parent LegacyBios interface
+ DevicePath - Parent Device Path
+
+Returns:
+ EFI_SUCCESS - If a child handle was added
+ other - A child handle was not added
+
+--*/
+{
+ EFI_STATUS Status;
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ PCI_TYPE00 Pci;
+ ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
+
+ //
+ // Allocate the private device structure for video device
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (BIOS_VIDEO_DEV),
+ &BiosVideoPrivate
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ EfiZeroMem (BiosVideoPrivate, sizeof (BIOS_VIDEO_DEV));
+
+ //
+ // See if this is a VGA compatible controller or not
+ //
+ Status = ParentPciIo->Pci.Read (
+ ParentPciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ ReportStatusCodeWithDevicePath (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
+ 0,
+ &gEfiCallerIdGuid,
+ ParentDevicePath
+ );
+ goto Done;
+ }
+ BiosVideoPrivate->VgaCompatible = FALSE;
+ if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) {
+ BiosVideoPrivate->VgaCompatible = TRUE;
+ }
+
+ if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) {
+ BiosVideoPrivate->VgaCompatible = TRUE;
+ }
+
+ //
+ // Initialize the child private structure
+ //
+ BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;
+ BiosVideoPrivate->Handle = NULL;
+
+//*** AMI PORTING BEGIN ***//
+//Exit Boot Services callback is not needed.
+/*
+ Status = gBS->CreateEvent (
+ EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
+ EFI_TPL_NOTIFY,
+ BiosVideoExitBootServices,
+ BiosVideoPrivate,
+ &BiosVideoPrivate->ExitBootServicesEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+*/
+//*** AMI PORTING END *****//
+
+ //
+ // Fill in Graphics Output specific mode structures
+ //
+ BiosVideoPrivate->HardwareNeedsStarting = TRUE;
+ BiosVideoPrivate->ModeData = NULL;
+ BiosVideoPrivate->LineBuffer = NULL;
+ BiosVideoPrivate->VgaFrameBuffer = NULL;
+ BiosVideoPrivate->VbeFrameBuffer = NULL;
+
+//*** AMI PORTING BEGIN ***//
+//Let's do it only if VgaMiniPort is going to be installed
+/*
+ //
+ // Fill in the VGA Mini Port Protocol fields
+ //
+ BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode;
+ BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000;
+ BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;
+ BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5;
+ BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+ BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+ BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+*/
+ //
+ // Assume that Graphics Output Protocol will be produced until proven otherwise
+ //
+ BiosVideoPrivate->ProduceGraphicsOutput = TRUE;
+
+ //
+ // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
+ //
+ if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {
+ if (RemainingDevicePath == NULL) {
+ EfiZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
+ AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
+ AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
+ AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
+ SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
+
+ BiosVideoPrivate->DevicePath = EfiAppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
+ );
+ } else {
+ BiosVideoPrivate->DevicePath = EfiAppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
+ }
+
+ //
+ // Create child handle associated with device path
+ // The newely created handle can be used for calling EDID_OVERRIDE_PROTOCOL
+ //
+ BiosVideoPrivate->Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &BiosVideoPrivate->Handle,
+ &gEfiDevicePathProtocolGuid,
+ BiosVideoPrivate->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Child handle need to consume the Legacy Bios protocol
+ //
+ BiosVideoPrivate->LegacyBios = ParentLegacyBios;
+
+ //
+ // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
+ //
+ BiosVideoPrivate->PciIo = ParentPciIo;
+
+ //
+ // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
+ //
+//*** AMI PORTING BEGIN ***//
+// Status = BiosVideoCheckForVbe (BiosVideoPrivate);
+#if INT10_VESA_GO_SUPPORT==1
+ if ( TextModePolicy )
+ Status = EFI_UNSUPPORTED;
+ else
+ Status = BiosVideoCheckForVbe (BiosVideoPrivate, &Pci);
+#else
+ Status = EFI_UNSUPPORTED;
+#endif
+//*** AMI PORTING END *****//
+ if (EFI_ERROR (Status)) {
+ //
+ // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support
+ // for the standard 640x480 16 color VGA mode
+ //
+//*** AMI PORTING BEGIN ***//
+// if (BiosVideoPrivate->VgaCompatible) {
+// Status = BiosVideoCheckForVga (BiosVideoPrivate);
+// }
+#if INT10_VGA_GO_SUPPORT==1
+ if (!TextModePolicy && BiosVideoPrivate->VgaCompatible) {
+ Status = BiosVideoCheckForVga (BiosVideoPrivate);
+ }
+#endif
+//*** AMI PORTING END *****//
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
+ // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.
+ //
+ BiosVideoPrivate->ProduceGraphicsOutput = FALSE;
+
+ //
+ // INT services are available, so on the 80x25 and 80x50 text mode are supported
+ //
+ BiosVideoPrivate->VgaMiniPort.MaxMode = 2;
+ }
+ }
+
+ if (BiosVideoPrivate->ProduceGraphicsOutput) {
+ //
+ // Create child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &BiosVideoPrivate->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &BiosVideoPrivate->GraphicsOutput,
+ &gEfiEdidDiscoveredProtocolGuid,
+ &BiosVideoPrivate->EdidDiscovered,
+ &gEfiEdidActiveProtocolGuid,
+ &BiosVideoPrivate->EdidActive,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Open the Parent Handle for the child
+ //
+ Status = gBS->OpenProtocol (
+ ParentHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &BiosVideoPrivate->PciIo,
+ This->DriverBindingHandle,
+ BiosVideoPrivate->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ }
+ } else {
+//*** AMI PORTING BEGIN ***//
+#if INT10_SIMPLE_TEXT_SUPPORT==1
+//The code if moved here from BiosVideoChildHandleInstall
+ //
+ // Fill in the VGA Mini Port Protocol fields
+ //
+ BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode;
+ BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000;
+ BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;
+ BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5;
+ BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+ BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+ BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+//*** AMI PORTING END *****//
+//*** AMI PORTING BEGIN ***//
+ //This is needed! Otherwise VgaClass driver rejects VgaMiniPort
+ //device due to the lack of PciIo protocol
+ BiosVideoPrivate->Handle=ParentHandle;
+//*** AMI PORTING END *****//
+ //
+ // Install VGA Mini Port Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &BiosVideoPrivate->Handle,
+ &gEfiVgaMiniPortProtocolGuid,
+ &BiosVideoPrivate->VgaMiniPort,
+ NULL
+ );
+//*** AMI PORTING BEGIN ***//
+#else
+#endif //INT10_SIMPLE_TEXT_SUPPORT==1
+//*** AMI PORTING END *****//
+ }
+
+Done:
+ if (EFI_ERROR (Status)) {
+ //
+ // Free private data structure
+ //
+ BiosVideoDeviceReleaseResource (BiosVideoPrivate);
+ }
+//*** AMI PORTING BEGIN ***//
+// The protocols are installed.
+// Update global variables used by the CsmVideoPolicy protocol implementation.
+ TextModePolicy = !BiosVideoPrivate->ProduceGraphicsOutput;
+ VgaControllerHandle = ParentHandle;
+//*** AMI PORTING END *****//
+ return Status;
+}
+
+EFI_STATUS
+BiosVideoChildHandleUninstall (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ Deregister an video child handle and free resources
+
+Arguments:
+
+ This - Protocol instance pointer.
+ Controller - Video controller handle
+ Handle - Video child handle
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET Regs;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ BiosVideoPrivate = NULL;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
+ }
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiVgaMiniPortProtocolGuid,
+ (VOID **) &VgaMiniPort,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);
+ }
+
+ if (BiosVideoPrivate == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Close PCI I/O protocol that opened by child handle
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ //
+ // Uninstall protocols on child handle
+ //
+ if (BiosVideoPrivate->ProduceGraphicsOutput) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ BiosVideoPrivate->Handle,
+ &gEfiDevicePathProtocolGuid,
+ BiosVideoPrivate->DevicePath,
+ &gEfiGraphicsOutputProtocolGuid,
+ &BiosVideoPrivate->GraphicsOutput,
+ &gEfiEdidDiscoveredProtocolGuid,
+ &BiosVideoPrivate->EdidDiscovered,
+ &gEfiEdidActiveProtocolGuid,
+ &BiosVideoPrivate->EdidActive,
+ NULL
+ );
+ } else {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ BiosVideoPrivate->Handle,
+ &gEfiVgaMiniPortProtocolGuid,
+ &BiosVideoPrivate->VgaMiniPort,
+ NULL
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ //
+ // Set the 80x25 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x03;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x14;
+ Regs.H.BL = 0;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ //
+ // Do not disable IO/memory decode since that would prevent legacy ROM from working
+ //
+
+ //
+ // Release all allocated resources
+ //
+ BiosVideoDeviceReleaseResource (BiosVideoPrivate);
+//*** AMI PORTING BEGIN ***//
+// The protocols are uninstalled.
+// Update global variables used by the CsmVideoPolicy protocol implementation.
+ VgaControllerHandle = NULL;
+//*** AMI PORTING END *****//
+ return EFI_SUCCESS;
+}
+
+VOID
+BiosVideoDeviceReleaseResource (
+ BIOS_VIDEO_DEV *BiosVideoPrivate
+ )
+/*++
+Routing Description:
+
+ Release resources of an video child device before stopping it.
+
+Arguments:
+
+ BiosVideoPrivate - Video child device private data structure
+
+Returns:
+
+ NONE
+
+---*/
+{
+ if (BiosVideoPrivate == NULL) {
+ return ;
+ }
+
+ //
+ // Release all the resourses occupied by the BIOS_VIDEO_DEV
+ //
+
+ //
+ // Free VGA Frame Buffer
+ //
+ if (BiosVideoPrivate->VgaFrameBuffer != NULL) {
+ gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);
+ BiosVideoPrivate->VgaFrameBuffer = NULL;
+ }
+ //
+ // Free VBE Frame Buffer
+ //
+ if (BiosVideoPrivate->VbeFrameBuffer != NULL) {
+ gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);
+ BiosVideoPrivate->VbeFrameBuffer = NULL;
+ }
+ //
+ // Free line buffer
+ //
+ if (BiosVideoPrivate->LineBuffer != NULL) {
+ gBS->FreePool (BiosVideoPrivate->LineBuffer);
+ BiosVideoPrivate->LineBuffer = NULL;
+ }
+ //
+ // Free mode data
+ //
+ if (BiosVideoPrivate->ModeData != NULL) {
+ gBS->FreePool (BiosVideoPrivate->ModeData);
+ BiosVideoPrivate->ModeData = NULL;
+ }
+ //
+ // Free memory allocated below 1MB
+ //
+ if (BiosVideoPrivate->PagesBelow1MB != 0) {
+ gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);
+ }
+
+ if (BiosVideoPrivate->VbeSaveRestorePages != 0) {
+ gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);
+ }
+ //
+ // Free graphics output protocol occupied resource
+ //
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
+ gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;
+ }
+ gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
+ BiosVideoPrivate->GraphicsOutput.Mode = NULL;
+ }
+ //
+ // Free EDID discovered protocol occupied resource
+ //
+ if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {
+ gBS->FreePool (BiosVideoPrivate->EdidDiscovered.Edid);
+ BiosVideoPrivate->EdidDiscovered.Edid = NULL;
+ }
+ //
+ // Free EDID active protocol occupied resource
+ //
+ if (BiosVideoPrivate->EdidActive.Edid != NULL) {
+ gBS->FreePool (BiosVideoPrivate->EdidActive.Edid);
+ BiosVideoPrivate->EdidActive.Edid = NULL;
+ }
+
+ if (BiosVideoPrivate->DevicePath!= NULL) {
+ gBS->FreePool (BiosVideoPrivate->DevicePath);
+ BiosVideoPrivate->DevicePath = NULL;
+ }
+
+ //
+ // Close the ExitBootServices event
+ //
+//*** AMI PORTING BEGIN ***//
+//ExitBootServicesEvent is not used
+/*
+ if (BiosVideoPrivate->ExitBootServicesEvent != NULL) {
+ gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);
+ }
+*/
+//*** AMI PORTING END *****//
+
+ gBS->FreePool (BiosVideoPrivate);
+
+ return ;
+}
+
+//*** AMI PORTING BEGIN ***//
+#if INT10_VESA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+STATIC
+UINT32
+CalculateEdidKey (
+ VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming
+ )
+/*++
+
+ Routine Description:
+
+ Generate a search key for a specified timing data.
+
+ Arguments:
+
+ EdidTiming - Pointer to EDID timing
+
+ Returns:
+ The 32 bit unique key for search.
+
+--*/
+{
+ UINT32 Key;
+
+ //
+ // Be sure no conflicts for all standard timing defined by VESA.
+ //
+ Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution + EdidTiming->RefreshRate;
+ return Key;
+}
+
+STATIC
+BOOLEAN
+ParseEdidData (
+ UINT8 *EdidBuffer
+ )
+/*++
+
+ Routine Description:
+
+ Parse the Established Timing and Standard Timing in EDID data block.
+
+ Arguments:
+
+ EdidBuffer - Pointer to EDID data block
+ ValidEdidTiming - Valid EDID timing information
+
+ Returns:
+ TRUE - The EDID data is valid.
+ FALSE - The EDID data is invalid.
+
+--*/
+{
+ UINT8 CheckSum;
+ UINT32 Index;
+ UINT32 ValidNumber;
+ UINT32 TimingBits;
+ UINT8 *BufferIndex;
+ UINT16 HorizontalResolution;
+ UINT16 VerticalResolution;
+ UINT8 AspectRatio;
+ VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock;
+
+ EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer;
+
+ //
+ // Check the checksum of EDID data
+ //
+ CheckSum = 0;
+ for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) {
+ CheckSum = CheckSum + EdidBuffer[Index];
+ }
+ if (CheckSum != 0) {
+ TRACE((TRACE_BIOS_VIDEO, "EDID checksum is invalid, EDID will be ignored.\n"));
+ return FALSE;
+ }
+
+ ValidNumber = 0;
+ //
+ // Established timing data
+ //
+ TimingBits = EdidDataBlock->EstablishedTimings[0] |
+ (EdidDataBlock->EstablishedTimings[1] << 8) |
+ ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;
+ for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {
+ if (TimingBits & 0x1) {
+ SupportedResolutions[Index] = mEstablishedEdidTiming[Index].VerticalResolution |
+ (mEstablishedEdidTiming[Index].HorizontalResolution << 16);
+ ValidNumber ++;
+ }
+ TimingBits = TimingBits >> 1;
+ }
+
+ //
+ // If no Established timing data, read the standard timing data
+ //
+ BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];
+ for (Index = 0; Index < 8; Index ++) {
+ if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){
+ //
+ // A valid Standard Timing
+ //
+ HorizontalResolution = BufferIndex[0] * 8 + 248;
+ AspectRatio = BufferIndex[1] >> 6;
+ switch (AspectRatio) {
+ case 0:
+ VerticalResolution = HorizontalResolution / 16 * 10;
+ break;
+ case 1:
+ VerticalResolution = HorizontalResolution / 4 * 3;
+ break;
+ case 2:
+ VerticalResolution = HorizontalResolution / 5 * 4;
+ break;
+ case 3:
+ VerticalResolution = HorizontalResolution / 16 * 9;
+ break;
+ default:
+ VerticalResolution = HorizontalResolution / 4 * 3;
+ break;
+ }
+
+ SupportedResolutions[Index + 17] = VerticalResolution |(HorizontalResolution << 16);
+ ValidNumber ++;
+ }
+ BufferIndex += 2;
+ }
+
+ if ( (EdidDataBlock->FeatureSupport & 2) == 2) {
+ // Preferred timing mode is indicated in the first detailed timing block
+ for (Index = 0; Index < 4; Index ++) {
+ if ((EdidDataBlock->DetailedTimingDescriptions[Index*18 + 0] |
+ EdidDataBlock->DetailedTimingDescriptions[Index*18 + 1]) &&
+ (EdidDataBlock->DetailedTimingDescriptions[Index*18 + 2] |
+ (EdidDataBlock->DetailedTimingDescriptions[Index*18 + 4] & 0xf0))) {
+
+ SupportedResolutions[Index + 25] =
+ (EdidDataBlock->DetailedTimingDescriptions[Index*18 + 5] | ((UINT16)(EdidDataBlock->DetailedTimingDescriptions[Index*18 + 7] & 0xF0) << 4))
+ | ((UINT32)(EdidDataBlock->DetailedTimingDescriptions[Index*18 + 2] | ((UINT16)(EdidDataBlock->DetailedTimingDescriptions[Index*18 + 4] & 0xF0) << 4)) << 16);
+
+TRACE((TRACE_BIOS_VIDEO, "EDID Detailed timing[%d]: inserted resolution 0x%x (%dx%d)\n", Index, SupportedResolutions[Index + 25],
+ EdidDataBlock->DetailedTimingDescriptions[Index*18 + 2] | ((EdidDataBlock->DetailedTimingDescriptions[Index*18 + 4] & 0xF0) << 4),
+ EdidDataBlock->DetailedTimingDescriptions[Index*18 + 5] | ((EdidDataBlock->DetailedTimingDescriptions[Index*18 + 7] & 0xF0) << 4)
+));
+
+ ValidNumber ++;
+ }
+ }
+ }
+
+//*** AMI PORTING BEGIN ***//
+// Bug fix. The function was returning TRUE even when no valid timings found.
+// return TRUE;
+ return (ValidNumber != 0);
+//*** AMI PORTING END ***//
+}
+
+STATIC
+BOOLEAN
+SearchEdidTiming (
+ UINT32 ResolutionKey
+ )
+/*++
+
+ Routine Description:
+
+ Search a specified Timing in all the valid EDID timings.
+
+ Arguments:
+
+ ValidEdidTiming - All valid EDID timing information.
+ EdidTiming - The Timing to search for.
+
+ Returns:
+
+ TRUE - Found.
+ FALSE - Not found.
+
+--*/
+{
+ UINT32 Index;
+ for (Index = 0; Index < 29; Index ++) {
+ if (ResolutionKey == SupportedResolutions[Index]) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//*** AMI PORTING BEGIN ***//
+#if CSM_VGA_64BITBAR_WORKAROUND
+BOOLEAN CheckAbove4g(PCI_TYPE00 *PciConfSpace){
+ UINTN i;
+//---------------------
+ for(i=0; i<PCI_MAX_BAR-1;i++){
+ //check all six bars if
+ if((PciConfSpace->Device.Bar[i] & 0x04) && ( PciConfSpace->Device.Bar[i+1]!=0) ) return TRUE;
+ }
+ return FALSE;
+}
+
+
+EFI_STATUS Update64BitLinearBufferAddr(EFI_PCI_IO_PROTOCOL *PciIo, UINT64 *LowerAddrPart, PCI_TYPE00 *PciConfSpace){
+ UINTN i,j;
+ EFI_STATUS Status;
+ ASLR_QWORD_ASD *BarRes=NULL;
+ UINT64 start, end, bar, test;
+ UINT32 *pUp32;
+//-----------------------------
+
+ //pBS->SetMem(&BarRes[0], sizeof(BarRes), 0);
+ //Get PciIo Bar ACPI QW Resource Descriptor and Count...
+
+ for(i=0; i<PCI_MAX_BAR; i++){
+ //Free Memory allocated for us by PciBus Driver...
+ //if we got here by continue statement...
+ if(BarRes!=NULL){
+ pBS->FreePool(BarRes);
+ BarRes=NULL;
+ }
+
+ Status = PciIo->GetBarAttributes(PciIo,(UINT8)i, NULL, &BarRes);
+ if(EFI_ERROR(Status)) return Status;
+
+ //care only about 64 bit resources end filter out Unused BARs and NOT64bit BARs
+ if(BarRes->Hdr.Name==ASLV_SR_EndTag) continue;
+ if(BarRes->_GRA < 64) continue;
+
+ start=BarRes->_MIN;
+ end=BarRes->_MAX;
+ test=*LowerAddrPart;
+
+ //Free Memory allocated for us by PciBus Driver...
+ if(BarRes!=NULL){
+ pBS->FreePool(BarRes);
+ BarRes=NULL;
+ }
+
+ //now try to match what we read from PCI Config to Res Descriptor returned by the call to PciIo...
+ for(j=0, bar=0; j<PCI_MAX_BAR-1;j++){
+ if(PciConfSpace->Device.Bar[j] & 0x04){
+ //here we got 64 bit BAR....
+ bar=PciConfSpace->Device.Bar[j] & (~0xF); //Mask read only Bar Type bits...
+ //fill Upper Part of BAR address
+ j++;
+ pUp32=((UINT32*)&bar)+1;
+ *pUp32=PciConfSpace->Device.Bar[j];
+ pUp32=((UINT32*)&test)+1;
+ *pUp32=PciConfSpace->Device.Bar[j];
+
+ //Check if we found match?
+ if(start==bar){
+ if((start <= test) && (test < end)) {
+ *LowerAddrPart=test;
+ return EFI_SUCCESS;
+ } else break;
+ }
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+#endif
+//*** AMI PORTING END *****//
+
+EFI_STATUS CheckForDuplicateMode (BIOS_VIDEO_DEV *VideoDev, UINTN ModeNumber)
+{
+ UINT16 Xres = VideoDev->VbeModeInformationBlock->XResolution;
+ UINT16 Yres = VideoDev->VbeModeInformationBlock->YResolution;
+ UINTN i;
+ BIOS_VIDEO_MODE_DATA *ModeData = VideoDev->ModeData;
+
+ // walk through the list of published modes, see if there is a match
+ for (i = 0; i < ModeNumber; i++)
+ {
+ if (ModeData->HorizontalResolution == Xres
+ && ModeData->VerticalResolution == Yres)
+ {
+ return EFI_SUCCESS;
+ }
+ ModeData++;
+ }
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+BiosVideoCheckForVbe (
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate,
+//*** AMI PORTING BEGIN ***//
+ PCI_TYPE00 *PciConfSpace
+//*** AMI PORTING END *****//
+ )
+/*++
+
+ Routine Description:
+
+ Check for VBE device
+
+ Arguments:
+
+ BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
+
+ Returns:
+
+ EFI_SUCCESS - VBE device found
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET Regs;
+ UINT16 *ModeNumberPtr;
+ BOOLEAN ModeFound;
+ BOOLEAN EdidFound;
+ BOOLEAN EdidMatch;
+ BIOS_VIDEO_MODE_DATA *ModeBuffer;
+ BIOS_VIDEO_MODE_DATA *CurrentModeData;
+ UINTN PreferMode;
+ UINTN ModeNumber;
+ UINT32 ResolutionKey;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *GraphicsOutputMode;
+ INT32 i;
+ EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride;
+ UINT32 EdidAttributes;
+ BOOLEAN EdidOverrideFound;
+ UINTN EdidOverrideDataSize;
+ UINT8 *EdidOverrideDataBlock;
+ UINTN EdidActiveDataSize;
+ UINT8 *EdidActiveDataBlock;
+//*** AMI PORTING BEGIN ***//
+#if CSM_VGA_64BITBAR_WORKAROUND
+ BOOLEAN Above4g;
+#endif
+//*** AMI PORTING END *****//
+
+ EdidOverrideFound = FALSE;
+ EdidOverrideDataBlock = NULL;
+ EdidActiveDataSize = 0;
+ EdidActiveDataBlock = NULL;
+
+//*** AMI PORTING BEGIN ***//
+#if CSM_VGA_64BITBAR_WORKAROUND
+ Above4g=CheckAbove4g(PciConfSpace);
+#endif
+//*** AMI PORTING END *****//
+
+ //
+ // Allocate buffer under 1MB for VBE data structures
+ //
+ BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (
+ sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +
+ sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +
+ sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +
+ sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)
+ );
+
+ BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ BiosVideoPrivate->NumberOfPagesBelow1MB,
+ &BiosVideoPrivate->PagesBelow1MB
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Fill in the Graphics Output Protocol
+ //
+ BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;
+ BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;
+ BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;
+ BiosVideoPrivate->GraphicsOutput.Mode = NULL;
+
+ //
+ // Fill in the VBE related data structures
+ //
+ BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);
+ BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);
+ BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);
+ BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);
+ BiosVideoPrivate->VbeSaveRestorePages = 0;
+ BiosVideoPrivate->VbeSaveRestoreBuffer = 0;
+
+ //
+ // Test to see if the Video Adapter is compliant with VBE 3.0
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;
+ gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);
+ BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);
+
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Status = EFI_DEVICE_ERROR;
+
+ //
+ // See if the VESA call succeeded
+ //
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
+ return Status;
+ }
+ //
+ // Check for 'VESA' signature
+ //
+ if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {
+ return Status;
+ }
+ //
+ // Check to see if this is VBE 2.0 or higher
+ //
+ if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {
+ return Status;
+ }
+
+ EdidFound = FALSE;
+ EdidAttributes = 0xff;
+ EdidOverrideDataSize = 0;
+
+ //
+ // Check if EDID Override protocol is installed by platform.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiEdidOverrideProtocolGuid,
+ NULL,
+ (VOID **) &EdidOverride
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof ((VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2)),
+ &EdidOverrideDataBlock
+ );
+
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ Status = EdidOverride->GetEdid (
+ EdidOverride,
+ BiosVideoPrivate->Handle,
+ &EdidAttributes,
+ &EdidOverrideDataSize,
+ (UINT8 **) &EdidOverrideDataBlock
+ );
+ if (!EFI_ERROR (Status) &&
+//*** AMI PORTING BEGIN ***//
+// EdidAttributes == 0 &&
+//*** AMI PORTING END ***//
+ EdidOverrideDataSize != 0) {
+ //
+ // Succeeded to get EDID Override Data
+ //
+ TRACE((TRACE_BIOS_VIDEO, "EDID override protocol found: data size %x, attribute %x\n", EdidOverrideDataSize, EdidAttributes));
+ EdidOverrideFound = TRUE;
+ }
+ }
+
+
+ // "EdidFound" is forcibly FALSE,
+ // because some SSUs(Server Switch Unit) return invalid response.
+ if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) {
+ //
+ // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,
+ // read EDID information through INT10 call and fill in EdidDiscovered structure
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;
+ Regs.X.BX = 1;
+ Regs.X.CX = 0;
+ Regs.X.DX = 0;
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);
+
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+ if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
+
+ BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,
+ &BiosVideoPrivate->EdidDiscovered.Edid
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ gBS->CopyMem (
+ BiosVideoPrivate->EdidDiscovered.Edid,
+ BiosVideoPrivate->VbeEdidDataBlock,
+ VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
+ );
+
+ EdidFound = TRUE;
+ }
+ }
+
+ //
+ // Set up ActiveEdid data pointer and size
+ //
+ if (EdidFound) {
+ EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;
+ EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid;
+ } else if (EdidOverrideFound) {
+ EdidActiveDataSize = EdidOverrideDataSize;
+ EdidActiveDataBlock = EdidOverrideDataBlock;
+ EdidFound = TRUE;
+ }
+
+ if (EdidFound) {
+ //
+ // Parse EDID data structure to retrieve modes supported by monitor
+ //
+ if (ParseEdidData ((UINT8 *) EdidActiveDataBlock) == TRUE) {
+ //
+ // Copy EDID Override Data to EDID Active Data
+ //
+ BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32)EdidActiveDataSize;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ EdidActiveDataSize,
+ &BiosVideoPrivate->EdidActive.Edid
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ gBS->CopyMem (
+ BiosVideoPrivate->EdidActive.Edid,
+ EdidActiveDataBlock,
+ EdidActiveDataSize
+ );
+ }
+ } else {
+ BiosVideoPrivate->EdidActive.SizeOfEdid = 0;
+ BiosVideoPrivate->EdidActive.Edid = NULL;
+ EdidFound = FALSE;
+ }
+
+ //
+ // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
+ //
+ ModeNumberPtr = (UINT16 *)
+ (
+ (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |
+ ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)
+ );
+
+ PreferMode = 0;
+ ModeNumber = 0;
+
+ TRACE((TRACE_BIOS_VIDEO, "VESA: fetching the list of VESA modes supported by the controller from %x\n", ModeNumberPtr));
+
+ for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {
+ //
+ // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
+ //
+ TRACE((TRACE_BIOS_VIDEO,"VESA mode %x ", *ModeNumberPtr));
+
+ if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {
+ TRACE((TRACE_BIOS_VIDEO,".. skipping as it is not a proper VESA mode number\n"));
+ continue;
+ }
+
+ //
+ // Get the information about the mode
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;
+ Regs.X.CX = *ModeNumberPtr;
+ gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);
+
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ //
+ // See if the call succeeded. If it didn't, then try the next mode.
+ //
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
+ TRACE((TRACE_BIOS_VIDEO,".. skipping as we can not retrieve mode details\n"));
+ continue;
+ }
+
+ TRACE((TRACE_BIOS_VIDEO, "(%dx%d) ", BiosVideoPrivate->VbeModeInformationBlock->XResolution, BiosVideoPrivate->VbeModeInformationBlock->YResolution));
+
+ //
+ // See if the mode supported in hardware. If it doesn't then try the next mode.
+ //
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE) == 0) {
+ TRACE((TRACE_BIOS_VIDEO,"skipping as the mode is not supported in hardware...\n"));
+ continue;
+ }
+
+ //
+ // See if the mode supports color. If it doesn't then try the next mode.
+ //
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {
+ TRACE((TRACE_BIOS_VIDEO,"is invalid, skipping...\n"));
+ continue;
+ }
+ //
+ // See if the mode supports graphics. If it doesn't then try the next mode.
+ //
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {
+ TRACE((TRACE_BIOS_VIDEO,"skipping as the mode is not graphical...\n"));
+ continue;
+ }
+ //
+ // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
+ //
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {
+ TRACE((TRACE_BIOS_VIDEO,"skipping as the mode has not linear frame buffer...\n"));
+ continue;
+ }
+ //
+ // See if the mode supports 32 bit color. If it doesn't then try the next mode.
+ // 32 bit mode can be implemented by 24 Bits Per Pixel. Also make sure the
+ // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
+ //
+ if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {
+ TRACE((TRACE_BIOS_VIDEO,"skipping as BPP (%d) is less than 24...\n", BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel));
+ continue;
+ }
+
+ if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {
+ TRACE((TRACE_BIOS_VIDEO,"skipping as BPP (%d) is more than 32...\n", BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel));
+ continue;
+ }
+
+ if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {
+ TRACE((TRACE_BIOS_VIDEO,"skipping as BPP (%d) modulo 8 is non-zero...\n", BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel));
+ continue;
+ }
+ //
+ // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
+ //
+ if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {
+ TRACE((TRACE_BIOS_VIDEO,"skipping as PhysBasePtr is zero...\n"));
+ continue;
+ }
+ EdidMatch = FALSE;
+ if (EdidFound) {
+ //
+ // EDID exist, check whether this mode match with any mode in EDID
+ //
+ ResolutionKey = BiosVideoPrivate->VbeModeInformationBlock->YResolution |
+ (BiosVideoPrivate->VbeModeInformationBlock->XResolution << 16);
+
+ if (SearchEdidTiming (ResolutionKey) == TRUE) {
+ EdidMatch = TRUE;
+ TRACE((TRACE_BIOS_VIDEO, "EDID match found.\n"));
+ }
+ }
+
+ //
+ // Select a reasonable mode to be set for current display mode
+ //
+ ModeFound = FALSE;
+
+ for(i = 0; i < MaxTextMode; i++)
+ {
+ if(TextModeArray[i].VideoCol == BiosVideoPrivate->VbeModeInformationBlock->XResolution &&
+ TextModeArray[i].VideoRow == BiosVideoPrivate->VbeModeInformationBlock->YResolution)
+ {
+ ModeFound = TRUE;
+ TRACE((TRACE_BIOS_VIDEO, "MODE match found (%d).\n", i));
+ }
+ }
+ if ((!EdidMatch) && (!ModeFound)) {
+ //
+ // When EDID exist and if the timing matches with VESA add it.
+ // And also add three possible resolutions, i.e. 1024x768, 800x600, 640x480
+ //
+ TRACE((TRACE_BIOS_VIDEO, "neither EDID nor MODE match is found.\n", i));
+ continue;
+ }
+
+ if (CheckForDuplicateMode(BiosVideoPrivate, ModeNumber) == EFI_SUCCESS)
+ {
+ TRACE((TRACE_BIOS_VIDEO, "skipping as the same resolution (%dx%d) is already available\n",
+ BiosVideoPrivate->VbeModeInformationBlock->XResolution,
+ BiosVideoPrivate->VbeModeInformationBlock->YResolution));
+ continue;
+ }
+
+ //
+ // Add mode to the list of available modes
+ //
+ ModeNumber ++;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA),
+ (VOID **) &ModeBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (ModeNumber > 1) {
+ gBS->CopyMem (
+ ModeBuffer,
+ BiosVideoPrivate->ModeData,
+ (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)
+ );
+ }
+
+ if (BiosVideoPrivate->ModeData != NULL) {
+ gBS->FreePool (BiosVideoPrivate->ModeData);
+ BiosVideoPrivate->ModeData = NULL;
+ }
+
+ CurrentModeData = &ModeBuffer[ModeNumber - 1];
+ CurrentModeData->VbeModeNumber = *ModeNumberPtr;
+ if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {
+ CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;
+ CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;
+ CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);
+ CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;
+ CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);
+ CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;
+ CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);
+ CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;
+ CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);
+ } else {
+ CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;
+ CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;
+ CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);
+ CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;
+ CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);
+ CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;
+ CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);
+ CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;
+ CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);
+ }
+//*** AMI PORTING BEGIN ***//
+//Bug fix: The original logic did not work for a modes with 24-bit pixels.
+// For a 24-bit pixels, the PixelFormat must be set to PixelBitMask, which
+// was not happening with the original "if" statement
+// if ((CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {
+ if ( (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32)
+ && (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)
+ ) {
+//*** AMI PORTING END *****//
+ if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8)) {
+ CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
+ } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8)) {
+ CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+ }
+ } else {
+ CurrentModeData->PixelFormat = PixelBitMask;
+ }
+ CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;
+ CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;
+ CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;
+ CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;
+
+//*** AMI PORTING BEGIN ***//
+#if CSM_VGA_64BITBAR_WORKAROUND
+ if(Above4g){
+ UINT64 PhysBasePtr4g=BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;
+ //------------------------------------
+ Status=Update64BitLinearBufferAddr(BiosVideoPrivate->PciIo, &PhysBasePtr4g, PciConfSpace);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)PhysBasePtr4g;
+ }else
+#endif
+ {
+ CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;
+ }
+ //CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;
+
+//*** AMI PORTING END *****//
+ CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;
+ CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;
+
+ CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;
+
+//*** AMI PORTING BEGIN ***//
+// UEFI SCT 2.3.1 Summer Summit version reports that framebuffersize mismatch in query mode of SCT test
+// Calculated the framebuffersize based for each mode configuration
+ if(CurrentModeData->PixelFormat == PixelRedGreenBlueReserved8BitPerColor ||
+ CurrentModeData->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
+ CurrentModeData->FrameBufferSize=((CurrentModeData->BytesPerScanLine * 8) / CurrentModeData->BitsPerPixel) *
+ CurrentModeData->VerticalResolution *
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ } else {
+ CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;
+ }
+//*** AMI PORTING END *****//
+
+ CurrentModeData->RefreshRate = 60;
+
+ BiosVideoPrivate->ModeData = ModeBuffer;
+ }
+ //
+ // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
+ //
+ if (ModeNumber == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Allocate buffer for Graphics Output Protocol mode information
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
+ (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+ (VOID **) &GraphicsOutputMode->Info
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ GraphicsOutputMode->MaxMode = (UINT32) ModeNumber;
+ //
+ // Current mode is still unknown, set it to an invalid mode.
+ //
+ GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
+ TRACE((TRACE_BIOS_VIDEO, "Total number of GOP modes: %d\n", ModeNumber));
+ //
+ // Find the best mode to initialize
+ //
+ Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);
+ if (EFI_ERROR (Status)) {
+ for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {
+ Status = BiosVideoGraphicsOutputSetMode (
+ &BiosVideoPrivate->GraphicsOutput,
+ (UINT32) PreferMode
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ if (PreferMode == ModeNumber) {
+ //
+ // None mode is set successfully.
+ //
+ goto Done;
+ }
+ }
+
+Done:
+ //
+ // If there was an error, then free the mode structure
+ //
+ if (EFI_ERROR (Status)) {
+ if (BiosVideoPrivate->ModeData != NULL) {
+ gBS->FreePool (BiosVideoPrivate->ModeData);
+ BiosVideoPrivate->ModeData = NULL;
+ }
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
+ gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;
+ }
+ gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
+ BiosVideoPrivate->GraphicsOutput.Mode = NULL;
+ }
+ }
+
+ return Status;
+}
+
+//*** AMI PORTING BEGIN ***//
+#endif//if INT10_VESA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+//*** AMI PORTING BEGIN ***//
+#if INT10_VGA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+EFI_STATUS
+EFIAPI
+BiosVideoCheckForVga (
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate
+ )
+/*++
+
+ Routine Description:
+
+ Check for VGA device
+
+ Arguments:
+
+ BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
+
+ Returns:
+
+ EFI_SUCCESS - Standard VGA device found
+
+--*/
+{
+ EFI_STATUS Status;
+ BIOS_VIDEO_MODE_DATA *ModeBuffer;
+
+ //
+ // Fill in the Graphics Output Protocol
+ //
+ BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;
+ BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;
+ BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;
+
+ //
+ // Allocate buffer for Graphics Output Protocol mode information
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
+ (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+ (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Add mode to the list of available modes
+ //
+ BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (BIOS_VIDEO_MODE_DATA),
+ (VOID **) &ModeBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ModeBuffer->VbeModeNumber = 0x0012;
+ ModeBuffer->BytesPerScanLine = 640;
+ ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);
+ ModeBuffer->FrameBufferSize = 0;
+ ModeBuffer->HorizontalResolution = 640;
+ ModeBuffer->VerticalResolution = 480;
+ ModeBuffer->RefreshRate = 60;
+ ModeBuffer->PixelFormat = PixelBltOnly;
+//*** AMI PORTING BEGIN ***//
+//Bug fix: initialize BitsPerPixel
+ ModeBuffer->BitsPerPixel = 4;
+//*** AMI PORTING END *****//
+
+ BiosVideoPrivate->ModeData = ModeBuffer;
+
+ //
+ // Test to see if the Video Adapter support the 640x480 16 color mode
+ //
+ BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
+ Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);
+
+Done:
+ //
+ // If there was an error, then free the mode structure
+ //
+ if (EFI_ERROR (Status)) {
+ if (BiosVideoPrivate->ModeData != NULL) {
+ gBS->FreePool (BiosVideoPrivate->ModeData);
+ BiosVideoPrivate->ModeData = NULL;
+ }
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
+ gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;
+ }
+ gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
+ BiosVideoPrivate->GraphicsOutput.Mode = NULL;
+ }
+ }
+ return Status;
+}
+//*** AMI PORTING BEGIN ***//
+#endif//if INT10_VGA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+
+//
+// Graphics Output Protocol Member Functions for VESA BIOS Extensions
+//
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol interface to get video mode
+
+ Arguments:
+ This - Protocol instance pointer.
+ ModeNumber - The mode number to return information on.
+ Info - Caller allocated buffer that returns information about ModeNumber.
+ SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
+
+ Returns:
+ EFI_SUCCESS - Mode information returned.
+ EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
+ EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
+ EFI_INVALID_PARAMETER - One of the input args was NULL.
+
+--*/
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_STATUS Status;
+ BIOS_VIDEO_MODE_DATA *ModeData;
+
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+ if (BiosVideoPrivate->HardwareNeedsStarting) {
+ ReportStatusCodeWithDevicePath (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,
+ 0,
+ &gEfiCallerIdGuid,
+ BiosVideoPrivate->DevicePath
+ );
+ return EFI_NOT_STARTED;
+ }
+
+ if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+ Info
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ ModeData = &BiosVideoPrivate->ModeData[ModeNumber];
+ (*Info)->Version = 0;
+ (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
+ (*Info)->VerticalResolution = ModeData->VerticalResolution;
+ (*Info)->PixelFormat = ModeData->PixelFormat;
+ (*Info)->PixelInformation = ModeData->PixelBitMask;
+
+ (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
+
+ return EFI_SUCCESS;
+}
+
+//*** AMI PORTING BEGIN ***//
+// The AllocateTheBuffers function below and certain modifications of
+// the BiosVideoGraphicsOutputVbeBlt nd BiosVideoVgaMiniPortSetMode functions
+// are made to address the issues reaised in EIP 35682.
+//
+// The BLT function (BiosVideoGraphicsOutputVbeBlt) uses several memory buffers.
+// Default implementation allocates the buffers in the SetMode(BiosVideoVgaMiniPortSetMode)
+// function. We are changing implementation to allocate the buffers right in the BLT function
+// before the first use. The code that releases the buffers is still in the SetMode function.
+//
+// This is a workaround for the "UEFI Windows 7 Startup Repair" bug.
+// When Startup Repair option is selected, it crashes with the 0xc0000225 error prior
+// to the call to ExitBootServices.
+// The problem is caused by the Windows inability to handle memory map changes.
+// The memory map changes when Windows calls Gop->SetMode and our implementation of the
+// SetMode(BiosVideoGraphicsOutputVbeBlt) allocates the buffers.
+// This workaround moves buffer allocation to the BLT function (BiosVideoGraphicsOutputVbeBlt),
+// which Windows never calls and therefore memory map never changes.
+EFI_STATUS AllocateTheBuffers(BIOS_VIDEO_DEV *BiosVideoPrivate){
+ EFI_STATUS Status;
+ BIOS_VIDEO_MODE_DATA *ModeData;
+ UINT16 MaxBytesPerScanLine = 0;
+ UINT32 MaxVerticalResolution = 0;
+ UINT32 CurrentMode = (BiosVideoPrivate->GraphicsOutput).Mode->Mode;
+ UINT32 MaxMode = (BiosVideoPrivate->GraphicsOutput).Mode->MaxMode;
+ UINT32 Index;
+
+ TRACE((TRACE_BIOS_VIDEO, "UefiBiosVideo AllocateTheBuffers()\n"));
+ for(Index = 0; Index < MaxMode; Index++) {
+ ModeData = &BiosVideoPrivate->ModeData[Index];
+
+ if (MaxBytesPerScanLine < ModeData->BytesPerScanLine) {
+ MaxBytesPerScanLine = ModeData->BytesPerScanLine;
+ }
+ if (MaxVerticalResolution < ModeData->VerticalResolution) {
+ MaxVerticalResolution = ModeData->VerticalResolution;
+ }
+
+ TRACE((TRACE_BIOS_VIDEO, "VbeModeNumber: 0x%x\n", ModeData->VbeModeNumber));
+ TRACE((TRACE_BIOS_VIDEO, "BytesPerScanLine: 0x%x\n", \
+ ModeData->BytesPerScanLine));
+ TRACE((TRACE_BIOS_VIDEO, "HorizontalResolution: 0x%x\n", \
+ ModeData->HorizontalResolution));
+ TRACE((TRACE_BIOS_VIDEO, "VerticalResolution: 0x%x\n", \
+ ModeData->VerticalResolution));
+ }
+
+ TRACE((TRACE_BIOS_VIDEO, "MaxBytesPerScanLine: 0x%x\n", MaxBytesPerScanLine));
+ TRACE((TRACE_BIOS_VIDEO, "MaxVerticalResolution: 0x%x\n", \
+ MaxVerticalResolution));
+
+ ModeData = &BiosVideoPrivate->ModeData[CurrentMode];
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ MaxBytesPerScanLine,
+ &BiosVideoPrivate->LineBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ BiosVideoPrivate->LineBuffer=NULL;
+ return Status;
+ }
+ MemSet(BiosVideoPrivate->LineBuffer, MaxBytesPerScanLine, 0);
+
+ //
+ // Allocate a working buffer for BLT operations to the VGA frame buffer
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ 4 * 480 * 80,
+ &BiosVideoPrivate->VgaFrameBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (BiosVideoPrivate->LineBuffer);
+ BiosVideoPrivate->LineBuffer=NULL;
+ return Status;
+ }
+ MemSet(BiosVideoPrivate->VgaFrameBuffer, 4 * 480 * 80, 0);
+
+ //
+ // Allocate a working buffer for BLT operations to the VBE frame buffer
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ MaxBytesPerScanLine * MaxVerticalResolution,
+ &BiosVideoPrivate->VbeFrameBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (BiosVideoPrivate->LineBuffer);
+ BiosVideoPrivate->LineBuffer=NULL;
+ return Status;
+ }
+ MemSet(
+ BiosVideoPrivate->VbeFrameBuffer,
+ MaxBytesPerScanLine * MaxVerticalResolution,
+ 0
+ );
+
+ //
+ // Initialize the state of the VbeFrameBuffer
+ //
+ if (ModeData->VbeModeNumber >= 0x100) {
+ gBS->CopyMem (
+ BiosVideoPrivate->VbeFrameBuffer,
+ ModeData->LinearFrameBuffer,
+ (ModeData->BytesPerScanLine * ModeData->VerticalResolution));
+
+ }
+ return Status;
+}
+
+//*** AMI PORTING END *****//
+
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
+ IN UINT32 ModeNumber
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol interface to set video mode
+
+ Arguments:
+ This - Protocol instance pointer.
+ ModeNumber - The mode number to be set.
+
+ Returns:
+ EFI_SUCCESS - Graphics mode was changed.
+ EFI_DEVICE_ERROR - The device had an error and could not complete the request.
+ EFI_UNSUPPORTED - ModeNumber is not supported by this device.
+
+--*/
+{
+//*** AMI PORTING BEGIN ***//
+//Workaround for EIP 35682. See comments above
+//AllocateTheBuffers function for additional details.
+// EFI_STATUS Status;
+//*** AMI PORTING END *****//
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_IA32_REGISTER_SET Regs;
+ BIOS_VIDEO_MODE_DATA *ModeData;
+
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ModeNumber >= This->Mode->MaxMode) {
+ return EFI_UNSUPPORTED;
+ }
+/*
+ if (ModeNumber == This->Mode->Mode) {
+ return EFI_SUCCESS;
+ }
+*/
+ ModeData = &BiosVideoPrivate->ModeData[ModeNumber];
+
+ if (BiosVideoPrivate->LineBuffer) {
+ gBS->FreePool (BiosVideoPrivate->LineBuffer);
+ BiosVideoPrivate->LineBuffer = NULL;
+ }
+
+ if (BiosVideoPrivate->VgaFrameBuffer) {
+ gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);
+ BiosVideoPrivate->VgaFrameBuffer = NULL;
+ }
+
+ if (BiosVideoPrivate->VbeFrameBuffer) {
+ gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);
+ BiosVideoPrivate->VbeFrameBuffer = NULL;
+ }
+
+ BiosVideoPrivate->LineBuffer = NULL;
+//*** AMI PORTING BEGIN ***//
+// Workaround for EIP 35682.
+// Buffer allocation code is moved to AllocateTheBuffers function,
+// which is called from the BiosVideoGraphicsOutputVbeBlt.
+// See comments above AllocateTheBuffers function for additional details.
+/*
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ ModeData->BytesPerScanLine,
+ &BiosVideoPrivate->LineBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+*/
+//*** AMI PORTING END *****//
+ //
+ // Clear all registers
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+
+ if (ModeData->VbeModeNumber < 0x100) {
+ //
+ // Allocate a working buffer for BLT operations to the VGA frame buffer
+ //
+ BiosVideoPrivate->VgaFrameBuffer = NULL;
+//*** AMI PORTING BEGIN ***//
+//*** AMI PORTING BEGIN ***//
+// Workaround for EIP 35682.
+// Buffer allocation code is moved to AllocateTheBuffers function,
+// which is called from the BiosVideoGraphicsOutputVbeBlt.
+// See comments above AllocateTheBuffers function for additional details.
+/*
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ 4 * 480 * 80,
+ &BiosVideoPrivate->VgaFrameBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+*/
+//*** AMI PORTING END *****//
+ //
+ // Set VGA Mode
+ //
+ Regs.X.AX = ModeData->VbeModeNumber;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ } else {
+ //
+ // Allocate a working buffer for BLT operations to the VBE frame buffer
+ //
+ BiosVideoPrivate->VbeFrameBuffer = NULL;
+//*** AMI PORTING BEGIN ***//
+//*** AMI PORTING BEGIN ***//
+// Workaround for EIP 35682.
+// Buffer allocation code is moved to AllocateTheBuffers function,
+// which is called from the BiosVideoGraphicsOutputVbeBlt.
+// See comments above AllocateTheBuffers function for additional details.
+/*
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ ModeData->BytesPerScanLine * ModeData->VerticalResolution,
+ &BiosVideoPrivate->VbeFrameBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+*/
+//*** AMI PORTING END *****//
+ //
+ // Set VBE mode
+ //
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;
+ Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);
+ gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0);
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ //
+ // Check to see if the call succeeded
+ //
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
+ ReportStatusCodeWithDevicePath (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,
+ 0,
+ &gEfiCallerIdGuid,
+ BiosVideoPrivate->DevicePath
+ );
+ return EFI_DEVICE_ERROR;
+ }
+//*** AMI PORTING BEGIN ***//
+ //
+ // Initialize the state of the VbeFrameBuffer
+ //
+
+/*
+ Status = BiosVideoPrivate->PciIo->Mem.Read (
+ BiosVideoPrivate->PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) ModeData->LinearFrameBuffer,
+ (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,
+ BiosVideoPrivate->VbeFrameBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+*/
+// Workaround for EIP 35682.
+// Buffer allocation and initialization code is moved to AllocateTheBuffers function,
+// which is called from the BiosVideoGraphicsOutputVbeBlt.
+// See comments above AllocateTheBuffers function for additional details.
+/*
+ gBS->CopyMem (
+ BiosVideoPrivate->VbeFrameBuffer,
+ ModeData->LinearFrameBuffer,
+ (ModeData->BytesPerScanLine * ModeData->VerticalResolution));
+*/
+ }
+//*** AMI PORTING END ***//
+
+ This->Mode->Mode = ModeNumber;
+ This->Mode->Info->Version = 0;
+ This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
+ This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
+ This->Mode->Info->PixelFormat = ModeData->PixelFormat;
+ This->Mode->Info->PixelInformation = ModeData->PixelBitMask;
+ This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
+ This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ //
+ // Frame BufferSize remain unchanged
+ //
+ This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) ModeData->LinearFrameBuffer;
+ This->Mode->FrameBufferSize = ModeData->FrameBufferSize;
+
+ BiosVideoPrivate->HardwareNeedsStarting = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+//*** AMI PORTING BEGIN ***//
+#if INT10_VESA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+//
+// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes
+//
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputVbeBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol instance to block transfer for VBE device
+
+Arguments:
+
+ This - Pointer to Graphics Output protocol instance
+ BltBuffer - The data to transfer to screen
+ BltOperation - The operation to perform
+ SourceX - The X coordinate of the source for BltOperation
+ SourceY - The Y coordinate of the source for BltOperation
+ DestinationX - The X coordinate of the destination for BltOperation
+ DestinationY - The Y coordinate of the destination for BltOperation
+ Width - The width of a rectangle in the blt rectangle in pixels
+ Height - The height of a rectangle in the blt rectangle in pixels
+ Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
+ If a Delta of 0 is used, the entire BltBuffer will be operated on.
+ If a subrectangle of the BltBuffer is used, then Delta represents
+ the number of bytes in a row of the BltBuffer.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter passed in
+ EFI_SUCCESS - Blt operation success
+
+--*/
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ BIOS_VIDEO_MODE_DATA *Mode;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_TPL OriginalTPL;
+ UINTN DstY;
+ UINTN SrcY;
+ UINTN DstX;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ VOID *MemAddress;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
+ UINTN BytesPerScanLine;
+ UINTN Index;
+ UINT8 *VbeBuffer;
+ UINT8 *VbeBuffer1;
+ UINT8 *BltUint8;
+ UINT32 VbePixelWidth;
+ UINT32 Pixel;
+
+//*** AMI PORTING BEGIN ***//
+//Bug fix: This is accessed before it's checked on NULL
+ if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+//*** AMI PORTING END *****//
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
+//*** AMI PORTING BEGIN ***//
+// Workaround for EIP 35682.
+// Allocate memory buffers during the first call of the funciton.
+// See comments above AllocateTheBuffers function for additional details.
+ if (BiosVideoPrivate->LineBuffer==NULL){
+ EFI_STATUS Status = AllocateTheBuffers(BiosVideoPrivate);
+ if (EFI_ERROR(Status)) return Status;
+ }
+//*** AMI PORTING END *****//
+ Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];
+ PciIo = BiosVideoPrivate->PciIo;
+
+ VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;
+ MemAddress = Mode->LinearFrameBuffer;
+ BytesPerScanLine = Mode->BytesPerScanLine;
+ VbePixelWidth = Mode->BitsPerPixel / 8;
+ BltUint8 = (UINT8 *) BltBuffer;
+
+//*** AMI PORTING BEGIN ***//
+//These parameter checks are moved to the beginning of the function
+/*
+ if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+*/
+//*** AMI PORTING END *****//
+
+ if (Width == 0 || Height == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // We need to fill the Virtual Screen buffer with the blt data.
+ // The virtual screen is upside down, as the first row is the bootom row of
+ // the image.
+ //
+ if (BltOperation == EfiBltVideoToBltBuffer) {
+ //
+ // Video to BltBuffer: Source is Video, destination is BltBuffer
+ //
+ if (SourceY + Height > Mode->VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SourceX + Width > Mode->HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // BltBuffer to Video: Source is BltBuffer, destination is Video
+ //
+ if (DestinationY + Height > Mode->VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestinationX + Width > Mode->HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // If Delta is zero, then the entire BltBuffer is being used, so Delta
+ // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
+ // the number of bytes in each row can be computed.
+ //
+ if (Delta == 0) {
+ Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ }
+ //
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+ // We would not want a timer based event (Cursor, ...) to come in while we are
+ // doing this operation.
+ //
+ OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+
+ switch (BltOperation) {
+ case EfiBltVideoToBltBuffer:
+ for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ //
+ // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
+ //
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));
+ for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
+ Pixel = *(UINT32 *) (VbeBuffer);
+ Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);
+ Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);
+ Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);
+ Blt->Reserved = 0;
+ Blt++;
+ VbeBuffer += VbePixelWidth;
+ }
+
+ }
+ break;
+
+ case EfiBltVideoToVideo:
+ for (Index = 0; Index < Height; Index++) {
+ if (DestinationY <= SourceY) {
+ SrcY = SourceY + Index;
+ DstY = DestinationY + Index;
+ } else {
+ SrcY = SourceY + Height - Index - 1;
+ DstY = DestinationY + Height - Index - 1;
+ }
+
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);
+ VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);
+
+ gBS->CopyMem (
+ VbeBuffer,
+ VbeBuffer1,
+ Width * VbePixelWidth
+ );
+
+ if (VbePixelWidth == 4) {
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with CopyMem to optimize performance
+/*
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
+ Width,
+ VbeBuffer
+ );
+*/
+ gBS->CopyMem ((UINT8*)MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth,
+ (UINT8*)VbeBuffer,
+ Width * VbePixelWidth);
+//*** AMI PORTING END *****//
+ } else {
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with CopyMem to optimize performance
+/*
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
+ Width * VbePixelWidth,
+ VbeBuffer
+ );
+*/
+ gBS->CopyMem ((UINT8*)MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth,
+ (UINT8*)VbeBuffer,
+ Width * VbePixelWidth);
+ }
+//*** AMI PORTING END *****//
+ }
+ break;
+
+ case EfiBltVideoFill:
+ VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;
+ //
+ // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
+ //
+ Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
+ (
+ (Blt->Green & Mode->Green.Mask) <<
+ Mode->Green.Position
+ ) |
+ ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
+
+ for (Index = 0; Index < Width; Index++) {
+ gBS->CopyMem (
+ VbeBuffer,
+ &Pixel,
+ VbePixelWidth
+ );
+ VbeBuffer += VbePixelWidth;
+ }
+
+ VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
+ for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {
+ gBS->CopyMem (
+ (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
+ VbeBuffer,
+ Width * VbePixelWidth
+ );
+ }
+
+ for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with CopyMem to optimize performance
+/*
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
+ Width * VbePixelWidth,
+ VbeBuffer
+ );
+*/
+ gBS->CopyMem ((UINT8*)MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth,
+ (UINT8*)VbeBuffer,
+ Width * VbePixelWidth);
+//*** AMI PORTING END *****//
+ }
+ break;
+
+ case EfiBltBufferToVideo:
+//*** AMI PORTING BEGIN ***//
+//The original BLT loop is replaced to optimize performance by:
+// replacing PciIo->Mem.Write with CopyMem and
+// replacing multiplication with addition
+/*
+ for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
+ for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
+ //
+ // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
+ //
+ Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
+ ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |
+ ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
+ gBS->CopyMem (
+ VbeBuffer,
+ &Pixel,
+ VbePixelWidth
+ );
+ Blt++;
+ VbeBuffer += VbePixelWidth;
+ }
+
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) ((UINTN) MemAddress + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
+ Width * VbePixelWidth,
+ VbeBuffer
+ );
+ }
+*/
+{
+ UINTN VbeBufferOffset = DestinationY * BytesPerScanLine + DestinationX * VbePixelWidth;
+ UINT8* BltBufferAddress = BltUint8 + SourceY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ UINTN VbeLineWidth = VbePixelWidth*Width;
+ UINTN BufferOffset = VbeBufferOffset;
+
+ for (SrcY = SourceY; SrcY < (Height + SourceY); SrcY++) {
+
+ VbeBuffer = (UINT8 *) VbeFrameBuffer + BufferOffset;
+
+ if (Mode->PixelFormat != PixelBlueGreenRedReserved8BitPerColor){
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)BltBufferAddress;
+ for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
+ //
+ // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
+ //
+ Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
+ ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |
+ ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
+ gBS->CopyMem (
+ VbeBuffer,
+ &Pixel,
+ VbePixelWidth
+ );
+ Blt++;
+ VbeBuffer += VbePixelWidth;
+ }
+ VbeBuffer = (UINT8 *) VbeFrameBuffer + BufferOffset;
+ }else{
+ gBS->CopyMem (VbeBuffer, BltBufferAddress, VbeLineWidth);
+ }
+ BufferOffset += BytesPerScanLine;
+ BltBufferAddress += Delta;
+ }
+ BufferOffset = VbeBufferOffset;
+ for (SrcY = SourceY; SrcY < (Height + SourceY); SrcY++) {
+ gBS->CopyMem ((UINT8*)MemAddress + BufferOffset,
+ (UINT8 *)VbeFrameBuffer + BufferOffset,
+ VbeLineWidth);
+ BufferOffset += BytesPerScanLine;
+ }
+}
+//*** AMI PORTING END *****//
+ break;
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return EFI_SUCCESS;
+}
+//*** AMI PORTING BEGIN ***//
+#endif //if INT10_VESA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+//*** AMI PORTING BEGIN ***//
+#if INT10_VGA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+STATIC
+VOID
+WriteGraphicsController (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN Address,
+ IN UINTN Data
+ )
+/*++
+
+Routine Description:
+
+ Write graphics controller registers
+
+Arguments:
+
+ PciIo - Pointer to PciIo protocol instance of the controller
+ Address - Register address
+ Data - Data to be written to register
+
+Returns:
+
+ None
+
+--*/
+{
+ Address = Address | (Data << 8);
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,
+ 1,
+ &Address
+ );
+}
+
+VOID
+VgaReadBitPlanes (
+ EFI_PCI_IO_PROTOCOL *PciIo,
+ UINT8 *HardwareBuffer,
+ UINT8 *MemoryBuffer,
+ UINTN WidthInBytes,
+ UINTN Height
+ )
+/*++
+
+Routine Description:
+
+ Read the four bit plane of VGA frame buffer
+
+Arguments:
+
+ PciIo - Pointer to PciIo protocol instance of the controller
+ HardwareBuffer - Hardware VGA frame buffer address
+ MemoryBuffer - Memory buffer address
+ WidthInBytes - Number of bytes in a line to read
+ Height - Height of the area to read
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN BitPlane;
+ UINTN Rows;
+ UINTN FrameBufferOffset;
+ UINT8 *Source;
+ UINT8 *Destination;
+
+ //
+ // Program the Mode Register Write mode 0, Read mode 0
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
+ );
+
+ for (BitPlane = 0, FrameBufferOffset = 0;
+ BitPlane < VGA_NUMBER_OF_BIT_PLANES;
+ BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE
+ ) {
+ //
+ // Program the Read Map Select Register to select the correct bit plane
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,
+ BitPlane
+ );
+
+ Source = HardwareBuffer;
+ Destination = MemoryBuffer + FrameBufferOffset;
+
+ for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with CopyMem to optimize performance
+/*
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Source,
+ WidthInBytes,
+ (VOID *) Destination
+ );
+*/
+ gBS->CopyMem ((UINT8*)Source,
+ (UINT8*)Destination,
+ WidthInBytes);
+//*** AMI PORTING END *****//
+ }
+ }
+}
+
+VOID
+VgaConvertToGraphicsOutputColor (
+ UINT8 *MemoryBuffer,
+ UINTN X,
+ UINTN Y,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ )
+/*++
+
+Routine Description:
+
+ Internal routine to convert VGA color to Grahpics Output color
+
+Arguments:
+
+ MemoryBuffer - Buffer containing VGA color
+ X - The X coordinate of pixel on screen
+ Y - The Y coordinate of pixel on screen
+ BltBuffer - Buffer to contain converted Grahpics Output color
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Mask;
+ UINTN Bit;
+ UINTN Color;
+
+ MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3));
+ Mask = mVgaBitMaskTable[X & 0x07];
+ for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {
+ if (*MemoryBuffer & Mask) {
+ Color |= Bit;
+ }
+ }
+
+ *BltBuffer = mVgaColorToGraphicsOutputColor[Color];
+}
+
+UINT8
+VgaConvertColor (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ )
+/*++
+
+Routine Description:
+
+ Internal routine to convert Grahpics Output color to VGA color
+
+Arguments:
+
+ BltBuffer - buffer containing Grahpics Output color
+
+Returns:
+
+ Converted VGA color
+
+--*/
+{
+ UINT8 Color;
+
+ Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));
+//*** AMI PORTING BEGIN ***//
+// if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {
+ if ((BltBuffer->Red >= 0xC0) || (BltBuffer->Blue >= 0xC0) || (BltBuffer->Green >= 0xC0)) {
+ Color |= 0x08;
+ }
+ // Prevent "washing out" of single color
+ if (((BltBuffer->Red >= 0xC0) && (BltBuffer->Blue == 0) && (BltBuffer->Green == 0)) || \
+ ((BltBuffer->Blue >= 0xC0) && (BltBuffer->Red == 0) && (BltBuffer->Green == 0)) || \
+ ((BltBuffer->Green >= 0xC0) && (BltBuffer->Blue == 0) && (BltBuffer->Red == 0))) {
+ Color &= 0x07;
+ }
+//*** AMI PORTING END ***//
+
+ return Color;
+}
+
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputVgaBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ )
+/*++
+
+Routine Description:
+
+ Grahpics Output protocol instance to block transfer for VGA device
+
+Arguments:
+
+ This - Pointer to Grahpics Output protocol instance
+ BltBuffer - The data to transfer to screen
+ BltOperation - The operation to perform
+ SourceX - The X coordinate of the source for BltOperation
+ SourceY - The Y coordinate of the source for BltOperation
+ DestinationX - The X coordinate of the destination for BltOperation
+ DestinationY - The Y coordinate of the destination for BltOperation
+ Width - The width of a rectangle in the blt rectangle in pixels
+ Height - The height of a rectangle in the blt rectangle in pixels
+ Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
+ If a Delta of 0 is used, the entire BltBuffer will be operated on.
+ If a subrectangle of the BltBuffer is used, then Delta represents
+ the number of bytes in a row of the BltBuffer.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter passed in
+ EFI_SUCCESS - Blt operation success
+
+--*/
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_TPL OriginalTPL;
+ UINT8 *MemAddress;
+ UINTN BytesPerScanLine;
+ UINTN BytesPerBitPlane;
+ UINTN Bit;
+ UINTN Index;
+ UINTN Index1;
+ UINTN StartAddress;
+ UINTN Bytes;
+ UINTN Offset;
+ UINT8 LeftMask;
+ UINT8 RightMask;
+ UINTN Address;
+ UINTN AddressFix;
+ UINT8 *Address1;
+ UINT8 *SourceAddress;
+ UINT8 *DestinationAddress;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Data;
+ UINT8 PixelColor;
+ UINT8 *VgaFrameBuffer;
+ UINTN SourceOffset;
+ UINTN SourceWidth;
+ UINTN Rows;
+ UINTN Columns;
+ UINTN X;
+ UINTN Y;
+ UINTN CurrentMode;
+
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+//*** AMI PORTING BEGIN ***//
+// Workaround for EIP 35682.
+// Allocate memory buffers during the first call of the funciton.
+// See comments above AllocateTheBuffers function for additional details.
+ if (BiosVideoPrivate->LineBuffer==NULL){
+ EFI_STATUS Status = AllocateTheBuffers(BiosVideoPrivate);
+ if (EFI_ERROR(Status)) return Status;
+ }
+//*** AMI PORTING END *****//
+
+ CurrentMode = This->Mode->Mode;
+ PciIo = BiosVideoPrivate->PciIo;
+ MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;
+ BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;
+ BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution;
+ VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;
+
+ if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width == 0 || Height == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // We need to fill the Virtual Screen buffer with the blt data.
+ // The virtual screen is upside down, as the first row is the bootom row of
+ // the image.
+ //
+ if (BltOperation == EfiBltVideoToBltBuffer) {
+ //
+ // Video to BltBuffer: Source is Video, destination is BltBuffer
+ //
+ if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // BltBuffer to Video: Source is BltBuffer, destination is Video
+ //
+ if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // If Delta is zero, then the entire BltBuffer is being used, so Delta
+ // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
+ // the number of bytes in each row can be computed.
+ //
+ if (Delta == 0) {
+ Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ }
+ //
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+ // We would not want a timer based event (Cursor, ...) to come in while we are
+ // doing this operation.
+ //
+ OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+
+ //
+ // Compute some values we need for VGA
+ //
+ switch (BltOperation) {
+ case EfiBltVideoToBltBuffer:
+
+ SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);
+ SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;
+
+ //
+ // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
+ //
+ VgaReadBitPlanes (
+ PciIo,
+ MemAddress + SourceOffset,
+ VgaFrameBuffer + SourceOffset,
+ SourceWidth,
+ Height
+ );
+
+ //
+ // Convert VGA Bit Planes to a Graphics Output 32-bit color value
+ //
+ BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);
+ for (Rows = 0, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) {
+ for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) {
+ VgaConvertToGraphicsOutputColor (VgaFrameBuffer, X, Y, BltBuffer);
+ }
+
+ BltBuffer -= Width;
+ }
+
+ break;
+
+ case EfiBltVideoToVideo:
+ //
+ // Check for an aligned Video to Video operation
+ //
+ if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {
+ //
+ // Program the Mode Register Write mode 1, Read mode 0
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
+ );
+
+ SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));
+ DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
+ Bytes = Width >> 3;
+ for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {
+ PciIo->CopyMem (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (DestinationAddress + Offset),
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (SourceAddress + Offset),
+ Bytes
+ );
+ }
+ } else {
+ SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);
+ SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;
+
+ //
+ // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
+ //
+ VgaReadBitPlanes (
+ PciIo,
+ MemAddress + SourceOffset,
+ VgaFrameBuffer + SourceOffset,
+ SourceWidth,
+ Height
+ );
+ }
+
+ break;
+
+ case EfiBltVideoFill:
+ StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
+ Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);
+ LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];
+ RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];
+ if (Bytes == 0) {
+ LeftMask &= RightMask;
+ RightMask = 0;
+ }
+
+ if (LeftMask == 0xff) {
+ StartAddress--;
+ Bytes++;
+ LeftMask = 0;
+ }
+
+ if (RightMask == 0xff) {
+ Bytes++;
+ RightMask = 0;
+ }
+
+ PixelColor = VgaConvertColor (BltBuffer);
+
+ //
+ // Program the Mode Register Write mode 2, Read mode 0
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
+ );
+
+ //
+ // Program the Data Rotate/Function Select Register to replace
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
+ );
+
+ if (LeftMask != 0) {
+ //
+ // Program the BitMask register with the Left column mask
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
+ LeftMask
+ );
+
+ for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {
+ //
+ // Read data from the bit planes into the latches
+ //
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with direct memory access to optimize performance
+/*
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Address,
+ 1,
+ &Data
+ );
+*/
+ Data = *(volatile UINT8*)(UINTN)Address;
+//*** AMI PORTING END *****//
+ //
+ // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
+ //
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with direct memory access to optimize performance
+/*
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Address,
+ 1,
+ &PixelColor
+ );
+*/
+ *(volatile UINT8*)(UINTN)Address = PixelColor;
+//*** AMI PORTING END *****//
+ }
+ }
+
+ if (Bytes > 1) {
+ //
+ // Program the BitMask register with the middle column mask of 0xff
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
+ 0xff
+ );
+
+ for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with SetMem to optimize performance
+/*
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthFillUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Address,
+ Bytes - 1,
+ &PixelColor
+ );
+*/
+ gBS->SetMem((VOID*)Address, Bytes - 1, PixelColor);
+//*** AMI PORTING END ***//
+ }
+ }
+
+ if (RightMask != 0) {
+ //
+ // Program the BitMask register with the Right column mask
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
+ RightMask
+ );
+
+ for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {
+ //
+ // Read data from the bit planes into the latches
+ //
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with direct memory access to optimize performance
+/*
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Address,
+ 1,
+ &Data
+ );
+*/
+ Data = *(volatile UINT8*)(UINTN)Address;
+//*** AMI PORTING END *****//
+ //
+ // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
+ //
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with direct memory access to optimize performance
+/*
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Address,
+ 1,
+ &PixelColor
+ );
+*/
+ *(volatile UINT8*)(UINTN)Address = PixelColor;
+//*** AMI PORTING END *****//
+ }
+ }
+ break;
+
+ case EfiBltBufferToVideo:
+ StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
+ LeftMask = mVgaBitMaskTable[DestinationX & 0x07];
+
+ //
+ // Program the Mode Register Write mode 2, Read mode 0
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
+ );
+
+ //
+ // Program the Data Rotate/Function Select Register to replace
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
+ );
+
+ for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {
+ for (Index1 = 0; Index1 < Width; Index1++) {
+ BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);
+ }
+ AddressFix = Address;
+
+ for (Bit = 0; Bit < 8; Bit++) {
+ //
+ // Program the BitMask register with the Left column mask
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
+ LeftMask
+ );
+
+ for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {
+ //
+ // Read data from the bit planes into the latches
+ //
+//*** AMI PORTING BEGIN ***//
+// Replace PciIo.Mem with direct memory access to optimize performance
+/*
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Address1,
+ 1,
+ &Data
+ );
+*/
+ Data = *(volatile UINT8*)(UINTN)Address1;
+
+/*
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Address1,
+ 1,
+ &BiosVideoPrivate->LineBuffer[Index1]
+ );
+*/
+ *(volatile UINT8*)(UINTN)Address1 = BiosVideoPrivate->LineBuffer[Index1];
+//*** AMI PORTING END *****//
+ }
+
+ LeftMask = (UINT8) (LeftMask >> 1);
+ if (LeftMask == 0) {
+ LeftMask = 0x80;
+ AddressFix++;
+ }
+ }
+ }
+
+ break;
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return EFI_SUCCESS;
+}
+//*** AMI PORTING BEGIN ***//
+#endif //if INT10_VGA_GO_SUPPORT==1
+//*** AMI PORTING END *****//
+//*** AMI PORTING BEGIN ***//
+#if INT10_SIMPLE_TEXT_SUPPORT==1
+//*** AMI PORTING END *****//
+//
+// VGA Mini Port Protocol Functions
+//
+EFI_STATUS
+EFIAPI
+BiosVideoVgaMiniPortSetMode (
+ IN EFI_VGA_MINI_PORT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ )
+/*++
+
+Routine Description:
+
+ VgaMiniPort protocol interface to set mode
+
+Arguments:
+
+ This - Pointer to VgaMiniPort protocol instance
+ ModeNumber - The index of the mode
+
+Returns:
+
+ EFI_UNSUPPORTED - The requested mode is not supported
+ EFI_SUCCESS - The requested mode is set successfully
+
+--*/
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_IA32_REGISTER_SET Regs;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Make sure the ModeNumber is a valid value
+ //
+ if (ModeNumber >= This->MaxMode) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the device structure for this device
+ //
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);
+
+ switch (ModeNumber) {
+ case 0:
+ //
+ // Set the 80x25 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x83;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x14;
+ Regs.H.BL = 0;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+ break;
+
+ case 1:
+ //
+ // Set the 80x50 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x83;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x12;
+ Regs.H.BL = 0;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+//*** AMI PORTING BEGIN ***//
+#endif //if INT10_SIMPLE_TEXT_SUPPORT==1
+//*** AMI PORTING END *****//
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.h b/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.h
new file mode 100644
index 0000000..9421b5e
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/UefiBiosVideo.h
@@ -0,0 +1,597 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//
+// This file contains a 'Sample Driver' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may be modified by the user, subject to
+// the additional terms of the license agreement
+//
+/*++
+
+Copyright (c) 2006 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ UefiBiosVideo.h
+
+Abstract:
+
+Revision History
+--*/
+
+#ifndef _BIOS_GRAPHICS_OUTPUT_H
+#define _BIOS_GRAPHICS_OUTPUT_H
+
+//*** AMI PORTING BEGIN ***//
+#include "AmiMapping.h"
+#include "EdkIICommon.h"
+//#include "Tiano.h"
+//#include "EfiDriverLib.h"
+#include <Protocol/CsmVideoPolicy.h>
+//*** AMI PORTING END *****//
+#include "VesaBiosExtensions.h"
+#include "Pci22.h"
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include EFI_PROTOCOL_DEFINITION (DevicePath)
+#include EFI_PROTOCOL_DEFINITION (PciIo)
+#include EFI_PROTOCOL_DEFINITION (LegacyBios)
+//*** AMI PORTING BEGIN ***//
+//AMI CSM Core does not need this GUID
+//#include EFI_GUID_DEFINITION (LegacyBios)
+//*** AMI PORTING END *****//
+//*** AMI PORTING BEGIN ***//
+//#include EFI_GUID_DEFINITION (StatusCodeCallerId)
+//#include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
+//*** AMI PORTING END *****//
+
+//
+// Driver Produced Protocol Prototypes
+//
+#include EFI_PROTOCOL_DEFINITION (DriverBinding)
+#include EFI_PROTOCOL_DEFINITION (ComponentName)
+#include EFI_PROTOCOL_DEFINITION (GraphicsOutput)
+#include EFI_PROTOCOL_DEFINITION (EdidDiscovered)
+#include EFI_PROTOCOL_DEFINITION (EdidActive)
+
+//*** AMI PORTING BEGIN ***//
+//#include EFI_PROTOCOL_DEFINITION (VgaMiniPort)
+#include "VgaMiniPort.h"
+
+// uncomment the following lind and remove the following block when Protocol/EdidOverride.h is available
+//#include EFI_PROTOCOL_DEFINITION (EdidOverride)
+#define EFI_EDID_OVERRIDE_PROTOCOL_GUID \
+ { 0x48ecb431, 0xfb72, 0x45c0, 0xa9, 0x22, 0xf4, 0x58, 0xfe, 0x4, 0xb, 0xd5 }
+
+#define EFI_EDID_OVERRIDE_DONT_OVERRIDE 0x01
+#define EFI_EDID_OVERRIDE_ENABLE_HOT_PLUG 0x02
+
+typedef struct _EFI_EDID_OVERRIDE_PROTOCOL EFI_EDID_OVERRIDE_PROTOCOL;
+
+typedef EFI_STATUS (EFIAPI *EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID) (
+ IN EFI_EDID_OVERRIDE_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle,
+ OUT UINT32 *Attributes,
+ IN OUT UINTN *EdidSize,
+ IN OUT UINT8 **Edid
+ );
+
+struct _EFI_EDID_OVERRIDE_PROTOCOL {
+ EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid;
+};
+//*** AMI PORTING END *****//
+
+//
+// Packed format support: The number of bits reserved for each of the colors and the actual
+// position of RGB in the frame buffer is specified in the VBE Mode information
+//
+typedef struct {
+ UINT8 Position; // Position of the color
+ UINT8 Mask; // The number of bits expressed as a mask
+} BIOS_VIDEO_COLOR_PLACEMENT;
+
+//
+// BIOS Graphics Output Graphical Mode Data
+//
+typedef struct {
+ UINT16 VbeModeNumber;
+ UINT16 BytesPerScanLine;
+ VOID *LinearFrameBuffer;
+ UINTN FrameBufferSize;
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ UINT32 RefreshRate;
+ UINT32 BitsPerPixel;
+ BIOS_VIDEO_COLOR_PLACEMENT Red;
+ BIOS_VIDEO_COLOR_PLACEMENT Green;
+ BIOS_VIDEO_COLOR_PLACEMENT Blue;
+ BIOS_VIDEO_COLOR_PLACEMENT Reserved;
+ EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
+ EFI_PIXEL_BITMASK PixelBitMask;
+} BIOS_VIDEO_MODE_DATA;
+
+//
+// BIOS video child handle private data Structure
+//
+#define BIOS_VIDEO_DEV_SIGNATURE EFI_SIGNATURE_32 ('B', 'V', 'M', 'p')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+
+ //
+ // Consumed Protocols
+ //
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+
+ //
+ // Produced Protocols
+ //
+ EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput;
+ EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered;
+ EFI_EDID_ACTIVE_PROTOCOL EdidActive;
+ EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort;
+
+ //
+ // General fields
+ //
+ BOOLEAN VgaCompatible;
+ BOOLEAN ProduceGraphicsOutput;
+//*** AMI PORTING BEGIN ***//
+// ExitBootServicesEvent is not used
+// EFI_EVENT ExitBootServicesEvent;
+//*** AMI PORTING END *****//
+
+ //
+ // Graphics Output Protocol related fields
+ //
+ BOOLEAN HardwareNeedsStarting;
+ BIOS_VIDEO_MODE_DATA *ModeData;
+ UINT8 *LineBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
+ UINT8 *VgaFrameBuffer;
+
+ //
+ // VESA Bios Extensions related fields
+ //
+ UINTN NumberOfPagesBelow1MB; // Number of 4KB pages in PagesBelow1MB
+ EFI_PHYSICAL_ADDRESS PagesBelow1MB; // Buffer for all VBE Information Blocks
+ VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *VbeInformationBlock; // 0x200 bytes. Must be allocated below 1MB
+ VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; // 0x100 bytes. Must be allocated below 1MB
+ VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *VbeEdidDataBlock; // 0x80 bytes. Must be allocated below 1MB
+ VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; // 59 bytes. Must be allocated below 1MB
+ UINTN VbeSaveRestorePages; // Number of 4KB pages in VbeSaveRestoreBuffer
+ EFI_PHYSICAL_ADDRESS VbeSaveRestoreBuffer; // Must be allocated below 1MB
+ //
+ // Status code
+ //
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} BIOS_VIDEO_DEV;
+
+#define BIOS_VIDEO_DEV_FROM_PCI_IO_THIS(a) CR (a, BIOS_VIDEO_DEV, PciIo, BIOS_VIDEO_DEV_SIGNATURE)
+#define BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS(a) CR (a, BIOS_VIDEO_DEV, GraphicsOutput, BIOS_VIDEO_DEV_SIGNATURE)
+#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV, VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE)
+
+#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2;
+
+//
+// Driver Binding Protocol functions
+//
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ RemainingDevicePath - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ RemainingDevicePath - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ NumberOfChildren - GC_TODO: add argument description
+ ChildHandleBuffer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// Private worker functions
+//
+EFI_STATUS
+BiosVideoCheckForVbe (
+ BIOS_VIDEO_DEV *BiosVideoPrivate,
+//*** AMI PORTING BEGIN ***//
+ PCI_TYPE00 *PciConfSpace
+//*** AMI PORTING END *****//
+)
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ BiosVideoPrivate - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+BiosVideoCheckForVga (
+ BIOS_VIDEO_DEV *BiosVideoPrivate
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ BiosVideoPrivate - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATIC
+EFI_STATUS
+DeRegisterVideoChildHandle (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ Deregister an video child handle and free resources
+
+Arguments:
+
+ This - Protocol instance pointer.
+ Controller - Video controller handle
+ Handle - Video child handle
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+;
+
+VOID
+BiosVideoDeviceReleaseResource (
+ BIOS_VIDEO_DEV *BiosVideoChildPrivate
+ )
+/*++
+Routing Description:
+
+ Release resources of a video child device before stopping it.
+
+Arguments:
+
+ BiosVideoChildPrivate - Video child device private data structure
+
+Returns:
+
+ NONE
+
+---*/
+;
+
+//
+// BIOS Graphics Output Protocol functions
+//
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol interface to get video mode
+
+ Arguments:
+ This - Protocol instance pointer.
+ ModeNumber - The mode number to return information on.
+ Info - Caller allocated buffer that returns information about ModeNumber.
+ SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
+
+ Returns:
+ EFI_SUCCESS - Mode information returned.
+ EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
+ EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
+ EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
+ EFI_INVALID_PARAMETER - One of the input args was NULL.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
+ IN UINT32 ModeNumber
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol interface to set video mode
+
+ Arguments:
+ This - Protocol instance pointer.
+ ModeNumber - The mode number to be set.
+
+ Returns:
+ EFI_SUCCESS - Graphics mode was changed.
+ EFI_DEVICE_ERROR - The device had an error and could not complete the request.
+ EFI_UNSUPPORTED - ModeNumber is not supported by this device.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputVbeBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol instance to block transfer for VBE device
+
+Arguments:
+
+ This - Pointer to Graphics Output protocol instance
+ BltBuffer - The data to transfer to screen
+ BltOperation - The operation to perform
+ SourceX - The X coordinate of the source for BltOperation
+ SourceY - The Y coordinate of the source for BltOperation
+ DestinationX - The X coordinate of the destination for BltOperation
+ DestinationY - The Y coordinate of the destination for BltOperation
+ Width - The width of a rectangle in the blt rectangle in pixels
+ Height - The height of a rectangle in the blt rectangle in pixels
+ Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
+ If a Delta of 0 is used, the entire BltBuffer will be operated on.
+ If a subrectangle of the BltBuffer is used, then Delta represents
+ the number of bytes in a row of the BltBuffer.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter passed in
+ EFI_SUCCESS - Blt operation success
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputVgaBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ )
+/*++
+
+Routine Description:
+
+ Grahpics Output protocol instance to block transfer for VGA device
+
+Arguments:
+
+ This - Pointer to Grahpics Output protocol instance
+ BltBuffer - The data to transfer to screen
+ BltOperation - The operation to perform
+ SourceX - The X coordinate of the source for BltOperation
+ SourceY - The Y coordinate of the source for BltOperation
+ DestinationX - The X coordinate of the destination for BltOperation
+ DestinationY - The Y coordinate of the destination for BltOperation
+ Width - The width of a rectangle in the blt rectangle in pixels
+ Height - The height of a rectangle in the blt rectangle in pixels
+ Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
+ If a Delta of 0 is used, the entire BltBuffer will be operated on.
+ If a subrectangle of the BltBuffer is used, then Delta represents
+ the number of bytes in a row of the BltBuffer.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter passed in
+ EFI_SUCCESS - Blt operation success
+
+--*/
+;
+
+//
+// BIOS VGA Mini Port Protocol functions
+//
+EFI_STATUS
+EFIAPI
+BiosVideoVgaMiniPortSetMode (
+ IN EFI_VGA_MINI_PORT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ )
+/*++
+
+Routine Description:
+
+ VgaMiniPort protocol interface to set mode
+
+Arguments:
+
+ This - Pointer to VgaMiniPort protocol instance
+ ModeNumber - The index of the mode
+
+Returns:
+
+ EFI_UNSUPPORTED - The requested mode is not supported
+ EFI_SUCCESS - The requested mode is set successfully
+
+--*/
+;
+
+//
+// Standard VGA Definitions
+//
+#define VGA_HORIZONTAL_RESOLUTION 640
+#define VGA_VERTICAL_RESOLUTION 480
+#define VGA_NUMBER_OF_BIT_PLANES 4
+#define VGA_PIXELS_PER_BYTE 8
+#define VGA_BYTES_PER_SCAN_LINE (VGA_HORIZONTAL_RESOLUTION / VGA_PIXELS_PER_BYTE)
+#define VGA_BYTES_PER_BIT_PLANE (VGA_VERTICAL_RESOLUTION * VGA_BYTES_PER_SCAN_LINE)
+
+#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER 0x3ce
+#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER 0x3cf
+
+#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER 0x00
+
+#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01
+
+#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER 0x02
+
+#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER 0x03
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE 0x00
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND 0x08
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR 0x10
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR 0x18
+
+#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER 0x04
+
+#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER 0x05
+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0 0x00
+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1 0x08
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 0x00
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 0x01
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 0x02
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3 0x03
+
+#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER 0x06
+
+#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER 0x07
+
+#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER 0x08
+
+#endif
diff --git a/Core/EM/CSM/thunk/CsmVideo/VesaBiosExtensions.h b/Core/EM/CSM/thunk/CsmVideo/VesaBiosExtensions.h
new file mode 100644
index 0000000..5adcdfb
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/VesaBiosExtensions.h
@@ -0,0 +1,463 @@
+//
+// This file contains a 'Sample Driver' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may be modified by the user, subject to
+// the additional terms of the license agreement
+//
+/*++
+
+Copyright (c) 1999 - 2006 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ VesaBiosExtensions.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _VESA_BIOS_EXTENSIONS_H
+#define _VESA_BIOS_EXTENSIONS_H
+
+//
+// Turn on byte packing of data structures
+//
+#pragma pack(1)
+//
+// VESA BIOS Extensions status codes
+//
+#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f
+
+//
+// VESA BIOS Extensions Services
+//
+#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION 0x4f00
+
+/*++
+
+ Routine Description:
+ Function 00 : Return Controller Information
+
+ Arguments:
+ Inputs:
+ AX = 0x4f00
+ ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure
+ Outputs:
+ AX = Return Status
+
+--*/
+#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION 0x4f01
+
+/*++
+
+ Routine Description:
+ Function 01 : Return Mode Information
+
+ Arguments:
+ Inputs:
+ AX = 0x4f01
+ CX = Mode Number
+ ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure
+ Outputs:
+ AX = Return Status
+
+--*/
+#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02
+
+/*++
+
+ Routine Description:
+ Function 02 : Set Mode
+
+ Arguments:
+ Inputs:
+ AX = 0x4f02
+ BX = Desired mode to set
+ D0-D8 = Mode Number
+ D9-D10 = Reserved (must be 0)
+ D11 = 0 - Use current default refresh rate
+ = 1 - Use user specfieid CRTC values for refresh rate
+ D12-D13 = Reserved (must be 0)
+ D14 = 0 - Use windowed frame buffer model
+ = 1 - Use linear/flat frame buffer model
+ D15 = 0 - Clear display memory
+ = 1 - Don't clear display memory
+ ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure
+ Outputs:
+ AX = Return Status
+
+--*/
+#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE 0x4f03
+
+/*++
+
+ Routine Description:
+ Function 03 : Return Current Mode
+
+ Arguments:
+ Inputs:
+ AX = 0x4f03
+ Outputs:
+ AX = Return Status
+ BX = Current mode
+ D0-D13 = Mode Number
+ D14 = 0 - Windowed frame buffer model
+ = 1 - Linear/flat frame buffer model
+ D15 = 0 - Memory cleared at last mode set
+ = 1 - Memory not cleared at last mode set
+
+--*/
+#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04
+
+/*++
+
+ Routine Description:
+ Function 04 : Save/Restore State
+
+ Arguments:
+ Inputs:
+ AX = 0x4f03
+ DL = 0x00 - Return Save/Restore State buffer size
+ = 0x01 - Save State
+ = 0x02 - Restore State
+ CX = Requested Status
+ D0 = Save/Restore controller hardware state
+ D1 = Save/Restore BIOS data state
+ D2 = Save/Restore DAC state
+ D3 = Save/Restore Regsiter state
+ ES:BX = Pointer to buffer if DL=1 or DL=2
+ Outputs:
+ AX = Return Status
+ BX = Number of 64 byte blocks to hold the state buffer if DL=0
+
+--*/
+#define VESA_BIOS_EXTENSIONS_EDID 0x4f15
+
+/*++
+
+ Routine Description:
+ Function 15 : implement VBE/DDC service
+
+ Arguments:
+ Inputs:
+ AX = 0x4f15
+ BL = 0x00 - Report VBE/DDC Capabilities
+ CX = 0x00 - Controller unit number (00 = primary controller)
+ ES:DI = Null pointer, must be 0:0 in version 1.0
+ Outputs:
+ AX = Return Status
+ BH = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes)
+ BL = DDC level supported
+ D0 = 0 DDC1 not supported
+ = 1 DDC1 supported
+ D1 = 0 DDC2 not supported
+ = 1 DDC2 supported
+ D2 = 0 Screen not blanked during data transfer
+ = 1 Screen blanked during data transfer
+
+ Inputs:
+ AX = 0x4f15
+ BL = 0x01 - Read EDID
+ CX = 0x00 - Controller unit number (00 = primary controller)
+ DX = 0x00 - EDID block number
+ ES:DI = Pointer to buffer in which the EDID block is returned
+ Outputs:
+ AX = Return Status
+--*/
+
+//
+// Timing data from EDID data block
+//
+#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE 128
+#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17
+
+typedef struct {
+ UINT16 HorizontalResolution;
+ UINT16 VerticalResolution;
+ UINT16 RefreshRate;
+} VESA_BIOS_EXTENSIONS_EDID_TIMING;
+
+typedef struct {
+ UINT32 ValidNumber;
+ UINT32 Key[VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER];
+} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING;
+
+typedef struct {
+ UINT8 Header[8]; //EDID header "00 FF FF FF FF FF FF 00"
+ UINT16 ManufactureName; //EISA 3-character ID
+ UINT16 ProductCode; //Vendor assigned code
+ UINT32 SerialNumber; //32-bit serial number
+ UINT8 WeekOfManufacture; //Week number
+ UINT8 YearOfManufacture; //Year
+ UINT8 EdidVersion; //EDID Structure Version
+ UINT8 EdidRevision; //EDID Structure Revision
+ UINT8 VideoInputDefinition;
+ UINT8 MaxHorizontalImageSize; //cm
+ UINT8 MaxVerticalImageSize; //cm
+ UINT8 DisplayTransferCharacteristic;
+ UINT8 FeatureSupport;
+ UINT8 RedGreenLowBits; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0
+ UINT8 BlueWhiteLowBits; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0
+ UINT8 RedX; //Red-x Bits 9 - 2
+ UINT8 RedY; //Red-y Bits 9 - 2
+ UINT8 GreenX; //Green-x Bits 9 - 2
+ UINT8 GreenY; //Green-y Bits 9 - 2
+ UINT8 BlueX; //Blue-x Bits 9 - 2
+ UINT8 BlueY; //Blue-y Bits 9 - 2
+ UINT8 WhiteX; //White-x Bits 9 - 2
+ UINT8 WhiteY; //White-x Bits 9 - 2
+ UINT8 EstablishedTimings[3];
+ UINT8 StandardTimingIdentification[16];
+ UINT8 DetailedTimingDescriptions[72];
+ UINT8 ExtensionFlag; //Number of (optional) 128-byte EDID extension blocks to follow
+ UINT8 Checksum;
+} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK;
+
+//
+// Super VGA Information Block
+//
+typedef struct {
+ UINT32 VESASignature; // 'VESA' 4 byte signature
+ UINT16 VESAVersion; // VBE version number
+ UINT32 OEMStringPtr; // Pointer to OEM string
+ UINT32 Capabilities; // Capabilities of video card
+ UINT32 VideoModePtr; // Pointer to an array of 16-bit supported modes values terminated by 0xFFFF
+ UINT16 TotalMemory; // Number of 64kb memory blocks
+ UINT16 OemSoftwareRev; // VBE implementation Software revision
+ UINT32 OemVendorNamePtr; // VbeFarPtr to Vendor Name String
+ UINT32 OemProductNamePtr; // VbeFarPtr to Product Name String
+ UINT32 OemProductRevPtr; // VbeFarPtr to Product Revision String
+ UINT8 Reserved[222]; // Reserved for VBE implementation scratch area
+ UINT8 OemData[256]; // Data area for OEM strings. Pad to 512 byte block size
+} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK;
+
+//
+// Super VGA Information Block VESASignature values
+//
+#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE EFI_SIGNATURE_32 ('V', 'E', 'S', 'A')
+#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE EFI_SIGNATURE_32 ('V', 'B', 'E', '2')
+
+//
+// Super VGA Information Block VESAVersion values
+//
+#define VESA_BIOS_EXTENSIONS_VERSION_1_2 0x0102
+#define VESA_BIOS_EXTENSIONS_VERSION_2_0 0x0200
+#define VESA_BIOS_EXTENSIONS_VERSION_3_0 0x0300
+
+//
+// Super VGA Information Block Capabilities field bit defintions
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01 // 0: DAC width is fixed at 6 bits/color
+// 1: DAC width switchable to 8 bits/color
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02 // 0: Controller is VGA compatible
+// 1: Controller is not VGA compatible
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04 // 0: Normal RAMDAC operation
+// 1: Use blank bit in function 9 to program RAMDAC
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC 0x08 // 0: No hardware stereoscopic signal support
+// 1: Hardware stereoscopic signal support
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC 0x10 // 0: Stero signaling supported via external VESA stereo connector
+// 1: Stero signaling supported via VESA EVC connector
+//
+// Super VGA mode number bite field definitions
+//
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100 // 0: Not a VESA defined VBE mode
+// 1: A VESA defined VBE mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800 // 0: Use current BIOS default referesh rate
+// 1: Use the user specified CRTC values for refresh rate
+//
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER 0x4000 // 0: Use a banked/windowed frame buffer
+// 1: Use a linear/flat frame buffer
+//
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY 0x8000 // 0: Clear display memory
+// 1: Preseve display memory
+//
+// Super VGA Information Block mode list terminator value
+//
+#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff
+
+//
+// Window Function
+//
+typedef
+VOID
+(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) (
+ VOID
+ );
+
+//
+// Super VGA Mode Information Block
+//
+typedef struct {
+ //
+ // Manadory fields for all VESA Bios Extensions revisions
+ //
+ UINT16 ModeAttributes; // Mode attributes
+ UINT8 WinAAttributes; // Window A attributes
+ UINT8 WinBAttributes; // Window B attributes
+ UINT16 WinGranularity; // Window granularity in k
+ UINT16 WinSize; // Window size in k
+ UINT16 WinASegment; // Window A segment
+ UINT16 WinBSegment; // Window B segment
+ UINT32 WindowFunction; // Pointer to window function
+ UINT16 BytesPerScanLine; // Bytes per scanline
+ //
+ // Manadory fields for VESA Bios Extensions 1.2 and above
+ //
+ UINT16 XResolution; // Horizontal resolution
+ UINT16 YResolution; // Vertical resolution
+ UINT8 XCharSize; // Character cell width
+ UINT8 YCharSize; // Character cell height
+ UINT8 NumberOfPlanes; // Number of memory planes
+ UINT8 BitsPerPixel; // Bits per pixel
+ UINT8 NumberOfBanks; // Number of CGA style banks
+ UINT8 MemoryModel; // Memory model type
+ UINT8 BankSize; // Size of CGA style banks
+ UINT8 NumberOfImagePages; // Number of images pages
+ UINT8 Reserved1; // Reserved
+ UINT8 RedMaskSize; // Size of direct color red mask
+ UINT8 RedFieldPosition; // Bit posn of lsb of red mask
+ UINT8 GreenMaskSize; // Size of direct color green mask
+ UINT8 GreenFieldPosition; // Bit posn of lsb of green mask
+ UINT8 BlueMaskSize; // Size of direct color blue mask
+ UINT8 BlueFieldPosition; // Bit posn of lsb of blue mask
+ UINT8 RsvdMaskSize; // Size of direct color res mask
+ UINT8 RsvdFieldPosition; // Bit posn of lsb of res mask
+ UINT8 DirectColorModeInfo; // Direct color mode attributes
+ //
+ // Manadory fields for VESA Bios Extensions 2.0 and above
+ //
+ UINT32 PhysBasePtr; // Physical Address for flat memory frame buffer
+ UINT32 Reserved2; // Reserved
+ UINT16 Reserved3; // Reserved
+ //
+ // Manadory fields for VESA Bios Extensions 3.0 and above
+ //
+ UINT16 LinBytesPerScanLine; // Bytes/scan line for linear modes
+ UINT8 BnkNumberOfImagePages; // Number of images for banked modes
+ UINT8 LinNumberOfImagePages; // Number of images for linear modes
+ UINT8 LinRedMaskSize; // Size of direct color red mask (linear mode)
+ UINT8 LinRedFieldPosition; // Bit posiiton of lsb of red mask (linear modes)
+ UINT8 LinGreenMaskSize; // Size of direct color green mask (linear mode)
+ UINT8 LinGreenFieldPosition; // Bit posiiton of lsb of green mask (linear modes)
+ UINT8 LinBlueMaskSize; // Size of direct color blue mask (linear mode)
+ UINT8 LinBlueFieldPosition; // Bit posiiton of lsb of blue mask (linear modes)
+ UINT8 LinRsvdMaskSize; // Size of direct color reserved mask (linear mode)
+ UINT8 LinRsvdFieldPosition; // Bit posiiton of lsb of reserved mask (linear modes)
+ UINT32 MaxPixelClock; // Maximum pixel clock (in Hz) for graphics mode
+ UINT8 Pad[190]; // Pad to 256 byte block size
+} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK;
+
+//
+// Super VGA Mode Information Block ModeAttributes field bit defintions
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE 0x0001 // 0: Mode not supported in handware
+// 1: Mode supported in handware
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004 // 0: TTY Output functions not supported by BIOS
+// 1: TTY Output functions supported by BIOS
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008 // 0: Monochrome mode
+// 1: Color mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS 0x0010 // 0: Text mode
+// 1: Graphics mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020 // 0: VGA compatible mode
+// 1: Not a VGA compatible mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED 0x0040 // 0: VGA compatible windowed memory mode
+// 1: Not a VGA compatible windowed memory mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080 // 0: No linear fram buffer mode available
+// 1: Linear frame buffer mode available
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100 // 0: No double scan mode available
+// 1: Double scan mode available
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED 0x0200 // 0: No interlaced mode is available
+// 1: Interlaced mode is available
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400 // 0: No hardware triple buffer mode support available
+// 1: Hardware triple buffer mode support available
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC 0x0800 // 0: No hardware steroscopic display support
+// 1: Hardware steroscopic display support
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY 0x1000 // 0: No dual display start address support
+// 1: Dual display start address support
+//
+// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit defintions
+//
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01 // 0: Single non-relocatable window only
+// 1: Relocatable window(s) are supported
+//
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE 0x02 // 0: Window is not readable
+// 1: Window is readable
+//
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE 0x04 // 0: Window is not writable
+// 1: Window is writable
+//
+// Super VGA Mode Information Block DirectColorMode field bit defintions
+//
+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP 0x01 // 0: Color ram is fixed
+// 1: Color ramp is programmable
+//
+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE 0x02 // 0: Bits in Rsvd field are reserved
+// 1: Bits in Rsdv field are usable
+//
+// Super VGA Memory Models
+//
+typedef enum {
+ memPL = 3, // Planar memory model
+ memPK = 4, // Packed pixel memory model
+ memRGB= 6, // Direct color RGB memory model
+ memYUV= 7, // Direct color YUV memory model
+} VESA_BIOS_EXTENSIONS_MEMORY_MODELS;
+
+//
+// Super VGA CRTC Information Block
+//
+typedef struct {
+ UINT16 HorizontalTotal; // Horizontal total in pixels
+ UINT16 HorizontalSyncStart; // Horizontal sync start in pixels
+ UINT16 HorizontalSyncEnd; // Horizontal sync end in pixels
+ UINT16 VericalTotal; // Vertical total in pixels
+ UINT16 VericalSyncStart; // Vertical sync start in pixels
+ UINT16 VericalSyncEnd; // Vertical sync end in pixels
+ UINT8 Flags; // Flags (Interlaced/DoubleScan/etc).
+ UINT32 PixelClock; // Pixel clock in units of Hz
+ UINT16 RefreshRate; // Refresh rate in units of 0.01 Hz
+ UINT8 Reserved[40]; // Pad
+} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK;
+
+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01 // 0: Graphics mode is not souble scanned
+// 1: Graphics mode is double scanned
+//
+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02 // 0: Graphics mode is not interlaced
+// 1: Graphics mode is interlaced
+//
+#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE 0x04 // 0: Horizontal sync polarity is positive(+)
+// 0: Horizontal sync polarity is negative(-)
+//
+#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08 // 0: Verical sync polarity is positive(+)
+// 0: Verical sync polarity is negative(-)
+//
+// Turn off byte packing of data structures
+//
+#pragma pack()
+
+#endif
diff --git a/Core/EM/CSM/thunk/CsmVideo/VgaClass.c b/Core/EM/CSM/thunk/CsmVideo/VgaClass.c
new file mode 100644
index 0000000..1315bf5
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/VgaClass.c
@@ -0,0 +1,1349 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+--*/
+/*++
+
+Copyright (c) 1999 - 2003 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ VgaClass.c
+
+Abstract:
+ This driver produces a VGA console.
+
+--*/
+#include "VgaClass.h"
+//*** AMI PORTING BEGIN ***//
+#if INT10_SIMPLE_TEXT_SUPPORT==1
+//*** AMI PORTING END *****//
+
+//
+// EFI Driver Binding Protocol for the VGA Class Driver
+//
+EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding = {
+ VgaClassDriverBindingSupported,
+ VgaClassDriverBindingStart,
+ VgaClassDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// Local variables
+//
+static CHAR16 CrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
+
+typedef struct {
+ CHAR16 Unicode;
+ CHAR8 PcAnsi;
+ CHAR8 Ascii;
+} UNICODE_TO_CHAR;
+
+//
+// This list is used to define the valid extend chars.
+// It also provides a mapping from Unicode to PCANSI or
+// ASCII. The ASCII mapping we just made up.
+//
+//
+STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = {
+ BOXDRAW_HORIZONTAL,
+ 0xc4,
+ L'-',
+ BOXDRAW_VERTICAL,
+ 0xb3,
+ L'|',
+ BOXDRAW_DOWN_RIGHT,
+ 0xda,
+ L'/',
+ BOXDRAW_DOWN_LEFT,
+ 0xbf,
+ L'\\',
+ BOXDRAW_UP_RIGHT,
+ 0xc0,
+ L'\\',
+ BOXDRAW_UP_LEFT,
+ 0xd9,
+ L'/',
+ BOXDRAW_VERTICAL_RIGHT,
+ 0xc3,
+ L'|',
+ BOXDRAW_VERTICAL_LEFT,
+ 0xb4,
+ L'|',
+ BOXDRAW_DOWN_HORIZONTAL,
+ 0xc2,
+ L'+',
+ BOXDRAW_UP_HORIZONTAL,
+ 0xc1,
+ L'+',
+ BOXDRAW_VERTICAL_HORIZONTAL,
+ 0xc5,
+ L'+',
+ BOXDRAW_DOUBLE_HORIZONTAL,
+ 0xcd,
+ L'-',
+ BOXDRAW_DOUBLE_VERTICAL,
+ 0xba,
+ L'|',
+ BOXDRAW_DOWN_RIGHT_DOUBLE,
+ 0xd5,
+ L'/',
+ BOXDRAW_DOWN_DOUBLE_RIGHT,
+ 0xd6,
+ L'/',
+ BOXDRAW_DOUBLE_DOWN_RIGHT,
+ 0xc9,
+ L'/',
+ BOXDRAW_DOWN_LEFT_DOUBLE,
+ 0xb8,
+ L'\\',
+ BOXDRAW_DOWN_DOUBLE_LEFT,
+ 0xb7,
+ L'\\',
+ BOXDRAW_DOUBLE_DOWN_LEFT,
+ 0xbb,
+ L'\\',
+ BOXDRAW_UP_RIGHT_DOUBLE,
+ 0xd4,
+ L'\\',
+ BOXDRAW_UP_DOUBLE_RIGHT,
+ 0xd3,
+ L'\\',
+ BOXDRAW_DOUBLE_UP_RIGHT,
+ 0xc8,
+ L'\\',
+ BOXDRAW_UP_LEFT_DOUBLE,
+ 0xbe,
+ L'/',
+ BOXDRAW_UP_DOUBLE_LEFT,
+ 0xbd,
+ L'/',
+ BOXDRAW_DOUBLE_UP_LEFT,
+ 0xbc,
+ L'/',
+ BOXDRAW_VERTICAL_RIGHT_DOUBLE,
+ 0xc6,
+ L'|',
+ BOXDRAW_VERTICAL_DOUBLE_RIGHT,
+ 0xc7,
+ L'|',
+ BOXDRAW_DOUBLE_VERTICAL_RIGHT,
+ 0xcc,
+ L'|',
+ BOXDRAW_VERTICAL_LEFT_DOUBLE,
+ 0xb5,
+ L'|',
+ BOXDRAW_VERTICAL_DOUBLE_LEFT,
+ 0xb6,
+ L'|',
+ BOXDRAW_DOUBLE_VERTICAL_LEFT,
+ 0xb9,
+ L'|',
+ BOXDRAW_DOWN_HORIZONTAL_DOUBLE,
+ 0xd1,
+ L'+',
+ BOXDRAW_DOWN_DOUBLE_HORIZONTAL,
+ 0xd2,
+ L'+',
+ BOXDRAW_DOUBLE_DOWN_HORIZONTAL,
+ 0xcb,
+ L'+',
+ BOXDRAW_UP_HORIZONTAL_DOUBLE,
+ 0xcf,
+ L'+',
+ BOXDRAW_UP_DOUBLE_HORIZONTAL,
+ 0xd0,
+ L'+',
+ BOXDRAW_DOUBLE_UP_HORIZONTAL,
+ 0xca,
+ L'+',
+ BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE,
+ 0xd8,
+ L'+',
+ BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL,
+ 0xd7,
+ L'+',
+ BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL,
+ 0xce,
+ L'+',
+
+ BLOCKELEMENT_FULL_BLOCK,
+ 0xdb,
+ L'*',
+ BLOCKELEMENT_LIGHT_SHADE,
+ 0xb0,
+ L'+',
+
+ GEOMETRICSHAPE_UP_TRIANGLE,
+ 0x1e,
+ L'^',
+ GEOMETRICSHAPE_RIGHT_TRIANGLE,
+ 0x10,
+ L'>',
+ GEOMETRICSHAPE_DOWN_TRIANGLE,
+ 0x1f,
+ L'v',
+ GEOMETRICSHAPE_LEFT_TRIANGLE,
+ 0x11,
+ L'<',
+
+ ARROW_LEFT,
+ 0x3c,
+ L'<',
+
+ ARROW_UP,
+ 0x18,
+ L'^',
+
+ ARROW_RIGHT,
+ 0x3e,
+ L'>',
+
+ ARROW_DOWN,
+ 0x19,
+ L'v',
+
+ 0x0000,
+ 0x00
+};
+
+//
+// Private worker functions
+//
+STATIC
+VOID
+SetVideoCursorPosition (
+ IN VGA_CLASS_DEV *VgaClassDev,
+ IN UINTN Column,
+ IN UINTN Row,
+ IN UINTN MaxColumn
+ );
+
+STATIC
+VOID
+WriteCrtc (
+ IN VGA_CLASS_DEV *VgaClassDev,
+ IN UINT16 Address,
+ IN UINT8 Data
+ );
+
+STATIC
+BOOLEAN
+LibIsValidTextGraphics (
+ IN CHAR16 Graphic,
+ OUT CHAR8 *PcAnsi, OPTIONAL
+ OUT CHAR8 *Ascii OPTIONAL
+ );
+
+STATIC
+BOOLEAN
+IsValidAscii (
+ IN CHAR16 Ascii
+ );
+
+STATIC
+BOOLEAN
+IsValidEfiCntlChar (
+ IN CHAR16 c
+ );
+
+//
+// Driver Entry Point
+//
+EFI_DRIVER_ENTRY_POINT (VgaClassDriverEntryPoint)
+
+EFI_STATUS
+EFIAPI
+VgaClassDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+ Routine Description:
+
+ Driver Entry Point.
+
+ Arguments:
+
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+ Returns:
+ EFI_STATUS
+--*/
+// GC_TODO: ImageHandle - add argument and description to function comment
+// GC_TODO: SystemTable - add argument and description to function comment
+{
+ return INSTALL_ALL_DRIVER_PROTOCOLS (
+ ImageHandle,
+ SystemTable,
+ &gVgaClassDriverBinding,
+ ImageHandle,
+//*** AMI PORTING BEGIN ***//
+ NULL,
+// &gVgaClassComponentName,
+//*** AMI PORTING END *****//
+ NULL,
+ NULL
+ );
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+
+ Supported.
+
+ Arguments:
+
+ (Standard DriverBinding Protocol Supported() function)
+
+ Returns:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: Controller - add argument and description to function comment
+// GC_TODO: RemainingDevicePath - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiVgaMiniPortProtocolGuid,
+ (VOID **) &VgaMiniPort,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+
+ Layers the Simple Text Output Protocol on top of the
+ VGA Mini Port Protocol
+
+ Arguments:
+
+ (Standard DriverBinding Protocol Start() function)
+
+ Returns:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: Controller - add argument and description to function comment
+// GC_TODO: RemainingDevicePath - add argument and description to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ VGA_CLASS_DEV *VgaClassPrivate;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Report that VGA Class driver is being enabled
+ //
+ ReportStatusCodeWithDevicePath (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,
+ 0,
+ &gEfiCallerIdGuid,
+ DevicePath
+ );
+
+ //
+ // Open the IO Abstraction(s) needed
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiVgaMiniPortProtocolGuid,
+ (VOID **) &VgaMiniPort,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate the private device structure
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (VGA_CLASS_DEV),
+ &VgaClassPrivate
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiVgaMiniPortProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EfiZeroMem (VgaClassPrivate, sizeof (VGA_CLASS_DEV));
+
+ //
+ // Initialize the private device structure
+ //
+ VgaClassPrivate->Signature = VGA_CLASS_DEV_SIGNATURE;
+ VgaClassPrivate->Handle = Controller;
+ VgaClassPrivate->VgaMiniPort = VgaMiniPort;
+ VgaClassPrivate->PciIo = PciIo;
+
+ VgaClassPrivate->SimpleTextOut.Reset = VgaClassReset;
+ VgaClassPrivate->SimpleTextOut.OutputString = VgaClassOutputString;
+ VgaClassPrivate->SimpleTextOut.TestString = VgaClassTestString;
+ VgaClassPrivate->SimpleTextOut.ClearScreen = VgaClassClearScreen;
+ VgaClassPrivate->SimpleTextOut.SetAttribute = VgaClassSetAttribute;
+ VgaClassPrivate->SimpleTextOut.SetCursorPosition = VgaClassSetCursorPosition;
+ VgaClassPrivate->SimpleTextOut.EnableCursor = VgaClassEnableCursor;
+ VgaClassPrivate->SimpleTextOut.QueryMode = VgaClassQueryMode;
+ VgaClassPrivate->SimpleTextOut.SetMode = VgaClassSetMode;
+
+ VgaClassPrivate->SimpleTextOut.Mode = &VgaClassPrivate->SimpleTextOutputMode;
+ VgaClassPrivate->SimpleTextOutputMode.MaxMode = VgaMiniPort->MaxMode;
+ VgaClassPrivate->DevicePath = DevicePath;
+
+ Status = VgaClassPrivate->SimpleTextOut.SetAttribute (
+ &VgaClassPrivate->SimpleTextOut,
+ EFI_TEXT_ATTR (EFI_WHITE,
+ EFI_BLACK)
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ Status = VgaClassPrivate->SimpleTextOut.Reset (
+ &VgaClassPrivate->SimpleTextOut,
+ FALSE
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ Status = VgaClassPrivate->SimpleTextOut.EnableCursor (
+ &VgaClassPrivate->SimpleTextOut,
+ TRUE
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiSimpleTextOutProtocolGuid,
+ &VgaClassPrivate->SimpleTextOut,
+ NULL
+ );
+
+ return Status;
+
+ErrorExit:
+ ReportStatusCodeWithDevicePath (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
+ 0,
+ &gEfiCallerIdGuid,
+ DevicePath
+ );
+
+ return Status;
+
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+
+ Stop.
+
+ Arguments:
+
+ (Standard DriverBinding Protocol Stop() function)
+
+ Returns:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: Controller - add argument and description to function comment
+// GC_TODO: NumberOfChildren - add argument and description to function comment
+// GC_TODO: ChildHandleBuffer - add argument and description to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOut;
+ VGA_CLASS_DEV *VgaClassPrivate;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimpleTextOutProtocolGuid,
+ (VOID **) &SimpleTextOut,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (SimpleTextOut);
+
+ //
+ // Report that VGA Class driver is being disabled
+ //
+ ReportStatusCodeWithDevicePath (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,
+ 0,
+ &gEfiCallerIdGuid,
+ VgaClassPrivate->DevicePath
+ );
+
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiSimpleTextOutProtocolGuid,
+ &VgaClassPrivate->SimpleTextOut
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Release PCI I/O and VGA Mini Port Protocols on the controller handle.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiVgaMiniPortProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->FreePool (VgaClassPrivate);
+
+ return EFI_SUCCESS;
+}
+//
+// Simple Text Output Protocol Functions
+//
+EFI_STATUS
+EFIAPI
+VgaClassReset (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ ExtendedVerification - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ EFI_STATUS Status;
+ VGA_CLASS_DEV *VgaClassPrivate;
+
+ VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (This);
+
+ ReportStatusCodeWithDevicePath (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_RESET,
+ 0,
+ &gEfiCallerIdGuid,
+ VgaClassPrivate->DevicePath
+ );
+
+ This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
+
+ Status = This->SetMode (This, 0);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return This->ClearScreen (This);
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassOutputString (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ WString - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ VGA_CLASS_DEV *VgaClassDev;
+ EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+ CHAR16 *SavedWString;
+ UINT32 VideoChar;
+ CHAR8 GraphicChar;
+
+ VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
+
+ Mode = This->Mode;
+
+ Status = This->QueryMode (
+ This,
+ Mode->Mode,
+ &MaxColumn,
+ &MaxRow
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SavedWString = WString;
+ for (; *WString != CHAR_NULL; WString++) {
+
+ switch (*WString) {
+ case CHAR_BACKSPACE:
+ if (Mode->CursorColumn > 0) {
+ Mode->CursorColumn--;
+ }
+ break;
+
+ case CHAR_LINEFEED:
+ if (Mode->CursorRow == (INT32) (MaxRow - 1)) {
+ //
+ // Scroll the screen by copying the contents
+ // of the VGA display up one line
+ //
+ VgaClassDev->PciIo->CopyMem (
+ VgaClassDev->PciIo,
+ EfiPciIoWidthUint32,
+ VgaClassDev->VgaMiniPort->VgaMemoryBar,
+ VgaClassDev->VgaMiniPort->VgaMemoryOffset,
+ VgaClassDev->VgaMiniPort->VgaMemoryBar,
+ VgaClassDev->VgaMiniPort->VgaMemoryOffset + MaxColumn * 2,
+ ((MaxRow - 1) * MaxColumn) >> 1
+ );
+
+ //
+ // Print Blank Line of spaces with the current color attributes
+ //
+ VideoChar = (Mode->Attribute << 8) | ' ';
+ VideoChar = (VideoChar << 16) | VideoChar;
+ VgaClassDev->PciIo->Mem.Write (
+ VgaClassDev->PciIo,
+ EfiPciIoWidthFillUint32,
+ VgaClassDev->VgaMiniPort->VgaMemoryBar,
+ VgaClassDev->VgaMiniPort->VgaMemoryOffset + (MaxRow - 1) * MaxColumn * 2,
+ MaxColumn >> 1,
+ &VideoChar
+ );
+ }
+
+ if (Mode->CursorRow < (INT32) (MaxRow - 1)) {
+ Mode->CursorRow++;
+ }
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ Mode->CursorColumn = 0;
+ break;
+
+ default:
+ if (!LibIsValidTextGraphics (*WString, &GraphicChar, NULL)) {
+ //
+ // Just convert to ASCII
+ //
+ GraphicChar = (CHAR8) *WString;
+ if (!IsValidAscii (GraphicChar)) {
+ //
+ // Keep the API from supporting PCANSI Graphics chars
+ //
+ GraphicChar = '?';
+ }
+ }
+
+ VideoChar = (Mode->Attribute << 8) | GraphicChar;
+ VgaClassDev->PciIo->Mem.Write (
+ VgaClassDev->PciIo,
+ EfiPciIoWidthUint16,
+ VgaClassDev->VgaMiniPort->VgaMemoryBar,
+ VgaClassDev->VgaMiniPort->VgaMemoryOffset + ((Mode->CursorRow * MaxColumn + Mode->CursorColumn) * 2),
+ 1,
+ &VideoChar
+ );
+
+ if (Mode->CursorColumn >= (INT32) (MaxColumn - 1)) {
+ This->OutputString (This, CrLfString);
+ } else {
+ Mode->CursorColumn++;
+ }
+ break;
+ }
+ }
+
+ SetVideoCursorPosition (
+ VgaClassDev,
+ (UINTN) Mode->CursorColumn,
+ (UINTN) Mode->CursorRow,
+ MaxColumn
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassTestString (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ WString - GC_TODO: add argument description
+
+Returns:
+
+ EFI_UNSUPPORTED - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ while (*WString != 0x0000) {
+ if (!(IsValidAscii (*WString) || IsValidEfiCntlChar (*WString) || LibIsValidTextGraphics (*WString, NULL, NULL))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ WString++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassClearScreen (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ VGA_CLASS_DEV *VgaClassDev;
+ UINTN MaxRow;
+ UINTN MaxColumn;
+ UINT32 VideoChar;
+
+ VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
+
+ Status = This->QueryMode (
+ This,
+ This->Mode->Mode,
+ &MaxColumn,
+ &MaxRow
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VideoChar = (This->Mode->Attribute << 8) | ' ';
+ VideoChar = (VideoChar << 16) | VideoChar;
+ VgaClassDev->PciIo->Mem.Write (
+ VgaClassDev->PciIo,
+ EfiPciIoWidthFillUint32,
+ VgaClassDev->VgaMiniPort->VgaMemoryBar,
+ VgaClassDev->VgaMiniPort->VgaMemoryOffset,
+ (MaxRow * MaxColumn) >> 1,
+ &VideoChar
+ );
+
+ This->SetCursorPosition (This, 0, 0);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassSetAttribute (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN UINTN Attribute
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Attribute - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_UNSUPPORTED - GC_TODO: Add description for return value
+
+--*/
+{
+//*** AMI PORTING BEGIN ***//
+// Comparison of unsigned value with zero
+// if (Attribute >= 0 && Attribute <= EFI_MAX_ATTRIBUTE) {
+ if (Attribute <= EFI_MAX_ATTRIBUTE) {
+//*** AMI PORTING END *****//
+ This->Mode->Attribute = (INT32) Attribute;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassSetCursorPosition (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Column - GC_TODO: add argument description
+ Row - GC_TODO: add argument description
+
+Returns:
+
+ EFI_UNSUPPORTED - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ VGA_CLASS_DEV *VgaClassDev;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+
+ VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
+
+ Status = This->QueryMode (
+ This,
+ This->Mode->Mode,
+ &MaxColumn,
+ &MaxRow
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Column >= MaxColumn || Row >= MaxRow) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SetVideoCursorPosition (VgaClassDev, Column, Row, MaxColumn);
+
+ This->Mode->CursorColumn = (INT32) Column;
+ This->Mode->CursorRow = (INT32) Row;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassEnableCursor (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Visible - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ VGA_CLASS_DEV *VgaClassDev;
+
+ VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
+ if (Visible) {
+ switch (This->Mode->Mode) {
+ case 1:
+ WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x06);
+ WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x07);
+ break;
+
+ default:
+ WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x0e);
+ WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x0f);
+ break;
+ }
+ } else {
+ WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x20);
+ }
+
+ This->Mode->CursorVisible = Visible;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassQueryMode (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ ModeNumber - GC_TODO: add argument description
+ Columns - GC_TODO: add argument description
+ Rows - GC_TODO: add argument description
+
+Returns:
+
+ EFI_UNSUPPORTED - GC_TODO: Add description for return value
+ EFI_UNSUPPORTED - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ VGA_CLASS_DEV *VgaClassDev;
+
+ VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
+
+ if ((INT32) ModeNumber >= This->Mode->MaxMode) {
+ *Columns = 0;
+ *Rows = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (ModeNumber) {
+ case 0:
+ *Columns = 80;
+ *Rows = 25;
+ break;
+
+ case 1:
+ *Columns = 80;
+ *Rows = 50;
+ break;
+
+ default:
+ *Columns = 0;
+ *Rows = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VgaClassSetMode (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ ModeNumber - GC_TODO: add argument description
+
+Returns:
+
+ EFI_UNSUPPORTED - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ VGA_CLASS_DEV *VgaClassDev;
+
+ VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
+
+ if ((INT32) ModeNumber >= This->Mode->MaxMode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ This->ClearScreen (This);
+
+ This->Mode->Mode = (INT32) ModeNumber;
+
+ Status = VgaClassDev->VgaMiniPort->SetMode (VgaClassDev->VgaMiniPort, ModeNumber);
+
+ return Status;
+}
+//
+// Private Worker Functions
+//
+STATIC
+VOID
+SetVideoCursorPosition (
+ IN VGA_CLASS_DEV *VgaClassDev,
+ IN UINTN Column,
+ IN UINTN Row,
+ IN UINTN MaxColumn
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ VgaClassDev - GC_TODO: add argument description
+ Column - GC_TODO: add argument description
+ Row - GC_TODO: add argument description
+ MaxColumn - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ Column = Column & 0xff;
+ Row = Row & 0xff;
+ MaxColumn = MaxColumn & 0xff;
+ WriteCrtc (
+ VgaClassDev,
+ CRTC_CURSOR_LOCATION_HIGH,
+ (UINT8) ((Row * MaxColumn + Column) >> 8)
+ );
+ WriteCrtc (
+ VgaClassDev,
+ CRTC_CURSOR_LOCATION_LOW,
+ (UINT8) ((Row * MaxColumn + Column) & 0xff)
+ );
+}
+
+STATIC
+VOID
+WriteCrtc (
+ IN VGA_CLASS_DEV *VgaClassDev,
+ IN UINT16 Address,
+ IN UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ VgaClassDev - GC_TODO: add argument description
+ Address - GC_TODO: add argument description
+ Data - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ VgaClassDev->PciIo->Io.Write (
+ VgaClassDev->PciIo,
+ EfiPciIoWidthUint8,
+ VgaClassDev->VgaMiniPort->CrtcAddressRegisterBar,
+ VgaClassDev->VgaMiniPort->CrtcAddressRegisterOffset,
+ 1,
+ &Address
+ );
+
+ VgaClassDev->PciIo->Io.Write (
+ VgaClassDev->PciIo,
+ EfiPciIoWidthUint8,
+ VgaClassDev->VgaMiniPort->CrtcDataRegisterBar,
+ VgaClassDev->VgaMiniPort->CrtcDataRegisterOffset,
+ 1,
+ &Data
+ );
+}
+
+STATIC
+BOOLEAN
+LibIsValidTextGraphics (
+ IN CHAR16 Graphic,
+ OUT CHAR8 *PcAnsi, OPTIONAL
+ OUT CHAR8 *Ascii OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Detects if a Unicode char is for Box Drawing text graphics.
+
+Arguments:
+
+ Grphic - Unicode char to test.
+
+ PcAnsi - Optional pointer to return PCANSI equivalent of Graphic.
+
+ Asci - Optional pointer to return Ascii equivalent of Graphic.
+
+Returns:
+
+ TRUE if Gpaphic is a supported Unicode Box Drawing character.
+
+--*/
+// GC_TODO: Graphic - add argument and description to function comment
+{
+ UNICODE_TO_CHAR *Table;
+
+ if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) {
+ //
+ // Unicode drawing code charts are all in the 0x25xx range,
+ // arrows are 0x21xx
+ //
+ return FALSE;
+ }
+
+ for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) {
+ if (Graphic == Table->Unicode) {
+ if (PcAnsi) {
+ *PcAnsi = Table->PcAnsi;
+ }
+
+ if (Ascii) {
+ *Ascii = Table->Ascii;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+STATIC
+BOOLEAN
+IsValidAscii (
+ IN CHAR16 Ascii
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Ascii - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ if ((Ascii >= 0x20) && (Ascii <= 0x7f)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+STATIC
+BOOLEAN
+IsValidEfiCntlChar (
+ IN CHAR16 c
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ c - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ if (c == CHAR_NULL || c == CHAR_BACKSPACE || c == CHAR_LINEFEED || c == CHAR_CARRIAGE_RETURN) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+//*** AMI PORTING BEGIN ***//
+#endif //if INT10_SIMPLE_TEXT_SUPPORT==1
+//*** AMI PORTING END *****// \ No newline at end of file
diff --git a/Core/EM/CSM/thunk/CsmVideo/VgaClass.h b/Core/EM/CSM/thunk/CsmVideo/VgaClass.h
new file mode 100644
index 0000000..fd184de
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/VgaClass.h
@@ -0,0 +1,418 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//
+// This file contains a 'Sample Driver' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may be modified by the user, subject to
+// the additional terms of the license agreement
+//
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ VgaClass.h
+
+Abstract:
+
+
+Revision History
+--*/
+
+#ifndef _VGA_CLASS_H
+#define _VGA_CLASS_H
+
+//*** AMI PORTING BEGIN ***//
+#include "AmiMapping.h"
+//#include "Tiano.h"
+//#include "EfiDriverLib.h"
+//*** AMI PORTING END *****//
+#include "Pci22.h"
+//*** AMI PORTING BEGIN ***//
+//#include "EfiStatusCode.h"
+//#include "EfiCompNameSupport.h"
+//#include "ComponentName.h"
+//*** AMI PORTING END *****//
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include EFI_PROTOCOL_DEFINITION (DevicePath)
+#include EFI_PROTOCOL_DEFINITION (PciIo)
+//*** AMI PORTING BEGIN ***//
+//#include EFI_PROTOCOL_DEFINITION (VgaMiniPort)
+#include "VgaMiniPort.h"
+//*** AMI PORTING END *****//
+#include EFI_PROTOCOL_DEFINITION (SimpleTextIn)
+//*** AMI PORTING BEGIN ***//
+//#include EFI_GUID_DEFINITION (StatusCodeCallerId)
+//#include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
+//*** AMI PORTING END *****//
+
+//
+// Driver Produced Protocol Prototypes
+//
+#include EFI_PROTOCOL_DEFINITION (DriverBinding)
+#include EFI_PROTOCOL_DEFINITION (SimpleTextOut)
+
+//
+// VGA specific registers
+//
+#define CRTC_CURSOR_START 0xA
+#define CRTC_CURSOR_END 0xB
+
+#define CRTC_CURSOR_LOCATION_HIGH 0xE
+#define CRTC_CURSOR_LOCATION_LOW 0xF
+
+#define EFI_MAX_ATTRIBUTE 0x7f
+
+//
+// VGA Class Device Structure
+//
+#define VGA_CLASS_DEV_SIGNATURE EFI_SIGNATURE_32 ('V', 'G', 'A', 'C')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SIMPLE_TEXT_OUT_PROTOCOL SimpleTextOut;
+ EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode;
+ EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} VGA_CLASS_DEV;
+
+#define VGA_CLASS_DEV_FROM_THIS(a) CR (a, VGA_CLASS_DEV, SimpleTextOut, VGA_CLASS_DEV_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding;
+
+//
+// Driver Binding Protocol functions
+//
+EFI_STATUS
+EFIAPI
+VgaClassDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ RemainingDevicePath - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ RemainingDevicePath - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ NumberOfChildren - GC_TODO: add argument description
+ ChildHandleBuffer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// Simple Text Output Protocol functions
+//
+EFI_STATUS
+EFIAPI
+VgaClassReset (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ ExtendedVerification - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassOutputString (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ WString - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassTestString (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ WString - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassClearScreen (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassSetAttribute (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN UINTN Attribute
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Attribute - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassSetCursorPosition (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Column - GC_TODO: add argument description
+ Row - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassEnableCursor (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Visible - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassQueryMode (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ ModeNumber - GC_TODO: add argument description
+ Columns - GC_TODO: add argument description
+ Rows - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+VgaClassSetMode (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ ModeNumber - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Core/EM/CSM/thunk/CsmVideo/VgaMiniPort.h b/Core/EM/CSM/thunk/CsmVideo/VgaMiniPort.h
new file mode 100644
index 0000000..e21a894
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/VgaMiniPort.h
@@ -0,0 +1,78 @@
+//
+// This file contains 'Framework Code' and is licensed as such
+// under the terms of your license agreement with Intel or your
+// vendor. This file may not be modified, except as allowed by
+// additional terms of your license agreement.
+//
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ VgaMiniPort.h
+
+Abstract:
+
+ Vga Mini port binding for a VGA controller
+
+Revision History
+
+--*/
+
+#ifndef _VGA_MINI_PORT_H
+#define _VGA_MINI_PORT_H
+
+#define EFI_VGA_MINI_PORT_PROTOCOL_GUID \
+ { \
+ 0xc7735a2f, 0x88f5, 0x4882, 0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3 \
+ }
+
+EFI_FORWARD_DECLARATION (EFI_VGA_MINI_PORT_PROTOCOL);
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_VGA_MINI_PORT_SET_MODE) (
+ IN EFI_VGA_MINI_PORT_PROTOCOL * This,
+ IN UINTN ModeNumber
+ );
+
+/*++
+
+ Routine Description:
+ Sets the text display mode of a VGA controller
+
+ Arguments:
+ This - Protocol instance pointer.
+ Mode - Mode number. 0 - 80x25 1-80x50
+
+ Returns:
+ EFI_SUCCESS - The mode was set
+ EFI_DEVICE_ERROR - The device is not functioning properly.
+
+--*/
+typedef struct _EFI_VGA_MINI_PORT_PROTOCOL {
+ EFI_VGA_MINI_PORT_SET_MODE SetMode;
+
+ UINT64 VgaMemoryOffset;
+ UINT64 CrtcAddressRegisterOffset;
+ UINT64 CrtcDataRegisterOffset;
+
+ UINT8 VgaMemoryBar;
+ UINT8 CrtcAddressRegisterBar;
+ UINT8 CrtcDataRegisterBar;
+
+ UINT8 MaxMode;
+} EFI_VGA_MINI_PORT_PROTOCOL;
+
+extern EFI_GUID gEfiVgaMiniPortProtocolGuid;
+
+#endif
diff --git a/Core/EM/CSM/thunk/CsmVideo/pci22.h b/Core/EM/CSM/thunk/CsmVideo/pci22.h
new file mode 100644
index 0000000..1c8ccd0
--- /dev/null
+++ b/Core/EM/CSM/thunk/CsmVideo/pci22.h
@@ -0,0 +1,621 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ pci22.h
+
+Abstract:
+ Support for PCI 2.2 standard.
+
+Revision History
+
+--*/
+
+#ifndef _PCI22_H
+#define _PCI22_H
+
+#define PCI_MAX_SEGMENT 0
+
+#define PCI_MAX_BUS 255
+
+#define PCI_MAX_DEVICE 31
+#define PCI_MAX_FUNC 7
+
+//
+// Command
+//
+#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20
+
+#pragma pack(push, 1)
+typedef struct {
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 Command;
+ UINT16 Status;
+ UINT8 RevisionID;
+ UINT8 ClassCode[3];
+ UINT8 CacheLineSize;
+ UINT8 LatencyTimer;
+ UINT8 HeaderType;
+ UINT8 BIST;
+} PCI_DEVICE_INDEPENDENT_REGION;
+
+typedef struct {
+ UINT32 Bar[6];
+ UINT32 CISPtr;
+ UINT16 SubsystemVendorID;
+ UINT16 SubsystemID;
+ UINT32 ExpansionRomBar;
+ UINT8 CapabilityPtr;
+ UINT8 Reserved1[3];
+ UINT32 Reserved2;
+ UINT8 InterruptLine;
+ UINT8 InterruptPin;
+ UINT8 MinGnt;
+ UINT8 MaxLat;
+} PCI_DEVICE_HEADER_TYPE_REGION;
+
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_DEVICE_HEADER_TYPE_REGION Device;
+} PCI_TYPE00;
+
+typedef struct {
+ UINT32 Bar[2];
+ UINT8 PrimaryBus;
+ UINT8 SecondaryBus;
+ UINT8 SubordinateBus;
+ UINT8 SecondaryLatencyTimer;
+ UINT8 IoBase;
+ UINT8 IoLimit;
+ UINT16 SecondaryStatus;
+ UINT16 MemoryBase;
+ UINT16 MemoryLimit;
+ UINT16 PrefetchableMemoryBase;
+ UINT16 PrefetchableMemoryLimit;
+ UINT32 PrefetchableBaseUpper32;
+ UINT32 PrefetchableLimitUpper32;
+ UINT16 IoBaseUpper16;
+ UINT16 IoLimitUpper16;
+ UINT8 CapabilityPtr;
+ UINT8 Reserved[3];
+ UINT32 ExpansionRomBAR;
+ UINT8 InterruptLine;
+ UINT8 InterruptPin;
+ UINT16 BridgeControl;
+} PCI_BRIDGE_CONTROL_REGISTER;
+
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_BRIDGE_CONTROL_REGISTER Bridge;
+} PCI_TYPE01;
+
+typedef union {
+ PCI_TYPE00 Device;
+ PCI_TYPE01 Bridge;
+} PCI_TYPE_GENERIC;
+
+typedef struct {
+ UINT32 CardBusSocketReg; // Cardus Socket/ExCA Base
+ // Address Register
+ //
+ UINT16 Reserved;
+ UINT16 SecondaryStatus; // Secondary Status
+ UINT8 PciBusNumber; // PCI Bus Number
+ UINT8 CardBusBusNumber; // CardBus Bus Number
+ UINT8 SubordinateBusNumber; // Subordinate Bus Number
+ UINT8 CardBusLatencyTimer; // CardBus Latency Timer
+ UINT32 MemoryBase0; // Memory Base Register 0
+ UINT32 MemoryLimit0; // Memory Limit Register 0
+ UINT32 MemoryBase1;
+ UINT32 MemoryLimit1;
+ UINT32 IoBase0;
+ UINT32 IoLimit0; // I/O Base Register 0
+ UINT32 IoBase1; // I/O Limit Register 0
+ UINT32 IoLimit1;
+ UINT8 InterruptLine; // Interrupt Line
+ UINT8 InterruptPin; // Interrupt Pin
+ UINT16 BridgeControl; // Bridge Control
+} PCI_CARDBUS_CONTROL_REGISTER;
+
+//
+// Definitions of PCI class bytes and manipulation macros.
+//
+#define PCI_CLASS_OLD 0x00
+#define PCI_CLASS_OLD_OTHER 0x00
+#define PCI_CLASS_OLD_VGA 0x01
+
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_CLASS_MASS_STORAGE_SCSI 0x00
+#define PCI_CLASS_MASS_STORAGE_IDE 0x01 // obsolete
+#define PCI_CLASS_IDE 0x01
+#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02
+#define PCI_CLASS_MASS_STORAGE_IPI 0x03
+#define PCI_CLASS_MASS_STORAGE_RAID 0x04
+#define PCI_CLASS_MASS_STORAGE_OTHER 0x80
+
+#define PCI_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x00
+#define PCI_CLASS_ETHERNET 0x00 // obsolete
+#define PCI_CLASS_NETWORK_TOKENRING 0x01
+#define PCI_CLASS_NETWORK_FDDI 0x02
+#define PCI_CLASS_NETWORK_ATM 0x03
+#define PCI_CLASS_NETWORK_ISDN 0x04
+#define PCI_CLASS_NETWORK_OTHER 0x80
+
+#define PCI_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_CTRL 0x03 // obsolete
+#define PCI_CLASS_DISPLAY_VGA 0x00
+#define PCI_CLASS_VGA 0x00 // obsolete
+#define PCI_CLASS_DISPLAY_XGA 0x01
+#define PCI_CLASS_DISPLAY_3D 0x02
+#define PCI_CLASS_DISPLAY_OTHER 0x80
+#define PCI_CLASS_DISPLAY_GFX 0x80
+#define PCI_CLASS_GFX 0x80 // obsolete
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x00
+#define PCI_CLASS_BRIDGE_ISA 0x01
+#define PCI_CLASS_ISA 0x01 // obsolete
+#define PCI_CLASS_BRIDGE_EISA 0x02
+#define PCI_CLASS_BRIDGE_MCA 0x03
+#define PCI_CLASS_BRIDGE_P2P 0x04
+#define PCI_CLASS_BRIDGE_PCMCIA 0x05
+#define PCI_CLASS_BRIDGE_NUBUS 0x06
+#define PCI_CLASS_BRIDGE_CARDBUS 0x07
+#define PCI_CLASS_BRIDGE_RACEWAY 0x08
+#define PCI_CLASS_BRIDGE_ISA_PDECODE 0x80
+#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80 // obsolete
+
+#define PCI_CLASS_SCC 0x07 // Simple communications controllers
+#define PCI_SUBCLASS_SERIAL 0x00
+#define PCI_IF_GENERIC_XT 0x00
+#define PCI_IF_16450 0x01
+#define PCI_IF_16550 0x02
+#define PCI_IF_16650 0x03
+#define PCI_IF_16750 0x04
+#define PCI_IF_16850 0x05
+#define PCI_IF_16950 0x06
+#define PCI_SUBCLASS_PARALLEL 0x01
+#define PCI_IF_PARALLEL_PORT 0x00
+#define PCI_IF_BI_DIR_PARALLEL_PORT 0x01
+#define PCI_IF_ECP_PARALLEL_PORT 0x02
+#define PCI_IF_1284_CONTROLLER 0x03
+#define PCI_IF_1284_DEVICE 0xFE
+#define PCI_SUBCLASS_MULTIPORT_SERIAL 0x02
+#define PCI_SUBCLASS_MODEM 0x03
+#define PCI_IF_GENERIC_MODEM 0x00
+#define PCI_IF_16450_MODEM 0x01
+#define PCI_IF_16550_MODEM 0x02
+#define PCI_IF_16650_MODEM 0x03
+#define PCI_IF_16750_MODEM 0x04
+#define PCI_SUBCLASS_OTHER 0x80
+
+#define PCI_CLASS_SYSTEM_PERIPHERAL 0x08
+#define PCI_SUBCLASS_PIC 0x00
+#define PCI_IF_8259_PIC 0x00
+#define PCI_IF_ISA_PIC 0x01
+#define PCI_IF_EISA_PIC 0x02
+#define PCI_IF_APIC_CONTROLLER 0x10 // I/O APIC interrupt controller , 32 bye none-prefectable memory.
+#define PCI_IF_APIC_CONTROLLER2 0x20
+#define PCI_SUBCLASS_TIMER 0x02
+#define PCI_IF_8254_TIMER 0x00
+#define PCI_IF_ISA_TIMER 0x01
+#define PCI_EISA_TIMER 0x02
+#define PCI_SUBCLASS_RTC 0x03
+#define PCI_IF_GENERIC_RTC 0x00
+#define PCI_IF_ISA_RTC 0x00
+#define PCI_SUBCLASS_PNP_CONTROLLER 0x04 // HotPlug Controller
+
+#define PCI_CLASS_INPUT_DEVICE 0x09
+#define PCI_SUBCLASS_KEYBOARD 0x00
+#define PCI_SUBCLASS_PEN 0x01
+#define PCI_SUBCLASS_MOUSE_CONTROLLER 0x02
+#define PCI_SUBCLASS_SCAN_CONTROLLER 0x03
+#define PCI_SUBCLASS_GAMEPORT 0x04
+
+#define PCI_CLASS_DOCKING_STATION 0x0A
+
+#define PCI_CLASS_PROCESSOR 0x0B
+#define PCI_SUBCLASS_PROC_386 0x00
+#define PCI_SUBCLASS_PROC_486 0x01
+#define PCI_SUBCLASS_PROC_PENTIUM 0x02
+#define PCI_SUBCLASS_PROC_ALPHA 0x10
+#define PCI_SUBCLASS_PROC_POWERPC 0x20
+#define PCI_SUBCLASS_PROC_MIPS 0x30
+#define PCI_SUBCLASS_PROC_CO_PORC 0x40 // Co-Processor
+
+#define PCI_CLASS_SERIAL 0x0C
+#define PCI_CLASS_SERIAL_FIREWIRE 0x00
+#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01
+#define PCI_CLASS_SERIAL_SSA 0x02
+#define PCI_CLASS_SERIAL_USB 0x03
+#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04
+#define PCI_CLASS_SERIAL_SMB 0x05
+
+#define PCI_CLASS_WIRELESS 0x0D
+#define PCI_SUBCLASS_IRDA 0x00
+#define PCI_SUBCLASS_IR 0x01
+#define PCI_SUBCLASS_RF 0x02
+
+#define PCI_CLASS_INTELLIGENT_IO 0x0E
+
+#define PCI_CLASS_SATELLITE 0x0F
+#define PCI_SUBCLASS_TV 0x01
+#define PCI_SUBCLASS_AUDIO 0x02
+#define PCI_SUBCLASS_VOICE 0x03
+#define PCI_SUBCLASS_DATA 0x04
+
+#define PCI_SECURITY_CONTROLLER 0x10 // Encryption and decryption controller
+#define PCI_SUBCLASS_NET_COMPUT 0x00
+#define PCI_SUBCLASS_ENTERTAINMENT 0x10
+
+#define PCI_CLASS_DPIO 0x11
+
+#define IS_CLASS1(_p, c) ((_p)->Hdr.ClassCode[2] == (c))
+#define IS_CLASS2(_p, c, s) (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s)))
+#define IS_CLASS3(_p, c, s, p) (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p)))
+
+#define IS_PCI_DISPLAY(_p) IS_CLASS1 (_p, PCI_CLASS_DISPLAY)
+#define IS_PCI_VGA(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 0)
+#define IS_PCI_8514(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 1)
+#define IS_PCI_GFX(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_GFX, 0)
+#define IS_PCI_OLD(_p) IS_CLASS1 (_p, PCI_CLASS_OLD)
+#define IS_PCI_OLD_VGA(_p) IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA)
+#define IS_PCI_IDE(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE)
+#define IS_PCI_SCSI(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI, 0)
+#define IS_PCI_RAID(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID, 0)
+#define IS_PCI_LPC(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA, 0)
+#define IS_PCI_P2P(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 0)
+#define IS_PCI_P2P_SUB(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 1)
+#define IS_PCI_USB(_p) IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB)
+
+#define HEADER_TYPE_DEVICE 0x00
+#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01
+#define HEADER_TYPE_CARDBUS_BRIDGE 0x02
+
+#define HEADER_TYPE_MULTI_FUNCTION 0x80
+#define HEADER_LAYOUT_CODE 0x7f
+
+#define IS_PCI_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE))
+#define IS_CARDBUS_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE))
+#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)
+
+#define PCI_DEVICE_ROMBAR 0x30
+#define PCI_BRIDGE_ROMBAR 0x38
+
+#define PCI_MAX_BAR 0x0006
+#define PCI_MAX_CONFIG_OFFSET 0x0100
+
+#define PCI_VENDOR_ID_OFFSET 0x00
+#define PCI_DEVICE_ID_OFFSET 0x02
+#define PCI_COMMAND_OFFSET 0x04
+#define PCI_PRIMARY_STATUS_OFFSET 0x06
+#define PCI_REVISION_ID_OFFSET 0x08
+#define PCI_CLASSCODE_OFFSET 0x09
+#define PCI_CACHELINE_SIZE_OFFSET 0x0C
+#define PCI_LATENCY_TIMER_OFFSET 0x0D
+#define PCI_HEADER_TYPE_OFFSET 0x0E
+#define PCI_BIST_OFFSET 0x0F
+#define PCI_BASE_ADDRESSREG_OFFSET 0x10
+#define PCI_CARDBUS_CIS_OFFSET 0x28
+#define PCI_SVID_OFFSET 0x2C // SubSystem Vendor id
+#define PCI_SUBSYSTEM_VENDOR_ID_OFFSET 0x2C
+#define PCI_SID_OFFSET 0x2E // SubSystem ID
+#define PCI_SUBSYSTEM_ID_OFFSET 0x2E
+#define PCI_EXPANSION_ROM_BASE 0x30
+#define PCI_CAPBILITY_POINTER_OFFSET 0x34
+#define PCI_INT_LINE_OFFSET 0x3C // Interrupt Line Register
+#define PCI_INT_PIN_OFFSET 0x3D // Interrupt Pin Register
+#define PCI_MAXGNT_OFFSET 0x3E // Max Grant Register
+#define PCI_MAXLAT_OFFSET 0x3F // Max Latency Register
+
+#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET 0x3E
+#define PCI_BRIDGE_STATUS_REGISTER_OFFSET 0x1E
+
+#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET 0x18
+#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET 0x19
+#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET 0x1a
+
+typedef struct {
+ UINT32 Reg : 8;
+ UINT32 Func : 3;
+ UINT32 Dev : 5;
+ UINT32 Bus : 8;
+ UINT32 Reserved : 7;
+ UINT32 Enable : 1;
+} PCI_CONFIG_ACCESS_CF8;
+
+#pragma pack()
+
+#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55
+#define PCI_DATA_STRUCTURE_SIGNATURE EFI_SIGNATURE_32 ('P', 'C', 'I', 'R')
+#define PCI_CODE_TYPE_PCAT_IMAGE 0x00
+#define PCI_CODE_TYPE_EFI_IMAGE 0x03
+#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED 0x0001
+
+#define EFI_PCI_COMMAND_IO_SPACE 0x0001
+#define EFI_PCI_COMMAND_MEMORY_SPACE 0x0002
+#define EFI_PCI_COMMAND_BUS_MASTER 0x0004
+#define EFI_PCI_COMMAND_SPECIAL_CYCLE 0x0008
+#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE 0x0010
+#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP 0x0020
+#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND 0x0040
+#define EFI_PCI_COMMAND_STEPPING_CONTROL 0x0080
+#define EFI_PCI_COMMAND_SERR 0x0100
+#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK 0x0200
+
+#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE 0x0001
+#define EFI_PCI_BRIDGE_CONTROL_SERR 0x0002
+#define EFI_PCI_BRIDGE_CONTROL_ISA 0x0004
+#define EFI_PCI_BRIDGE_CONTROL_VGA 0x0008
+#define EFI_PCI_BRIDGE_CONTROL_VGA_16 0x0010
+#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT 0x0020
+#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS 0x0040
+#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK 0x0080
+#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER 0x0100
+#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER 0x0200
+#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS 0x0400
+#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR 0x0800
+
+//
+// Following are the PCI-CARDBUS bridge control bit
+//
+#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE 0x0080
+#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE 0x0100
+#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE 0x0200
+#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE 0x0400
+
+//
+// Following are the PCI status control bit
+//
+#define EFI_PCI_STATUS_CAPABILITY 0x0010
+#define EFI_PCI_STATUS_66MZ_CAPABLE 0x0020
+#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE 0x0080
+#define EFI_PCI_MASTER_DATA_PARITY_ERROR 0x0100
+
+#define EFI_PCI_CAPABILITY_PTR 0x34
+#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Signature; // 0xaa55
+ UINT8 Reserved[0x16];
+ UINT16 PcirOffset;
+} PCI_EXPANSION_ROM_HEADER;
+
+typedef struct {
+ UINT16 Signature; // 0xaa55
+ UINT8 Size512;
+ UINT8 InitEntryPoint[3];
+ UINT8 Reserved[0x12];
+ UINT16 PcirOffset;
+} EFI_LEGACY_EXPANSION_ROM_HEADER;
+
+typedef struct {
+ UINT32 Signature; // "PCIR"
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 Reserved0;
+ UINT16 Length;
+ UINT8 Revision;
+ UINT8 ClassCode[3];
+ UINT16 ImageLength;
+ UINT16 CodeRevision;
+ UINT8 CodeType;
+ UINT8 Indicator;
+ UINT16 Reserved1;
+} PCI_DATA_STRUCTURE;
+
+//
+// PCI Capability List IDs and records
+//
+#define EFI_PCI_CAPABILITY_ID_PMI 0x01
+#define EFI_PCI_CAPABILITY_ID_AGP 0x02
+#define EFI_PCI_CAPABILITY_ID_VPD 0x03
+#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04
+#define EFI_PCI_CAPABILITY_ID_MSI 0x05
+#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06
+#define EFI_PCI_CAPABILITY_ID_PCIX 0x07
+
+typedef struct {
+ UINT8 CapabilityID;
+ UINT8 NextItemPtr;
+} EFI_PCI_CAPABILITY_HDR;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_PMI
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 PMC;
+ UINT16 PMCSR;
+ UINT8 BridgeExtention;
+ UINT8 Data;
+} EFI_PCI_CAPABILITY_PMI;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_AGP
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT8 Rev;
+ UINT8 Reserved;
+ UINT32 Status;
+ UINT32 Command;
+} EFI_PCI_CAPABILITY_AGP;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_VPD
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 AddrReg;
+ UINT32 DataReg;
+} EFI_PCI_CAPABILITY_VPD;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_SLOTID
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT8 ExpnsSlotReg;
+ UINT8 ChassisNo;
+} EFI_PCI_CAPABILITY_SLOTID;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_MSI
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 MsgCtrlReg;
+ UINT32 MsgAddrReg;
+ UINT16 MsgDataReg;
+} EFI_PCI_CAPABILITY_MSI32;
+
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 MsgCtrlReg;
+ UINT32 MsgAddrRegLsdw;
+ UINT32 MsgAddrRegMsdw;
+ UINT16 MsgDataReg;
+} EFI_PCI_CAPABILITY_MSI64;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ //
+ // not finished - fields need to go here
+ //
+} EFI_PCI_CAPABILITY_HOTPLUG;
+
+//
+// Capability EFI_PCI_CAPABILITY_ID_PCIX
+//
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 CommandReg;
+ UINT32 StatusReg;
+} EFI_PCI_CAPABILITY_PCIX;
+
+typedef struct {
+ EFI_PCI_CAPABILITY_HDR Hdr;
+ UINT16 SecStatusReg;
+ UINT32 StatusReg;
+ UINT32 SplitTransCtrlRegUp;
+ UINT32 SplitTransCtrlRegDn;
+} EFI_PCI_CAPABILITY_PCIX_BRDG;
+
+#define DEVICE_ID_NOCARE 0xFFFF
+
+#define PCI_ACPI_UNUSED 0
+#define PCI_BAR_NOCHANGE 0
+#define PCI_BAR_OLD_ALIGN 0xFFFFFFFFFFFFFFFF
+#define PCI_BAR_EVEN_ALIGN 0xFFFFFFFFFFFFFFFE
+#define PCI_BAR_SQUAD_ALIGN 0xFFFFFFFFFFFFFFFD
+#define PCI_BAR_DQUAD_ALIGN 0xFFFFFFFFFFFFFFFC
+
+#define PCI_BAR_IDX0 0x00
+#define PCI_BAR_IDX1 0x01
+#define PCI_BAR_IDX2 0x02
+#define PCI_BAR_IDX3 0x03
+#define PCI_BAR_IDX4 0x04
+#define PCI_BAR_IDX5 0x05
+#define PCI_BAR_ALL 0xFF
+
+#pragma pack(pop)
+
+//
+// NOTE: The following header files are included here for
+// compatibility consideration.
+//
+//*** AMI PORTING BEGIN ***//
+//Include content
+//#include "pci23.h"
+#define PCI_EXP_MAX_CONFIG_OFFSET 0x1000
+#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10
+
+//#include "pci30.h"
+#define PCI_CLASS_MASS_STORAGE_SATADPA 0x06
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT32 Signature; // "PCIR"
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 DeviceListOffset;
+ UINT16 Length;
+ UINT8 Revision;
+ UINT8 ClassCode[3];
+ UINT16 ImageLength;
+ UINT16 CodeRevision;
+ UINT8 CodeType;
+ UINT8 Indicator;
+ UINT16 MaxRuntimeImageLength;
+ UINT16 ConfigUtilityCodeHeaderOffset;
+ UINT16 DMTFCLPEntryPointOffset;
+} PCI_3_0_DATA_STRUCTURE;
+
+#pragma pack(pop)
+
+//#include "EfiPci.h"
+#pragma pack(push, 1)
+
+typedef struct {
+ UINT8 Register;
+ UINT8 Function;
+ UINT8 Device;
+ UINT8 Bus;
+ UINT8 Reserved[4];
+} DEFIO_PCI_ADDR;
+
+#define EFI_ROOT_BRIDGE_LIST 'eprb'
+#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1
+
+typedef struct {
+ UINT16 Signature; // 0xaa55
+ UINT16 InitializationSize;
+ UINT32 EfiSignature; // 0x0EF1
+ UINT16 EfiSubsystem;
+ UINT16 EfiMachineType;
+ UINT16 CompressionType;
+ UINT8 Reserved[8];
+ UINT16 EfiImageHeaderOffset;
+ UINT16 PcirOffset;
+} EFI_PCI_EXPANSION_ROM_HEADER;
+
+typedef union {
+ UINT8 *Raw;
+ PCI_EXPANSION_ROM_HEADER *Generic;
+ EFI_PCI_EXPANSION_ROM_HEADER *Efi;
+ EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt;
+} EFI_PCI_ROM_HEADER;
+
+#pragma pack(pop)
+//*** AMI PORTING END *****//
+#endif
diff --git a/Core/EM/CSM/thunk/Snp16/snp16.cif b/Core/EM/CSM/thunk/Snp16/snp16.cif
new file mode 100644
index 0000000..632b1c5
--- /dev/null
+++ b/Core/EM/CSM/thunk/Snp16/snp16.cif
@@ -0,0 +1,8 @@
+<component>
+ name = "SNP16"
+ category = ModulePart
+ LocalRoot = "core\em\csm\thunk\Snp16"
+ RefName = "BIOSSNP16"
+[files]
+[parts]
+<endComponent>
diff --git a/Core/EM/CSM/thunk/thunk.cif b/Core/EM/CSM/thunk/thunk.cif
new file mode 100644
index 0000000..4e0af2e
--- /dev/null
+++ b/Core/EM/CSM/thunk/thunk.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "CSM Thunk"
+ category = ModulePart
+ LocalRoot = "core\em\csm\thunk"
+ RefName = "THUNK"
+[parts]
+"X86THUNK"
+"BIOSBLKIO"
+"BIOSSNP16"
+"CsmVideo"
+<endComponent>
diff --git a/Core/EM/CSM/thunk/x86/thunk.c b/Core/EM/CSM/thunk/x86/thunk.c
new file mode 100644
index 0000000..57233e4
--- /dev/null
+++ b/Core/EM/CSM/thunk/x86/thunk.c
@@ -0,0 +1,793 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/thunk.c 49 10/07/13 9:41a Olegi $
+//
+// $Revision: 49 $
+//
+// $Date: 10/07/13 9:41a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/thunk.c $
+//
+// 49 10/07/13 9:41a Olegi
+// Undone previous checkin related to EIP125856 as it is causing assert
+// during boot.
+//
+// 48 8/30/13 4:25a Srikantakumarp
+// [TAG] EIP125856
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Assert came in SetKbcPresenceInMiscInfo() when FarCall86()
+// function is called first time in POST.
+// [RootCause] BiosLessThan1MB value is used in
+// SetKbcPresenceInMiscInfo(); and this has been initialized only after
+// the function 0 csm16 call.
+// [Solution] Returned from SetKbcPresenceInMiscInfo() if
+// BiosLessThan1MB value is not initialized.
+// [Files] thunk.c
+//
+// 47 9/12/12 1:45a Srikantakumarp
+// [TAG] EIP99561
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] KbcEmulation enabled in Int86 call but NO_KBC_PRESENT_BIT
+// bit not set properly.
+// [RootCause] Incase of INT86 , it directly calls the interrupt service
+// routine and it might be that the NO_KBC_PRESENT_BIT is not set
+// according to the KbcEmulation enabled or disabled.
+// [Solution] The NO_KBC_PRESENT_BIT is set according to the
+// KbcEmulation enabled or disabled before the call to thunk in Int86
+// function in thunk.c.
+// [Files] thunk.c
+//
+// 46 3/02/12 3:24a Rameshr
+// [TAG] EIP81041
+// [Category] Improvement
+// [Description] Re-entrance support for Farcall86 and Int86 protocol
+// function
+// [Files] thunk.c
+//
+// 45 10/19/11 3:31p Olegi
+// [TAG] EIP72642, 72645, 72810
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Adaptec x805 SAS Option ROM code hangs
+// [RootCause] Adaptec ROM has a code that directly access KBC during
+// INT handler. We did not have KBC emulation enabled for Int86 function.
+// [Solution] Added enabling KBC emulation in Int86 function.
+// [Files] thunk.c
+//
+// 44 9/29/11 11:00a Olegi
+// [TAG] EIP70382
+// [Category] Improvement
+// [Description] Clear keyboard status in BDA after FarCall86 execution.
+// [Files] thunk.c
+//
+// 43 12/14/10 4:46p Olegi
+// [TAG] EIP50111
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] TPL asserts in some cases during LegacyBoot
+// [RootCause] TPL.C asserts during LocateHandleBuffer call executed
+// during LegacyBoot from FarCall86.
+// [Solution] removed a call GetPs2SimpleTextInProtocolInterface
+// execution during FarCall86. The existing handle of Ps2SimpleTextIn will
+// be used.
+// [Files] thunk.c
+//
+// 42 10/23/10 3:22p Olegi
+// Undone the changes related to moving TPL raising/lowering outside of
+// FarCall86. This made the IF to be active during thunk that caused
+// various problems.
+//
+// 41 8/17/10 2:26p Olegi
+// Reset PS/2 keyboard before legacy boot. EIP40711
+//
+// 40 7/25/10 2:43p Olegi
+// RaiseTPL/RestroreTPL are moved from FarCall86 to the ASM area.
+//
+// 39 7/19/10 4:44p Olegi
+//
+// 38 6/28/10 5:04p Olegi
+// EIP26277: Added a callback notification on
+// NonSmmEmul6064TrapProtocolGuid installation.
+//
+// 37 6/19/10 12:32p Olegi
+// Temporary undone the resolution for EIP26277 until the final resolution
+// is found. Current changes causes ASSERT due to LocateHandle is executed
+// on TPL_LEVEL_HIGH.
+//
+// 36 2/22/10 9:46a Olegi
+// Fixed the problem where some keys pressed on USB keyboard are lost
+// during the transition to OpROM. EIP26277
+//
+// 35 1/18/10 3:41a Rameshr
+// NumLock,Capslock,Scroll Lock LED's synced properly between EFI and
+// Legacy Mode.
+// EIP 27917
+//
+// 34 1/12/10 11:47a Olegi
+// Copyright message updated.
+//
+// 33 9/23/09 11:13a Olegi
+// Changed the global variable name according to the coding standard.
+//
+// 32 9/09/09 3:11p Davidd
+// Fixed hanging problem when USB is disabled by the newly added "USB
+// Support" setup question - EIP 25360
+//
+// 31 2/05/09 12:28p Olegi
+//
+// 30 2/04/09 5:30p Olegi
+// Several modifications in FarCall86:
+// - PIC SetMode is moved after raising TPL to highest level (cli)
+// - Set Pmode interrupt mask to FF before setting Rmode mask. That avoids
+// the problem where IVT is not yet set in real mode (before Func#0) and
+// some HW interrupt is pending.
+//
+// 29 11/13/08 10:00a Olegi
+// Reverse thunk implementation started.
+//
+// 28 11/07/08 4:04p Rameshraju
+// Removed unused code.
+//
+// 27 11/07/08 4:01p Rameshraju
+// BugFix- Sometime system hangs on S4 resume.
+// Fix Reason : If the Timer interrupt generates between CLI and Timer
+// Interrupt mask code, Next STI instruction try to services the Timer
+// interrupt.In this case before setting IVT system will hang
+// EIP:17401
+//
+// 26 6/12/08 8:14a Olegi
+// Modified FarCall86 to execute USB keyboard change mode code for CSM16
+// function #5 (EIP14051).
+//
+// 25 8/27/07 12:44p Olegi
+//
+// 23 6/28/07 4:14p Olegi
+//
+// 22 6/25/07 12:27p Olegi
+//
+// 21 6/18/07 5:54p Olegi
+//
+// 20 5/29/07 6:17p Olegi
+// Added UsbChangeEfiToLegacy call.
+//
+// 19 4/27/07 5:14p Olegi
+// CSM.CHM file preparation.
+//
+// 18 8/24/06 6:56p Felixp
+//
+// 17 8/24/06 6:55p Felixp
+// x64 support (warnings/errors fixed)
+//
+// 16 8/24/06 3:11p Felixp
+// Preliminary x64 support (work in progress)
+//
+// 15 7/28/06 4:45p Olegi
+//
+// 14 5/19/06 11:22p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 13 3/13/06 2:35p Felixp
+//
+// 12 10/13/05 6:19p Olegi
+// Added condition to a previous change.
+//
+// 11 10/11/05 4:20p Srinin
+// PS2 KBD reset function is called after CM16 function 2, 3 and 5 are
+// called.
+//
+// 10 8/25/05 10:28a Olegi
+// Previous changes undone - instead the vector base for the master 8259
+// is changed from 0x68 to 0x58; with this there is no need to preserve
+// and restore IVT.
+//
+// 8 3/04/05 1:47p Mandal
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Thunk.c
+//
+// Description: 32/64 bit to 16 bit code thunk implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Protocol\DevicePath.h>
+#include <Protocol\LegacyBios.h>
+#include <Protocol\Legacy8259.h>
+#include <Protocol\SimpleTextin.h>
+#include <protocol\FirmwareVolume.h >
+#include <Ffs.h>
+#include "csm.h"
+#include <AmiDxeLib.h>
+#include "token.h"
+#if defined(AMIUSB_SUPPORT)
+#include <protocol\amiusbcontroller.h>
+#endif
+#include <Protocol\SimpleTextInEx.h>
+#include <Protocol\AmiKeycode.h>
+
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Offset;
+ UINT16 Segment;
+} FAR_CALL_PTR_16;
+
+typedef struct {
+ UINT32 Stack;
+ UINT32 StackSize;
+} STACK;
+
+typedef struct {
+ FAR_CALL_PTR_16 FarCall;
+ EFI_IA32_REGISTER_SET Regs;
+ STACK Stack;
+ BOOLEAN isFarCall; //if false, then INT86.
+ UINT8 BiosInt;
+} THUNK_DATA;
+
+typedef struct _ACPI_PNPID {
+ UINT32 Signature :16;
+ UINT32 PnpID :16;
+} ACPI_PNPID;
+#pragma pack()
+
+
+#if defined(AMIUSB_SUPPORT)
+EFI_USB_PROTOCOL *gUsbProtocol = NULL;
+#endif
+AMI_EFIKEYCODE_PROTOCOL *pKeyCodeProtocol=NULL;
+
+EFI_SIMPLE_TEXT_INPUT_PROTOCOL *gPS2KBDInterface = NULL;
+EFI_GUID gCsmThunkGuid = {
+ 0xA08276EC,0xA0FE,0x4e06,0x86,0x70,0x38,0x53,0x36,0xC7,0xD0,0x93
+};
+
+EFI_LEGACY_8259_PROTOCOL *gLegacy8259;
+extern BIOS_INFO *CoreBiosInfo;
+
+UINTN gThunkAsmAddr;
+extern BOOLEAN gIsBootPrepared;
+BOOLEAN gInsideThunk = FALSE;
+
+EFI_STATUS GetPs2SimpleTextInProtocolInterface(
+ BIOS_INFO *This,
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL **PS2KBDInterface
+);
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: SetKbcPresenceInMiscInfo
+//
+// Description: Updates CSM16_NO_KBC_PRESENT_BIT of MiscInfoAddress accordingly
+// by checking if the KbcEmulation is Enabled or Disabled.
+//
+// Input:
+//
+// Output:
+// EFI_STATUS
+//
+// Referrals:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SetKbcPresenceInMiscInfo()
+{
+ EFI_TO_COMPATIBILITY16_INIT_TABLE *Csm16InitTable;
+ LEGACY16_TO_EFI_DATA_TABLE_STRUC *Csm16Data;
+ UINT8 KbcSupport,KbcCheck=0;
+ EFI_STATUS Status;
+
+ //
+ // Retrieving the Data at MiscInfoAddress
+ //
+ Csm16InitTable = &CoreBiosInfo->Thunk->Csm16InitTable;
+ Csm16Data = (LEGACY16_TO_EFI_DATA_TABLE_STRUC*)(UINTN)Csm16InitTable->BiosLessThan1MB;
+
+ KbcCheck = *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress;
+
+ //
+ // Setting/Resetting the CSM16_NO_KBC_PRESENT_BIT according to the KbcEmulation
+ //
+ KbcSupport = IoRead8(0x64);
+ if (KbcSupport != 0xff) {
+ KbcCheck &= ~(CSM16_NO_KBC_PRESENT_BIT);
+ }
+ else {
+ KbcCheck |= (CSM16_NO_KBC_PRESENT_BIT);
+ }
+ //
+ // Checking if the Data at MiscInfoAddress is already updated
+ //
+ if((*(UINT8*)(UINTN)Csm16Data->MiscInfoAddress) != KbcCheck){
+ //
+ // Checking if F0000 region is writable
+ //
+ *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress = KbcCheck;
+
+ if((*(UINT8*)(UINTN)Csm16Data->MiscInfoAddress) == KbcCheck){
+ return;
+ }
+ else{
+ //
+ // Unlocking the region 0xE0000 - 0xFFFFF
+ //
+ Status = CoreBiosInfo->iRegion->UnLock (CoreBiosInfo->iRegion,
+ 0xE0000,
+ 0x20000,
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Updating the Data at MiscInfoAddress
+ //
+ *(UINT8*)(UINTN)Csm16Data->MiscInfoAddress = KbcCheck;
+
+ //
+ // Locking the region 0xE0000 - 0xFFFFF
+ //
+ CoreBiosInfo->iRegion->Lock (CoreBiosInfo->iRegion,
+ 0xE0000,
+ 0x20000,
+ NULL);
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: Int86
+//
+// Description: Executes BIOS interrupt routine
+//
+// Input:
+// LegacyBios protocol instance pointer
+// BiosInt Interrupt number
+// Regs CPU register values to pass to the interrupt handler
+//
+// Output:
+// TRUE Interrupt was not executed
+// FALSE INT completed. Caller will see Regs for status
+//
+// Referrals: EFI_IA32_REGISTER_SET
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN Int86(
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,
+ IN UINT8 BiosInt,
+ IN OUT EFI_IA32_REGISTER_SET *Regs
+)
+{
+ EFI_TPL OldTpl;
+
+ THUNK_DATA *ThunkData = (THUNK_DATA*)(gThunkAsmAddr+6);
+ //
+ // To avoid reentrance in Int86
+ //
+ if(gInsideThunk){
+ return FALSE;
+ }
+ gInsideThunk = TRUE;
+ ThunkData->isFarCall = FALSE;
+ ThunkData->BiosInt = BiosInt;
+ ThunkData->Stack.StackSize = 0; //This is required
+
+
+ //Copy thunk registers.
+ ThunkData->Regs = *Regs;
+
+#if defined(AMIUSB_SUPPORT)
+{
+ EFI_STATUS Status;
+
+ if (gUsbProtocol == NULL) {
+ Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &gUsbProtocol);
+ if (EFI_ERROR(Status)) {
+ gUsbProtocol=NULL; // To be used later, after returning from INT
+ }
+ }
+ if (gUsbProtocol != NULL) {
+ gUsbProtocol->UsbChangeEfiToLegacy(1);
+ }
+}
+#endif
+
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ gLegacy8259->SetMode(gLegacy8259,Efi8259LegacyMode,NULL,NULL);
+
+ SetKbcPresenceInMiscInfo();
+
+ ((void(*)(UINTN))gThunkAsmAddr)(gThunkAsmAddr);
+
+#if defined(AMIUSB_SUPPORT)
+ if (gUsbProtocol) {
+ gUsbProtocol->UsbChangeEfiToLegacy(0);
+ }
+#endif
+
+ gLegacy8259->SetMode(gLegacy8259,Efi8259ProtectedMode,NULL,NULL);
+ pBS->RestoreTPL(OldTpl);
+
+ //Restore thunk registers.
+ *Regs = ThunkData->Regs;
+ gInsideThunk = FALSE;
+
+ return FALSE; // INT completed. Caller will see Regs for status.
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: FarCall86
+//
+// Description: Executes 16 bit code starting from a given address
+//
+// Input:
+// This LegacyBiosProtocol instance pointer
+// Segment, Offset Starting address of the 16 bit routine
+// Regs CPU register values to pass to the routine
+// Stack Stack pointer with the possible data to be passed to the routine
+// StackSize Size of the stack passed to the routine
+//
+// Output:
+// TRUE Call was not executed
+// FALSE Call completed. Caller will see Regs for status
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN FarCall86(
+ 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_TPL OldTpl;
+ UINT16 IrqMask, SaveIrqMask;
+ UINT16 ProtectedIrqMask, ProtectedSaveIrqMask;
+ THUNK_DATA *ThunkData = (THUNK_DATA*)(gThunkAsmAddr+6);
+ UINT16 FuncNumber;
+ BOOLEAN IsCsm16Call =
+ Segment == CoreBiosInfo->Csm16EntrySeg &&
+ CoreBiosInfo->Csm16EntryOfs == Offset;
+ BOOLEAN IsCsm16DispatchOpRom = IsCsm16Call &&
+ Regs->X.AX == Compatibility16DispatchOprom;
+
+ BOOLEAN IsCsm16LegacyBoot = IsCsm16Call &&
+ Regs->X.AX == Compatibility16Boot;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_KEY_TOGGLE_STATE KeyToggleState=0;
+ //
+ // To avoid reentrance in FarCall86
+ //
+ if(gInsideThunk){
+ return FALSE;
+ }
+
+ gInsideThunk = TRUE;
+
+ //
+ // Change USB operation mode indicator from EFI to Legacy
+ //
+#if defined(AMIUSB_SUPPORT)
+ if (IsCsm16LegacyBoot == FALSE) {
+ if (gUsbProtocol == NULL) {
+ Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &gUsbProtocol);
+ if (EFI_ERROR(Status)) {
+ gUsbProtocol=NULL; // To be used later, after FarCall execution
+ }
+ }
+ }
+ if (gUsbProtocol != NULL) {
+ gUsbProtocol->UsbChangeEfiToLegacy(1);
+ }
+#endif
+
+ ThunkData->isFarCall = TRUE;
+
+ //Copy address for thunk.
+ ThunkData->FarCall.Segment = Segment;
+ ThunkData->FarCall.Offset = Offset;
+
+ //Copy address for stack
+ if (Stack)
+ {
+ ThunkData->Stack.Stack = (UINT32)Stack;
+ ThunkData->Stack.StackSize = (UINT32)StackSize;
+ } else ThunkData->Stack.StackSize = 0;
+
+ //Copy thunk registers.
+ ThunkData->Regs = *Regs;
+
+ // Reset the PS/2 keyboard before legacy boot
+ if (IsCsm16LegacyBoot == TRUE) {
+ if (gPS2KBDInterface) gPS2KBDInterface->Reset(gPS2KBDInterface, FALSE);
+ }
+
+ FuncNumber = Regs->X.AX;
+
+ if (IsCsm16Call) {
+ if (FuncNumber != 05 && FuncNumber != 02 && FuncNumber != 03) {
+ gLegacy8259->GetMask(gLegacy8259, &SaveIrqMask, NULL, NULL, NULL); // Save current Mask
+
+ IrqMask = -1;
+ gLegacy8259->SetMask(gLegacy8259, &IrqMask, NULL, NULL, NULL); // Set new Mask
+ }
+ }
+
+ //
+ // Mask all HW interrupts for real mode for CSM16 function #0 (InitializeYourself).
+ // This is needed since IVT is not installed before executing function #0.
+ //
+ // TODO: Explore the possibility of IVT installation from CSM32; in this case the
+ // code that is updating and using ProtectedIrqMask can be removed.
+ //
+ if (IsCsm16Call && FuncNumber == 00 ) {
+ gLegacy8259->GetMask(gLegacy8259, NULL, NULL, &ProtectedSaveIrqMask, NULL); // Save current Mask
+ ProtectedIrqMask = -1;
+ gLegacy8259->SetMask(gLegacy8259, NULL , NULL, &ProtectedIrqMask, NULL); // Set new Mask
+ }
+
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ //
+ // The following call will change the PIC settings to real mode; this includes
+ // unmasking all real mode interrupts. Note, that at this point HW interrupts
+ // must be disabled. This is done by the previous RaiseTPL call.
+ //
+ gLegacy8259->SetMode(gLegacy8259,Efi8259LegacyMode,NULL,NULL);
+
+ ((void(*)(UINTN))gThunkAsmAddr)(gThunkAsmAddr);
+
+#if defined(AMIUSB_SUPPORT)
+ if (gUsbProtocol) {
+ gUsbProtocol->UsbChangeEfiToLegacy(0);
+ }
+#endif
+
+ if (IsCsm16Call && FuncNumber == 00 ) {
+ gLegacy8259->SetMask(gLegacy8259, NULL , NULL, &ProtectedSaveIrqMask, NULL); // Set new Mask
+ }
+
+ gLegacy8259->SetMode(gLegacy8259,Efi8259ProtectedMode,NULL,NULL);
+
+ //Restore thunk registers.
+ *Regs = ThunkData->Regs;
+ pBS->RestoreTPL(OldTpl);
+
+ //
+ // Change USB operation mode indicator back to EFI
+ //
+
+ if (!IsCsm16Call ||
+ (IsCsm16Call &&
+ (FuncNumber == 05 || FuncNumber == 02 || FuncNumber == 03))) {
+// Reset PS2 Mouse
+ if (!gPS2KBDInterface) {
+ GetPs2SimpleTextInProtocolInterface((BIOS_INFO *)This, &gPS2KBDInterface);
+ }
+
+ if (gPS2KBDInterface) gPS2KBDInterface->Reset(gPS2KBDInterface, FALSE);
+
+ }
+ else gLegacy8259->SetMask(gLegacy8259, &SaveIrqMask, NULL, NULL, NULL); // Restore mask
+
+ if(IsCsm16DispatchOpRom) {
+ if((pKeyCodeProtocol == NULL && IsCsm16LegacyBoot == FALSE)) {
+ pBS->HandleProtocol(pST->ConsoleInHandle, &gAmiEfiKeycodeProtocolGuid, (void*)&pKeyCodeProtocol);
+ }
+ if(pKeyCodeProtocol != NULL) {
+ UINT8 KeyState;
+ KeyState = *(UINT8*)(UINTN)0x417;
+ if(KeyState & 0x10) {
+ KeyToggleState |= SCROLL_LOCK_ACTIVE;
+ }
+ if(KeyState & 0x20) {
+ KeyToggleState |= NUM_LOCK_ACTIVE;
+ }
+ if(KeyState & 0x40) {
+ KeyToggleState |= CAPS_LOCK_ACTIVE;
+ }
+ KeyToggleState |= TOGGLE_STATE_VALID;
+ pKeyCodeProtocol->SetState((EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL*)pKeyCodeProtocol,&KeyToggleState);
+ }
+ }
+
+ *(UINT8*)(UINTN)0x417 &= 0x70; // Clear key modifiers status in BDA
+
+ gInsideThunk = FALSE;
+
+ return FALSE; // CALL completed. Caller will see Regs for status.
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: LoadRealModeFile
+//
+// Description: Code that loads 16-bit thunk code at a particular address
+//
+// Input:
+// 16-bit binary file GUID
+// Address to load the binary to
+//
+// Output:
+// Status of the load operation
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS LoadRealModeFile(EFI_GUID *Guid, VOID *Address)
+{
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ UINT32 Authentication;
+ VOID *BufferAddr=0;
+ UINTN BufferSize=0;
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN i;
+
+ Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiFirmwareVolumeProtocolGuid,NULL,&NumHandles,&HandleBuffer);
+ if (EFI_ERROR(Status)) return Status;
+
+ for (i = 0; i< NumHandles; ++i)
+ {
+ Status = pBS->HandleProtocol(HandleBuffer[i],&guidFV,&Fv);
+ if (EFI_ERROR(Status)) continue;
+
+ Status = Fv->ReadSection(Fv,
+ Guid,
+ EFI_SECTION_RAW,
+ 0,
+ &BufferAddr,
+ &BufferSize,
+ &Authentication);
+
+ if (Status == EFI_SUCCESS)
+ {
+ MemCpy(
+ Address,
+ (UINT8*)BufferAddr,
+ BufferSize
+ );
+ pBS->FreePool(BufferAddr);
+ break;
+ }
+ }
+
+ pBS->FreePool(HandleBuffer);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitializeThunk
+//
+// Description: 16-bit thunk initialization routine. It calls 16 bit code to
+// do the address fixups within 16-bit code.
+//
+// Input: The instance of BIOS_INFO pointer
+//
+// Output: Status of the initialization completion
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InitializeThunk(
+ BIOS_INFO* CoreBiosInfo
+)
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Thunkaddr = (EFI_PHYSICAL_ADDRESS)CoreBiosInfo->Thunk;
+ UINT16 ThunkFixupsOffset;
+
+ //Locate Legacy8259 Protocol
+ gLegacy8259 = CoreBiosInfo->i8259;
+
+ //Copy ThunkAsm to memory.
+ Status = LoadRealModeFile(&gCsmThunkGuid, (VOID*)Thunkaddr);
+ if (EFI_ERROR(Status)) return Status;
+
+ gThunkAsmAddr = (UINT32)Thunkaddr;
+
+ //Call fixups
+ ThunkFixupsOffset = *(UINT16*)(gThunkAsmAddr+2);
+ ((void(*)(UINTN))(gThunkAsmAddr+ThunkFixupsOffset))(gThunkAsmAddr);
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetPs2SimpleTextInProtocolInterface
+//
+// Description: This function returns the SimpleTextIn protocol interface
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GetPs2SimpleTextInProtocolInterface(
+ BIOS_INFO *This,
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL **PS2KBDInterface
+)
+{
+ EFI_STATUS Status;
+ UINTN i,cnt;
+ ACPI_HID_DEVICE_PATH *siodp;
+ ACPI_PNPID *pnpid;
+ EFI_HANDLE *hbuff = NULL;
+ EFI_DEVICE_PATH_PROTOCOL *dp;
+ BOOLEAN bIsConnected = FALSE;
+
+ Status = pBS->LocateHandleBuffer(ByProtocol,&gEfiSimpleTextInProtocolGuid, NULL, &cnt, &hbuff);
+
+ if (EFI_ERROR(Status)) return Status;
+
+ for(i=0; i<cnt; i++){
+ Status=pBS->HandleProtocol(hbuff[i],&gEfiDevicePathProtocolGuid,&dp);
+ if(EFI_ERROR(Status)) continue;
+
+ siodp=DPGetLastNode(dp);
+ if(siodp->Header.Type!=ACPI_DEVICE_PATH
+ || siodp->Header.SubType!=ACPI_DP
+ || NODE_LENGTH(&siodp->Header) != ACPI_DEVICE_PATH_LENGTH) continue;
+
+ pnpid=(ACPI_PNPID*)&siodp->HID;
+ if (pnpid->PnpID == 0x0303) {
+// Status = pBS->OpenProtocol (hbuff[i], &gEfiSimpleTextInProtocolGuid, &PS2KBDInterface, This->hBios, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ Status = pBS->HandleProtocol(hbuff[i],&gEfiSimpleTextInProtocolGuid, PS2KBDInterface);
+ break;
+ }
+ Status = EFI_NOT_FOUND;
+ }
+ pBS->FreePool(hbuff);
+ return Status;
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/CSM/thunk/x86/x86thunk.asm b/Core/EM/CSM/thunk/x86/x86thunk.asm
new file mode 100644
index 0000000..9a5a781
--- /dev/null
+++ b/Core/EM/CSM/thunk/x86/x86thunk.asm
@@ -0,0 +1,828 @@
+;**********************************************************************
+;**********************************************************************
+;** **
+;** (C)Copyright 1985-2012, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;**********************************************************************
+;**********************************************************************
+
+;**********************************************************************
+; $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/x86thunk.asm 37 10/07/13 9:01a Olegi $
+;
+; $Revision: 37 $
+;
+; $Date: 10/07/13 9:01a $
+;**********************************************************************
+; Revision History
+; ----------------
+; $Log: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/x86thunk.asm $
+;
+; 37 10/07/13 9:01a Olegi
+; EIP135289
+; Legacy2Efi changes - CR4 save/restore
+;
+; 36 12/14/12 6:19p Olegi
+; [TAG] EIP109554
+; [Category] Improvement
+; [Description] Aptio4: Update CSM thunk to use private GDT instead of
+; GDT on entry point
+; [Files] x86thunk.asm
+;
+; 35 7/23/12 12:59p Olegi
+; [TAG] EIP95386
+; [Category] Improvement
+; [Description] CR3 register save/restore
+;
+; 34 6/13/12 12:49p Olegi
+; [TAG] EIP92524
+; [Category] Improvement
+; [Description] IDT location is limited to 4GB in CSM thunk
+;
+; 33 12/05/11 5:53p Olegi
+; [TAG] EIP77045
+; [Category] Improvement
+; [Description] Changed the values to be loaded to the segment
+; registers from static number (8) to a dynamic number that represents a
+; valid descriptor.
+; [Files] x86thunk.asm
+;
+; 32 12/01/10 9:37a Olegi
+; FarCall86 is modified to return data in stack when expected.
+;
+; 31 11/15/10 6:21p Olegi
+; [TAG] EIP48242
+; [Category] Bug Fix
+; [Severity] Critical
+; [Symptom] thunk problems for IA32 projects
+; [RootCause] wrong paths in thunk code for IA32 projects
+; [Solution] fixed the thunk code
+; [Files] x86thunk.asm
+;
+; 30 9/15/10 1:40p Olegi
+; Reverse thunk stack usage modified: stack for the PM operations will be
+; allocated externally.
+;
+; 29 9/13/10 5:26p Vyacheslava
+; Added variable PmStackPtr to use a new stack space.
+;
+; 28 9/08/10 6:16p Vyacheslava
+; Bugfix in reverse thunk: there was wrong assumption about stack
+; re-assignment. When caller (OptionROM) reassignes stack, reverse thunk
+; was failing.
+;
+; 27 7/26/10 2:23p Vyacheslava
+;
+; 26 7/25/10 2:44p Olegi
+;
+; 25 7/25/10 1:07p Olegi
+; Bugfixes in the reverse thunk implementation.
+;
+; 24 7/24/10 12:38p Olegi
+;
+; 23 7/23/10 4:09p Olegi
+; Initial reverse thunk implementation.
+;
+; 22 7/19/10 4:44p Olegi
+;
+; 21 1/12/10 11:47a Olegi
+; Copyright message updated.
+;
+; 20 11/12/08 5:02p Olegi
+;
+; 19 5/11/07 11:12a Markw
+; Save ss and set it to a flat descriptor in 64-bit mode.
+;
+; 18 4/27/07 5:14p Olegi
+; CSM.CHM file preparation.
+;
+; 17 9/15/06 12:02p Markw
+; Disable PAE when thunking because windows expects PAE in CR4 to be
+; disabled after calling INT19h to boot.
+;
+; 16 8/24/06 3:11p Felixp
+; Preliminary x64 support (work in progress)
+;
+; 15 5/25/06 2:23p Olegi
+;
+; 14 3/03/06 11:09a Markw
+; Removed some duplicate code.
+;
+; 13 10/14/05 10:16a Markw
+; Removed previous changes.
+;
+; 11 8/02/05 4:24p Markw
+; Removed some db66 from sgdt and sidt. It was instructing the CPU to do
+; a 24-bit load. However, the CPU was loading 32-bit that was needed, so
+; it worked even though the spec described the operation differently.
+;
+; 10 5/12/05 12:57p Markw
+; Fixed lidt in portected mode. It was only loading 24 of 32 bits.
+;
+; 9 4/18/05 10:54a Markw
+; Remove pushing/popping ebx (entry point).
+; make segments equal segement instead of fixup.
+;
+; 8 3/04/05 1:48p Mandal
+;
+;**********************************************************************
+;<AMI_FHDR_START>
+;
+; Name: x86Thunk.asm
+;
+; Description: x86 CPU thunk functions
+;
+;<AMI_FHDR_END>
+;**********************************************************************
+
+.586P
+.model small
+
+;STACK_SIZE equ 8192
+STACK_TOP equ (4096 * 3)
+
+FAR_CALL_PTR_16 struct
+ ptr_offset dw ?
+ seg_offset dw ?
+FAR_CALL_PTR_16 ends
+
+REGISTERS struct
+ reg_eax dd ?
+ reg_ebx dd ?
+ reg_ecx dd ?
+ reg_edx dd ?
+ reg_esi dd ?
+ reg_edi dd ?
+ reg_eflags dd ?
+ reg_es dw ?
+ reg_cs dw ?
+ reg_ss dw ?
+ reg_ds dw ?
+ reg_fs dw ?
+ reg_gs dw ?
+ reg_ebp dd ?
+REGISTERS ends
+
+STACK_PARAM struct
+ StackPtr dd ?
+ StackSize dd ?
+STACK_PARAM ends
+
+THUNK_DATA struct
+ FarCallPtr16 FAR_CALL_PTR_16 <>
+ Regs REGISTERS <>
+ StackParm STACK_PARAM<>
+ isFarCall db 0
+ BiosInt db 0
+THUNK_DATA ends
+
+
+ASSUME ds:THUNK_SEG
+
+THUNK_SEG SEGMENT USE32 'CODE'
+
+THUNK proc
+ jmp over_data
+; The following data must be here. Don't move. These are used by the Thunk C driver.
+ dw LOWWORD offset Fixups
+ dw LOWWORD offset ReverseThunk
+ ThunkData THUNK_DATA <>
+over_data:
+ cli
+;--------------------------------------------------------------------------------
+; The following code switches from protected mode (from x64 if EFIx64 is defined,
+; otherwise from 32-bit protected mode) to 16-bit real mode.
+;--------------------------------------------------------------------------------
+; Calculate entry point and load EBX/RBX with it.
+
+ push ebx
+
+ call @f
+@@:
+ pop ebx
+ sub ebx, @b ; RBX/EBX - physical address of CSM16 entry point
+
+ mov DWORD PTR [RtReturnResult+ebx], eax
+
+ sidt fword ptr [IdtSave+ebx] ;Save IDT
+ sgdt fword ptr [GdtSave+ebx] ;Save GDT
+ lgdt fword ptr [GdtDescriptor+ebx]
+
+ mov eax, cr3 ;;Save CR3, CR4
+ mov [CR3Save+ebx], eax
+ mov eax, cr4
+ mov [CR4Save+ebx], eax
+
+ ;Save segement registers.
+ mov ax, ds
+ push eax ;64-bit doesn't support push ds, es, ss
+ mov ax, es
+ push eax
+ mov ax, ss
+ push eax
+ push fs
+ push gs
+ mov ax, cs ;This must be last for cs restore.
+ push eax
+
+ mov eax, DATA_SEL ;make sure segments are approriate for 32-bit mode.
+ mov ds, ax ; Load SS with the known descriptor value
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+
+ifdef EFIx64
+;---Jump from long mode to compatiblity mode---
+ ;jmp far ptr [ComModeAdr]
+ db 0ffh,2dh
+ dd ComModeAdr - $ - 4
+
+ComMode:
+;---Go to protected mode---
+ mov eax, cr0
+ btr eax, 31
+ mov cr0, eax ;Now in protected mode.
+ jmp $+2
+
+ mov ecx, 0c0000080h
+ rdmsr
+ btr eax, 8
+ wrmsr
+
+ mov eax, cr4
+ btr eax, 5
+ mov cr4, eax ;Turn off PAE bit. Windows expects when calling INT19h.
+endif
+
+ cmp BYTE PTR [IsReverseThunk+ebx], 1
+ je no_stack_to_copy
+
+ pushad
+ pushfd
+
+;--Save Data--
+ mov [StackSave+ebx], esp ;Save 32 bit stack address of this module.
+
+ ;---Copy Stack parameters of LegacyBiosFarCall---
+ mov ecx, [ThunkData.StackParm.StackSize+ebx]
+ or ecx, ecx
+ jz no_stack_to_copy
+
+ mov esi, [ThunkData.StackParm.StackPtr+ebx]
+ mov edi, ebx
+ add edi, STACK_TOP
+ sub edi, ecx
+ rep movsb
+no_stack_to_copy:
+;--Switch to real mode--
+ lidt fword ptr [LegacyLdtDescriptor+ebx]
+
+ mov ax, DATA_SEL_16
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+ ;jmp CODE_SEL_16:next
+ db 0eah
+ dd offset next
+ dw CODE_SEL_16
+next:
+ mov eax, cr0
+ and al, 0feh
+ mov cr0, eax
+
+ ;--ITP doesn't display disassebly correctly until jump to real mode.
+
+ ;jmp CS_SEGMENT:RealModeAddr
+ db 0eah
+ dw LOWWORD offset RealMode
+RealModeFixUp:
+ dw 0
+RealMode:
+ db 8ch, 0c8h ;mov ax, cs
+ db 8eh, 0d8h ;mov ds, ax
+ db 8eh, 0c0h ;mov es, ax
+ db 8eh, 0d0h ;mov ss, ax
+ db 8eh, 0e0h ;mov fs, ax
+ db 8eh, 0e8h ;mov gs, ax
+
+; sti
+;---------------Real mode operations-----------
+ db 2eh, 80h, 3eh
+ dw LOWWORD offset IsReverseThunk
+ db 1 ;cmp cs:IsReverseThunk, 1
+
+ jnz @f
+
+ db 2eh, 0c6h, 6
+ dw LOWWORD offset IsReverseThunk
+ db 0 ;mov cs:IsReverseThunk, 0
+
+ ; Restore the registers from RtRegs
+ push cs
+ pop ss
+
+ db 0bch ; mov sp, LOWWORD OFFSET RtRegs
+ dw LOWWORD OFFSET RtRegs
+
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ db 66h, 61h ; popad
+
+ ; Restore stack pointer and its contents
+
+ db 2eh, 8eh, 16h ;mov cs:RtStackSave+4, ss
+ dw LOWWORD offset RtStackSave+4
+
+ db 66h, 2eh, 8bh, 26h ;mov sp, cs:RtStackSave
+ dw LOWWORD offset RtStackSave
+
+ ; Restore flags
+ db 66h, 2eh, 0ffh, 36h ; push DWORD PTR cs:RtSavedFlags
+ dw LOWWORD OFFSET RtSavedFlags
+ db 66h, 9dh ; popfd
+
+ db 83h, 0c4h, 4 ; add sp, 4: prepare stack for a push
+
+ db 66h, 2eh, 0ffh, 36h ; push dword ptr cs:RtRetAddressSave
+ dw LOWWORD offset RtRetAddressSave
+
+ db 66h, 2eh, 0a1h ;mov eax, RtReturnResult
+ dw LOWWORD offset RtReturnResult
+
+ db 0cbh ;retf ; reverse thunk call returns control
+
+@@:
+ db 66h
+ mov esp, STACK_TOP ;This is the top stack for real mode.
+
+ db 2bh, 26h ;sub sp, word ptr ThunkData.StackParm.StackSize
+ dw LOWWORD offset ThunkData.StackParm.StackSize
+
+ ;---copy registers for FarCall and BIOS INT---
+
+ db 66h, 8bh, 1eh ;mov ebx, ThunkData.regs.reg_ebx
+ dw LOWWORD offset ThunkData.regs.reg_ebx
+ db 66h, 8bh, 0eh ;mov ecx, ThunkData.regs.reg_ecx
+ dw LOWWORD offset ThunkData.regs.reg_ecx
+ db 66h, 8bh, 16h ;mov edx, ThunkData.regs.reg_edx
+ dw LOWWORD offset ThunkData.regs.reg_edx
+ db 66h, 8bh, 36h ;mov esi, ThunkData.regs.reg_esi
+ dw LOWWORD offset ThunkData.regs.reg_esi
+ db 66h, 8bh, 3eh ;mov edi, ThunkData.regs.reg_edi
+ dw LOWWORD offset ThunkData.regs.reg_edi
+ db 66h, 8bh, 2eh ;mov ebp, ThunkData.regs.reg_ebp
+ dw LOWWORD offset ThunkData.regs.reg_ebp
+
+ db 0a1h ;mov ax, ThunkData.regs.reg_es
+ dw LOWWORD offset ThunkData.regs.reg_es
+
+ db 08eh, 0c0h ;mov es, ax
+
+ db 66h, 0a1h ;mov eax, ThunkData.regs.reg_eax
+ dw LOWWORD offset ThunkData.regs.reg_eax
+
+ ;Change ds last, since above operations depend on ds.
+ db 0ffh, 36h ;push ThunkData.regs.reg_ds
+ dw LOWWORD offset ThunkData.regs.reg_ds
+ pop ds
+
+ ;Don't load the flags! They aren't needed, and if they aren't
+ ;initialized properly, the system hangs.
+
+ ;--Call real mode function or interrupt--
+ sti
+
+ db 2eh, 80h, 3eh ;cmp cs:ThunkData.isFarCall, 0
+ dw LOWWORD offset ThunkData.isFarCall
+ db 0
+
+ jnz FarCall
+
+ db 66h
+ pushad
+
+ db 2eh, 0a0h ;mov al, cs:ThunkData.BiosInt
+ dw LOWWORD offset ThunkData.BiosInt
+
+ db 2eh, 0a2h ;mov cs:intxx, al ;Sets the intermediate value for intxx below.
+ dw LOWWORD offset intxx
+
+ db 66h
+ mov eax, 1
+ cpuid ;serializing instruction because of runtime code modification.
+
+ db 66h
+ popad
+
+ db 0cdh ;Execute int x
+intxx label byte
+ db 0
+
+ jmp @f
+FarCall:
+ ;call dword ptr cs:[ThunkData.FarCallPtr16]
+ db 02eh, 0ffh, 1eh ;Execute far call
+ dw LOWWORD offset ThunkData.FarCallPtr16
+@@:
+
+ cli
+ ;--Copy registers back for FarCall and BIOS INT---
+
+ db 66h, 2eh, 0a3h ;mov cs:ThunkData.regs.reg_eax, eax
+ dw LOWWORD offset ThunkData.regs.reg_eax
+
+ push ds
+
+ db 2eh, 08fh, 6 ;pop cs:ThunkData.regs.reg_ds
+ dw LOWWORD offset ThunkData.regs.reg_ds
+
+ db 8ch, 0c8h ;mov ax, cs
+ db 8eh, 0d8h ;mov ds, ax
+
+ db 66h, 89h, 1eh ;mov ThunkData.regs.reg_ebx, ebx
+ dw LOWWORD offset ThunkData.regs.reg_ebx
+
+ db 66h, 89h, 0eh ;mov ThunkData.regs.reg_ecx, ecx
+ dw LOWWORD offset ThunkData.regs.reg_ecx
+
+ db 66h, 89h, 16h ;mov ThunkData.regs.reg_edx, edx
+ dw LOWWORD offset ThunkData.regs.reg_edx
+
+ db 66h, 89h, 36h ;mov ThunkData.regs.reg_esi, esi
+ dw LOWWORD offset ThunkData.regs.reg_esi
+
+ db 66h, 89h, 3eh ;mov ThunkData.regs.reg_edi, edi
+ dw LOWWORD offset ThunkData.regs.reg_edi
+
+ db 66h, 89h, 2eh ;mov ThunkData.regs.reg_ebp, ebp
+ dw LOWWORD offset ThunkData.regs.reg_ebp
+
+ db 08ch ,0c0h ;mov ax, es
+
+ db 0a3h ;mov ThunkData.regs.reg_es, ax
+ dw LOWWORD offset ThunkData.regs.reg_es
+
+ db 09ch ;pushf
+ db 08fh, 6 ;pop ThunkData.regs.reg_eflags
+ dw LOWWORD offset ThunkData.regs.reg_eflags
+
+;--------------End Real Mode operations---------
+RealToPm:
+ db 66h
+ xor ebx, ebx
+ db 8ch, 0cbh ;mov bx, cs
+ db 66h
+ shl ebx, 4 ;ebx = entry point
+
+ ;--Switch to protected mode--
+; cli
+
+ ;Reload GDT in case it was changed.
+ ;lgdt fword ptr cs:[GdtDescriptor]
+ db 66h,02eh,0fh,1,16h
+ dw LOWWORD offset GdtDescriptor
+
+ mov eax, cr0
+ or al, 1 ;Set PE bit
+ mov cr0, eax ;Turn on Protected Mode
+
+ ;jmp CODE_SEL:P32MODE
+ db 66h, 0eah
+P32ModeFixUp:
+ dd offset P32Mode
+ dw CODE_SEL
+
+P32Mode::
+ mov ax, DATA_SEL
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+ cmp BYTE PTR [IsReverseThunk + ebx], 1
+ je CreateReverseThunkESP
+ mov esp, [StackSave + ebx] ;Get original stack back.
+ ;---Copy Stack parameters of LegacyBiosFarCall---;
+ mov ecx, [ThunkData.StackParm.StackSize+ebx]
+ or ecx, ecx
+ jz @F
+ mov edi, [ThunkData.StackParm.StackPtr+ebx]
+ mov esi, ebx
+ add esi, STACK_TOP
+ sub esi, ecx
+ rep movsb
+@@:
+ popfd
+ popad
+ jmp DonePreparingESP
+
+CreateReverseThunkESP: ; EBX = ThunkStart code segment << 4
+ mov [ThunkStart + ebx], ebx
+ mov esp, [PmStackPtr + ebx]
+
+ifdef EFIx64
+ sub esp, 20h ; allocate 20h bytes in stack (x64 calling convention)
+endif
+ mov [esp], ebx
+ifdef EFIx64
+ mov DWORD PTR [esp+4], 0
+endif
+ sub esp, 4
+ mov [esp], esi ; Function pointer (DWORD)
+ifdef EFIx64
+ mov DWORD PTR [esp], 0
+ sub esp, 4
+ mov [esp], esi ; Function pointer (QWORD)
+endif
+
+DonePreparingESP:
+ xor eax, eax ; short/quick way to set EAX = 0
+ lldt ax ; (source operand == 0) => LDTR is invalid
+
+ifdef EFIx64
+ mov eax, cr4
+ bts eax, 5
+ mov cr4, eax ;Enable PAE
+
+ mov ecx, 0c0000080h
+ rdmsr
+ bts eax, 8
+ wrmsr
+
+ mov eax, cr0
+ bts eax, 31
+ mov cr0, eax ;Now in compatibility mode.
+ jmp $+2
+
+ pushd CODE_SEL_64
+ call @f ;push rip/eip
+@@:
+ add dword ptr [esp], @f - $
+ retf
+@@:
+
+ ;--In long mode.
+endif
+
+ lgdt fword ptr [GdtSave + ebx] ;Restore GDT
+ lidt fword ptr [IdtSave+ebx] ;Restore IDT
+
+ ;restore original cs
+ ;rsp/esp = cs
+ call @f ;push rip/eip
+@@:
+ add dword ptr [esp], @f - $
+ifdef EFIx64
+ db 48h
+endif
+ retf ;pop cs and eip.
+@@:
+
+ pop gs
+ pop fs
+ pop eax
+ mov ss, ax
+ pop eax
+ mov es, ax
+ pop eax
+ mov ds, ax
+
+ifdef EFIx64
+ ;TODO: Double check Reverse Thunk code.
+ cmp BYTE PTR [IsReverseThunk+ebx], 1
+ jne @f
+; Reverse thunk - copy parameters to RCX, RDX, R8, R9
+ db 48h, 8bh, 4ch, 24h, 28h ; mov rcx, [rsp + 28h]
+ db 48h, 8bh, 54h, 24h, 30h ; mov rdx, [rsp + 30h]
+ db 67h, 4ch, 8bh, 44h, 24h, 38h ; mov r8d, [rsp + 38h]
+ db 67h, 4ch, 8bh, 4ch, 24h, 40h ; mov r9d, [rsp + 40h]
+
+ jmp RealToPm_Exit
+@@:
+endif
+
+ mov eax, cs:[CR3Save + ebx]
+ mov cr3, eax
+ mov eax, cs:[CR4Save + ebx]
+ mov cr4, eax
+ pop ebx
+RealToPm_Exit:
+ ret
+
+;-----------------------------------------------------------
+ReverseThunk:
+ ; Save flags
+ db 66h, 9ch ; pushfd
+ db 66h, 2eh, 8fh, 6 ; pop DWORD PTR cs:RtSavedFlags
+ dw LOWWORD OFFSET RtSavedFlags
+
+ cli
+
+ db 66h, 2eh, 89h, 26h ;mov cs:RtStackSave, esp
+ dw LOWWORD offset RtStackSave
+
+ db 2eh, 8ch, 16h ;mov cs:RtStackSave+4, ss
+ dw LOWWORD offset RtStackSave+4
+
+ ; Get the PM stack pointer from the stack
+ db 89h, 0e5h ; mov bp, sp
+ db 66h, 8bh, 46h, 4 ; mov eax, [bp+4]
+ db 66h, 2eh, 0a3h ; mov cs:PmStackPtr, eax
+ dw LOWWORD offset PmStackPtr
+
+ ; Get return address and store it in cs:RtRetAddressSave
+ db 66h, 8bh, 46h, 0 ; mov eax, [bp+0]
+ db 66h, 2eh, 0a3h ; mov cs:RtRetAddressSave, eax
+ dw LOWWORD offset RtRetAddressSave
+
+ ; Save the registers in RtRegs
+ push cs
+ pop ss
+
+ db 0bch ; mov sp, LOWWORD OFFSET RtRegs+28h
+ dw LOWWORD OFFSET RtRegs+28h
+
+ db 66h, 60h ; pushad
+ push ds
+ push es
+ push fs
+ push gs
+
+ ; Restore SS:ESP
+ db 66h, 2eh, 8bh, 26h ;mov esp, cs:RtStackSave
+ dw LOWWORD offset RtStackSave
+
+ db 2eh, 8eh, 16h ;mov ss, cs:RtStackSave+4
+ dw LOWWORD offset RtStackSave+4
+
+ db 2eh, 0c6h, 06h ;mov cs:[IsReverseThunk], 1
+ dw LOWWORD offset IsReverseThunk
+ db 1
+
+ db 0e9h
+ dw RealToPm - ($+2) ;jmp NEAR RealToPm
+
+;-----------------------------------------------------------
+ reg_gs dw ?
+ reg_fs dw ?
+ reg_es dw ?
+ reg_ds dw ?
+ reg_eflags dd ?
+
+Fixups:
+ifdef EFIx64
+ ;In 64 bit mode, but compiled under 32-bit mode.
+ push ebx ;(push rbx) cpuid changes ebx
+ mov edx, ecx
+ shr edx, 4 ;Get segment
+
+;--Fixups---
+ ;add ComModeFixup, ecx
+ db 01, 0dh
+ dd ComModeFixup - $ - 4
+ ;add P32ModeFixUp, ecx
+ db 01, 0dh
+ dd P32ModeFixUp - $ - 4
+ ;add GdtDescriptorFixUp, ecx
+ db 01, 0dh
+ dd GdtDescriptorFixUp - $ - 4
+; add CODE_SEL_BASE_FIXUP, ecx ;must use add because upper 8 bit shouldn't change. Only 20 bit number.
+ db 01, 0dh
+ dd CODE_SEL_BASE_FIXUP - $ - 4
+; mov word ptr RealModeFixUp, dx
+ db 66h, 89h, 15h
+ dd RealModeFixUp - $ - 4
+ mov eax, 1
+ cpuid ;serialization for fixups
+ pop ebx ;pop rbx
+else
+ push ebp
+ mov ebp, esp
+
+ push ebx
+ push edx
+
+ mov ebx, [ebp+8] ;Get base address of this module
+ mov edx, ebx
+ shr edx, 4 ;Get segment
+
+;--Fixups---
+ add [P32ModeFixUp+ebx], ebx
+ add [GdtDescriptorFixUp+ebx], ebx
+ add [CODE_SEL_BASE_FIXUP+ebx], ebx ;must use add because upper 8 bit shouldn't change. Only 20 bit number.
+ mov word ptr [RealModeFixUp+ebx], dx
+
+ mov eax, 1
+ cpuid ;serialization for fixups
+ mov ebx, [ebp + 8] ;restore ebx
+
+ pop edx
+ pop ebx
+ pop ebp
+endif
+ ret
+
+align 16
+GDT_BASE:
+NULL_SEL equ $-GDT_BASE ;NULL Selector 0
+ dq 0
+DATA_SEL equ $-GDT_BASE
+ dq 00cf93000000ffffh
+CODE_SEL equ $-GDT_BASE
+ dq 00cf9b000000ffffh
+CODE_SEL_64 equ $-GDT_BASE
+ dq 00af9b000000ffffh
+DATA_SEL_16 equ $-GDT_BASE
+ dq 008f93000000ffffh
+
+CODE_SEL_16 equ $-GDT_BASE
+ dw 0ffffh
+CODE_SEL_BASE_FIXUP: ;Only 20 bits max
+ dw 0
+ db 0
+
+ db 09ah
+ db 0
+ db 0
+
+GDT_SIZE equ $-GDT_BASE ;Size of Descriptor Table
+GdtDescriptor:
+ dw GDT_SIZE - 1 ; GDT limit
+GdtDescriptorFixUp:
+ dq OFFSET GDT_BASE ; GDT base
+
+ifdef EFIx64
+align 8
+ComModeFixup equ $
+ComModeAdr equ $
+ dd offset ComMode
+ dw CODE_SEL
+endif
+
+ public StackSave
+StackSave label dword
+ dd 0
+align 8
+ public CR3Save
+CR3Save label dword
+ dq 0
+align 8
+ public CR4Save
+CR4Save label dword
+ dq 0
+align 8
+ public GdtSave
+GdtSave label fword
+ dw 0
+ dq 0
+
+align 8
+ public IdtSave
+IdtSave label fword
+ dw 0
+ dq 0
+align 8
+ public LegacyLdtDescriptor
+LegacyLdtDescriptor label fword
+ dw 3ffh
+ dq 0
+
+;------Reverse thunk data------------
+IsReverseThunk db 0
+RtReturnResult dd 0
+RtSavedFlags dd 0
+RtStackSave db 6 dup (0) ; DW for SS, DD for ESP
+PmStackPtr dd 0
+RtRetAddressSave dd 0
+ThunkStart dd 0
+RtRegs REGISTERS <>
+
+THUNK endp
+THUNK_SEG ENDS
+end
+
+;**********************************************************************
+;**********************************************************************
+;** **
+;** (C)Copyright 1985-2012, American Megatrends, Inc. **
+;** **
+;** All Rights Reserved. **
+;** **
+;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+;** **
+;** Phone: (770)-246-8600 **
+;** **
+;**********************************************************************
+;**********************************************************************
diff --git a/Core/EM/CSM/thunk/x86/x86thunk.cif b/Core/EM/CSM/thunk/x86/x86thunk.cif
new file mode 100644
index 0000000..61600c3
--- /dev/null
+++ b/Core/EM/CSM/thunk/x86/x86thunk.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "x86Thunk"
+ category = ModulePart
+ LocalRoot = "core\em\csm\thunk\x86"
+ RefName = "x86THUNK"
+[files]
+"\thunk.c"
+"\x86thunk.asm"
+"\x86thunk.mak"
+<endComponent>
diff --git a/Core/EM/CSM/thunk/x86/x86thunk.mak b/Core/EM/CSM/thunk/x86/x86thunk.mak
new file mode 100644
index 0000000..724023f
--- /dev/null
+++ b/Core/EM/CSM/thunk/x86/x86thunk.mak
@@ -0,0 +1,67 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/CSM/Generic/Thunk/x86/x86thunk.mak 7 1/12/10 11:47a Olegi $
+#
+# $Revision: 7 $
+#
+# $Date: 1/12/10 11:47a $
+#**********************************************************************
+
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: x86Thunk.mak
+#
+# Description: This file has a set of rules to create a binary that will
+# be copied into lower memory that will give control to CSM16
+# code.
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+
+all: CREATE_THUNK_FFS
+
+CREATE_THUNK_FFS: $(BUILD_DIR)\x86Thunk.ffs
+
+$(BUILD_DIR)\x86Thunk.ffs : $(BUILD_DIR)\x86Thunk.bin
+ $(MAKE) /f Core\FFS.mak \
+ BUILD_DIR=$(BUILD_DIR) SOURCE_DIR=$(CSM_THUNKASM_DIR) \
+ GUID=A08276EC-A0FE-4e06-8670-385336C7D093 \
+ TYPE=EFI_FV_FILETYPE_FREEFORM \
+ BINFILE=$** FFSFILE=$@ COMPRESS=0 NAME=$(**B)
+
+$(BUILD_DIR)\x86Thunk.bin: $(X86THUNK_DIR)\x86Thunk.asm
+!IF "$(x64_BUILD)"=="1"
+ $(ASM) /c /nologo /DEFIx64 /Fo$(BUILD_DIR)\x86thunk.obj $(X86THUNK_DIR)\x86Thunk.asm
+!ELSE
+ $(ASM) /c /nologo /Fo$(BUILD_DIR)\x86thunk.obj $(X86THUNK_DIR)\x86Thunk.asm
+!ENDIF
+ $(ASMLINK) /MAP $(BUILD_DIR)\x86thunk.obj, $(BUILD_DIR)\x86thunk.exe, $(BUILD_DIR)\x86thunk.map,,,
+ exe2bin $(BUILD_DIR)\x86thunk.exe $(BUILD_DIR)\x86Thunk.bin
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************