diff options
Diffstat (limited to 'Core/EM/CSM/thunk')
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 ** +#** ** +#********************************************************************** +#********************************************************************** |