diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/CSM/thunk/BlockIo | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/CSM/thunk/BlockIo')
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/CsmBlkIoComponentName.c | 260 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/CsmBlockIo.c | 1076 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/CsmBlockIo.h | 277 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/CsmBlockIo.sdl | 25 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/CsmEdd.h | 407 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/CsmInt13.c | 1525 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/biosblkio.dxs | 46 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/biosblkio.mak | 63 | ||||
-rw-r--r-- | Core/EM/CSM/thunk/BlockIo/int13thunk.cif | 15 |
9 files changed, 3694 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> |