summaryrefslogtreecommitdiff
path: root/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe
diff options
context:
space:
mode:
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-06-27 23:32:56 +0000
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-06-27 23:32:56 +0000
commitbcecde140a561c64e297225904afebebd62336ce (patch)
tree5f6333ccb04d851d151970e5dee6c9d8ac7ade71 /IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe
parenta7a0f78bd6fa1fe4684bf6de2b3e5ed5d9b5bf1c (diff)
downloadedk2-platforms-bcecde140a561c64e297225904afebebd62336ce.tar.xz
IntelFrameworkModulePkg: Add Compatibility Support Module (CSM) drivers
Added these drivers: * LegacyBiosDxe * BlockIoDxe * KeyboardDxe * Snp16Dxe * VideoDxe Signed-off-by: jljusten Reviewed-by: mdkinney Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11905 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe')
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c782
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h439
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c1485
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf58
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c309
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h209
6 files changed, 3282 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c
new file mode 100644
index 0000000000..309cf1a9ed
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c
@@ -0,0 +1,782 @@
+/** @file
+ EFI glue for BIOS INT 13h block devices.
+
+ This file is coded to EDD 3.0 as defined by T13 D1386 Revision 4
+ Availible on http://www.t13.org/#Project drafts
+ Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r4.pdf
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosBlkIo.h"
+
+//
+// Global data declaration
+//
+//
+// EFI Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gBiosBlockIoDriverBinding = {
+ BiosBlockIoDriverBindingSupported,
+ BiosBlockIoDriverBindingStart,
+ BiosBlockIoDriverBindingStop,
+ 0x3,
+ NULL,
+ NULL
+};
+
+//
+// Semaphore to control access to global variables mActiveInstances and mBufferUnder1Mb
+//
+EFI_LOCK mGlobalDataLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_APPLICATION);
+
+//
+// Number of active instances of this protocol. This is used to allocate/free
+// the shared buffer. You must acquire the semaphore to modify.
+//
+UINTN mActiveInstances = 0;
+
+//
+// Pointer to the beginning of the buffer used for real mode thunk
+// You must acquire the semaphore to modify.
+//
+EFI_PHYSICAL_ADDRESS mBufferUnder1Mb = 0;
+
+//
+// Address packet is a buffer under 1 MB for all version EDD calls
+//
+EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb;
+
+//
+// This is a buffer for INT 13h func 48 information
+//
+BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb;
+
+//
+// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB
+// 0xFE00 bytes is the max transfer size supported.
+//
+VOID *mEdd11Buffer;
+
+EFI_GUID mUnknownDevGuid = UNKNOWN_DEVICE_GUID;
+
+/**
+ Driver entry point.
+
+ @param ImageHandle Handle of driver image.
+ @param SystemTable Pointer to system table.
+
+ @retval EFI_SUCCESS Entrypoint successfully executed.
+ @retval Others Fail to execute entrypoint.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install protocols
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gBiosBlockIoDriverBinding,
+ ImageHandle,
+ &gBiosBlockIoComponentName,
+ &gBiosBlockIoComponentName2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver
+ //
+ return gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiLegacyBiosGuid,
+ NULL,
+ NULL
+ );
+}
+
+/**
+ Check whether the driver supports this device.
+
+ @param This The Udriver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval other This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingSupported (
+ 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;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ PCI_TYPE00 Pci;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // See if this is a PCI VGA Controller by looking at the Command register and
+ // Class Code Register
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (Pci.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE ||
+ (Pci.Hdr.ClassCode[2] == PCI_BASE_CLASS_INTELLIGENT && Pci.Hdr.ClassCode[1] == PCI_SUB_CLASS_INTELLIGENT)
+ ) {
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+/**
+ Starts the device with this driver.
+
+ @param This The driver binding instance.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS The controller is controlled by the driver.
+ @retval Other This controller cannot be started.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingStart (
+ 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;
+ UINT8 DiskStart;
+ UINT8 DiskEnd;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate;
+ EFI_DEVICE_PATH_PROTOCOL *PciDevPath;
+ UINTN Index;
+ UINTN Flags;
+ UINTN TmpAddress;
+ BOOLEAN DeviceEnable;
+
+ //
+ // Initialize variables
+ //
+ PciIo = NULL;
+ PciDevPath = NULL;
+
+ DeviceEnable = FALSE;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Open the IO Abstraction(s) needed
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &PciDevPath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Enable the device and make sure VGA cycles are being forwarded to this VGA device
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ DeviceEnable = TRUE;
+
+ //
+ // Check to see if there is a legacy option ROM image associated with this PCI device
+ //
+ Status = LegacyBios->CheckPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ NULL,
+ &Flags
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Post the legacy option ROM if it is available.
+ //
+ Status = LegacyBios->InstallPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ &Flags,
+ &DiskStart,
+ &DiskEnd,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // All instances share a buffer under 1MB to put real mode thunk code in
+ // If it has not been allocated, then we allocate it.
+ //
+ if (mBufferUnder1Mb == 0) {
+ //
+ // Should only be here if there are no active instances
+ //
+ ASSERT (mActiveInstances == 0);
+
+ //
+ // Acquire the lock
+ //
+ EfiAcquireLock (&mGlobalDataLock);
+
+ //
+ // Allocate below 1MB
+ //
+ mBufferUnder1Mb = 0x00000000000FFFFF;
+ Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb);
+
+ //
+ // Release the lock
+ //
+ EfiReleaseLock (&mGlobalDataLock);
+
+ //
+ // Check memory allocation success
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // In checked builds we want to assert if the allocate failed.
+ //
+ ASSERT_EFI_ERROR (Status);
+ Status = EFI_OUT_OF_RESOURCES;
+ mBufferUnder1Mb = 0;
+ goto Error;
+ }
+
+ TmpAddress = (UINTN) mBufferUnder1Mb;
+ //
+ // Adjusting the value to be on proper boundary
+ //
+ mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress);
+
+ TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER;
+ //
+ // Adjusting the value to be on proper boundary
+ //
+ mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress);
+
+ TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE);
+ //
+ // Adjusting the value to be on proper boundary
+ //
+ mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress);
+ }
+ //
+ // Allocate the private device structure for each disk
+ //
+ for (Index = DiskStart; Index < DiskEnd; Index++) {
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (BIOS_BLOCK_IO_DEV),
+ (VOID **) &BiosBlockIoPrivate
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Zero the private device structure
+ //
+ ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV));
+
+ //
+ // Initialize the private device structure
+ //
+ BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE;
+ BiosBlockIoPrivate->ControllerHandle = Controller;
+ BiosBlockIoPrivate->LegacyBios = LegacyBios;
+ BiosBlockIoPrivate->PciIo = PciIo;
+
+ BiosBlockIoPrivate->Bios.Floppy = FALSE;
+ BiosBlockIoPrivate->Bios.Number = (UINT8) Index;
+ BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C');
+ BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE;
+
+ if (BiosInitBlockIo (BiosBlockIoPrivate)) {
+ SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath);
+
+ //
+ // Install the Block Io Protocol onto a new child handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &BiosBlockIoPrivate->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &BiosBlockIoPrivate->BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ BiosBlockIoPrivate->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (BiosBlockIoPrivate);
+ }
+ //
+ // Open For Child Device
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &BiosBlockIoPrivate->PciIo,
+ This->DriverBindingHandle,
+ BiosBlockIoPrivate->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ } else {
+ gBS->FreePool (BiosBlockIoPrivate);
+ }
+ }
+
+Error:
+ if (EFI_ERROR (Status)) {
+ if (PciIo != NULL) {
+ if (DeviceEnable) {
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (PciDevPath != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ if (mBufferUnder1Mb != 0 && mActiveInstances == 0) {
+ gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE);
+
+ //
+ // Clear the buffer back to 0
+ //
+ EfiAcquireLock (&mGlobalDataLock);
+ mBufferUnder1Mb = 0;
+ EfiReleaseLock (&mGlobalDataLock);
+ }
+ }
+ } else {
+ //
+ // Successfully installed, so increment the number of active instances
+ //
+ EfiAcquireLock (&mGlobalDataLock);
+ mActiveInstances++;
+ EfiReleaseLock (&mGlobalDataLock);
+ }
+
+ return Status;
+}
+
+/**
+ Stop the device handled by this driver.
+
+ @param This The driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval Others Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingStop (
+ 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;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate;
+ UINTN Index;
+
+ //
+ // Decrement the number of active instances
+ //
+ if (mActiveInstances != 0) {
+ //
+ // Add a check since the stop function will be called 2 times for each handle
+ //
+ EfiAcquireLock (&mGlobalDataLock);
+ mActiveInstances--;
+ EfiReleaseLock (&mGlobalDataLock);
+ }
+
+ if ((mActiveInstances == 0) && (mBufferUnder1Mb != 0)) {
+ //
+ // Free our global buffer
+ //
+ Status = gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE);
+ ASSERT_EFI_ERROR (Status);
+
+ EfiAcquireLock (&mGlobalDataLock);
+ mBufferUnder1Mb = 0;
+ EfiReleaseLock (&mGlobalDataLock);
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BiosBlockIoPrivate = BIOS_BLOCK_IO_FROM_THIS (BlockIo);
+
+ //
+ // Release PCI I/O and Block IO Protocols on the clild handle.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ &BiosBlockIoPrivate->BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ BiosBlockIoPrivate->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ //
+ // Shutdown the hardware
+ //
+ BiosBlockIoPrivate->PciIo->Attributes (
+ BiosBlockIoPrivate->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ gBS->FreePool (BiosBlockIoPrivate);
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Build device path for device.
+
+ @param BaseDevicePath Base device path.
+ @param Drive Legacy drive.
+ @param DevicePath Device path for output.
+
+**/
+VOID
+SetBiosInitBlockIoDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN BIOS_LEGACY_DRIVE *Drive,
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ EFI_STATUS Status;
+ UNKNOWN_DEVICE_VENDOR_DEVICE_PATH VendorNode;
+
+ Status = EFI_UNSUPPORTED;
+
+ //
+ // BugBug: Check for memory leaks!
+ //
+ if (Drive->EddVersion == EDD_VERSION_30) {
+ //
+ // EDD 3.0 case.
+ //
+ Status = BuildEdd30DevicePath (BaseDevicePath, Drive, DevicePath);
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // EDD 1.1 device case or it is unrecognized EDD 3.0 device
+ //
+ ZeroMem (&VendorNode, sizeof (VendorNode));
+ VendorNode.DevicePath.Header.Type = HARDWARE_DEVICE_PATH;
+ VendorNode.DevicePath.Header.SubType = HW_VENDOR_DP;
+ SetDevicePathNodeLength (&VendorNode.DevicePath.Header, sizeof (VendorNode));
+ CopyMem (&VendorNode.DevicePath.Guid, &mUnknownDevGuid, sizeof (EFI_GUID));
+ VendorNode.LegacyDriveLetter = Drive->Number;
+ *DevicePath = AppendDevicePathNode (BaseDevicePath, &VendorNode.DevicePath.Header);
+ }
+}
+
+/**
+ Build device path for EDD 3.0.
+
+ @param BaseDevicePath Base device path.
+ @param Drive Legacy drive.
+ @param DevicePath Device path for output.
+
+ @retval EFI_SUCCESS The device path is built successfully.
+ @retval EFI_UNSUPPORTED It is failed to built device path.
+
+**/
+EFI_STATUS
+BuildEdd30DevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN BIOS_LEGACY_DRIVE *Drive,
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ //
+ // AVL UINT64 Address;
+ // AVL EFI_HANDLE Handle;
+ //
+ EFI_DEV_PATH Node;
+ UINT32 Controller;
+
+ Controller = (UINT32) Drive->Parameters.InterfacePath.Pci.Controller;
+
+ ZeroMem (&Node, sizeof (Node));
+ if ((AsciiStrnCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) ||
+ (AsciiStrnCmp ("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;
+ SetDevicePathNodeLength (&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) {
+ ZeroMem (&Node, sizeof (Node));
+ Node.Controller.Header.Type = HARDWARE_DEVICE_PATH;
+ Node.Controller.Header.SubType = HW_CONTROLLER_DP;
+ SetDevicePathNodeLength (&Node.Controller.Header, sizeof (CONTROLLER_DEVICE_PATH));
+ Node.Controller.ControllerNumber = Controller;
+ *DevicePath = AppendDevicePathNode (*DevicePath, &Node.DevPath);
+ }
+
+ ZeroMem (&Node, sizeof (Node));
+
+ if (AsciiStrnCmp ("SCSI", Drive->Parameters.InterfaceType, 4) == 0) {
+ //
+ // SCSI drive
+ //
+ Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.Scsi.Header.SubType = MSG_SCSI_DP;
+ SetDevicePathNodeLength (&Node.Scsi.Header, sizeof (SCSI_DEVICE_PATH));
+
+ //
+ // Lun is miss aligned in both EDD and Device Path data structures.
+ // thus we do a byte copy, to prevent alignment traps on IA-64.
+ //
+ CopyMem (&Node.Scsi.Lun, &Drive->Parameters.DevicePath.Scsi.Lun, sizeof (UINT16));
+ Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.Pun;
+
+ } else if (AsciiStrnCmp ("USB", Drive->Parameters.InterfaceType, 3) == 0) {
+ //
+ // USB drive
+ //
+ Node.Usb.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.Usb.Header.SubType = MSG_USB_DP;
+ SetDevicePathNodeLength (&Node.Usb.Header, sizeof (USB_DEVICE_PATH));
+ Node.Usb.ParentPortNumber = (UINT8) Drive->Parameters.DevicePath.Usb.Reserved;
+
+ } else if (AsciiStrnCmp ("1394", Drive->Parameters.InterfaceType, 4) == 0) {
+ //
+ // 1394 drive
+ //
+ Node.F1394.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.F1394.Header.SubType = MSG_1394_DP;
+ SetDevicePathNodeLength (&Node.F1394.Header, sizeof (F1394_DEVICE_PATH));
+ Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid;
+
+ } else if (AsciiStrnCmp ("FIBRE", Drive->Parameters.InterfaceType, 5) == 0) {
+ //
+ // Fibre drive
+ //
+ Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP;
+ SetDevicePathNodeLength (&Node.FibreChannel.Header, sizeof (FIBRECHANNEL_DEVICE_PATH));
+ Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn;
+ Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun;
+
+ } else {
+ DEBUG (
+ (
+ DEBUG_BLKIO, "It is unrecognized EDD 3.0 device, Drive Number = %x, InterfaceType = %s\n",
+ Drive->Number,
+ Drive->Parameters.InterfaceType
+ )
+ );
+ }
+ }
+
+ if (Node.DevPath.Type == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *DevicePath = AppendDevicePathNode (BaseDevicePath, &Node.DevPath);
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h
new file mode 100644
index 0000000000..de3c8d3518
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h
@@ -0,0 +1,439 @@
+/** @file
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BIOS_BLOCK_IO_H_
+#define _BIOS_BLOCK_IO_H_
+
+#include <Uefi.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/DevicePath.h>
+#include <Guid/LegacyBios.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include "Edd.h"
+
+#define UNKNOWN_DEVICE_GUID \
+ { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} }
+
+typedef struct {
+ VENDOR_DEVICE_PATH DevicePath;
+ UINT8 LegacyDriveLetter;
+} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH;
+
+//
+// Global Variables
+//
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2;
+
+
+//
+// Define the I2O class code
+//
+#define PCI_BASE_CLASS_INTELLIGENT 0x0e
+#define PCI_SUB_CLASS_INTELLIGENT 0x00
+
+//
+// Number of pages needed for our buffer under 1MB
+//
+#define BLOCK_IO_BUFFER_PAGE_SIZE (((sizeof (EDD_DEVICE_ADDRESS_PACKET) + sizeof (BIOS_LEGACY_DRIVE) + MAX_EDD11_XFER) / EFI_PAGE_SIZE) + 1 \
+ )
+
+//
+// Driver Binding Protocol functions
+//
+
+/**
+ Check whether the driver supports this device.
+
+ @param This The Udriver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval other This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+
+/**
+ Starts the device with this driver.
+
+ @param This The driver binding instance.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS The controller is controlled by the driver.
+ @retval Other This controller cannot be started.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop the device handled by this driver.
+
+ @param This The driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval Others Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Other internal functions
+//
+
+/**
+ Build device path for EDD 3.0.
+
+ @param BaseDevicePath Base device path.
+ @param Drive Legacy drive.
+ @param DevicePath Device path for output.
+
+ @retval EFI_SUCCESS The device path is built successfully.
+ @retval EFI_UNSUPPORTED It is failed to built device path.
+
+**/
+EFI_STATUS
+BuildEdd30DevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN BIOS_LEGACY_DRIVE *Drive,
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+/**
+ Initialize block I/O device instance
+
+ @param Dev Instance of block I/O device instance
+
+ @retval TRUE Initialization succeeds.
+ @retval FALSE Initialization fails.
+
+**/
+BOOLEAN
+BiosInitBlockIo (
+ IN BIOS_BLOCK_IO_DEV *Dev
+ );
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd30BiosReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd30BiosWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Flush the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+/**
+ Reset the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd11BiosReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd11BiosWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosReadLegacyDrive (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosWriteLegacyDrive (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Gets parameters of block I/O device.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of device parameter retrieval.
+
+**/
+UINTN
+Int13GetDeviceParameters (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ );
+
+/**
+ Extension of INT13 call.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of this extension.
+
+**/
+UINTN
+Int13Extensions (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ );
+
+/**
+ Gets parameters of legacy drive.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of drive parameter retrieval.
+
+**/
+UINTN
+GetDriveParameters (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ );
+
+/**
+ Build device path for device.
+
+ @param BaseDevicePath Base device path.
+ @param Drive Legacy drive.
+ @param DevicePath Device path for output.
+
+**/
+VOID
+SetBiosInitBlockIoDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN BIOS_LEGACY_DRIVE *Drive,
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c
new file mode 100644
index 0000000000..c53490b0e3
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c
@@ -0,0 +1,1485 @@
+/** @file
+ Routines that use BIOS to support INT 13 devices.
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosBlkIo.h"
+
+//
+// Module global variables
+//
+//
+// Address packet is a buffer under 1 MB for all version EDD calls
+//
+extern EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb;
+
+//
+// This is a buffer for INT 13h func 48 information
+//
+extern BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb;
+
+//
+// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB
+// 0xFE00 bytes is the max transfer size supported.
+//
+extern VOID *mEdd11Buffer;
+
+
+/**
+ Initialize block I/O device instance
+
+ @param Dev Instance of block I/O device instance
+
+ @retval TRUE Initialization succeeds.
+ @retval FALSE Initialization fails.
+
+**/
+BOOLEAN
+BiosInitBlockIo (
+ IN BIOS_BLOCK_IO_DEV *Dev
+ )
+{
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_BLOCK_IO_MEDIA *BlockMedia;
+ BIOS_LEGACY_DRIVE *Bios;
+
+ BlockIo = &Dev->BlockIo;
+ BlockIo->Media = &Dev->BlockMedia;
+ BlockMedia = BlockIo->Media;
+ Bios = &Dev->Bios;
+
+ if (Int13GetDeviceParameters (Dev, Bios) != 0) {
+ if (Int13Extensions (Dev, Bios) != 0) {
+ BlockMedia->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ BlockMedia->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+
+ if ((Bios->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) {
+ BlockMedia->RemovableMedia = TRUE;
+ }
+
+ } else {
+ //
+ // Legacy Interfaces
+ //
+ BlockMedia->BlockSize = 512;
+ BlockMedia->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
+ }
+
+ DEBUG ((DEBUG_INIT, "BlockSize = %d LastBlock = %d\n", BlockMedia->BlockSize, BlockMedia->LastBlock));
+
+ BlockMedia->LogicalPartition = FALSE;
+ BlockMedia->WriteCaching = FALSE;
+
+ //
+ // BugBug: Need to set this for removable media devices if they do not
+ // have media present
+ //
+ BlockMedia->ReadOnly = FALSE;
+ BlockMedia->MediaPresent = TRUE;
+
+ BlockIo->Reset = BiosBlockIoReset;
+ BlockIo->FlushBlocks = BiosBlockIoFlushBlocks;
+
+ if (!Bios->ExtendedInt13) {
+ //
+ // Legacy interfaces
+ //
+ BlockIo->ReadBlocks = BiosReadLegacyDrive;
+ BlockIo->WriteBlocks = BiosWriteLegacyDrive;
+ } else if ((Bios->EddVersion == EDD_VERSION_30) && (Bios->Extensions64Bit)) {
+ //
+ // EDD 3.0 Required for Device path, but extended reads are not required.
+ //
+ BlockIo->ReadBlocks = Edd30BiosReadBlocks;
+ BlockIo->WriteBlocks = Edd30BiosWriteBlocks;
+ } else {
+ //
+ // Assume EDD 1.1 - Read and Write functions.
+ // This could be EDD 3.0 without Extensions64Bit being set.
+ // If it's EDD 1.1 this will work, but the device path will not
+ // be correct. This will cause confusion to EFI OS installation.
+ //
+ BlockIo->ReadBlocks = Edd11BiosReadBlocks;
+ BlockIo->WriteBlocks = Edd11BiosWriteBlocks;
+ }
+
+ BlockMedia->LogicalPartition = FALSE;
+ BlockMedia->WriteCaching = FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Gets parameters of block I/O device.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of device parameter retrieval.
+
+**/
+UINTN
+Int13GetDeviceParameters (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ )
+{
+ UINTN CarryFlag;
+ UINT16 Cylinder;
+ EFI_IA32_REGISTER_SET Regs;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Regs.H.AH = 0x08;
+ Regs.H.DL = Drive->Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG ((DEBUG_INIT, "Int13GetDeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH));
+ if (CarryFlag != 0 || 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) {
+ //
+ // BugBug: You can not trust the Carry flag.
+ //
+ return FALSE;
+ }
+ }
+ } else {
+ Drive->MaxHead = (UINT8) (Regs.H.DH & 0x3f);
+ Cylinder = (UINT16) (((UINT16) Regs.H.DH & 0xc0) << 4);
+ Cylinder = (UINT16) (Cylinder | ((UINT16) Regs.H.CL & 0xc0) << 2);
+ Drive->MaxCylinder = (UINT16) (Cylinder + Regs.H.CH);
+ Drive->MaxSector = (UINT8) (Regs.H.CL & 0x3f);
+ }
+
+ return TRUE;
+}
+
+/**
+ Extension of INT13 call.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of this extension.
+
+**/
+UINTN
+Int13Extensions (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ )
+{
+ INTN CarryFlag;
+ EFI_IA32_REGISTER_SET Regs;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Regs.H.AH = 0x41;
+ Regs.X.BX = 0x55aa;
+ Regs.H.DL = Drive->Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG ((DEBUG_INIT, "Int13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX));
+ if (CarryFlag != 0 || 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 (BiosBlockIoDev, Drive);
+ return TRUE;
+}
+
+/**
+ Gets parameters of legacy drive.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of drive parameter retrieval.
+
+**/
+UINTN
+GetDriveParameters (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ )
+{
+ INTN CarryFlag;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN PointerMath;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Regs.H.AH = 0x48;
+ Regs.H.DL = Drive->Number;
+
+ //
+ // EDD Buffer must be passed in with max buffer size as first entry in the buffer
+ //
+ mLegacyDriverUnder1Mb->Parameters.StructureSize = (UINT16) sizeof (EDD_DRIVE_PARAMETERS);
+ Regs.X.DS = EFI_SEGMENT ((UINTN)(&mLegacyDriverUnder1Mb->Parameters));
+ Regs.X.SI = EFI_OFFSET ((UINTN)(&mLegacyDriverUnder1Mb->Parameters));
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 48 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH));
+ if (CarryFlag != 0 || Regs.H.AH != 0x00) {
+ Drive->ErrorCode = Regs.H.AH;
+ SetMem (&Drive->Parameters, sizeof (Drive->Parameters), 0xaf);
+ return FALSE;
+ }
+ //
+ // We only have one buffer < 1MB, so copy into our instance data
+ //
+ CopyMem (
+ &Drive->Parameters,
+ &mLegacyDriverUnder1Mb->Parameters,
+ sizeof (Drive->Parameters)
+ );
+
+ if (Drive->AtapiFloppy) {
+ //
+ // Sense Media Type
+ //
+ Regs.H.AH = 0x20;
+ Regs.H.DL = Drive->Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 20 DL=%02x : CF=%d AL=%02x\n", Drive->Number, CarryFlag, Regs.H.AL));
+ if (CarryFlag != 0) {
+ //
+ // Media not present or unknown 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
+ //
+ switch (Regs.H.AL) {
+ case 0x03:
+ //
+ // 720 KB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 9;
+ Drive->MaxCylinder = 79;
+ break;
+
+ case 0x04:
+ //
+ // 1.44MB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 18;
+ Drive->MaxCylinder = 79;
+ break;
+
+ case 0x06:
+ //
+ // 2.88MB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 36;
+ Drive->MaxCylinder = 79;
+ break;
+
+ case 0x0C:
+ //
+ // 360 KB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 9;
+ Drive->MaxCylinder = 39;
+ break;
+
+ case 0x0D:
+ //
+ // 1.2 MB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 15;
+ Drive->MaxCylinder = 79;
+ break;
+
+ case 0x0E:
+ //
+ // Toshiba 3 mode
+ //
+ case 0x0F:
+ //
+ // NEC 3 mode
+ //
+ case 0x10:
+ //
+ // Default Media
+ //
+ 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;
+ }
+ break;
+
+ default:
+ //
+ // Unknown media type.
+ //
+ Drive->MaxHead = 0;
+ Drive->MaxSector = 1;
+ Drive->MaxCylinder = 0;
+ break;
+ }
+ }
+
+ 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;
+
+ return TRUE;
+}
+//
+// Block IO Routines
+//
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd30BiosReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ //
+ // I exist only for readability
+ //
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ 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;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ AddressPacket = mEddBufferUnder1Mb;
+
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;
+
+ TransferBuffer = (UINT64)(UINTN) Buffer;
+ for (; BufferSize > 0;) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;
+ //
+ // Max transfer MaxTransferBlocks
+ //
+ AddressPacket->PacketSizeInBytes = (UINT8) 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 = BiosBlockIoDev->Bios.Number;
+ Regs.X.SI = EFI_OFFSET (AddressPacket);
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "Edd30BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,
+ CarryFlag, Regs.H.AH
+ )
+ );
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ BufferSize = BufferSize - TransferByteSize;
+ TransferBuffer += TransferByteSize;
+ Lba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd30BiosWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ //
+ // I exist only for readability
+ //
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Lba > Media->LastBlock) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ 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;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ AddressPacket = mEddBufferUnder1Mb;
+
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;
+
+ TransferBuffer = (UINT64)(UINTN) Buffer;
+ for (; BufferSize > 0;) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;
+ //
+ // Max transfer MaxTransferBlocks
+ //
+ AddressPacket->PacketSizeInBytes = (UINT8) 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) (BiosBlockIoDev->Bios.Number);
+ Regs.X.SI = EFI_OFFSET (AddressPacket);
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "Edd30BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,
+ CarryFlag, Regs.H.AH
+ )
+ );
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ Media->ReadOnly = FALSE;
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ BufferSize = BufferSize - TransferByteSize;
+ TransferBuffer += TransferByteSize;
+ Lba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Flush the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN CarryFlag;
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Regs.H.AH = 0x00;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag,
+ Regs.H.AH
+ )
+ );
+ if (CarryFlag != 0) {
+ if (Regs.H.AL == BIOS_RESET_FAILED) {
+ Regs.H.AH = 0x00;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag,
+ Regs.H.AH
+ )
+ );
+ if (CarryFlag != 0) {
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+//
+//
+// These functions need to double buffer all data under 1MB!
+//
+//
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd11BiosReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ //
+ // I exist only for readability
+ //
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ 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;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ AddressPacket = mEddBufferUnder1Mb;
+
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;
+
+ TransferBuffer = (UINT64)(UINTN) mEdd11Buffer;
+ for (; BufferSize > 0;) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;
+ //
+ // Max transfer MaxTransferBlocks
+ //
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+ AddressPacket->SegOffset = EFI_SEGMENT (TransferBuffer) << 16;
+ AddressPacket->SegOffset |= EFI_OFFSET (TransferBuffer);
+ AddressPacket->Lba = (UINT64) Lba;
+
+ Regs.H.AH = 0x42;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ Regs.X.SI = EFI_OFFSET (AddressPacket);
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "Edd11BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n",
+ BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks
+ )
+ );
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ CopyMem (Buffer, (VOID *) (UINTN) TransferBuffer, TransferByteSize);
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);
+ Lba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd11BiosWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ //
+ // I exist only for readability
+ //
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ 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;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ AddressPacket = mEddBufferUnder1Mb;
+
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;
+
+ TransferBuffer = (UINT64)(UINTN) mEdd11Buffer;
+ for (; BufferSize > 0;) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;
+ //
+ // Max transfer MaxTransferBlocks
+ //
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+ AddressPacket->SegOffset = EFI_SEGMENT (TransferBuffer) << 16;
+ AddressPacket->SegOffset |= EFI_OFFSET (TransferBuffer);
+ AddressPacket->Lba = (UINT64) Lba;
+
+ Regs.H.AH = 0x43;
+ Regs.H.AL = 0x00;
+ //
+ // Write Verify disable
+ //
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ Regs.X.SI = EFI_OFFSET (AddressPacket);
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ CopyMem ((VOID *) (UINTN) TransferBuffer, Buffer, TransferByteSize);
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "Edd11BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n",
+ BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks
+ )
+ );
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ Media->ReadOnly = FALSE;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);
+ Lba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosReadLegacyDrive (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN UpperCylinder;
+ UINTN Temp;
+ UINTN Cylinder;
+ UINTN Head;
+ UINTN Sector;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN ShortLba;
+ UINTN CheckLba;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN Retry;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ 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;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ ShortLba = (UINTN) Lba;
+
+ while (BufferSize != 0) {
+ //
+ // Compute I/O location in Sector, Head, Cylinder format
+ //
+ Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1;
+ Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector;
+ Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1);
+ Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1);
+
+ //
+ // Limit transfer to this Head & Cylinder
+ //
+ NumberOfBlocks = BufferSize / BlockSize;
+ Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1;
+ NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;
+
+ Retry = 3;
+ do {
+ //
+ // Perform the IO
+ //
+ Regs.H.AH = 2;
+ Regs.H.AL = (UINT8) NumberOfBlocks;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+
+ UpperCylinder = (Cylinder & 0x0f00) >> 2;
+
+ CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head;
+ CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1;
+
+ DEBUG (
+ (DEBUG_BLKIO,
+ "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n",
+ ShortLba,
+ CheckLba,
+ Sector,
+ BiosBlockIoDev->Bios.MaxSector,
+ Head,
+ BiosBlockIoDev->Bios.MaxHead,
+ Cylinder,
+ UpperCylinder)
+ );
+ 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 (mEdd11Buffer);
+ Regs.X.ES = EFI_SEGMENT (mEdd11Buffer);
+
+ DEBUG (
+ (DEBUG_BLKIO,
+ "INT 13h: AX:(02%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n",
+ Regs.H.AL,
+ (UINT8) (Head & 0x3f),
+ Regs.H.DL,
+ (UINT8) (Cylinder & 0xff),
+ (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)),
+ EFI_OFFSET (mEdd11Buffer),
+ EFI_SEGMENT (mEdd11Buffer))
+ );
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "BiosReadLegacyDrive: INT 13 02 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,
+ CarryFlag, Regs.H.AH
+ )
+ );
+ Retry--;
+ } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED);
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ //
+ // If the size of the media changed we need to reset the disk geometry
+ //
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ //
+ // Legacy Interfaces
+ //
+ Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
+ Media->BlockSize = 512;
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ CopyMem (Buffer, mEdd11Buffer, TransferByteSize);
+
+ ShortLba = ShortLba + NumberOfBlocks;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosWriteLegacyDrive (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN UpperCylinder;
+ UINTN Temp;
+ UINTN Cylinder;
+ UINTN Head;
+ UINTN Sector;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN ShortLba;
+ UINTN CheckLba;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN Retry;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ 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;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ ShortLba = (UINTN) Lba;
+
+ while (BufferSize != 0) {
+ //
+ // Compute I/O location in Sector, Head, Cylinder format
+ //
+ Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1;
+ Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector;
+ Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1);
+ Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1);
+
+ //
+ // Limit transfer to this Head & Cylinder
+ //
+ NumberOfBlocks = BufferSize / BlockSize;
+ Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1;
+ NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;
+
+ Retry = 3;
+ do {
+ //
+ // Perform the IO
+ //
+ Regs.H.AH = 3;
+ Regs.H.AL = (UINT8) NumberOfBlocks;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+
+ UpperCylinder = (Cylinder & 0x0f00) >> 2;
+
+ CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head;
+ CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1;
+
+ DEBUG (
+ (DEBUG_BLKIO,
+ "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n",
+ ShortLba,
+ CheckLba,
+ Sector,
+ BiosBlockIoDev->Bios.MaxSector,
+ Head,
+ BiosBlockIoDev->Bios.MaxHead,
+ Cylinder,
+ UpperCylinder)
+ );
+ 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 (mEdd11Buffer);
+ Regs.X.ES = EFI_SEGMENT (mEdd11Buffer);
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ CopyMem (mEdd11Buffer, Buffer, TransferByteSize);
+
+ DEBUG (
+ (DEBUG_BLKIO,
+ "INT 13h: AX:(03%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n",
+ Regs.H.AL,
+ (UINT8) (Head & 0x3f),
+ Regs.H.DL,
+ (UINT8) (Cylinder & 0xff),
+ (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)),
+ EFI_OFFSET (mEdd11Buffer),
+ EFI_SEGMENT (mEdd11Buffer))
+ );
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "BiosWriteLegacyDrive: INT 13 03 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,
+ CarryFlag, Regs.H.AH
+ )
+ );
+ Retry--;
+ } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED);
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ //
+ // Legacy Interfaces
+ //
+ Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
+ Media->BlockSize = 512;
+ }
+ //
+ // If the size of the media changed we need to reset the disk geometry
+ //
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ Media->ReadOnly = FALSE;
+ ShortLba = ShortLba + NumberOfBlocks;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf
new file mode 100644
index 0000000000..3fcaa2723c
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf
@@ -0,0 +1,58 @@
+## @file
+# Component description file for BIOS Block IO module.
+#
+# Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions
+# of the BSD License which accompanies this distribution. The
+# full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BlockIoDxe
+ FILE_GUID = 4495E47E-42A9-4007-8c17-B6664F909D04
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BiosBlockIoDriverEntryPoint
+
+[Sources]
+ BiosBlkIo.h
+ Edd.h
+ BiosBlkIo.c
+ BiosInt13.c
+ ComponentName.c
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ UefiLib
+ DevicePathLib
+ MemoryAllocationLib
+
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiLegacyBiosProtocolGuid
+
+
+[Guids]
+ gEfiLegacyBiosGuid
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c
new file mode 100644
index 0000000000..88bca13d5f
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c
@@ -0,0 +1,309 @@
+/** @file
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosBlkIo.h"
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name 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. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] 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.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] 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.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name 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. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] 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.
+
+ @retval 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.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName = {
+ BiosBlockIoComponentNameGetDriverName,
+ BiosBlockIoComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosBlockIoComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosBlockIoComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosBlockIoDriverNameTable[] = {
+ {
+ "eng;en",
+ L"BIOS[INT13] Block Io Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name 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. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] 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.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mBiosBlockIoDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gBiosBlockIoComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] 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.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name 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. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] 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.
+
+ @retval 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.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h
new file mode 100644
index 0000000000..be4d8302cf
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h
@@ -0,0 +1,209 @@
+/** @file
+ Include file to suport EDD 3.0.
+ This file is coded to T13 D1386 Revision 3
+ Availible on http://www.t13.org/#Project drafts
+ Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r3.pdf
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EDD_H_
+#define _EDD_H_
+
+//
+// packing with no compiler padding, so that the fields
+// of the following architected structures can be
+// properly accessed from C code.
+//
+#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 Pun;
+ 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 {
+ 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;
+
+//
+// EDD_DRIVE_PARAMETERS.Flags defines
+//
+#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
+
+//
+// BUGBUG: This bit does not follow the spec. It tends to be always set
+// to work properly with Win98.
+//
+#define EDD_DEVICE_GEOMETRY_MAX 0x40
+
+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 EDD_VERSION_30 0x30
+
+//
+// Int 13 BIOS Errors
+//
+#define BIOS_PASS 0x00
+#define BIOS_WRITE_PROTECTED 0x03
+#define BIOS_SECTOR_NOT_FOUND 0x04
+#define BIOS_RESET_FAILED 0x05
+#define BIOS_DISK_CHANGED 0x06
+#define BIOS_DRIVE_DOES_NOT_EXIST 0x07
+#define BIOS_DMA_ERROR 0x08
+#define BIOS_DATA_BOUNDRY_ERROR 0x09
+#define BIOS_BAD_SECTOR 0x0a
+#define BIOS_BAD_TRACK 0x0b
+#define BIOS_MEADIA_TYPE_NOT_FOUND 0x0c
+#define BIOS_INVALED_FORMAT 0x0d
+#define BIOS_ECC_ERROR 0x10
+#define BIOS_ECC_CORRECTED_ERROR 0x11
+#define BIOS_HARD_DRIVE_FAILURE 0x20
+#define BIOS_SEEK_FAILED 0x40
+#define BIOS_DRIVE_TIMEOUT 0x80
+#define BIOS_DRIVE_NOT_READY 0xaa
+#define BIOS_UNDEFINED_ERROR 0xbb
+#define BIOS_WRITE_FAULT 0xcc
+#define BIOS_SENSE_FAILED 0xff
+
+#define MAX_EDD11_XFER 0xfe00
+
+#pragma pack()
+//
+// Internal Data Structures
+//
+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;
+} BIOS_LEGACY_DRIVE;
+
+#define BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE SIGNATURE_32 ('b', 'b', 'i', 'o')
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE Handle;
+ EFI_HANDLE ControllerHandle;
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ EFI_BLOCK_IO_MEDIA BlockMedia;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+
+ BIOS_LEGACY_DRIVE Bios;
+
+} BIOS_BLOCK_IO_DEV;
+
+#define BIOS_BLOCK_IO_FROM_THIS(a) CR (a, BIOS_BLOCK_IO_DEV, BlockIo, BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE)
+
+#endif