--- /dev/null
+/** @file\r
+ EFI glue for BIOS INT 13h block devices.\r
+\r
+ This file is coded to EDD 3.0 as defined by T13 D1386 Revision 4\r
+ Availible on http://www.t13.org/#Project drafts\r
+ Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r4.pdf\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosBlkIo.h"\r
+\r
+//\r
+// Global data declaration\r
+//\r
+//\r
+// EFI Driver Binding Protocol Instance\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gBiosBlockIoDriverBinding = {\r
+ BiosBlockIoDriverBindingSupported,\r
+ BiosBlockIoDriverBindingStart,\r
+ BiosBlockIoDriverBindingStop,\r
+ 0x3,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+//\r
+// Semaphore to control access to global variables mActiveInstances and mBufferUnder1Mb\r
+//\r
+EFI_LOCK mGlobalDataLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_APPLICATION);\r
+\r
+//\r
+// Number of active instances of this protocol. This is used to allocate/free\r
+// the shared buffer. You must acquire the semaphore to modify.\r
+//\r
+UINTN mActiveInstances = 0;\r
+\r
+//\r
+// Pointer to the beginning of the buffer used for real mode thunk\r
+// You must acquire the semaphore to modify.\r
+//\r
+EFI_PHYSICAL_ADDRESS mBufferUnder1Mb = 0;\r
+\r
+//\r
+// Address packet is a buffer under 1 MB for all version EDD calls\r
+//\r
+EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb;\r
+\r
+//\r
+// This is a buffer for INT 13h func 48 information\r
+//\r
+BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb;\r
+\r
+//\r
+// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB\r
+// 0xFE00 bytes is the max transfer size supported.\r
+//\r
+VOID *mEdd11Buffer;\r
+\r
+EFI_GUID mUnknownDevGuid = UNKNOWN_DEVICE_GUID;\r
+\r
+/**\r
+ Driver entry point.\r
+\r
+ @param ImageHandle Handle of driver image.\r
+ @param SystemTable Pointer to system table.\r
+\r
+ @retval EFI_SUCCESS Entrypoint successfully executed.\r
+ @retval Others Fail to execute entrypoint.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Install protocols\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gBiosBlockIoDriverBinding,\r
+ ImageHandle,\r
+ &gBiosBlockIoComponentName,\r
+ &gBiosBlockIoComponentName2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver\r
+ //\r
+ return gBS->InstallMultipleProtocolInterfaces (\r
+ &ImageHandle,\r
+ &gEfiLegacyBiosGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+}\r
+\r
+/**\r
+ Check whether the driver supports this device.\r
+\r
+ @param This The Udriver binding protocol.\r
+ @param Controller The controller handle to check.\r
+ @param RemainingDevicePath The remaining device path.\r
+\r
+ @retval EFI_SUCCESS The driver supports this controller.\r
+ @retval other This device isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ PCI_TYPE00 Pci;\r
+\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ ); \r
+ \r
+ //\r
+ // Open the IO Abstraction(s) needed to perform the supported test\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // See if this is a PCI VGA Controller by looking at the Command register and\r
+ // Class Code Register\r
+ //\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ if (Pci.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE ||\r
+ (Pci.Hdr.ClassCode[2] == PCI_BASE_CLASS_INTELLIGENT && Pci.Hdr.ClassCode[1] == PCI_SUB_CLASS_INTELLIGENT)\r
+ ) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+Done:\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Starts the device with this driver.\r
+\r
+ @param This The driver binding instance.\r
+ @param Controller Handle of device to bind driver to.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS The controller is controlled by the driver.\r
+ @retval Other This controller cannot be started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 DiskStart;\r
+ UINT8 DiskEnd;\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate;\r
+ EFI_DEVICE_PATH_PROTOCOL *PciDevPath;\r
+ UINTN Index;\r
+ UINTN Flags;\r
+ UINTN TmpAddress;\r
+ BOOLEAN DeviceEnable;\r
+\r
+ //\r
+ // Initialize variables\r
+ //\r
+ PciIo = NULL;\r
+ PciDevPath = NULL;\r
+ \r
+ DeviceEnable = FALSE; \r
+\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ //\r
+ // Open the IO Abstraction(s) needed\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &PciDevPath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ //\r
+ // Enable the device and make sure VGA cycles are being forwarded to this VGA device\r
+ //\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ EFI_PCI_DEVICE_ENABLE,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ \r
+ DeviceEnable = TRUE;\r
+ \r
+ //\r
+ // Check to see if there is a legacy option ROM image associated with this PCI device\r
+ //\r
+ Status = LegacyBios->CheckPciRom (\r
+ LegacyBios,\r
+ Controller,\r
+ NULL,\r
+ NULL,\r
+ &Flags\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ //\r
+ // Post the legacy option ROM if it is available.\r
+ //\r
+ Status = LegacyBios->InstallPciRom (\r
+ LegacyBios,\r
+ Controller,\r
+ NULL,\r
+ &Flags,\r
+ &DiskStart,\r
+ &DiskEnd,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ //\r
+ // All instances share a buffer under 1MB to put real mode thunk code in\r
+ // If it has not been allocated, then we allocate it.\r
+ //\r
+ if (mBufferUnder1Mb == 0) {\r
+ //\r
+ // Should only be here if there are no active instances\r
+ //\r
+ ASSERT (mActiveInstances == 0);\r
+\r
+ //\r
+ // Acquire the lock\r
+ //\r
+ EfiAcquireLock (&mGlobalDataLock);\r
+\r
+ //\r
+ // Allocate below 1MB\r
+ //\r
+ mBufferUnder1Mb = 0x00000000000FFFFF;\r
+ Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb);\r
+\r
+ //\r
+ // Release the lock\r
+ //\r
+ EfiReleaseLock (&mGlobalDataLock);\r
+\r
+ //\r
+ // Check memory allocation success\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // In checked builds we want to assert if the allocate failed.\r
+ //\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ mBufferUnder1Mb = 0;\r
+ goto Error;\r
+ }\r
+\r
+ TmpAddress = (UINTN) mBufferUnder1Mb;\r
+ //\r
+ // Adjusting the value to be on proper boundary\r
+ //\r
+ mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress);\r
+\r
+ TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER;\r
+ //\r
+ // Adjusting the value to be on proper boundary\r
+ //\r
+ mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress);\r
+\r
+ TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE);\r
+ //\r
+ // Adjusting the value to be on proper boundary\r
+ //\r
+ mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress);\r
+ }\r
+ //\r
+ // Allocate the private device structure for each disk\r
+ //\r
+ for (Index = DiskStart; Index < DiskEnd; Index++) {\r
+\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData,\r
+ sizeof (BIOS_BLOCK_IO_DEV),\r
+ (VOID **) &BiosBlockIoPrivate\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ //\r
+ // Zero the private device structure\r
+ //\r
+ ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV));\r
+\r
+ //\r
+ // Initialize the private device structure\r
+ //\r
+ BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE;\r
+ BiosBlockIoPrivate->ControllerHandle = Controller;\r
+ BiosBlockIoPrivate->LegacyBios = LegacyBios;\r
+ BiosBlockIoPrivate->PciIo = PciIo;\r
+\r
+ BiosBlockIoPrivate->Bios.Floppy = FALSE;\r
+ BiosBlockIoPrivate->Bios.Number = (UINT8) Index;\r
+ BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C');\r
+ BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE;\r
+\r
+ if (BiosInitBlockIo (BiosBlockIoPrivate)) {\r
+ SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath);\r
+\r
+ //\r
+ // Install the Block Io Protocol onto a new child handle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &BiosBlockIoPrivate->Handle,\r
+ &gEfiBlockIoProtocolGuid,\r
+ &BiosBlockIoPrivate->BlockIo,\r
+ &gEfiDevicePathProtocolGuid,\r
+ BiosBlockIoPrivate->DevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (BiosBlockIoPrivate);\r
+ }\r
+ //\r
+ // Open For Child Device\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &BiosBlockIoPrivate->PciIo,\r
+ This->DriverBindingHandle,\r
+ BiosBlockIoPrivate->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+\r
+ } else {\r
+ gBS->FreePool (BiosBlockIoPrivate);\r
+ }\r
+ }\r
+\r
+Error:\r
+ if (EFI_ERROR (Status)) {\r
+ if (PciIo != NULL) {\r
+ if (DeviceEnable) {\r
+ PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationDisable,\r
+ EFI_PCI_DEVICE_ENABLE,\r
+ NULL\r
+ );\r
+ }\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ if (PciDevPath != NULL) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+ if (mBufferUnder1Mb != 0 && mActiveInstances == 0) {\r
+ gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE);\r
+\r
+ //\r
+ // Clear the buffer back to 0\r
+ //\r
+ EfiAcquireLock (&mGlobalDataLock);\r
+ mBufferUnder1Mb = 0;\r
+ EfiReleaseLock (&mGlobalDataLock);\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // Successfully installed, so increment the number of active instances\r
+ //\r
+ EfiAcquireLock (&mGlobalDataLock);\r
+ mActiveInstances++;\r
+ EfiReleaseLock (&mGlobalDataLock);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Stop the device handled by this driver.\r
+\r
+ @param This The driver binding protocol.\r
+ @param Controller The controller to release.\r
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
+ @param ChildHandleBuffer The array of child handle.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+ @retval Others Fail to uninstall protocols attached on the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN AllChildrenStopped;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Decrement the number of active instances\r
+ //\r
+ if (mActiveInstances != 0) {\r
+ //\r
+ // Add a check since the stop function will be called 2 times for each handle\r
+ //\r
+ EfiAcquireLock (&mGlobalDataLock);\r
+ mActiveInstances--;\r
+ EfiReleaseLock (&mGlobalDataLock);\r
+ }\r
+\r
+ if ((mActiveInstances == 0) && (mBufferUnder1Mb != 0)) {\r
+ //\r
+ // Free our global buffer\r
+ //\r
+ Status = gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ EfiAcquireLock (&mGlobalDataLock);\r
+ mBufferUnder1Mb = 0;\r
+ EfiReleaseLock (&mGlobalDataLock);\r
+ }\r
+\r
+ AllChildrenStopped = TRUE;\r
+\r
+ for (Index = 0; Index < NumberOfChildren; Index++) {\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandleBuffer[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlockIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BiosBlockIoPrivate = BIOS_BLOCK_IO_FROM_THIS (BlockIo);\r
+\r
+ //\r
+ // Release PCI I/O and Block IO Protocols on the clild handle.\r
+ //\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ ChildHandleBuffer[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ &BiosBlockIoPrivate->BlockIo,\r
+ &gEfiDevicePathProtocolGuid,\r
+ BiosBlockIoPrivate->DevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ AllChildrenStopped = FALSE;\r
+ }\r
+ //\r
+ // Shutdown the hardware\r
+ //\r
+ BiosBlockIoPrivate->PciIo->Attributes (\r
+ BiosBlockIoPrivate->PciIo,\r
+ EfiPciIoAttributeOperationDisable,\r
+ EFI_PCI_DEVICE_ENABLE,\r
+ NULL\r
+ );\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ChildHandleBuffer[Index]\r
+ );\r
+\r
+ gBS->FreePool (BiosBlockIoPrivate);\r
+ }\r
+\r
+ if (!AllChildrenStopped) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Build device path for device.\r
+\r
+ @param BaseDevicePath Base device path.\r
+ @param Drive Legacy drive.\r
+ @param DevicePath Device path for output.\r
+\r
+**/\r
+VOID\r
+SetBiosInitBlockIoDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,\r
+ IN BIOS_LEGACY_DRIVE *Drive,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UNKNOWN_DEVICE_VENDOR_DEVICE_PATH VendorNode;\r
+ \r
+ Status = EFI_UNSUPPORTED;\r
+ \r
+ //\r
+ // BugBug: Check for memory leaks!\r
+ //\r
+ if (Drive->EddVersion == EDD_VERSION_30) {\r
+ //\r
+ // EDD 3.0 case.\r
+ //\r
+ Status = BuildEdd30DevicePath (BaseDevicePath, Drive, DevicePath);\r
+ }\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // EDD 1.1 device case or it is unrecognized EDD 3.0 device\r
+ //\r
+ ZeroMem (&VendorNode, sizeof (VendorNode));\r
+ VendorNode.DevicePath.Header.Type = HARDWARE_DEVICE_PATH;\r
+ VendorNode.DevicePath.Header.SubType = HW_VENDOR_DP;\r
+ SetDevicePathNodeLength (&VendorNode.DevicePath.Header, sizeof (VendorNode));\r
+ CopyMem (&VendorNode.DevicePath.Guid, &mUnknownDevGuid, sizeof (EFI_GUID));\r
+ VendorNode.LegacyDriveLetter = Drive->Number;\r
+ *DevicePath = AppendDevicePathNode (BaseDevicePath, &VendorNode.DevicePath.Header);\r
+ }\r
+}\r
+\r
+/**\r
+ Build device path for EDD 3.0.\r
+\r
+ @param BaseDevicePath Base device path.\r
+ @param Drive Legacy drive.\r
+ @param DevicePath Device path for output.\r
+\r
+ @retval EFI_SUCCESS The device path is built successfully.\r
+ @retval EFI_UNSUPPORTED It is failed to built device path.\r
+\r
+**/\r
+EFI_STATUS\r
+BuildEdd30DevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,\r
+ IN BIOS_LEGACY_DRIVE *Drive,\r
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ )\r
+{\r
+ //\r
+ // AVL UINT64 Address;\r
+ // AVL EFI_HANDLE Handle;\r
+ //\r
+ EFI_DEV_PATH Node;\r
+ UINT32 Controller;\r
+\r
+ Controller = (UINT32) Drive->Parameters.InterfacePath.Pci.Controller;\r
+\r
+ ZeroMem (&Node, sizeof (Node));\r
+ if ((AsciiStrnCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) ||\r
+ (AsciiStrnCmp ("ATA", Drive->Parameters.InterfaceType, 3) == 0)\r
+ ) {\r
+ //\r
+ // ATA or ATAPI drive found\r
+ //\r
+ Node.Atapi.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Node.Atapi.Header.SubType = MSG_ATAPI_DP;\r
+ SetDevicePathNodeLength (&Node.Atapi.Header, sizeof (ATAPI_DEVICE_PATH));\r
+ Node.Atapi.SlaveMaster = Drive->Parameters.DevicePath.Atapi.Master;\r
+ Node.Atapi.Lun = Drive->Parameters.DevicePath.Atapi.Lun;\r
+ Node.Atapi.PrimarySecondary = (UINT8) Controller;\r
+ } else {\r
+ //\r
+ // Not an ATA/ATAPI drive\r
+ //\r
+ if (Controller != 0) {\r
+ ZeroMem (&Node, sizeof (Node));\r
+ Node.Controller.Header.Type = HARDWARE_DEVICE_PATH;\r
+ Node.Controller.Header.SubType = HW_CONTROLLER_DP;\r
+ SetDevicePathNodeLength (&Node.Controller.Header, sizeof (CONTROLLER_DEVICE_PATH));\r
+ Node.Controller.ControllerNumber = Controller;\r
+ *DevicePath = AppendDevicePathNode (*DevicePath, &Node.DevPath);\r
+ }\r
+\r
+ ZeroMem (&Node, sizeof (Node));\r
+\r
+ if (AsciiStrnCmp ("SCSI", Drive->Parameters.InterfaceType, 4) == 0) {\r
+ //\r
+ // SCSI drive\r
+ //\r
+ Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Node.Scsi.Header.SubType = MSG_SCSI_DP;\r
+ SetDevicePathNodeLength (&Node.Scsi.Header, sizeof (SCSI_DEVICE_PATH));\r
+\r
+ //\r
+ // Lun is miss aligned in both EDD and Device Path data structures.\r
+ // thus we do a byte copy, to prevent alignment traps on IA-64.\r
+ //\r
+ CopyMem (&Node.Scsi.Lun, &Drive->Parameters.DevicePath.Scsi.Lun, sizeof (UINT16));\r
+ Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.Pun;\r
+\r
+ } else if (AsciiStrnCmp ("USB", Drive->Parameters.InterfaceType, 3) == 0) {\r
+ //\r
+ // USB drive\r
+ //\r
+ Node.Usb.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Node.Usb.Header.SubType = MSG_USB_DP;\r
+ SetDevicePathNodeLength (&Node.Usb.Header, sizeof (USB_DEVICE_PATH));\r
+ Node.Usb.ParentPortNumber = (UINT8) Drive->Parameters.DevicePath.Usb.Reserved;\r
+\r
+ } else if (AsciiStrnCmp ("1394", Drive->Parameters.InterfaceType, 4) == 0) {\r
+ //\r
+ // 1394 drive\r
+ //\r
+ Node.F1394.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Node.F1394.Header.SubType = MSG_1394_DP;\r
+ SetDevicePathNodeLength (&Node.F1394.Header, sizeof (F1394_DEVICE_PATH));\r
+ Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid;\r
+\r
+ } else if (AsciiStrnCmp ("FIBRE", Drive->Parameters.InterfaceType, 5) == 0) {\r
+ //\r
+ // Fibre drive\r
+ //\r
+ Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP;\r
+ SetDevicePathNodeLength (&Node.FibreChannel.Header, sizeof (FIBRECHANNEL_DEVICE_PATH));\r
+ Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn;\r
+ Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun;\r
+\r
+ } else {\r
+ DEBUG (\r
+ (\r
+ DEBUG_BLKIO, "It is unrecognized EDD 3.0 device, Drive Number = %x, InterfaceType = %s\n",\r
+ Drive->Number,\r
+ Drive->Parameters.InterfaceType\r
+ )\r
+ ); \r
+ }\r
+ }\r
+\r
+ if (Node.DevPath.Type == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ *DevicePath = AppendDevicePathNode (BaseDevicePath, &Node.DevPath);\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BIOS_BLOCK_IO_H_\r
+#define _BIOS_BLOCK_IO_H_\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Guid/LegacyBios.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#include "Edd.h"\r
+\r
+#define UNKNOWN_DEVICE_GUID \\r
+ { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} }\r
+\r
+typedef struct {\r
+ VENDOR_DEVICE_PATH DevicePath;\r
+ UINT8 LegacyDriveLetter;\r
+} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH;\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2;\r
+\r
+\r
+//\r
+// Define the I2O class code\r
+//\r
+#define PCI_BASE_CLASS_INTELLIGENT 0x0e\r
+#define PCI_SUB_CLASS_INTELLIGENT 0x00\r
+\r
+//\r
+// Number of pages needed for our buffer under 1MB\r
+//\r
+#define BLOCK_IO_BUFFER_PAGE_SIZE (((sizeof (EDD_DEVICE_ADDRESS_PACKET) + sizeof (BIOS_LEGACY_DRIVE) + MAX_EDD11_XFER) / EFI_PAGE_SIZE) + 1 \\r
+ )\r
+\r
+//\r
+// Driver Binding Protocol functions\r
+//\r
+\r
+/**\r
+ Check whether the driver supports this device.\r
+\r
+ @param This The Udriver binding protocol.\r
+ @param Controller The controller handle to check.\r
+ @param RemainingDevicePath The remaining device path.\r
+\r
+ @retval EFI_SUCCESS The driver supports this controller.\r
+ @retval other This device isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+\r
+/**\r
+ Starts the device with this driver.\r
+\r
+ @param This The driver binding instance.\r
+ @param Controller Handle of device to bind driver to.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS The controller is controlled by the driver.\r
+ @retval Other This controller cannot be started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+/**\r
+ Stop the device handled by this driver.\r
+\r
+ @param This The driver binding protocol.\r
+ @param Controller The controller to release.\r
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
+ @param ChildHandleBuffer The array of child handle.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+ @retval Others Fail to uninstall protocols attached on the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ );\r
+\r
+//\r
+// Other internal functions\r
+//\r
+\r
+/**\r
+ Build device path for EDD 3.0.\r
+\r
+ @param BaseDevicePath Base device path.\r
+ @param Drive Legacy drive.\r
+ @param DevicePath Device path for output.\r
+\r
+ @retval EFI_SUCCESS The device path is built successfully.\r
+ @retval EFI_UNSUPPORTED It is failed to built device path.\r
+\r
+**/\r
+EFI_STATUS\r
+BuildEdd30DevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,\r
+ IN BIOS_LEGACY_DRIVE *Drive,\r
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ );\r
+\r
+/**\r
+ Initialize block I/O device instance\r
+\r
+ @param Dev Instance of block I/O device instance\r
+\r
+ @retval TRUE Initialization succeeds.\r
+ @retval FALSE Initialization fails.\r
+\r
+**/\r
+BOOLEAN\r
+BiosInitBlockIo (\r
+ IN BIOS_BLOCK_IO_DEV *Dev\r
+ );\r
+\r
+/**\r
+ Read BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId Id of the media, changes every time the media is replaced.\r
+ @param Lba The starting Logical Block Address to read from\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller is\r
+ responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The data was read correctly from the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Edd30BiosReadBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Write BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the write request is for.\r
+ @param Lba The starting logical block address to be written. The caller is\r
+ responsible for writing to only legitimate locations.\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The data was written correctly to the device.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Edd30BiosWriteBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Flush the Block Device.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+\r
+ @retval EFI_SUCCESS All outstanding data was written to the device\r
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoFlushBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ Reset the Block Device.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param ExtendedVerification Driver may perform diagnostics on reset.\r
+\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
+ not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoReset (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ );\r
+\r
+/**\r
+ Read BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId Id of the media, changes every time the media is replaced.\r
+ @param Lba The starting Logical Block Address to read from\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller is\r
+ responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The data was read correctly from the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Edd11BiosReadBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Write BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the write request is for.\r
+ @param Lba The starting logical block address to be written. The caller is\r
+ responsible for writing to only legitimate locations.\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The data was written correctly to the device.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Edd11BiosWriteBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Read BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId Id of the media, changes every time the media is replaced.\r
+ @param Lba The starting Logical Block Address to read from\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller is\r
+ responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The data was read correctly from the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosReadLegacyDrive (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Write BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the write request is for.\r
+ @param Lba The starting logical block address to be written. The caller is\r
+ responsible for writing to only legitimate locations.\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The data was written correctly to the device.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosWriteLegacyDrive (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Gets parameters of block I/O device.\r
+\r
+ @param BiosBlockIoDev Instance of block I/O device.\r
+ @param Drive Legacy drive.\r
+\r
+ @return Result of device parameter retrieval.\r
+ \r
+**/\r
+UINTN\r
+Int13GetDeviceParameters (\r
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,\r
+ IN BIOS_LEGACY_DRIVE *Drive\r
+ );\r
+\r
+/**\r
+ Extension of INT13 call.\r
+\r
+ @param BiosBlockIoDev Instance of block I/O device.\r
+ @param Drive Legacy drive.\r
+\r
+ @return Result of this extension.\r
+ \r
+**/\r
+UINTN\r
+Int13Extensions (\r
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,\r
+ IN BIOS_LEGACY_DRIVE *Drive\r
+ );\r
+\r
+/**\r
+ Gets parameters of legacy drive.\r
+\r
+ @param BiosBlockIoDev Instance of block I/O device.\r
+ @param Drive Legacy drive.\r
+\r
+ @return Result of drive parameter retrieval.\r
+ \r
+**/\r
+UINTN\r
+GetDriveParameters (\r
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,\r
+ IN BIOS_LEGACY_DRIVE *Drive\r
+ );\r
+\r
+/**\r
+ Build device path for device.\r
+\r
+ @param BaseDevicePath Base device path.\r
+ @param Drive Legacy drive.\r
+ @param DevicePath Device path for output.\r
+\r
+**/\r
+VOID\r
+SetBiosInitBlockIoDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,\r
+ IN BIOS_LEGACY_DRIVE *Drive,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Routines that use BIOS to support INT 13 devices.\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosBlkIo.h"\r
+\r
+//\r
+// Module global variables\r
+//\r
+//\r
+// Address packet is a buffer under 1 MB for all version EDD calls\r
+//\r
+extern EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb;\r
+\r
+//\r
+// This is a buffer for INT 13h func 48 information\r
+//\r
+extern BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb;\r
+\r
+//\r
+// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB\r
+// 0xFE00 bytes is the max transfer size supported.\r
+//\r
+extern VOID *mEdd11Buffer;\r
+\r
+\r
+/**\r
+ Initialize block I/O device instance\r
+\r
+ @param Dev Instance of block I/O device instance\r
+\r
+ @retval TRUE Initialization succeeds.\r
+ @retval FALSE Initialization fails.\r
+\r
+**/\r
+BOOLEAN\r
+BiosInitBlockIo (\r
+ IN BIOS_BLOCK_IO_DEV *Dev\r
+ )\r
+{\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ EFI_BLOCK_IO_MEDIA *BlockMedia;\r
+ BIOS_LEGACY_DRIVE *Bios;\r
+\r
+ BlockIo = &Dev->BlockIo;\r
+ BlockIo->Media = &Dev->BlockMedia;\r
+ BlockMedia = BlockIo->Media;\r
+ Bios = &Dev->Bios;\r
+\r
+ if (Int13GetDeviceParameters (Dev, Bios) != 0) {\r
+ if (Int13Extensions (Dev, Bios) != 0) {\r
+ BlockMedia->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;\r
+ BlockMedia->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;\r
+\r
+ if ((Bios->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) {\r
+ BlockMedia->RemovableMedia = TRUE;\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // Legacy Interfaces\r
+ //\r
+ BlockMedia->BlockSize = 512;\r
+ BlockMedia->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INIT, "BlockSize = %d LastBlock = %d\n", BlockMedia->BlockSize, BlockMedia->LastBlock));\r
+\r
+ BlockMedia->LogicalPartition = FALSE;\r
+ BlockMedia->WriteCaching = FALSE;\r
+\r
+ //\r
+ // BugBug: Need to set this for removable media devices if they do not\r
+ // have media present\r
+ //\r
+ BlockMedia->ReadOnly = FALSE;\r
+ BlockMedia->MediaPresent = TRUE;\r
+\r
+ BlockIo->Reset = BiosBlockIoReset;\r
+ BlockIo->FlushBlocks = BiosBlockIoFlushBlocks;\r
+\r
+ if (!Bios->ExtendedInt13) {\r
+ //\r
+ // Legacy interfaces\r
+ //\r
+ BlockIo->ReadBlocks = BiosReadLegacyDrive;\r
+ BlockIo->WriteBlocks = BiosWriteLegacyDrive;\r
+ } else if ((Bios->EddVersion == EDD_VERSION_30) && (Bios->Extensions64Bit)) {\r
+ //\r
+ // EDD 3.0 Required for Device path, but extended reads are not required.\r
+ //\r
+ BlockIo->ReadBlocks = Edd30BiosReadBlocks;\r
+ BlockIo->WriteBlocks = Edd30BiosWriteBlocks;\r
+ } else {\r
+ //\r
+ // Assume EDD 1.1 - Read and Write functions.\r
+ // This could be EDD 3.0 without Extensions64Bit being set.\r
+ // If it's EDD 1.1 this will work, but the device path will not\r
+ // be correct. This will cause confusion to EFI OS installation.\r
+ //\r
+ BlockIo->ReadBlocks = Edd11BiosReadBlocks;\r
+ BlockIo->WriteBlocks = Edd11BiosWriteBlocks;\r
+ }\r
+\r
+ BlockMedia->LogicalPartition = FALSE;\r
+ BlockMedia->WriteCaching = FALSE;\r
+\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Gets parameters of block I/O device.\r
+\r
+ @param BiosBlockIoDev Instance of block I/O device.\r
+ @param Drive Legacy drive.\r
+\r
+ @return Result of device parameter retrieval.\r
+ \r
+**/\r
+UINTN\r
+Int13GetDeviceParameters (\r
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,\r
+ IN BIOS_LEGACY_DRIVE *Drive\r
+ )\r
+{\r
+ UINTN CarryFlag;\r
+ UINT16 Cylinder;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ Regs.H.AH = 0x08;\r
+ Regs.H.DL = Drive->Number;\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG ((DEBUG_INIT, "Int13GetDeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH));\r
+ if (CarryFlag != 0 || Regs.H.AH != 0x00) {\r
+ Drive->ErrorCode = Regs.H.AH;\r
+ return FALSE;\r
+ }\r
+\r
+ if (Drive->Floppy) {\r
+ if (Regs.H.BL == 0x10) {\r
+ Drive->AtapiFloppy = TRUE;\r
+ } else {\r
+ Drive->MaxHead = Regs.H.DH;\r
+ Drive->MaxSector = Regs.H.CL;\r
+ Drive->MaxCylinder = Regs.H.CH;\r
+ if (Drive->MaxSector == 0) {\r
+ //\r
+ // BugBug: You can not trust the Carry flag.\r
+ //\r
+ return FALSE;\r
+ }\r
+ }\r
+ } else {\r
+ Drive->MaxHead = (UINT8) (Regs.H.DH & 0x3f);\r
+ Cylinder = (UINT16) (((UINT16) Regs.H.DH & 0xc0) << 4);\r
+ Cylinder = (UINT16) (Cylinder | ((UINT16) Regs.H.CL & 0xc0) << 2);\r
+ Drive->MaxCylinder = (UINT16) (Cylinder + Regs.H.CH);\r
+ Drive->MaxSector = (UINT8) (Regs.H.CL & 0x3f);\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Extension of INT13 call.\r
+\r
+ @param BiosBlockIoDev Instance of block I/O device.\r
+ @param Drive Legacy drive.\r
+\r
+ @return Result of this extension.\r
+ \r
+**/\r
+UINTN\r
+Int13Extensions (\r
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,\r
+ IN BIOS_LEGACY_DRIVE *Drive\r
+ )\r
+{\r
+ INTN CarryFlag;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ Regs.H.AH = 0x41;\r
+ Regs.X.BX = 0x55aa;\r
+ Regs.H.DL = Drive->Number;\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG ((DEBUG_INIT, "Int13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX));\r
+ if (CarryFlag != 0 || Regs.X.BX != 0xaa55) {\r
+ Drive->ExtendedInt13 = FALSE;\r
+ Drive->DriveLockingAndEjecting = FALSE;\r
+ Drive->Edd = FALSE;\r
+ return FALSE;\r
+ }\r
+\r
+ Drive->EddVersion = Regs.H.AH;\r
+ Drive->ExtendedInt13 = (BOOLEAN) ((Regs.X.CX & 0x01) == 0x01);\r
+ Drive->DriveLockingAndEjecting = (BOOLEAN) ((Regs.X.CX & 0x02) == 0x02);\r
+ Drive->Edd = (BOOLEAN) ((Regs.X.CX & 0x04) == 0x04);\r
+ Drive->Extensions64Bit = (BOOLEAN) (Regs.X.CX & 0x08);\r
+\r
+ Drive->ParametersValid = (UINT8) GetDriveParameters (BiosBlockIoDev, Drive);\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Gets parameters of legacy drive.\r
+\r
+ @param BiosBlockIoDev Instance of block I/O device.\r
+ @param Drive Legacy drive.\r
+\r
+ @return Result of drive parameter retrieval.\r
+ \r
+**/\r
+UINTN\r
+GetDriveParameters (\r
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,\r
+ IN BIOS_LEGACY_DRIVE *Drive\r
+ )\r
+{\r
+ INTN CarryFlag;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINTN PointerMath;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ Regs.H.AH = 0x48;\r
+ Regs.H.DL = Drive->Number;\r
+\r
+ //\r
+ // EDD Buffer must be passed in with max buffer size as first entry in the buffer\r
+ //\r
+ mLegacyDriverUnder1Mb->Parameters.StructureSize = (UINT16) sizeof (EDD_DRIVE_PARAMETERS);\r
+ Regs.X.DS = EFI_SEGMENT ((UINTN)(&mLegacyDriverUnder1Mb->Parameters));\r
+ Regs.X.SI = EFI_OFFSET ((UINTN)(&mLegacyDriverUnder1Mb->Parameters));\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 48 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH));\r
+ if (CarryFlag != 0 || Regs.H.AH != 0x00) {\r
+ Drive->ErrorCode = Regs.H.AH;\r
+ SetMem (&Drive->Parameters, sizeof (Drive->Parameters), 0xaf);\r
+ return FALSE;\r
+ }\r
+ //\r
+ // We only have one buffer < 1MB, so copy into our instance data\r
+ //\r
+ CopyMem (\r
+ &Drive->Parameters,\r
+ &mLegacyDriverUnder1Mb->Parameters,\r
+ sizeof (Drive->Parameters)\r
+ );\r
+\r
+ if (Drive->AtapiFloppy) {\r
+ //\r
+ // Sense Media Type\r
+ //\r
+ Regs.H.AH = 0x20;\r
+ Regs.H.DL = Drive->Number;\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 20 DL=%02x : CF=%d AL=%02x\n", Drive->Number, CarryFlag, Regs.H.AL));\r
+ if (CarryFlag != 0) {\r
+ //\r
+ // Media not present or unknown media present\r
+ //\r
+ if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) {\r
+ Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1);\r
+ Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack;\r
+ ASSERT (Drive->MaxSector != 0);\r
+ Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1);\r
+ } else {\r
+ Drive->MaxHead = 0;\r
+ Drive->MaxSector = 1;\r
+ Drive->MaxCylinder = 0;\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // Media Present\r
+ //\r
+ switch (Regs.H.AL) {\r
+ case 0x03:\r
+ //\r
+ // 720 KB\r
+ //\r
+ Drive->MaxHead = 1;\r
+ Drive->MaxSector = 9;\r
+ Drive->MaxCylinder = 79;\r
+ break;\r
+\r
+ case 0x04:\r
+ //\r
+ // 1.44MB\r
+ //\r
+ Drive->MaxHead = 1;\r
+ Drive->MaxSector = 18;\r
+ Drive->MaxCylinder = 79;\r
+ break;\r
+\r
+ case 0x06:\r
+ //\r
+ // 2.88MB\r
+ //\r
+ Drive->MaxHead = 1;\r
+ Drive->MaxSector = 36;\r
+ Drive->MaxCylinder = 79;\r
+ break;\r
+\r
+ case 0x0C:\r
+ //\r
+ // 360 KB\r
+ //\r
+ Drive->MaxHead = 1;\r
+ Drive->MaxSector = 9;\r
+ Drive->MaxCylinder = 39;\r
+ break;\r
+\r
+ case 0x0D:\r
+ //\r
+ // 1.2 MB\r
+ //\r
+ Drive->MaxHead = 1;\r
+ Drive->MaxSector = 15;\r
+ Drive->MaxCylinder = 79;\r
+ break;\r
+\r
+ case 0x0E:\r
+ //\r
+ // Toshiba 3 mode\r
+ //\r
+ case 0x0F:\r
+ //\r
+ // NEC 3 mode\r
+ //\r
+ case 0x10:\r
+ //\r
+ // Default Media\r
+ //\r
+ if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) {\r
+ Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1);\r
+ Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack;\r
+ ASSERT (Drive->MaxSector != 0);\r
+ Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1);\r
+ } else {\r
+ Drive->MaxHead = 0;\r
+ Drive->MaxSector = 1;\r
+ Drive->MaxCylinder = 0;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Unknown media type.\r
+ //\r
+ Drive->MaxHead = 0;\r
+ Drive->MaxSector = 1;\r
+ Drive->MaxCylinder = 0;\r
+ break;\r
+ }\r
+ }\r
+\r
+ Drive->Parameters.PhysicalSectors = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1);\r
+ Drive->Parameters.BytesPerSector = 512;\r
+ }\r
+ //\r
+ // This data comes from the BIOS so it may not allways be valid\r
+ // since the BIOS may reuse this buffer for future accesses\r
+ //\r
+ PointerMath = EFI_SEGMENT (Drive->Parameters.Fdpt) << 4;\r
+ PointerMath += EFI_OFFSET (Drive->Parameters.Fdpt);\r
+ Drive->FdptPointer = (VOID *) PointerMath;\r
+\r
+ return TRUE;\r
+}\r
+//\r
+// Block IO Routines\r
+//\r
+\r
+/**\r
+ Read BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId Id of the media, changes every time the media is replaced.\r
+ @param Lba The starting Logical Block Address to read from\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller is\r
+ responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The data was read correctly from the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Edd30BiosReadBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_BLOCK_IO_MEDIA *Media;\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;\r
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;\r
+ //\r
+ // I exist only for readability\r
+ //\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT64 TransferBuffer;\r
+ UINTN NumberOfBlocks;\r
+ UINTN TransferByteSize;\r
+ UINTN BlockSize;\r
+ BIOS_LEGACY_DRIVE *Bios;\r
+ UINTN CarryFlag;\r
+ UINTN MaxTransferBlocks;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ Media = This->Media;\r
+ BlockSize = Media->BlockSize;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ if (MediaId != Media->MediaId) {\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+\r
+ if (Lba > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize % BlockSize != 0) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);\r
+ AddressPacket = mEddBufferUnder1Mb;\r
+\r
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;\r
+\r
+ TransferBuffer = (UINT64)(UINTN) Buffer;\r
+ for (; BufferSize > 0;) {\r
+ NumberOfBlocks = BufferSize / BlockSize;\r
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;\r
+ //\r
+ // Max transfer MaxTransferBlocks\r
+ //\r
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);\r
+ AddressPacket->Zero = 0;\r
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;\r
+ AddressPacket->Zero2 = 0;\r
+ AddressPacket->SegOffset = 0xffffffff;\r
+ AddressPacket->Lba = (UINT64) Lba;\r
+ AddressPacket->TransferBuffer = TransferBuffer;\r
+\r
+ Regs.H.AH = 0x42;\r
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;\r
+ Regs.X.SI = EFI_OFFSET (AddressPacket);\r
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);\r
+\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG (\r
+ (\r
+ DEBUG_BLKIO, "Edd30BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,\r
+ CarryFlag, Regs.H.AH\r
+ )\r
+ );\r
+\r
+ Media->MediaPresent = TRUE;\r
+ if (CarryFlag != 0) {\r
+ //\r
+ // Return Error Status\r
+ //\r
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;\r
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {\r
+ Media->MediaId++;\r
+ Bios = &BiosBlockIoDev->Bios;\r
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {\r
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {\r
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;\r
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;\r
+ } else {\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ Media->ReadOnly = FALSE;\r
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+ }\r
+\r
+ if (Media->RemovableMedia) {\r
+ Media->MediaPresent = FALSE;\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ TransferByteSize = NumberOfBlocks * BlockSize;\r
+ BufferSize = BufferSize - TransferByteSize;\r
+ TransferBuffer += TransferByteSize;\r
+ Lba += NumberOfBlocks;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Write BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the write request is for.\r
+ @param Lba The starting logical block address to be written. The caller is\r
+ responsible for writing to only legitimate locations.\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The data was written correctly to the device.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Edd30BiosWriteBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_BLOCK_IO_MEDIA *Media;\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;\r
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;\r
+ //\r
+ // I exist only for readability\r
+ //\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT64 TransferBuffer;\r
+ UINTN NumberOfBlocks;\r
+ UINTN TransferByteSize;\r
+ UINTN BlockSize;\r
+ BIOS_LEGACY_DRIVE *Bios;\r
+ UINTN CarryFlag;\r
+ UINTN MaxTransferBlocks;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ Media = This->Media;\r
+ BlockSize = Media->BlockSize;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ if (MediaId != Media->MediaId) {\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+\r
+ if (Lba > Media->LastBlock) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize % BlockSize != 0) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);\r
+ AddressPacket = mEddBufferUnder1Mb;\r
+\r
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;\r
+\r
+ TransferBuffer = (UINT64)(UINTN) Buffer;\r
+ for (; BufferSize > 0;) {\r
+ NumberOfBlocks = BufferSize / BlockSize;\r
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;\r
+ //\r
+ // Max transfer MaxTransferBlocks\r
+ //\r
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);\r
+ AddressPacket->Zero = 0;\r
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;\r
+ AddressPacket->Zero2 = 0;\r
+ AddressPacket->SegOffset = 0xffffffff;\r
+ AddressPacket->Lba = (UINT64) Lba;\r
+ AddressPacket->TransferBuffer = TransferBuffer;\r
+\r
+ Regs.H.AH = 0x43;\r
+ Regs.H.AL = 0x00;\r
+ //\r
+ // Write Verify Off\r
+ //\r
+ Regs.H.DL = (UINT8) (BiosBlockIoDev->Bios.Number);\r
+ Regs.X.SI = EFI_OFFSET (AddressPacket);\r
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);\r
+\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG (\r
+ (\r
+ DEBUG_BLKIO, "Edd30BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,\r
+ CarryFlag, Regs.H.AH\r
+ )\r
+ );\r
+\r
+ Media->MediaPresent = TRUE;\r
+ if (CarryFlag != 0) {\r
+ //\r
+ // Return Error Status\r
+ //\r
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;\r
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {\r
+ Media->MediaId++;\r
+ Bios = &BiosBlockIoDev->Bios;\r
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {\r
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {\r
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;\r
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;\r
+ } else {\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ Media->ReadOnly = FALSE;\r
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {\r
+ Media->ReadOnly = TRUE;\r
+ return EFI_WRITE_PROTECTED;\r
+ }\r
+\r
+ if (Media->RemovableMedia) {\r
+ Media->MediaPresent = FALSE;\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Media->ReadOnly = FALSE;\r
+ TransferByteSize = NumberOfBlocks * BlockSize;\r
+ BufferSize = BufferSize - TransferByteSize;\r
+ TransferBuffer += TransferByteSize;\r
+ Lba += NumberOfBlocks;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Flush the Block Device.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+\r
+ @retval EFI_SUCCESS All outstanding data was written to the device\r
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoFlushBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Reset the Block Device.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param ExtendedVerification Driver may perform diagnostics on reset.\r
+\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
+ not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoReset (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+{\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINTN CarryFlag;\r
+\r
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG (\r
+ (\r
+ DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag,\r
+ Regs.H.AH\r
+ )\r
+ );\r
+ if (CarryFlag != 0) {\r
+ if (Regs.H.AL == BIOS_RESET_FAILED) {\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG (\r
+ (\r
+ DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag,\r
+ Regs.H.AH\r
+ )\r
+ );\r
+ if (CarryFlag != 0) {\r
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+//\r
+//\r
+// These functions need to double buffer all data under 1MB!\r
+//\r
+//\r
+\r
+/**\r
+ Read BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId Id of the media, changes every time the media is replaced.\r
+ @param Lba The starting Logical Block Address to read from\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller is\r
+ responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The data was read correctly from the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Edd11BiosReadBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_BLOCK_IO_MEDIA *Media;\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;\r
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;\r
+ //\r
+ // I exist only for readability\r
+ //\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT64 TransferBuffer;\r
+ UINTN NumberOfBlocks;\r
+ UINTN TransferByteSize;\r
+ UINTN BlockSize;\r
+ BIOS_LEGACY_DRIVE *Bios;\r
+ UINTN CarryFlag;\r
+ UINTN MaxTransferBlocks;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ Media = This->Media;\r
+ BlockSize = Media->BlockSize;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ if (MediaId != Media->MediaId) {\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+\r
+ if (Lba > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize % BlockSize != 0) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);\r
+ AddressPacket = mEddBufferUnder1Mb;\r
+\r
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;\r
+\r
+ TransferBuffer = (UINT64)(UINTN) mEdd11Buffer;\r
+ for (; BufferSize > 0;) {\r
+ NumberOfBlocks = BufferSize / BlockSize;\r
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;\r
+ //\r
+ // Max transfer MaxTransferBlocks\r
+ //\r
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);\r
+ AddressPacket->Zero = 0;\r
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;\r
+ AddressPacket->Zero2 = 0;\r
+ AddressPacket->SegOffset = EFI_SEGMENT (TransferBuffer) << 16;\r
+ AddressPacket->SegOffset |= EFI_OFFSET (TransferBuffer);\r
+ AddressPacket->Lba = (UINT64) Lba;\r
+\r
+ Regs.H.AH = 0x42;\r
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;\r
+ Regs.X.SI = EFI_OFFSET (AddressPacket);\r
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);\r
+\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG (\r
+ (\r
+ DEBUG_BLKIO, "Edd11BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n",\r
+ BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks\r
+ )\r
+ );\r
+ Media->MediaPresent = TRUE;\r
+ if (CarryFlag != 0) {\r
+ //\r
+ // Return Error Status\r
+ //\r
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;\r
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {\r
+ Media->MediaId++;\r
+ Bios = &BiosBlockIoDev->Bios;\r
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {\r
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {\r
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;\r
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;\r
+ } else {\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ Media->ReadOnly = FALSE;\r
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+ }\r
+\r
+ if (Media->RemovableMedia) {\r
+ Media->MediaPresent = FALSE;\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ TransferByteSize = NumberOfBlocks * BlockSize;\r
+ CopyMem (Buffer, (VOID *) (UINTN) TransferBuffer, TransferByteSize);\r
+ BufferSize = BufferSize - TransferByteSize;\r
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);\r
+ Lba += NumberOfBlocks;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Write BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the write request is for.\r
+ @param Lba The starting logical block address to be written. The caller is\r
+ responsible for writing to only legitimate locations.\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The data was written correctly to the device.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Edd11BiosWriteBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_BLOCK_IO_MEDIA *Media;\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;\r
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;\r
+ //\r
+ // I exist only for readability\r
+ //\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT64 TransferBuffer;\r
+ UINTN NumberOfBlocks;\r
+ UINTN TransferByteSize;\r
+ UINTN BlockSize;\r
+ BIOS_LEGACY_DRIVE *Bios;\r
+ UINTN CarryFlag;\r
+ UINTN MaxTransferBlocks;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ Media = This->Media;\r
+ BlockSize = Media->BlockSize;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ if (MediaId != Media->MediaId) {\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+\r
+ if (Lba > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize % BlockSize != 0) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);\r
+ AddressPacket = mEddBufferUnder1Mb;\r
+\r
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;\r
+\r
+ TransferBuffer = (UINT64)(UINTN) mEdd11Buffer;\r
+ for (; BufferSize > 0;) {\r
+ NumberOfBlocks = BufferSize / BlockSize;\r
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;\r
+ //\r
+ // Max transfer MaxTransferBlocks\r
+ //\r
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);\r
+ AddressPacket->Zero = 0;\r
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;\r
+ AddressPacket->Zero2 = 0;\r
+ AddressPacket->SegOffset = EFI_SEGMENT (TransferBuffer) << 16;\r
+ AddressPacket->SegOffset |= EFI_OFFSET (TransferBuffer);\r
+ AddressPacket->Lba = (UINT64) Lba;\r
+\r
+ Regs.H.AH = 0x43;\r
+ Regs.H.AL = 0x00;\r
+ //\r
+ // Write Verify disable\r
+ //\r
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;\r
+ Regs.X.SI = EFI_OFFSET (AddressPacket);\r
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);\r
+\r
+ TransferByteSize = NumberOfBlocks * BlockSize;\r
+ CopyMem ((VOID *) (UINTN) TransferBuffer, Buffer, TransferByteSize);\r
+\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG (\r
+ (\r
+ DEBUG_BLKIO, "Edd11BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n",\r
+ BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks\r
+ )\r
+ );\r
+ Media->MediaPresent = TRUE;\r
+ if (CarryFlag != 0) {\r
+ //\r
+ // Return Error Status\r
+ //\r
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;\r
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {\r
+ Media->MediaId++;\r
+ Bios = &BiosBlockIoDev->Bios;\r
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {\r
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {\r
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;\r
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;\r
+ } else {\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ Media->ReadOnly = FALSE;\r
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {\r
+ Media->ReadOnly = TRUE;\r
+ return EFI_WRITE_PROTECTED;\r
+ }\r
+\r
+ if (Media->RemovableMedia) {\r
+ Media->MediaPresent = FALSE;\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Media->ReadOnly = FALSE;\r
+ BufferSize = BufferSize - TransferByteSize;\r
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);\r
+ Lba += NumberOfBlocks;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Read BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId Id of the media, changes every time the media is replaced.\r
+ @param Lba The starting Logical Block Address to read from\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller is\r
+ responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The data was read correctly from the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosReadLegacyDrive (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_BLOCK_IO_MEDIA *Media;\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINTN UpperCylinder;\r
+ UINTN Temp;\r
+ UINTN Cylinder;\r
+ UINTN Head;\r
+ UINTN Sector;\r
+ UINTN NumberOfBlocks;\r
+ UINTN TransferByteSize;\r
+ UINTN ShortLba;\r
+ UINTN CheckLba;\r
+ UINTN BlockSize;\r
+ BIOS_LEGACY_DRIVE *Bios;\r
+ UINTN CarryFlag;\r
+ UINTN Retry;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ Media = This->Media;\r
+ BlockSize = Media->BlockSize;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ if (MediaId != Media->MediaId) {\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+\r
+ if (Lba > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize % BlockSize != 0) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);\r
+ ShortLba = (UINTN) Lba;\r
+\r
+ while (BufferSize != 0) {\r
+ //\r
+ // Compute I/O location in Sector, Head, Cylinder format\r
+ //\r
+ Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1;\r
+ Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector;\r
+ Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1);\r
+ Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1);\r
+\r
+ //\r
+ // Limit transfer to this Head & Cylinder\r
+ //\r
+ NumberOfBlocks = BufferSize / BlockSize;\r
+ Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1;\r
+ NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;\r
+\r
+ Retry = 3;\r
+ do {\r
+ //\r
+ // Perform the IO\r
+ //\r
+ Regs.H.AH = 2;\r
+ Regs.H.AL = (UINT8) NumberOfBlocks;\r
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;\r
+\r
+ UpperCylinder = (Cylinder & 0x0f00) >> 2;\r
+\r
+ CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head;\r
+ CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1;\r
+\r
+ DEBUG (\r
+ (DEBUG_BLKIO,\r
+ "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n",\r
+ ShortLba,\r
+ CheckLba,\r
+ Sector,\r
+ BiosBlockIoDev->Bios.MaxSector,\r
+ Head,\r
+ BiosBlockIoDev->Bios.MaxHead,\r
+ Cylinder,\r
+ UpperCylinder)\r
+ );\r
+ ASSERT (CheckLba == ShortLba);\r
+\r
+ Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff));\r
+ Regs.H.DH = (UINT8) (Head & 0x3f);\r
+ Regs.H.CH = (UINT8) (Cylinder & 0xff);\r
+\r
+ Regs.X.BX = EFI_OFFSET (mEdd11Buffer);\r
+ Regs.X.ES = EFI_SEGMENT (mEdd11Buffer);\r
+\r
+ DEBUG (\r
+ (DEBUG_BLKIO,\r
+ "INT 13h: AX:(02%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n",\r
+ Regs.H.AL,\r
+ (UINT8) (Head & 0x3f),\r
+ Regs.H.DL,\r
+ (UINT8) (Cylinder & 0xff),\r
+ (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)),\r
+ EFI_OFFSET (mEdd11Buffer),\r
+ EFI_SEGMENT (mEdd11Buffer))\r
+ );\r
+\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG (\r
+ (\r
+ DEBUG_BLKIO, "BiosReadLegacyDrive: INT 13 02 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,\r
+ CarryFlag, Regs.H.AH\r
+ )\r
+ );\r
+ Retry--;\r
+ } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED);\r
+\r
+ Media->MediaPresent = TRUE;\r
+ if (CarryFlag != 0) {\r
+ //\r
+ // Return Error Status\r
+ //\r
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;\r
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {\r
+ Media->MediaId++;\r
+ Bios = &BiosBlockIoDev->Bios;\r
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {\r
+ //\r
+ // If the size of the media changed we need to reset the disk geometry\r
+ //\r
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {\r
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;\r
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;\r
+ } else {\r
+ //\r
+ // Legacy Interfaces\r
+ //\r
+ Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;\r
+ Media->BlockSize = 512;\r
+ }\r
+\r
+ Media->ReadOnly = FALSE;\r
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+ }\r
+\r
+ if (Media->RemovableMedia) {\r
+ Media->MediaPresent = FALSE;\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ TransferByteSize = NumberOfBlocks * BlockSize;\r
+ CopyMem (Buffer, mEdd11Buffer, TransferByteSize);\r
+\r
+ ShortLba = ShortLba + NumberOfBlocks;\r
+ BufferSize = BufferSize - TransferByteSize;\r
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Write BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the write request is for.\r
+ @param Lba The starting logical block address to be written. The caller is\r
+ responsible for writing to only legitimate locations.\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The data was written correctly to the device.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosWriteLegacyDrive (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_BLOCK_IO_MEDIA *Media;\r
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINTN UpperCylinder;\r
+ UINTN Temp;\r
+ UINTN Cylinder;\r
+ UINTN Head;\r
+ UINTN Sector;\r
+ UINTN NumberOfBlocks;\r
+ UINTN TransferByteSize;\r
+ UINTN ShortLba;\r
+ UINTN CheckLba;\r
+ UINTN BlockSize;\r
+ BIOS_LEGACY_DRIVE *Bios;\r
+ UINTN CarryFlag;\r
+ UINTN Retry;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ Media = This->Media;\r
+ BlockSize = Media->BlockSize;\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ if (MediaId != Media->MediaId) {\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+\r
+ if (Lba > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize % BlockSize != 0) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);\r
+ ShortLba = (UINTN) Lba;\r
+\r
+ while (BufferSize != 0) {\r
+ //\r
+ // Compute I/O location in Sector, Head, Cylinder format\r
+ //\r
+ Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1;\r
+ Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector;\r
+ Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1);\r
+ Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1);\r
+\r
+ //\r
+ // Limit transfer to this Head & Cylinder\r
+ //\r
+ NumberOfBlocks = BufferSize / BlockSize;\r
+ Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1;\r
+ NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;\r
+\r
+ Retry = 3;\r
+ do {\r
+ //\r
+ // Perform the IO\r
+ //\r
+ Regs.H.AH = 3;\r
+ Regs.H.AL = (UINT8) NumberOfBlocks;\r
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;\r
+\r
+ UpperCylinder = (Cylinder & 0x0f00) >> 2;\r
+\r
+ CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head;\r
+ CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1;\r
+\r
+ DEBUG (\r
+ (DEBUG_BLKIO,\r
+ "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n",\r
+ ShortLba,\r
+ CheckLba,\r
+ Sector,\r
+ BiosBlockIoDev->Bios.MaxSector,\r
+ Head,\r
+ BiosBlockIoDev->Bios.MaxHead,\r
+ Cylinder,\r
+ UpperCylinder)\r
+ );\r
+ ASSERT (CheckLba == ShortLba);\r
+\r
+ Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff));\r
+ Regs.H.DH = (UINT8) (Head & 0x3f);\r
+ Regs.H.CH = (UINT8) (Cylinder & 0xff);\r
+\r
+ Regs.X.BX = EFI_OFFSET (mEdd11Buffer);\r
+ Regs.X.ES = EFI_SEGMENT (mEdd11Buffer);\r
+\r
+ TransferByteSize = NumberOfBlocks * BlockSize;\r
+ CopyMem (mEdd11Buffer, Buffer, TransferByteSize);\r
+\r
+ DEBUG (\r
+ (DEBUG_BLKIO,\r
+ "INT 13h: AX:(03%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n",\r
+ Regs.H.AL,\r
+ (UINT8) (Head & 0x3f),\r
+ Regs.H.DL,\r
+ (UINT8) (Cylinder & 0xff),\r
+ (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)),\r
+ EFI_OFFSET (mEdd11Buffer),\r
+ EFI_SEGMENT (mEdd11Buffer))\r
+ );\r
+\r
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);\r
+ DEBUG (\r
+ (\r
+ DEBUG_BLKIO, "BiosWriteLegacyDrive: INT 13 03 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,\r
+ CarryFlag, Regs.H.AH\r
+ )\r
+ );\r
+ Retry--;\r
+ } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED);\r
+\r
+ Media->MediaPresent = TRUE;\r
+ if (CarryFlag != 0) {\r
+ //\r
+ // Return Error Status\r
+ //\r
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;\r
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {\r
+ Media->MediaId++;\r
+ Bios = &BiosBlockIoDev->Bios;\r
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {\r
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {\r
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;\r
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;\r
+ } else {\r
+ //\r
+ // Legacy Interfaces\r
+ //\r
+ Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;\r
+ Media->BlockSize = 512;\r
+ }\r
+ //\r
+ // If the size of the media changed we need to reset the disk geometry\r
+ //\r
+ Media->ReadOnly = FALSE;\r
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {\r
+ Media->ReadOnly = TRUE;\r
+ return EFI_WRITE_PROTECTED;\r
+ }\r
+\r
+ if (Media->RemovableMedia) {\r
+ Media->MediaPresent = FALSE;\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Media->ReadOnly = FALSE;\r
+ ShortLba = ShortLba + NumberOfBlocks;\r
+ BufferSize = BufferSize - TransferByteSize;\r
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+## @file\r
+# Component description file for BIOS Block IO module.\r
+#\r
+# Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions\r
+# of the BSD License which accompanies this distribution. The\r
+# full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = BlockIoDxe\r
+ FILE_GUID = 4495E47E-42A9-4007-8c17-B6664F909D04\r
+ MODULE_TYPE = UEFI_DRIVER\r
+ VERSION_STRING = 1.0\r
+\r
+ ENTRY_POINT = BiosBlockIoDriverEntryPoint\r
+\r
+[Sources]\r
+ BiosBlkIo.h\r
+ Edd.h\r
+ BiosBlkIo.c\r
+ BiosInt13.c\r
+ ComponentName.c\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ DebugLib\r
+ BaseMemoryLib\r
+ UefiBootServicesTableLib\r
+ UefiLib\r
+ DevicePathLib\r
+ MemoryAllocationLib\r
+\r
+\r
+[Protocols]\r
+ gEfiBlockIoProtocolGuid\r
+ gEfiDevicePathProtocolGuid\r
+ gEfiPciIoProtocolGuid\r
+ gEfiLegacyBiosProtocolGuid\r
+\r
+\r
+[Guids]\r
+ gEfiLegacyBiosGuid\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosBlkIo.h"\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName = {\r
+ BiosBlockIoComponentNameGetDriverName,\r
+ BiosBlockIoComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosBlockIoComponentNameGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosBlockIoComponentNameGetControllerName,\r
+ "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosBlockIoDriverNameTable[] = {\r
+ {\r
+ "eng;en",\r
+ L"BIOS[INT13] Block Io Driver"\r
+ },\r
+ {\r
+ NULL,\r
+ NULL\r
+ }\r
+};\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mBiosBlockIoDriverNameTable,\r
+ DriverName,\r
+ (BOOLEAN)(This == &gBiosBlockIoComponentName)\r
+ );\r
+}\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosBlockIoComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+ Include file to suport EDD 3.0.\r
+ This file is coded to T13 D1386 Revision 3\r
+ Availible on http://www.t13.org/#Project drafts\r
+ Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r3.pdf\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EDD_H_\r
+#define _EDD_H_\r
+\r
+//\r
+// packing with no compiler padding, so that the fields\r
+// of the following architected structures can be\r
+// properly accessed from C code.\r
+//\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+ UINT8 Bus;\r
+ UINT8 Device;\r
+ UINT8 Function;\r
+ UINT8 Controller;\r
+ UINT32 Reserved;\r
+} EDD_PCI;\r
+\r
+typedef struct {\r
+ UINT16 Base;\r
+ UINT16 Reserved;\r
+ UINT32 Reserved2;\r
+} EDD_LEGACY;\r
+\r
+typedef union {\r
+ EDD_PCI Pci;\r
+ EDD_LEGACY Legacy;\r
+} EDD_INTERFACE_PATH;\r
+\r
+typedef struct {\r
+ UINT8 Master;\r
+ UINT8 Reserved[15];\r
+} EDD_ATA;\r
+\r
+typedef struct {\r
+ UINT8 Master;\r
+ UINT8 Lun;\r
+ UINT8 Reserved[14];\r
+} EDD_ATAPI;\r
+\r
+typedef struct {\r
+ UINT16 Pun;\r
+ UINT64 Lun;\r
+ UINT8 Reserved[6];\r
+} EDD_SCSI;\r
+\r
+typedef struct {\r
+ UINT64 SerialNumber;\r
+ UINT64 Reserved;\r
+} EDD_USB;\r
+\r
+typedef struct {\r
+ UINT64 Guid;\r
+ UINT64 Reserved;\r
+} EDD_1394;\r
+\r
+typedef struct {\r
+ UINT64 Wwn;\r
+ UINT64 Lun;\r
+} EDD_FIBRE;\r
+\r
+typedef union {\r
+ EDD_ATA Ata;\r
+ EDD_ATAPI Atapi;\r
+ EDD_SCSI Scsi;\r
+ EDD_USB Usb;\r
+ EDD_1394 FireWire;\r
+ EDD_FIBRE FibreChannel;\r
+} EDD_DEVICE_PATH;\r
+\r
+typedef struct {\r
+ UINT16 StructureSize;\r
+ UINT16 Flags;\r
+ UINT32 MaxCylinders;\r
+ UINT32 MaxHeads;\r
+ UINT32 SectorsPerTrack;\r
+ UINT64 PhysicalSectors;\r
+ UINT16 BytesPerSector;\r
+ UINT32 Fdpt;\r
+ UINT16 Key;\r
+ UINT8 DevicePathLength;\r
+ UINT8 Reserved1;\r
+ UINT16 Reserved2;\r
+ CHAR8 HostBusType[4];\r
+ CHAR8 InterfaceType[8];\r
+ EDD_INTERFACE_PATH InterfacePath;\r
+ EDD_DEVICE_PATH DevicePath;\r
+ UINT8 Reserved3;\r
+ UINT8 Checksum;\r
+} EDD_DRIVE_PARAMETERS;\r
+\r
+//\r
+// EDD_DRIVE_PARAMETERS.Flags defines\r
+//\r
+#define EDD_GEOMETRY_VALID 0x02\r
+#define EDD_DEVICE_REMOVABLE 0x04\r
+#define EDD_WRITE_VERIFY_SUPPORTED 0x08\r
+#define EDD_DEVICE_CHANGE 0x10\r
+#define EDD_DEVICE_LOCKABLE 0x20\r
+\r
+//\r
+// BUGBUG: This bit does not follow the spec. It tends to be always set\r
+// to work properly with Win98.\r
+//\r
+#define EDD_DEVICE_GEOMETRY_MAX 0x40\r
+\r
+typedef struct {\r
+ UINT8 PacketSizeInBytes; // 0x18\r
+ UINT8 Zero;\r
+ UINT8 NumberOfBlocks; // Max 0x7f\r
+ UINT8 Zero2;\r
+ UINT32 SegOffset;\r
+ UINT64 Lba;\r
+ UINT64 TransferBuffer;\r
+ UINT32 ExtendedBlockCount; // Max 0xffffffff\r
+ UINT32 Zero3;\r
+} EDD_DEVICE_ADDRESS_PACKET;\r
+\r
+#define EDD_VERSION_30 0x30\r
+\r
+//\r
+// Int 13 BIOS Errors\r
+//\r
+#define BIOS_PASS 0x00\r
+#define BIOS_WRITE_PROTECTED 0x03\r
+#define BIOS_SECTOR_NOT_FOUND 0x04\r
+#define BIOS_RESET_FAILED 0x05\r
+#define BIOS_DISK_CHANGED 0x06\r
+#define BIOS_DRIVE_DOES_NOT_EXIST 0x07\r
+#define BIOS_DMA_ERROR 0x08\r
+#define BIOS_DATA_BOUNDRY_ERROR 0x09\r
+#define BIOS_BAD_SECTOR 0x0a\r
+#define BIOS_BAD_TRACK 0x0b\r
+#define BIOS_MEADIA_TYPE_NOT_FOUND 0x0c\r
+#define BIOS_INVALED_FORMAT 0x0d\r
+#define BIOS_ECC_ERROR 0x10\r
+#define BIOS_ECC_CORRECTED_ERROR 0x11\r
+#define BIOS_HARD_DRIVE_FAILURE 0x20\r
+#define BIOS_SEEK_FAILED 0x40\r
+#define BIOS_DRIVE_TIMEOUT 0x80\r
+#define BIOS_DRIVE_NOT_READY 0xaa\r
+#define BIOS_UNDEFINED_ERROR 0xbb\r
+#define BIOS_WRITE_FAULT 0xcc\r
+#define BIOS_SENSE_FAILED 0xff\r
+\r
+#define MAX_EDD11_XFER 0xfe00\r
+\r
+#pragma pack()\r
+//\r
+// Internal Data Structures\r
+//\r
+typedef struct {\r
+ CHAR8 Letter;\r
+ UINT8 Number;\r
+ UINT8 EddVersion;\r
+ BOOLEAN ExtendedInt13;\r
+ BOOLEAN DriveLockingAndEjecting;\r
+ BOOLEAN Edd;\r
+ BOOLEAN Extensions64Bit;\r
+ BOOLEAN ParametersValid;\r
+ UINT8 ErrorCode;\r
+ VOID *FdptPointer;\r
+ BOOLEAN Floppy;\r
+ BOOLEAN AtapiFloppy;\r
+ UINT8 MaxHead;\r
+ UINT8 MaxSector;\r
+ UINT16 MaxCylinder;\r
+ UINT16 Pad;\r
+ EDD_DRIVE_PARAMETERS Parameters;\r
+} BIOS_LEGACY_DRIVE;\r
+\r
+#define BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE SIGNATURE_32 ('b', 'b', 'i', 'o')\r
+typedef struct {\r
+ UINTN Signature;\r
+\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE ControllerHandle;\r
+ EFI_BLOCK_IO_PROTOCOL BlockIo;\r
+ EFI_BLOCK_IO_MEDIA BlockMedia;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+\r
+ BIOS_LEGACY_DRIVE Bios;\r
+\r
+} BIOS_BLOCK_IO_DEV;\r
+\r
+#define BIOS_BLOCK_IO_FROM_THIS(a) CR (a, BIOS_BLOCK_IO_DEV, BlockIo, BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE)\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ ConsoleOut Routines that speak VGA.\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosKeyboard.h"\r
+\r
+//\r
+// EFI Driver Binding Protocol Instance\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding = {\r
+ BiosKeyboardDriverBindingSupported,\r
+ BiosKeyboardDriverBindingStart,\r
+ BiosKeyboardDriverBindingStop,\r
+ 0x3,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+\r
+/**\r
+ Enqueue the key.\r
+\r
+ @param Queue The queue to be enqueued.\r
+ @param KeyData The key data to be enqueued.\r
+\r
+ @retval EFI_NOT_READY The queue is full.\r
+ @retval EFI_SUCCESS Successfully enqueued the key data.\r
+\r
+**/\r
+EFI_STATUS\r
+Enqueue (\r
+ IN SIMPLE_QUEUE *Queue,\r
+ IN EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));\r
+ Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Dequeue the key.\r
+ \r
+ @param Queue The queue to be dequeued.\r
+ @param KeyData The key data to be dequeued.\r
+\r
+ @retval EFI_NOT_READY The queue is empty.\r
+ @retval EFI_SUCCESS Successfully dequeued the key data.\r
+\r
+**/\r
+EFI_STATUS\r
+Dequeue (\r
+ IN SIMPLE_QUEUE *Queue,\r
+ IN EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ if (Queue->Front == Queue->Rear) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA));\r
+ Queue->Front = (Queue->Front + 1) % QUEUE_MAX_COUNT;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Check whether the queue is empty.\r
+ \r
+ @param Queue The queue to be checked.\r
+\r
+ @retval EFI_NOT_READY The queue is empty.\r
+ @retval EFI_SUCCESS The queue is not empty.\r
+\r
+**/\r
+EFI_STATUS\r
+CheckQueue (\r
+ IN SIMPLE_QUEUE *Queue\r
+ )\r
+{\r
+ if (Queue->Front == Queue->Rear) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// EFI Driver Binding Protocol Functions\r
+//\r
+\r
+/**\r
+ Check whether the driver supports this device.\r
+\r
+ @param This The Udriver binding protocol.\r
+ @param Controller The controller handle to check.\r
+ @param RemainingDevicePath The remaining device path.\r
+\r
+ @retval EFI_SUCCESS The driver supports this controller.\r
+ @retval other This device isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_ISA_IO_PROTOCOL *IsaIo;\r
+\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Open the IO Abstraction(s) needed to perform the supported test\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiIsaIoProtocolGuid,\r
+ (VOID **) &IsaIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Use the ISA I/O Protocol to see if Controller is the Keyboard controller\r
+ //\r
+ if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiIsaIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Starts the device with this driver.\r
+\r
+ @param This The driver binding instance.\r
+ @param Controller Handle of device to bind driver to.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS The controller is controlled by the driver.\r
+ @retval Other This controller cannot be started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_ISA_IO_PROTOCOL *IsaIo;\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ BOOLEAN CarryFlag;\r
+ EFI_PS2_POLICY_PROTOCOL *Ps2Policy;\r
+ UINT8 Command;\r
+ EFI_STATUS_CODE_VALUE StatusCode;\r
+\r
+ BiosKeyboardPrivate = NULL;\r
+ IsaIo = NULL;\r
+ StatusCode = 0;\r
+\r
+ //\r
+ // Get Ps2 policy to set. Will be use if present.\r
+ //\r
+ gBS->LocateProtocol (\r
+ &gEfiPs2PolicyProtocolGuid,\r
+ NULL,\r
+ (VOID **) &Ps2Policy\r
+ );\r
+\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Open the IO Abstraction(s) needed\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiIsaIoProtocolGuid,\r
+ (VOID **) &IsaIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Allocate the private device structure\r
+ //\r
+ BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV));\r
+ if (NULL == BiosKeyboardPrivate) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Initialize the private device structure\r
+ //\r
+ BiosKeyboardPrivate->Signature = BIOS_KEYBOARD_DEV_SIGNATURE;\r
+ BiosKeyboardPrivate->Handle = Controller;\r
+ BiosKeyboardPrivate->LegacyBios = LegacyBios;\r
+ BiosKeyboardPrivate->IsaIo = IsaIo;\r
+\r
+ BiosKeyboardPrivate->SimpleTextIn.Reset = BiosKeyboardReset;\r
+ BiosKeyboardPrivate->SimpleTextIn.ReadKeyStroke = BiosKeyboardReadKeyStroke;\r
+\r
+ BiosKeyboardPrivate->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER;\r
+ BiosKeyboardPrivate->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER;\r
+ BiosKeyboardPrivate->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;\r
+ BiosKeyboardPrivate->ExtendedKeyboard = TRUE;\r
+ \r
+ BiosKeyboardPrivate->Queue.Front = 0;\r
+ BiosKeyboardPrivate->Queue.Rear = 0;\r
+ BiosKeyboardPrivate->SimpleTextInputEx.Reset = BiosKeyboardResetEx;\r
+ BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx;\r
+ BiosKeyboardPrivate->SimpleTextInputEx.SetState = BiosKeyboardSetState;\r
+ BiosKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify = BiosKeyboardRegisterKeyNotify; \r
+ BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify; \r
+ InitializeListHead (&BiosKeyboardPrivate->NotifyList);\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &BiosKeyboardPrivate->DevicePath\r
+ );\r
+\r
+ //\r
+ // Report that the keyboard is being enabled\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,\r
+ BiosKeyboardPrivate->DevicePath\r
+ );\r
+\r
+ //\r
+ // Setup the WaitForKey event\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ BiosKeyboardWaitForKey,\r
+ &(BiosKeyboardPrivate->SimpleTextIn),\r
+ &((BiosKeyboardPrivate->SimpleTextIn).WaitForKey)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ (BiosKeyboardPrivate->SimpleTextIn).WaitForKey = NULL;\r
+ goto Done;\r
+ }\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ BiosKeyboardWaitForKeyEx,\r
+ &(BiosKeyboardPrivate->SimpleTextInputEx),\r
+ &(BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL;\r
+ goto Done;\r
+ } \r
+\r
+ //\r
+ // Setup a periodic timer, used for reading keystrokes at a fixed interval\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ BiosKeyboardTimerHandler,\r
+ BiosKeyboardPrivate,\r
+ &BiosKeyboardPrivate->TimerEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ Status = gBS->SetTimer (\r
+ BiosKeyboardPrivate->TimerEvent,\r
+ TimerPeriodic,\r
+ KEYBOARD_TIMER_INTERVAL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,\r
+ BiosKeyboardPrivate->DevicePath\r
+ );\r
+\r
+ //\r
+ // Reset the keyboard device\r
+ //\r
+ Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset (\r
+ &BiosKeyboardPrivate->SimpleTextInputEx,\r
+ FALSE\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Do platform specific policy like port swapping and keyboard light default\r
+ //\r
+ if (Ps2Policy != NULL) {\r
+\r
+ Ps2Policy->Ps2InitHardware (Controller);\r
+\r
+ Command = 0;\r
+ if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {\r
+ Command |= 4;\r
+ }\r
+\r
+ if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {\r
+ Command |= 2;\r
+ }\r
+\r
+ if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {\r
+ Command |= 1;\r
+ }\r
+\r
+ KeyboardWrite (BiosKeyboardPrivate, 0xed);\r
+ KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);\r
+ KeyboardWrite (BiosKeyboardPrivate, Command);\r
+ //\r
+ // Call Legacy BIOS Protocol to set whatever is necessary\r
+ //\r
+ LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);\r
+ }\r
+ //\r
+ // Get Configuration\r
+ //\r
+ Regs.H.AH = 0xc0;\r
+ CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (\r
+ BiosKeyboardPrivate->LegacyBios,\r
+ 0x15,\r
+ &Regs\r
+ );\r
+\r
+ if (!CarryFlag) {\r
+ //\r
+ // Check bit 6 of Feature Byte 2.\r
+ // If it is set, then Int 16 Func 09 is supported\r
+ //\r
+ if (*(UINT8 *)(UINTN) ((Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) {\r
+ //\r
+ // Get Keyboard Functionality\r
+ //\r
+ Regs.H.AH = 0x09;\r
+ CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (\r
+ BiosKeyboardPrivate->LegacyBios,\r
+ 0x16,\r
+ &Regs\r
+ );\r
+\r
+ if (!CarryFlag) {\r
+ //\r
+ // Check bit 5 of AH.\r
+ // If it is set, then INT 16 Finc 10-12 are supported.\r
+ //\r
+ if ((Regs.H.AL & 0x40) != 0) {\r
+ //\r
+ // Set the flag to use INT 16 Func 10-12\r
+ //\r
+ BiosKeyboardPrivate->ExtendedKeyboard = TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Install protocol interfaces for the keyboard device.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Controller,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ &BiosKeyboardPrivate->SimpleTextIn,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &BiosKeyboardPrivate->SimpleTextInputEx,\r
+ NULL\r
+ );\r
+\r
+Done:\r
+ if (StatusCode != 0) {\r
+ //\r
+ // Report an Error Code for failing to start the keyboard device\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ StatusCode,\r
+ BiosKeyboardPrivate->DevicePath\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+\r
+ if (BiosKeyboardPrivate != NULL) { \r
+ if ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) {\r
+ gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);\r
+ }\r
+\r
+ if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {\r
+ gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx); \r
+ }\r
+ BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);\r
+\r
+ if (BiosKeyboardPrivate->TimerEvent != NULL) {\r
+ gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent); \r
+ }\r
+\r
+ FreePool (BiosKeyboardPrivate);\r
+ }\r
+\r
+ if (IsaIo != NULL) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiIsaIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Stop the device handled by this driver.\r
+\r
+ @param This The driver binding protocol.\r
+ @param Controller The controller to release.\r
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
+ @param ChildHandleBuffer The array of child handle.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+ @retval Others Fail to uninstall protocols attached on the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn;\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+\r
+ //\r
+ // Disable Keyboard\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ (VOID **) &SimpleTextIn,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (SimpleTextIn);\r
+\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Controller,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ &BiosKeyboardPrivate->SimpleTextIn,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &BiosKeyboardPrivate->SimpleTextInputEx,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Release the IsaIo protocol on the controller handle\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiIsaIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ //\r
+ // Free other resources\r
+ //\r
+ gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);\r
+ gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);\r
+ gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx);\r
+ BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);\r
+\r
+ FreePool (BiosKeyboardPrivate);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer-empty state.\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+\r
+ @return The data byte read from output buffer of Keyboard Controller from data port which often is port 60H.\r
+\r
+**/\r
+UINT8\r
+KeyReadDataRegister (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate\r
+ )\r
+{\r
+ UINT8 Data;\r
+\r
+ //\r
+ // Use IsaIo protocol to perform IO operations\r
+ //\r
+ BiosKeyboardPrivate->IsaIo->Io.Read (\r
+ BiosKeyboardPrivate->IsaIo,\r
+ EfiIsaIoWidthUint8,\r
+ BiosKeyboardPrivate->DataRegisterAddress,\r
+ 1,\r
+ &Data\r
+ );\r
+\r
+ return Data;\r
+}\r
+\r
+/**\r
+ Read status byte from status register of Keyboard Controller without delay and waiting for buffer-empty state.\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+\r
+ @return The status byte read from status register of Keyboard Controller from command port which often is port 64H.\r
+\r
+**/\r
+UINT8\r
+KeyReadStatusRegister (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate\r
+ )\r
+{\r
+ UINT8 Data;\r
+\r
+ //\r
+ // Use IsaIo protocol to perform IO operations\r
+ //\r
+ BiosKeyboardPrivate->IsaIo->Io.Read (\r
+ BiosKeyboardPrivate->IsaIo,\r
+ EfiIsaIoWidthUint8,\r
+ BiosKeyboardPrivate->StatusRegisterAddress,\r
+ 1,\r
+ &Data\r
+ );\r
+\r
+ return Data;\r
+}\r
+\r
+/**\r
+ Write command byte to control register of Keyboard Controller without delay and waiting for buffer-empty state.\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+ @param Data Data byte to write.\r
+\r
+**/\r
+VOID\r
+KeyWriteCommandRegister (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ IN UINT8 Data\r
+ )\r
+{\r
+ //\r
+ // Use IsaIo protocol to perform IO operations\r
+ //\r
+ BiosKeyboardPrivate->IsaIo->Io.Write (\r
+ BiosKeyboardPrivate->IsaIo,\r
+ EfiIsaIoWidthUint8,\r
+ BiosKeyboardPrivate->CommandRegisterAddress,\r
+ 1,\r
+ &Data\r
+ );\r
+}\r
+\r
+/**\r
+ Write data byte to input buffer or input/output ports of Keyboard Controller without delay and waiting for buffer-empty state.\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+ @param Data Data byte to write.\r
+\r
+**/\r
+VOID\r
+KeyWriteDataRegister (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ IN UINT8 Data\r
+ )\r
+{\r
+ //\r
+ // Use IsaIo protocol to perform IO operations\r
+ //\r
+ BiosKeyboardPrivate->IsaIo->Io.Write (\r
+ BiosKeyboardPrivate->IsaIo,\r
+ EfiIsaIoWidthUint8,\r
+ BiosKeyboardPrivate->DataRegisterAddress,\r
+ 1,\r
+ &Data\r
+ );\r
+}\r
+\r
+/**\r
+ Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer-empty state.\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+ @param Data The pointer for data that being read out.\r
+\r
+ @retval EFI_SUCCESS The data byte read out successfully.\r
+ @retval EFI_TIMEOUT Timeout occurred during reading out data byte.\r
+\r
+**/\r
+EFI_STATUS\r
+KeyboardRead (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ OUT UINT8 *Data\r
+ )\r
+{\r
+ UINT32 TimeOut;\r
+ UINT32 RegFilled;\r
+\r
+ TimeOut = 0;\r
+ RegFilled = 0;\r
+\r
+ //\r
+ // wait till output buffer full then perform the read\r
+ //\r
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) {\r
+ RegFilled = 1;\r
+ *Data = KeyReadDataRegister (BiosKeyboardPrivate);\r
+ break;\r
+ }\r
+\r
+ gBS->Stall (30);\r
+ }\r
+\r
+ if (RegFilled == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state.\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+ @param Data Data byte to write.\r
+\r
+ @retval EFI_SUCCESS The data byte is written successfully.\r
+ @retval EFI_TIMEOUT Timeout occurred during writing.\r
+\r
+**/\r
+EFI_STATUS\r
+KeyboardWrite (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ IN UINT8 Data\r
+ )\r
+{\r
+ UINT32 TimeOut;\r
+ UINT32 RegEmptied;\r
+\r
+ TimeOut = 0;\r
+ RegEmptied = 0;\r
+\r
+ //\r
+ // wait for input buffer empty\r
+ //\r
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {\r
+ RegEmptied = 1;\r
+ break;\r
+ }\r
+\r
+ gBS->Stall (30);\r
+ }\r
+\r
+ if (RegEmptied == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+ //\r
+ // Write it\r
+ //\r
+ KeyWriteDataRegister (BiosKeyboardPrivate, Data);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Write command byte to control register of Keyboard Controller with delay and waiting for buffer-empty state.\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+ @param Data Command byte to write.\r
+\r
+ @retval EFI_SUCCESS The command byte is written successfully.\r
+ @retval EFI_TIMEOUT Timeout occurred during writing.\r
+\r
+**/\r
+EFI_STATUS\r
+KeyboardCommand (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ IN UINT8 Data\r
+ )\r
+{\r
+ UINT32 TimeOut;\r
+ UINT32 RegEmptied;\r
+\r
+ TimeOut = 0;\r
+ RegEmptied = 0;\r
+\r
+ //\r
+ // Wait For Input Buffer Empty\r
+ //\r
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {\r
+ RegEmptied = 1;\r
+ break;\r
+ }\r
+\r
+ gBS->Stall (30);\r
+ }\r
+\r
+ if (RegEmptied == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+ //\r
+ // issue the command\r
+ //\r
+ KeyWriteCommandRegister (BiosKeyboardPrivate, Data);\r
+\r
+ //\r
+ // Wait For Input Buffer Empty again\r
+ //\r
+ RegEmptied = 0;\r
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {\r
+ RegEmptied = 1;\r
+ break;\r
+ }\r
+\r
+ gBS->Stall (30);\r
+ }\r
+\r
+ if (RegEmptied == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Wait for a specific value to be presented in\r
+ Data register of Keyboard Controller by keyboard and then read it,\r
+ used in keyboard commands ack\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+ @param Value The value to be waited for\r
+ @param WaitForValueTimeOut The limit of microseconds for timeout\r
+\r
+ @retval EFI_SUCCESS The command byte is written successfully.\r
+ @retval EFI_TIMEOUT Timeout occurred during writing.\r
+\r
+**/\r
+EFI_STATUS\r
+KeyboardWaitForValue (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ IN UINT8 Value,\r
+ IN UINTN WaitForValueTimeOut\r
+ )\r
+{\r
+ UINT8 Data;\r
+ UINT32 TimeOut;\r
+ UINT32 SumTimeOut;\r
+ UINT32 GotIt;\r
+\r
+ GotIt = 0;\r
+ TimeOut = 0;\r
+ SumTimeOut = 0;\r
+\r
+ //\r
+ // Make sure the initial value of 'Data' is different from 'Value'\r
+ //\r
+ Data = 0;\r
+ if (Data == Value) {\r
+ Data = 1;\r
+ }\r
+ //\r
+ // Read from 8042 (multiple times if needed)\r
+ // until the expected value appears\r
+ // use SumTimeOut to control the iteration\r
+ //\r
+ while (1) {\r
+ //\r
+ // Perform a read\r
+ //\r
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) {\r
+ Data = KeyReadDataRegister (BiosKeyboardPrivate);\r
+ break;\r
+ }\r
+\r
+ gBS->Stall (30);\r
+ }\r
+\r
+ SumTimeOut += TimeOut;\r
+\r
+ if (Data == Value) {\r
+ GotIt = 1;\r
+ break;\r
+ }\r
+\r
+ if (SumTimeOut >= WaitForValueTimeOut) {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Check results\r
+ //\r
+ if (GotIt != 0) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ @param BiosKeyboardPrivate Bioskeyboard driver private structure.\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ @retval EFI_SUCCESS The keystroke information was returned.\r
+ @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to \r
+ hardware errors.\r
+ @retval EFI_INVALID_PARAMETER KeyData is NULL. \r
+ \r
+**/\r
+EFI_STATUS\r
+KeyboardReadKeyStrokeWorker (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Use TimerEvent callback funciton to check whether there's any key pressed\r
+ //\r
+ \r
+ //\r
+ // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.\r
+ // Csm will be used to check whether there is a key pending, but the csm will disable all \r
+ // interrupt before switch to compatibility16, which mean all the efiCompatibility timer\r
+ // event will stop work during the compatibility16. And If a caller recursivly invoke this function, \r
+ // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period, \r
+ // e.g. usb keyboard driver. \r
+ // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.\r
+ // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.\r
+ //\r
+ gBS->Stall (1000);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ BiosKeyboardTimerHandler (NULL, BiosKeyboardPrivate);\r
+ //\r
+ // If there's no key, just return\r
+ //\r
+ Status = CheckQueue (&BiosKeyboardPrivate->Queue);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Status = Dequeue (&BiosKeyboardPrivate->Queue, KeyData);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// EFI Simple Text In Protocol Functions\r
+//\r
+/**\r
+ Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.\r
+\r
+ @param This Pointer of simple text Protocol.\r
+ @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.\r
+\r
+ @retval EFI_SUCCESS The command byte is written successfully.\r
+ @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardReset (\r
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+{\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ UINT8 CommandByte;\r
+ BOOLEAN MouseEnable;\r
+ EFI_INPUT_KEY Key;\r
+\r
+ MouseEnable = FALSE;\r
+ BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+ //\r
+ // 1\r
+ // Report reset progress code\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,\r
+ BiosKeyboardPrivate->DevicePath\r
+ );\r
+\r
+ //\r
+ // Report a Progress Code for clearing the keyboard buffer\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,\r
+ BiosKeyboardPrivate->DevicePath\r
+ );\r
+\r
+ //\r
+ // 2\r
+ // Raise TPL to avoid mouse operation impact\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ //\r
+ //\r
+ // Exhaust output buffer data\r
+ //\r
+ do {\r
+ Status = BiosKeyboardReadKeyStroke (\r
+ This,\r
+ &Key\r
+ );\r
+ } while (!EFI_ERROR (Status));\r
+ //\r
+ // 3\r
+ // check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H\r
+ // if not skip step 4&5 and jump to step 6 to selftest KBC and report this\r
+ // else go step 4\r
+ //\r
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) {\r
+ //\r
+ // 4\r
+ // CheckMouseStatus to decide enable it later or not\r
+ //\r
+ //\r
+ // Read the command byte of KBC\r
+ //\r
+ Status = KeyboardCommand (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDREG_VIA64_CMDBYTE_R\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardRead (\r
+ BiosKeyboardPrivate,\r
+ &CommandByte\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ //\r
+ // Check mouse enabled or not before\r
+ //\r
+ if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) {\r
+ MouseEnable = FALSE;\r
+ } else {\r
+ MouseEnable = TRUE;\r
+ }\r
+ //\r
+ // 5\r
+ // disable mouse (via KBC) and Keyborad device\r
+ //\r
+ Status = KeyboardCommand (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDREG_VIA64_AUX_DISABLE\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardCommand (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDREG_VIA64_KB_DISABLE\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // 6\r
+ // KBC Self Test\r
+ //\r
+ //\r
+ // Report a Progress Code for performing a self test on the keyboard controller\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,\r
+ BiosKeyboardPrivate->DevicePath\r
+ );\r
+\r
+ Status = KeyboardCommand (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDREG_VIA64_KBC_SLFTEST\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardWaitForValue (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDECHO_KBCSLFTEST_OK,\r
+ KEYBOARD_WAITFORVALUE_TIMEOUT\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ }\r
+ //\r
+ // 7\r
+ // Disable Mouse interface, enable Keyboard interface and declare selftest success\r
+ //\r
+ // Mouse device will block keyboard interface before it be configured, so we should disable mouse first.\r
+ //\r
+ Status = KeyboardCommand (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDREG_VIA64_CMDBYTE_W\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Write 8042 Command Byte, set System Flag\r
+ // While at the same time:\r
+ // 1. disable mouse interface,\r
+ // 2. enable kbd interface,\r
+ // 3. enable PC/XT kbd translation mode\r
+ // 4. enable mouse and kbd interrupts\r
+ //\r
+ //Command Byte bits:\r
+ // 7: Reserved\r
+ // 6: PC/XT translation mode\r
+ // 5: Disable Auxiliary device interface\r
+ // 4: Disable keyboard interface\r
+ // 3: Reserved\r
+ // 2: System Flag\r
+ // 1: Enable Auxiliary device interrupt\r
+ // 0: Enable Keyboard interrupt\r
+ //\r
+ CommandByte = 0;\r
+ Status = KeyboardWrite (\r
+ BiosKeyboardPrivate,\r
+ (UINT8) ((CommandByte &\r
+ (~KB_CMMBYTE_DISABLE_KB)) |\r
+ KB_CMMBYTE_KSCAN2UNI_COV |\r
+ KB_CMMBYTE_ENABLE_AUXINT |\r
+ KB_CMMBYTE_ENABLE_KBINT |\r
+ KB_CMMBYTE_SLFTEST_SUCC |\r
+ KB_CMMBYTE_DISABLE_AUX)\r
+ );\r
+\r
+ //\r
+ // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
+ // so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped.\r
+ // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,\r
+ // Real reset will not do.\r
+ //\r
+ if (ExtendedVerification && CheckKeyboardConnect (BiosKeyboardPrivate)) {\r
+ //\r
+ // 8\r
+ // Send keyboard reset command then read ACK\r
+ //\r
+ Status = KeyboardWrite (\r
+ BiosKeyboardPrivate,\r
+ KBC_INPBUF_VIA60_KBRESET\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardWaitForValue (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDECHO_ACK,\r
+ KEYBOARD_WAITFORVALUE_TIMEOUT\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ //\r
+ // 9\r
+ // Wait for keyboard return test OK.\r
+ //\r
+ Status = KeyboardWaitForValue (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDECHO_BATTEST_OK,\r
+ KEYBOARD_WAITFORVALUE_TIMEOUT\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ //\r
+ // 10\r
+ // set keyboard scan code set = 02 (standard configuration)\r
+ //\r
+ Status = KeyboardWrite (\r
+ BiosKeyboardPrivate,\r
+ KBC_INPBUF_VIA60_KBSCODE\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardWaitForValue (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDECHO_ACK,\r
+ KEYBOARD_WAITFORVALUE_TIMEOUT\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardWrite (\r
+ BiosKeyboardPrivate,\r
+ KBC_INPBUF_VIA60_SCODESET2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardWaitForValue (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDECHO_ACK,\r
+ KEYBOARD_WAITFORVALUE_TIMEOUT\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ //\r
+ // 11\r
+ // enable keyboard itself (not via KBC) by writing CMD F4 via 60H\r
+ //\r
+ Status = KeyboardWrite (\r
+ BiosKeyboardPrivate,\r
+ KBC_INPBUF_VIA60_KBEN\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardWaitForValue (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDECHO_ACK,\r
+ KEYBOARD_WAITFORVALUE_TIMEOUT\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ //\r
+ // 12\r
+ // Additional validation, do it as follow:\r
+ // 1). check for status register of PARE && TIM via 64H\r
+ // 2). perform KB checking by writing ABh via 64H\r
+ //\r
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & (KBC_STSREG_VIA64_PARE | KBC_STSREG_VIA64_TIM)) != 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardCommand (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDREG_VIA64_KB_CKECK\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = KeyboardWaitForValue (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDECHO_KBCHECK_OK,\r
+ KEYBOARD_WAITFORVALUE_TIMEOUT\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ }\r
+ //\r
+ // 13\r
+ // Done for validating keyboard. Enable keyboard (via KBC)\r
+ // and recover the command byte to proper value\r
+ //\r
+ Status = KeyboardCommand (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDREG_VIA64_KB_ENABLE\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // 14\r
+ // conditionally enable mouse (via KBC)\r
+ //\r
+ if (MouseEnable) {\r
+ Status = KeyboardCommand (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDREG_VIA64_AUX_ENABLE\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+\r
+ }\r
+ }\r
+\r
+Exit:\r
+ //\r
+ // 15\r
+ // resume priority of task level\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+/**\r
+ Read out the scan code of the key that has just been stroked.\r
+\r
+ @param This Pointer of simple text Protocol.\r
+ @param Key Pointer for store the key that read out.\r
+\r
+ @retval EFI_SUCCESS The key is read out successfully.\r
+ @retval other The key reading failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardReadKeyStroke (\r
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
+ OUT EFI_INPUT_KEY *Key\r
+ )\r
+{\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_STATUS Status;\r
+ EFI_KEY_DATA KeyData;\r
+\r
+ BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+ Status = KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, &KeyData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); \r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Waiting on the keyboard event, if there's any key pressed by the user, signal the event\r
+\r
+ @param Event The event that be siganlled when any key has been stroked.\r
+ @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BiosKeyboardWaitForKey (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.\r
+ // Csm will be used to check whether there is a key pending, but the csm will disable all\r
+ // interrupt before switch to compatibility16, which mean all the efiCompatibility timer\r
+ // event will stop work during the compatibility16. And If a caller recursivly invoke this function,\r
+ // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,\r
+ // e.g. usb keyboard driver.\r
+ // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.\r
+ // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.\r
+ //\r
+ gBS->Stall (1000);\r
+ //\r
+ // Use TimerEvent callback funciton to check whether there's any key pressed\r
+ //\r
+ BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context));\r
+\r
+ if (!EFI_ERROR (BiosKeyboardCheckForKey (Context))) {\r
+ gBS->SignalEvent (Event);\r
+ }\r
+}\r
+\r
+/**\r
+ Check key buffer to get the key stroke status.\r
+\r
+ @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.\r
+ \r
+ @retval EFI_SUCCESS A key is being pressed now.\r
+ @retval Other No key is now pressed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardCheckForKey (\r
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This\r
+ )\r
+{\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+\r
+ BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+ return CheckQueue (&BiosKeyboardPrivate->Queue);\r
+}\r
+//\r
+// Private worker functions\r
+//\r
+#define TABLE_END 0x0\r
+\r
+typedef struct _CONVERT_TABLE_ENTRY {\r
+ UINT16 ScanCode;\r
+ UINT16 EfiScanCode;\r
+} CONVERT_TABLE_ENTRY;\r
+\r
+CONVERT_TABLE_ENTRY mConvertTable[] = {\r
+ {\r
+ 0x47,\r
+ SCAN_HOME\r
+ },\r
+ {\r
+ 0x48,\r
+ SCAN_UP\r
+ },\r
+ {\r
+ 0x49,\r
+ SCAN_PAGE_UP\r
+ },\r
+ {\r
+ 0x4b,\r
+ SCAN_LEFT\r
+ },\r
+ {\r
+ 0x4d,\r
+ SCAN_RIGHT\r
+ },\r
+ {\r
+ 0x4f,\r
+ SCAN_END\r
+ },\r
+ {\r
+ 0x50,\r
+ SCAN_DOWN\r
+ },\r
+ {\r
+ 0x51,\r
+ SCAN_PAGE_DOWN\r
+ },\r
+ {\r
+ 0x52,\r
+ SCAN_INSERT\r
+ },\r
+ {\r
+ 0x53,\r
+ SCAN_DELETE\r
+ },\r
+ //\r
+ // Function Keys are only valid if KeyChar == 0x00\r
+ // This function does not require KeyChar to be 0x00\r
+ //\r
+ {\r
+ 0x3b,\r
+ SCAN_F1\r
+ },\r
+ {\r
+ 0x3c,\r
+ SCAN_F2\r
+ },\r
+ {\r
+ 0x3d,\r
+ SCAN_F3\r
+ },\r
+ {\r
+ 0x3e,\r
+ SCAN_F4\r
+ },\r
+ {\r
+ 0x3f,\r
+ SCAN_F5\r
+ },\r
+ {\r
+ 0x40,\r
+ SCAN_F6\r
+ },\r
+ {\r
+ 0x41,\r
+ SCAN_F7\r
+ },\r
+ {\r
+ 0x42,\r
+ SCAN_F8\r
+ },\r
+ {\r
+ 0x43,\r
+ SCAN_F9\r
+ },\r
+ {\r
+ 0x44,\r
+ SCAN_F10\r
+ },\r
+ {\r
+ 0x85,\r
+ SCAN_F11\r
+ },\r
+ {\r
+ 0x86,\r
+ SCAN_F12\r
+ },\r
+ //\r
+ // Convert ALT + Fn keys\r
+ //\r
+ {\r
+ 0x68,\r
+ SCAN_F1\r
+ },\r
+ {\r
+ 0x69,\r
+ SCAN_F2\r
+ },\r
+ {\r
+ 0x6a,\r
+ SCAN_F3\r
+ },\r
+ {\r
+ 0x6b,\r
+ SCAN_F4\r
+ },\r
+ {\r
+ 0x6c,\r
+ SCAN_F5\r
+ },\r
+ {\r
+ 0x6d,\r
+ SCAN_F6\r
+ },\r
+ {\r
+ 0x6e,\r
+ SCAN_F7\r
+ },\r
+ {\r
+ 0x6f,\r
+ SCAN_F8\r
+ },\r
+ {\r
+ 0x70,\r
+ SCAN_F9\r
+ },\r
+ {\r
+ 0x71,\r
+ SCAN_F10\r
+ },\r
+ {\r
+ TABLE_END,\r
+ SCAN_NULL\r
+ },\r
+};\r
+\r
+/**\r
+ Convert unicode combined with scan code of key to the counterpart of EFIScancode of it.\r
+\r
+ @param KeyChar Unicode of key.\r
+ @param ScanCode Scan code of key.\r
+\r
+ @return The value of EFI Scancode for the key. \r
+ @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key.\r
+\r
+**/\r
+UINT16\r
+ConvertToEFIScanCode (\r
+ IN CHAR16 KeyChar,\r
+ IN UINT16 ScanCode\r
+ )\r
+{\r
+ UINT16 EfiScanCode;\r
+ UINT16 Index;\r
+\r
+ if (KeyChar == CHAR_ESC) {\r
+ EfiScanCode = SCAN_ESC;\r
+ } else if (KeyChar == 0x00 || KeyChar == 0xe0) {\r
+ //\r
+ // Movement & Function Keys\r
+ //\r
+ for (Index = 0; (Index < sizeof (mConvertTable) / sizeof (CONVERT_TABLE_ENTRY)) && (mConvertTable[Index].ScanCode != TABLE_END); Index += 1) {\r
+ if (ScanCode == mConvertTable[Index].ScanCode) {\r
+ return mConvertTable[Index].EfiScanCode;\r
+ }\r
+ }\r
+ //\r
+ // Reach Table end, return default value\r
+ //\r
+ return SCAN_NULL;\r
+ } else {\r
+ return SCAN_NULL;\r
+ }\r
+\r
+ return EfiScanCode;\r
+}\r
+\r
+/**\r
+ Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command\r
+ If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device\r
+ should not be in system. \r
+\r
+ @param BiosKeyboardPrivate Keyboard Private Data Struture\r
+\r
+ @retval TRUE Keyboard in System.\r
+ @retval FALSE Keyboard not in System.\r
+\r
+**/\r
+BOOLEAN\r
+CheckKeyboardConnect (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+ //\r
+ // enable keyboard itself and wait for its ack\r
+ // If can't receive ack, Keyboard should not be connected.\r
+ //\r
+ Status = KeyboardWrite (\r
+ BiosKeyboardPrivate,\r
+ KBC_INPBUF_VIA60_KBEN\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ Status = KeyboardWaitForValue (\r
+ BiosKeyboardPrivate,\r
+ KBC_CMDECHO_ACK,\r
+ KEYBOARD_WAITFORVALUE_TIMEOUT\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Timer event handler: read a series of key stroke from 8042\r
+ and put them into memory key buffer. \r
+ It is registered as running under TPL_NOTIFY\r
+ \r
+ @param Event The timer event\r
+ @param Context A BIOS_KEYBOARD_DEV pointer\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BiosKeyboardTimerHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_TPL OldTpl;\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT8 KbFlag1; // 0040h:0017h - KEYBOARD - STATUS FLAGS 1\r
+ UINT8 KbFlag2; // 0040h:0018h - KEYBOARD - STATUS FLAGS 2\r
+ EFI_KEY_DATA KeyData;\r
+ LIST_ENTRY *Link;\r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+\r
+ BiosKeyboardPrivate = Context;\r
+\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ //\r
+ // if there is no key present, just return\r
+ //\r
+ if (BiosKeyboardPrivate->ExtendedKeyboard) {\r
+ Regs.H.AH = 0x11;\r
+ } else {\r
+ Regs.H.AH = 0x01;\r
+ }\r
+\r
+ BiosKeyboardPrivate->LegacyBios->Int86 (\r
+ BiosKeyboardPrivate->LegacyBios,\r
+ 0x16,\r
+ &Regs\r
+ );\r
+ if (Regs.X.Flags.ZF != 0) {\r
+ gBS->RestoreTPL (OldTpl);\r
+ return;\r
+ } \r
+\r
+ //\r
+ // Read the key\r
+ //\r
+ if (BiosKeyboardPrivate->ExtendedKeyboard) {\r
+ Regs.H.AH = 0x10;\r
+ } else {\r
+ Regs.H.AH = 0x00;\r
+ }\r
+\r
+ BiosKeyboardPrivate->LegacyBios->Int86 (\r
+ BiosKeyboardPrivate->LegacyBios,\r
+ 0x16,\r
+ &Regs\r
+ );\r
+\r
+ KeyData.Key.ScanCode = (UINT16) Regs.H.AH;\r
+ KeyData.Key.UnicodeChar = (UINT16) Regs.H.AL;\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
+ KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+ //\r
+ // Leagcy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB buffer in BDA (BIOS DATE AREA), then \r
+ // Int 16 depend KB buffer and some key bits in BDA to translate the scancode to ASCII code, and return both the scancode and ASCII \r
+ // code to Int 16 caller. This translation process works well if the Int 9 could response user input in time. But in Tiano enviorment, the Int 9 \r
+ // will be disabled after the thunk call finish, which means if user crazy input during int 9 being disabled, some keystrokes will be lost when \r
+ // KB device own hardware buffer overflows. And if the lost keystroke code is CTRL or ALT or SHIFT release code, these function key flags bit \r
+ // in BDA will not be updated. So the Int 16 will believe the CTRL or ALT or SHIFT is still pressed, and Int 16 will translate later scancode \r
+ // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other dirvers \r
+ // performance, like USB.\r
+ //\r
+ // 1. If CTRL or ALT release code is missed, all later input keys will be translated to wrong ASCII codes which the Tiano cannot support. In \r
+ // this case, the KB input seems fail to work, and user input is blocked. To solve the problem, we can help to clear the CTRL or ALT flag in BDA \r
+ // after every Int 16 finish. Thus persist to press CTRL or ALT has same effection as only press one time. It is Ok, since user not often use the \r
+ // CTRL and ALT.\r
+ //\r
+ // 2. If SHIFT release code is missed, all later lowercase input will become capital. This is ugly, but not block user input. If user press the lost \r
+ // SHIFT again, the lowercase will come back to normal. Since user often use the SHIFT, it is not reasonable to help to clear the SHIFT flag in BDA,\r
+ // which will let persist to press SHIFT has same effection as only press one time. \r
+ //\r
+ //0040h:0017h - KEYBOARD - STATUS FLAGS 1\r
+ // 7 INSert active\r
+ // 6 Caps Lock active\r
+ // 5 Num Lock active\r
+ // 4 Scroll Lock active\r
+ // 3 either Alt pressed\r
+ // 2 either Ctrl pressed\r
+ // 1 Left Shift pressed\r
+ // 0 Right Shift pressed\r
+\r
+\r
+ //\r
+ // Clear the CTRL and ALT BDA flag\r
+ //\r
+ KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1\r
+ KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2\r
+\r
+ //\r
+ // Record toggle state\r
+ //\r
+ if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) {\r
+ KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
+ }\r
+ if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) {\r
+ KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
+ }\r
+ if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) {\r
+ KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
+ }\r
+ //\r
+ // Record shift state\r
+ // BUGBUG: Need add Menu key and Left/Right Logo key state in the future\r
+ // \r
+ if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) {\r
+ KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) ? EFI_LEFT_ALT_PRESSED : EFI_RIGHT_ALT_PRESSED;\r
+ } \r
+ if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) {\r
+ KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) ? EFI_LEFT_CONTROL_PRESSED : EFI_RIGHT_CONTROL_PRESSED;\r
+ } \r
+ if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) {\r
+ KeyData.KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
+ }\r
+ if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) {\r
+ KeyData.KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
+ }\r
+\r
+ //\r
+ // Clear left alt and left ctrl BDA flag\r
+ //\r
+ KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED);\r
+ *((UINT8 *) (UINTN) 0x418) = KbFlag2;\r
+ KbFlag1 &= ~0x0C; \r
+ *((UINT8 *) (UINTN) 0x417) = KbFlag1; \r
+\r
+ \r
+ //\r
+ // Output EFI input key and shift/toggle state\r
+ //\r
+ if (KeyData.Key.UnicodeChar == CHAR_NULL || KeyData.Key.UnicodeChar == CHAR_SCANCODE || KeyData.Key.UnicodeChar == CHAR_ESC) {\r
+ KeyData.Key.ScanCode = ConvertToEFIScanCode (KeyData.Key.UnicodeChar, KeyData.Key.ScanCode);\r
+ KeyData.Key.UnicodeChar = CHAR_NULL;\r
+ } else {\r
+ KeyData.Key.ScanCode = SCAN_NULL;\r
+ }\r
+\r
+ //\r
+ // CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back.\r
+ //\r
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
+ if (KeyData.Key.UnicodeChar >= 1 && KeyData.Key.UnicodeChar <= 26) {\r
+ if (((KeyData.KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) ==\r
+ ((KeyData.KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0)\r
+ ) {\r
+ KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'a' - 1);\r
+ } else {\r
+ KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'A' - 1);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Need not return associated shift state if a class of printable characters that\r
+ // are normally adjusted by shift modifiers.\r
+ // e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'.\r
+ //\r
+ if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') ||\r
+ (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z')\r
+ ) {\r
+ KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);\r
+ }\r
+\r
+ //\r
+ // Invoke notification functions if exist\r
+ //\r
+ for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { \r
+ CurrentNotify->KeyNotificationFn (&KeyData);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Convert the Ctrl+[a-z] to Ctrl+[1-26]\r
+ //\r
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
+ if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
+ KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
+ } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
+ KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
+ }\r
+ }\r
+ Enqueue (&BiosKeyboardPrivate->Queue, &KeyData);\r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return ; \r
+}\r
+\r
+/**\r
+ Free keyboard notify list.\r
+\r
+ @param ListHead The list head\r
+\r
+ @retval EFI_SUCCESS Free the notify list successfully\r
+ @retval EFI_INVALID_PARAMETER ListHead is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+BiosKeyboardFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
+ )\r
+{\r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+\r
+ if (ListHead == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ while (!IsListEmpty (ListHead)) {\r
+ NotifyNode = CR (\r
+ ListHead->ForwardLink, \r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ RemoveEntryList (ListHead->ForwardLink);\r
+ gBS->FreePool (NotifyNode);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Check if key is registered.\r
+\r
+ @param RegsiteredData A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was registered.\r
+ @param InputData A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ @retval TRUE Key be pressed matches a registered key.\r
+ @retval FLASE Match failed. \r
+ \r
+**/\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ )\r
+{\r
+ ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+ \r
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+ return FALSE; \r
+ } \r
+ \r
+ //\r
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
+ //\r
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
+ return FALSE; \r
+ } \r
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
+ return FALSE; \r
+ } \r
+ \r
+ return TRUE;\r
+\r
+}\r
+\r
+/**\r
+ Waiting on the keyboard event, if there's any key pressed by the user, signal the event\r
+\r
+ @param Event The event that be siganlled when any key has been stroked.\r
+ @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+BiosKeyboardWaitForKeyEx (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{ \r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ \r
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (Context); \r
+ BiosKeyboardWaitForKey (Event, &BiosKeyboardPrivate->SimpleTextIn);\r
+\r
+}\r
+\r
+/**\r
+ Reset the input device and optionaly run diagnostics\r
+ \r
+ @param This Protocol instance pointer.\r
+ @param ExtendedVerification Driver may perform diagnostics on reset.\r
+\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could \r
+ not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+{\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ \r
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); \r
+\r
+ Status = BiosKeyboardPrivate->SimpleTextIn.Reset (\r
+ &BiosKeyboardPrivate->SimpleTextIn, \r
+ ExtendedVerification\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ \r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+ \r
+ @retval EFI_SUCCESS The keystroke information was returned.\r
+ @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to \r
+ hardware errors.\r
+ @retval EFI_INVALID_PARAMETER KeyData is NULL. \r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+\r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+ return KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, KeyData);\r
+ \r
+}\r
+\r
+/**\r
+ Set certain state for the input device.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+\r
+ @retval EFI_SUCCESS The device state was set successfully.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ @retval EFI_UNSUPPORTED The device does not have the ability to set its state.\r
+ @retval EFI_INVALID_PARAMETER KeyToggleState is NULL. \r
+\r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_TPL OldTpl;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINT8 Command;\r
+\r
+ if (KeyToggleState == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ Command = 0;\r
+ if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
+ Command |= 4;\r
+ }\r
+ if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
+ Command |= 2;\r
+ }\r
+ if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
+ Command |= 1;\r
+ }\r
+\r
+ Status = KeyboardWrite (BiosKeyboardPrivate, 0xed);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ } \r
+ Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ Status = KeyboardWrite (BiosKeyboardPrivate, Command);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ } \r
+ //\r
+ // Call Legacy BIOS Protocol to set whatever is necessary\r
+ //\r
+ LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+/**\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ @param KeyNotificationFunction Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ @param NotifyHandle Points to the unique handle assigned to the registered notification. \r
+\r
+ \r
+ @retval EFI_SUCCESS The notification function was registered successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_TPL OldTpl;\r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
+ LIST_ENTRY *Link;\r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+\r
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ //\r
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+ //\r
+ for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+ *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+ } \r
+ }\r
+\r
+ //\r
+ // Allocate resource to save the notification function\r
+ //\r
+ \r
+ NewNotify = (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
+ if (NewNotify == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ NewNotify->Signature = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+ NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
+ InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);\r
+\r
+ *NotifyHandle = NewNotify->NotifyHandle; \r
+ Status = EFI_SUCCESS;\r
+ \r
+Exit:\r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status; \r
+}\r
+\r
+/**\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ @param This Protocol instance pointer. \r
+ @param NotificationHandle The handle of the notification function being unregistered.\r
+ \r
+ @retval EFI_SUCCESS The notification function was unregistered successfully.\r
+ @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_TPL OldTpl;\r
+ LIST_ENTRY *Link;\r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+\r
+ //\r
+ // Check incoming notification handle\r
+ //\r
+ if (NotificationHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (((BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+ \r
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
+ \r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY); \r
+\r
+ for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ ); \r
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ //\r
+ // Remove the notification function from NotifyList and free resources\r
+ //\r
+ RemoveEntryList (&CurrentNotify->NotifyEntry); \r
+\r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Can not find the specified Notification Handle\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+\r
+Exit:\r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The user Entry Point for module BiosKeyboard. The user code starts with this function.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeBiosKeyboard(\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Install driver model protocol(s).\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gBiosKeyboardDriverBinding,\r
+ ImageHandle,\r
+ &gBiosKeyboardComponentName,\r
+ &gBiosKeyboardComponentName2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BIOS_KEYBOARD_H_\r
+#define _BIOS_KEYBOARD_H_\r
+\r
+\r
+#include <FrameworkDxe.h>\r
+\r
+#include <Guid/StatusCodeDataTypeId.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/IsaIo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/Ps2Policy.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseLib.h>\r
+\r
+//\r
+// Driver Binding Externs\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2;\r
+\r
+\r
+#include <IndustryStandard/Pci.h>\r
+\r
+//\r
+// BISO Keyboard Defines\r
+//\r
+#define CHAR_SCANCODE 0xe0\r
+#define CHAR_ESC 0x1b\r
+\r
+#define KEYBOARD_8042_DATA_REGISTER 0x60\r
+#define KEYBOARD_8042_STATUS_REGISTER 0x64\r
+#define KEYBOARD_8042_COMMAND_REGISTER 0x64\r
+\r
+#define KEYBOARD_TIMEOUT 65536 // 0.07s\r
+#define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s\r
+#define KEYBOARD_BAT_TIMEOUT 4000000 // 4s\r
+#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s\r
+// KEYBOARD COMMAND BYTE -- read by writing command KBC_CMDREG_VIA64_CMDBYTE_R to 64H, then read from 60H\r
+// write by wrting command KBC_CMDREG_VIA64_CMDBYTE_W to 64H, then write to 60H\r
+// 7: Reserved\r
+// 6: PC/XT translation mode convert\r
+// 5: Disable Auxiliary device interface\r
+// 4: Disable keyboard interface\r
+// 3: Reserved\r
+// 2: System Flag: selftest successful\r
+// 1: Enable Auxiliary device interrupt\r
+// 0: Enable Keyboard interrupt )\r
+//\r
+#define KB_CMMBYTE_KSCAN2UNI_COV (0x1 << 6)\r
+#define KB_CMMBYTE_DISABLE_AUX (0x1 << 5)\r
+#define KB_CMMBYTE_DISABLE_KB (0x1 << 4)\r
+#define KB_CMMBYTE_SLFTEST_SUCC (0x1 << 2)\r
+#define KB_CMMBYTE_ENABLE_AUXINT (0x1 << 1)\r
+#define KB_CMMBYTE_ENABLE_KBINT (0x1 << 0)\r
+\r
+//\r
+// KEYBOARD CONTROLLER STATUS REGISTER - read from 64h\r
+// 7: Parity error\r
+// 6: General time out\r
+// 5: Output buffer holds data for AUX\r
+// 4: Keyboard is not locked\r
+// 3: Command written via 64h / Data written via 60h\r
+// 2: KBC self-test successful / Power-on reset\r
+// 1: Input buffer holds CPU data / empty\r
+// 0: Output buffer holds keyboard data / empty\r
+//\r
+#define KBC_STSREG_VIA64_PARE (0x1 << 7)\r
+#define KBC_STSREG_VIA64_TIM (0x1 << 6)\r
+#define KBC_STSREG_VIA64_AUXB (0x1 << 5)\r
+#define KBC_STSREG_VIA64_KEYL (0x1 << 4)\r
+#define KBC_STSREG_VIA64_C_D (0x1 << 3)\r
+#define KBC_STSREG_VIA64_SYSF (0x1 << 2)\r
+#define KBC_STSREG_VIA64_INPB (0x1 << 1)\r
+#define KBC_STSREG_VIA64_OUTB (0x1 << 0)\r
+\r
+//\r
+// COMMANDs of KEYBOARD CONTROLLER COMMAND REGISTER - write to 64h\r
+//\r
+#define KBC_CMDREG_VIA64_CMDBYTE_R 0x20\r
+#define KBC_CMDREG_VIA64_CMDBYTE_W 0x60\r
+#define KBC_CMDREG_VIA64_AUX_DISABLE 0xA7\r
+#define KBC_CMDREG_VIA64_AUX_ENABLE 0xA8\r
+#define KBC_CMDREG_VIA64_KBC_SLFTEST 0xAA\r
+#define KBC_CMDREG_VIA64_KB_CKECK 0xAB\r
+#define KBC_CMDREG_VIA64_KB_DISABLE 0xAD\r
+#define KBC_CMDREG_VIA64_KB_ENABLE 0xAE\r
+#define KBC_CMDREG_VIA64_INTP_LOW_R 0xC0\r
+#define KBC_CMDREG_VIA64_INTP_HIGH_R 0xC2\r
+#define KBC_CMDREG_VIA64_OUTP_R 0xD0\r
+#define KBC_CMDREG_VIA64_OUTP_W 0xD1\r
+#define KBC_CMDREG_VIA64_OUTB_KB_W 0xD2\r
+#define KBC_CMDREG_VIA64_OUTB_AUX_W 0xD3\r
+#define KBC_CMDREG_VIA64_AUX_W 0xD4\r
+\r
+//\r
+// echos of KEYBOARD CONTROLLER COMMAND - read from 60h\r
+//\r
+#define KBC_CMDECHO_KBCSLFTEST_OK 0x55\r
+#define KBC_CMDECHO_KBCHECK_OK 0x00\r
+#define KBC_CMDECHO_ACK 0xFA\r
+#define KBC_CMDECHO_BATTEST_OK 0xAA\r
+#define KBC_CMDECHO_BATTEST_FAILE 0xFC\r
+\r
+//\r
+// OUTPUT PORT COMMANDs - write port by writing KBC_CMDREG_VIA64_OUTP_W via 64H, then write the command to 60H\r
+// drive data and clock of KB to high for at least 500us for BAT needs\r
+//\r
+#define KBC_OUTPORT_DCHIGH_BAT 0xC0\r
+//\r
+// scan code set type\r
+//\r
+#define KBC_INPBUF_VIA60_SCODESET1 0x01\r
+#define KBC_INPBUF_VIA60_SCODESET2 0x02\r
+#define KBC_INPBUF_VIA60_SCODESET3 0x03\r
+\r
+//\r
+// COMMANDs written to INPUT BUFFER - write to 60h\r
+//\r
+#define KBC_INPBUF_VIA60_KBECHO 0xEE\r
+#define KBC_INPBUF_VIA60_KBSCODE 0xF0\r
+#define KBC_INPBUF_VIA60_KBTYPE 0xF2\r
+#define KBC_INPBUF_VIA60_KBDELAY 0xF3\r
+#define KBC_INPBUF_VIA60_KBEN 0xF4\r
+#define KBC_INPBUF_VIA60_KBSTDDIS 0xF5\r
+#define KBC_INPBUF_VIA60_KBSTDEN 0xF6\r
+#define KBC_INPBUF_VIA60_KBRESEND 0xFE\r
+#define KBC_INPBUF_VIA60_KBRESET 0xFF\r
+\r
+//\r
+// 0040h:0017h - KEYBOARD - STATUS FLAGS 1\r
+// 7 INSert active\r
+// 6 Caps Lock active\r
+// 5 Num Lock active\r
+// 4 Scroll Lock active\r
+// 3 either Alt pressed\r
+// 2 either Ctrl pressed\r
+// 1 Left Shift pressed\r
+// 0 Right Shift pressed\r
+//\r
+// 0040h:0018h - KEYBOARD - STATUS FLAGS 2\r
+// 7: insert key is depressed\r
+// 6: caps-lock key is depressed (does not work well)\r
+// 5: num-lock key is depressed (does not work well)\r
+// 4: scroll lock key is depressed (does not work well)\r
+// 3: suspend key has been toggled (does not work well)\r
+// 2: system key is pressed and held (does not work well)\r
+// 1: left ALT key is pressed\r
+// 0: left CTRL key is pressed\r
+//\r
+#define KB_INSERT_BIT (0x1 << 7)\r
+#define KB_CAPS_LOCK_BIT (0x1 << 6)\r
+#define KB_NUM_LOCK_BIT (0x1 << 5)\r
+#define KB_SCROLL_LOCK_BIT (0x1 << 4)\r
+#define KB_ALT_PRESSED (0x1 << 3)\r
+#define KB_CTRL_PRESSED (0x1 << 2)\r
+#define KB_LEFT_SHIFT_PRESSED (0x1 << 1)\r
+#define KB_RIGHT_SHIFT_PRESSED (0x1 << 0)\r
+\r
+#define KB_SUSPEND_PRESSED (0x1 << 3)\r
+#define KB_SYSREQ_PRESSED (0x1 << 2)\r
+#define KB_LEFT_ALT_PRESSED (0x1 << 1)\r
+#define KB_LEFT_CTRL_PRESSED (0x1 << 0)\r
+\r
+//\r
+// BIOS Keyboard Device Structure\r
+//\r
+#define BIOS_KEYBOARD_DEV_SIGNATURE SIGNATURE_32 ('B', 'K', 'B', 'D')\r
+#define BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('c', 'b', 'k', 'h')\r
+\r
+typedef struct _BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY {\r
+ UINTN Signature;\r
+ EFI_HANDLE NotifyHandle;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn;\r
+ LIST_ENTRY NotifyEntry;\r
+} BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY;\r
+\r
+#define QUEUE_MAX_COUNT 32\r
+typedef struct {\r
+ UINTN Front;\r
+ UINTN Rear;\r
+ EFI_KEY_DATA Buffer[QUEUE_MAX_COUNT];\r
+} SIMPLE_QUEUE;\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ EFI_HANDLE Handle;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_ISA_IO_PROTOCOL *IsaIo;\r
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInputEx;\r
+ UINT16 DataRegisterAddress;\r
+ UINT16 StatusRegisterAddress;\r
+ UINT16 CommandRegisterAddress;\r
+ BOOLEAN ExtendedKeyboard;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ \r
+ //\r
+ // Buffer storing EFI_KEY_DATA\r
+ //\r
+ SIMPLE_QUEUE Queue;\r
+\r
+ //\r
+ // Notification Function List\r
+ //\r
+ LIST_ENTRY NotifyList;\r
+ EFI_EVENT TimerEvent;\r
+ \r
+} BIOS_KEYBOARD_DEV;\r
+\r
+#define BIOS_KEYBOARD_DEV_FROM_THIS(a) CR (a, BIOS_KEYBOARD_DEV, SimpleTextIn, BIOS_KEYBOARD_DEV_SIGNATURE)\r
+#define TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS(a) \\r
+ CR (a, \\r
+ BIOS_KEYBOARD_DEV, \\r
+ SimpleTextInputEx, \\r
+ BIOS_KEYBOARD_DEV_SIGNATURE \\r
+ )\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding;\r
+\r
+//\r
+// Driver Binding Protocol functions\r
+//\r
+\r
+/**\r
+ Check whether the driver supports this device.\r
+\r
+ @param This The Udriver binding protocol.\r
+ @param Controller The controller handle to check.\r
+ @param RemainingDevicePath The remaining device path.\r
+\r
+ @retval EFI_SUCCESS The driver supports this controller.\r
+ @retval other This device isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+/**\r
+ Starts the device with this driver.\r
+\r
+ @param This The driver binding instance.\r
+ @param Controller Handle of device to bind driver to.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS The controller is controlled by the driver.\r
+ @retval Other This controller cannot be started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+/**\r
+ Stop the device handled by this driver.\r
+\r
+ @param This The driver binding protocol.\r
+ @param Controller The controller to release.\r
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
+ @param ChildHandleBuffer The array of child handle.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+ @retval Others Fail to uninstall protocols attached on the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ );\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+\r
+//\r
+// Simple Text Input Protocol functions\r
+//\r
+/**\r
+ Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.\r
+\r
+ @param This Pointer of simple text Protocol.\r
+ @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.\r
+\r
+ @retval EFI_SUCCESS The command byte is written successfully.\r
+ @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardReset (\r
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ );\r
+\r
+/**\r
+ Read out the scan code of the key that has just been stroked.\r
+\r
+ @param This Pointer of simple text Protocol.\r
+ @param Key Pointer for store the key that read out.\r
+\r
+ @retval EFI_SUCCESS The key is read out successfully.\r
+ @retval other The key reading failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardReadKeyStroke (\r
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
+ OUT EFI_INPUT_KEY *Key\r
+ );\r
+\r
+//\r
+// Private worker functions\r
+//\r
+/**\r
+ Waiting on the keyboard event, if there's any key pressed by the user, signal the event\r
+\r
+ @param Event The event that be siganlled when any key has been stroked.\r
+ @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BiosKeyboardWaitForKey (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
+/**\r
+ Check key buffer to get the key stroke status.\r
+\r
+ @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.\r
+ \r
+ @retval EFI_SUCCESS A key is being pressed now.\r
+ @retval Other No key is now pressed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardCheckForKey (\r
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ Convert unicode combined with scan code of key to the counterpart of EFIScancode of it.\r
+\r
+ @param KeyChar Unicode of key.\r
+ @param ScanCode Scan code of key.\r
+\r
+ @return The value of EFI Scancode for the key. \r
+ @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key.\r
+\r
+**/\r
+UINT16\r
+ConvertToEFIScanCode (\r
+ IN CHAR16 KeyChar,\r
+ IN UINT16 ScanCode\r
+ );\r
+\r
+/**\r
+ Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command\r
+ If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device\r
+ should not be in system. \r
+\r
+ @param BiosKeyboardPrivate Keyboard Private Data Struture\r
+\r
+ @retval TRUE Keyboard in System.\r
+ @retval FALSE Keyboard not in System.\r
+\r
+**/\r
+BOOLEAN\r
+CheckKeyboardConnect (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate\r
+ );\r
+\r
+/**\r
+ Timer event handler: read a series of key stroke from 8042\r
+ and put them into memory key buffer. \r
+ It is registered as running under TPL_NOTIFY\r
+ \r
+ @param Event The timer event\r
+ @param Context A BIOS_KEYBOARD_DEV pointer\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BiosKeyboardTimerHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
+/**\r
+ Reset the input device and optionaly run diagnostics\r
+ \r
+ @param This Protocol instance pointer.\r
+ @param ExtendedVerification Driver may perform diagnostics on reset.\r
+\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could \r
+ not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ );\r
+\r
+/**\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+ \r
+ @retval EFI_SUCCESS The keystroke information was returned.\r
+ @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to \r
+ hardware errors.\r
+ @retval EFI_INVALID_PARAMETER KeyData is NULL. \r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ );\r
+\r
+/**\r
+ Set certain state for the input device.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+\r
+ @retval EFI_SUCCESS The device state was set successfully.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ @retval EFI_UNSUPPORTED The device does not have the ability to set its state.\r
+ @retval EFI_INVALID_PARAMETER KeyToggleState is NULL. \r
+\r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ );\r
+\r
+/**\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ @param KeyNotificationFunction Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ @param NotifyHandle Points to the unique handle assigned to the registered notification. \r
+\r
+ \r
+ @retval EFI_SUCCESS The notification function was registered successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ );\r
+\r
+/**\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ @param This Protocol instance pointer. \r
+ @param NotificationHandle The handle of the notification function being unregistered.\r
+ \r
+ @retval EFI_SUCCESS The notification function was unregistered successfully.\r
+ @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
+ \r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ );\r
+\r
+/**\r
+ Wait for a specific value to be presented in\r
+ Data register of Keyboard Controller by keyboard and then read it,\r
+ used in keyboard commands ack\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+ @param Value The value to be waited for\r
+ @param WaitForValueTimeOut The limit of microseconds for timeout\r
+\r
+ @retval EFI_SUCCESS The command byte is written successfully.\r
+ @retval EFI_TIMEOUT Timeout occurred during writing.\r
+\r
+**/\r
+EFI_STATUS\r
+KeyboardWaitForValue (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ IN UINT8 Value,\r
+ IN UINTN WaitForValueTimeOut\r
+ );\r
+\r
+/**\r
+ Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state.\r
+\r
+ @param BiosKeyboardPrivate Keyboard instance pointer.\r
+ @param Data Data byte to write.\r
+\r
+ @retval EFI_SUCCESS The data byte is written successfully.\r
+ @retval EFI_TIMEOUT Timeout occurred during writing.\r
+\r
+**/\r
+EFI_STATUS\r
+KeyboardWrite (\r
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
+ IN UINT8 Data\r
+ );\r
+\r
+/**\r
+ Free keyboard notify list.\r
+\r
+ @param ListHead The list head\r
+\r
+ @retval EFI_SUCCESS Free the notify list successfully\r
+ @retval EFI_INVALID_PARAMETER ListHead is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+BiosKeyboardFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
+ ); \r
+\r
+/**\r
+ Check if key is registered.\r
+\r
+ @param RegsiteredData A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was registered.\r
+ @param InputData A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ @retval TRUE Key be pressed matches a registered key.\r
+ @retval FLASE Match failed. \r
+ \r
+**/\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ );\r
+\r
+/**\r
+ Waiting on the keyboard event, if there's any key pressed by the user, signal the event\r
+\r
+ @param Event The event that be siganlled when any key has been stroked.\r
+ @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+BiosKeyboardWaitForKeyEx (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosKeyboard.h"\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName = {\r
+ BiosKeyboardComponentNameGetDriverName,\r
+ BiosKeyboardComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosKeyboardComponentNameGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosKeyboardComponentNameGetControllerName,\r
+ "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosKeyboardDriverNameTable[] = {\r
+ {\r
+ "eng;en",\r
+ L"BIOS[INT16] Keyboard Driver"\r
+ },\r
+ {\r
+ NULL,\r
+ NULL\r
+ }\r
+};\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mBiosKeyboardDriverNameTable,\r
+ DriverName,\r
+ (BOOLEAN)(This == &gBiosKeyboardComponentName)\r
+ );\r
+}\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BIOS_KEYBOARD_COMPONENT_NAME_H_\r
+#define _BIOS_KEYBOARD_COMPONENT_NAME_H_\r
+\r
+\r
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2;\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosKeyboardComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+\r
+#endif\r
--- /dev/null
+## @file\r
+# Component description file for BiosKeyboard module.\r
+#\r
+# Ps2 Keyboard driver by using Legacy Bios protocol service and IsaIo protocol service.\r
+# This dirver uses legacy INT16 to get the key stroke status.\r
+#\r
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions\r
+# of the BSD License which accompanies this distribution. The\r
+# full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = KeyboardDxe\r
+ FILE_GUID = 5479662B-6AE4-49e8-A6BD-6DE4B625811F\r
+ MODULE_TYPE = UEFI_DRIVER\r
+ VERSION_STRING = 1.0\r
+\r
+ ENTRY_POINT = InitializeBiosKeyboard\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+# DRIVER_BINDING = gBiosKeyboardDriverBinding\r
+# COMPONENT_NAME = gBiosKeyboardComponentName\r
+#\r
+\r
+[Sources]\r
+ ComponentName.c\r
+ ComponentName.h\r
+ BiosKeyboard.c\r
+ BiosKeyboard.h\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ ReportStatusCodeLib\r
+ BaseMemoryLib\r
+ UefiLib\r
+ DebugLib\r
+ BaseLib\r
+\r
+[Protocols]\r
+ gEfiIsaIoProtocolGuid # PROTOCOL TO_START\r
+ gEfiSimpleTextInProtocolGuid # PROTOCOL BY_START\r
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL BY_START\r
+ gEfiLegacyBiosProtocolGuid # PROTOCOL TO_START\r
+ gEfiPs2PolicyProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosSnp16.h"\r
+\r
+\r
+///\r
+/// EFI Driver Binding Protocol Instance\r
+///\r
+EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = {\r
+ BiosSnp16DriverBindingSupported,\r
+ BiosSnp16DriverBindingStart,\r
+ BiosSnp16DriverBindingStop,\r
+ 0x3,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+///\r
+/// This boolean is used to determine if we should release the cached vector during an error condition.\r
+///\r
+BOOLEAN mCachedInt1A = FALSE;\r
+\r
+//\r
+// Private worker functions;\r
+//\r
+\r
+/**\r
+ Start the UNDI interface.\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ @param Ax PCI address of Undi device.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. \r
+ @retval Others Status of start 16 bit UNDI ROM. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkStartUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ UINT16 Ax\r
+ );\r
+\r
+/**\r
+ Start the UNDI interface\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. \r
+ @retval Others Status of start 16 bit UNDI ROM. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkStopUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice\r
+ );\r
+\r
+/**\r
+ Stop the UNDI interface\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM. \r
+ @retval Others Status of stop 16 bit UNDI ROM. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkCleanupUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice\r
+ );\r
+\r
+/**\r
+ Get runtime information for Undi network interface\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_SUCCESS Sucess operation. \r
+ @retval Others Fail to get runtime information for Undi network interface. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkGetInformation (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ Get NIC type\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_SUCCESS Sucess operation. \r
+ @retval Others Fail to get NIC type.\r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkGetNicType (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ Get NDIS information\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_SUCCESS Sucess operation. \r
+ @retval Others Fail to get NDIS information.\r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkGetNdisInfo (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ Signal handlers for ExitBootServices event.\r
+ \r
+ Clean up any Real-mode UNDI residue from the system \r
+ \r
+ @param Event ExitBootServices event\r
+ @param Context \r
+**/\r
+VOID\r
+EFIAPI\r
+Undi16SimpleNetworkEvent (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
+/**\r
+ Loads the undi driver.\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ \r
+ @retval EFI_SUCCESS - Successfully loads undi driver.\r
+ @retval EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.\r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkLoadUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice\r
+ );\r
+\r
+/**\r
+ Unload 16 bit UNDI Option ROM from memory\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ \r
+ @return EFI_STATUS \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkUnloadUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice\r
+ );\r
+\r
+/**\r
+ Entry point for EFI drivers.\r
+\r
+ @param ImageHandle Handle that identifies the loaded image.\r
+ @param SystemTable System Table for this image.\r
+ \r
+ @return EFI_STATUS Return status from EfiLibInstallAllDriverProtocols. \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16DriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ return EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gBiosSnp16DriverBinding,\r
+ ImageHandle,\r
+ &gBiosSnp16ComponentName,\r
+ &gBiosSnp16ComponentName2\r
+ );\r
+}\r
+\r
+//\r
+// EFI Driver Binding Protocol Functions\r
+//\r
+/**\r
+ Tests to see if this driver supports a given controller.\r
+\r
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param Controller The handle of the controller to test.\r
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
+ \r
+ @retval EFI_SUCCESS The driver supports given controller.\r
+ @retval EFI_UNSUPPORT The driver doesn't support given controller.\r
+ @retval Other Other errors prevent driver finishing to test\r
+ if the driver supports given controller.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE00 Pci;\r
+\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Open the IO Abstraction(s) needed to perform the supported test\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ //\r
+ // Open the IO Abstraction(s) needed to perform the supported test\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // See if this is a PCI Network Controller by looking at the Command register and\r
+ // Class Code Register\r
+ //\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+Done:\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Starts the Snp device controller\r
+\r
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param Controller The handle of the controller to test.\r
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
+ \r
+ @retval EFI_SUCCESS - The device was started. \r
+ @retval EFI_DEVICE_ERROR - The device could not be started due to a device error.\r
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ EFI_DEV_PATH Node;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN Segment;\r
+ UINTN Bus;\r
+ UINTN Device;\r
+ UINTN Function;\r
+ UINTN Flags;\r
+ UINT64 Supports;\r
+\r
+ SimpleNetworkDevice = NULL;\r
+ PciIo = NULL;\r
+\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Open the IO Abstraction(s) needed\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ Supports,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Check to see if there is a legacy option ROM image associated with this PCI device\r
+ //\r
+ Status = LegacyBios->CheckPciRom (\r
+ LegacyBios,\r
+ Controller,\r
+ NULL,\r
+ NULL,\r
+ &Flags\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Post the legacy option ROM if it is available.\r
+ //\r
+ Status = LegacyBios->InstallPciRom (\r
+ LegacyBios,\r
+ Controller,\r
+ NULL,\r
+ &Flags,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Allocate memory for this SimpleNetwork device instance\r
+ //\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData,\r
+ sizeof (EFI_SIMPLE_NETWORK_DEV),\r
+ (VOID **) &SimpleNetworkDevice\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV));\r
+\r
+ //\r
+ // Initialize the SimpleNetwork device instance\r
+ //\r
+ SimpleNetworkDevice->Signature = EFI_SIMPLE_NETWORK_DEV_SIGNATURE;\r
+ SimpleNetworkDevice->LegacyBios = LegacyBios;\r
+ SimpleNetworkDevice->BaseDevicePath = DevicePath;\r
+ SimpleNetworkDevice->PciIo = PciIo;\r
+\r
+ //\r
+ // Initialize the Nii Protocol\r
+ //\r
+ SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;\r
+ SimpleNetworkDevice->Nii.Type = EfiNetworkInterfaceUndi;\r
+\r
+ CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4);\r
+\r
+ //\r
+ // Load 16 bit UNDI Option ROM into Memory\r
+ //\r
+ Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI. Status = %r\n", Status));\r
+ goto Done;\r
+ }\r
+\r
+ SimpleNetworkDevice->UndiLoaded = TRUE;\r
+\r
+ //\r
+ // Call PXENV_START_UNDI - Initilizes the UNID interface for use.\r
+ //\r
+ PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
+ Status = Undi16SimpleNetworkStartUndi (\r
+ SimpleNetworkDevice,\r
+ (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi. Status = %r\n", Status));\r
+ goto Done;\r
+ }\r
+ //\r
+ // Initialize the Simple Network Protocol\r
+ //\r
+ DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n"));\r
+\r
+ SimpleNetworkDevice->SimpleNetwork.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
+ SimpleNetworkDevice->SimpleNetwork.Start = Undi16SimpleNetworkStart;\r
+ SimpleNetworkDevice->SimpleNetwork.Stop = Undi16SimpleNetworkStop;\r
+ SimpleNetworkDevice->SimpleNetwork.Initialize = Undi16SimpleNetworkInitialize;\r
+ SimpleNetworkDevice->SimpleNetwork.Reset = Undi16SimpleNetworkReset;\r
+ SimpleNetworkDevice->SimpleNetwork.Shutdown = Undi16SimpleNetworkShutdown;\r
+ SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters;\r
+ SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress;\r
+ SimpleNetworkDevice->SimpleNetwork.Statistics = Undi16SimpleNetworkStatistics;\r
+ SimpleNetworkDevice->SimpleNetwork.MCastIpToMac = Undi16SimpleNetworkMCastIpToMac;\r
+ SimpleNetworkDevice->SimpleNetwork.NvData = Undi16SimpleNetworkNvData;\r
+ SimpleNetworkDevice->SimpleNetwork.GetStatus = Undi16SimpleNetworkGetStatus;\r
+ SimpleNetworkDevice->SimpleNetwork.Transmit = Undi16SimpleNetworkTransmit;\r
+ SimpleNetworkDevice->SimpleNetwork.Receive = Undi16SimpleNetworkReceive;\r
+ SimpleNetworkDevice->SimpleNetwork.Mode = &(SimpleNetworkDevice->SimpleNetworkMode);\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ Undi16SimpleNetworkWaitForPacket,\r
+ &SimpleNetworkDevice->SimpleNetwork,\r
+ &SimpleNetworkDevice->SimpleNetwork.WaitForPacket\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR : Could not create event. Status = %r\n", Status));\r
+ goto Done;\r
+ }\r
+ //\r
+ // Create an event to be signalled when ExitBootServices occurs in order\r
+ // to clean up nicely\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ Undi16SimpleNetworkEvent,\r
+ NULL,\r
+ &gEfiEventExitBootServicesGuid,\r
+ &SimpleNetworkDevice->EfiBootEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR : Could not create event. Status = %r\n", Status));\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Create an event to be signalled when Legacy Boot occurs to clean up the IVT\r
+ //\r
+ Status = EfiCreateEventLegacyBootEx(\r
+ TPL_NOTIFY, \r
+ Undi16SimpleNetworkEvent, \r
+ NULL, \r
+ &SimpleNetworkDevice->LegacyBootEvent\r
+ );\r
+ \r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((DEBUG_ERROR,"ERROR : Could not create event. Status = %r\n",Status));\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Initialize the SimpleNetwork Mode Information\r
+ //\r
+ DEBUG ((DEBUG_NET, "Initialize Mode Information\n"));\r
+\r
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;\r
+ SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize = 14;\r
+ SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE;\r
+ SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported = TRUE;\r
+ SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |\r
+ EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |\r
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |\r
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |\r
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
+ SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR;\r
+\r
+ //\r
+ // Initialize the SimpleNetwork Private Information\r
+ //\r
+ DEBUG ((DEBUG_NET, "Initialize Private Information\n"));\r
+\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1,\r
+ (VOID **) &SimpleNetworkDevice->Xmit\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ 1,\r
+ &SimpleNetworkDevice->TxRealModeMediaHeader\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ 1,\r
+ &SimpleNetworkDevice->TxRealModeDataBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ 1,\r
+ &SimpleNetworkDevice->TxDestAddr\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ SimpleNetworkDevice->Xmit->XmitOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f);\r
+\r
+ SimpleNetworkDevice->Xmit->XmitSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4);\r
+\r
+ SimpleNetworkDevice->Xmit->DataBlkCount = 1;\r
+\r
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType = 1;\r
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte = 0;\r
+\r
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f);\r
+\r
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4);\r
+\r
+ SimpleNetworkDevice->TxBufferFifo.First = 0;\r
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;\r
+\r
+ //\r
+ // Start() the SimpleNetwork device\r
+ //\r
+ DEBUG ((DEBUG_NET, "Start()\n"));\r
+\r
+ Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // GetInformation() the SimpleNetwork device\r
+ //\r
+ DEBUG ((DEBUG_NET, "GetInformation()\n"));\r
+\r
+ Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Build the device path for the child device\r
+ //\r
+ ZeroMem (&Node, sizeof (Node));\r
+ Node.DevPath.Type = MESSAGING_DEVICE_PATH;\r
+ Node.DevPath.SubType = MSG_MAC_ADDR_DP;\r
+ SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));\r
+ CopyMem (\r
+ &Node.MacAddr.MacAddress,\r
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,\r
+ sizeof (EFI_MAC_ADDRESS)\r
+ );\r
+ SimpleNetworkDevice->DevicePath = AppendDevicePathNode (\r
+ SimpleNetworkDevice->BaseDevicePath,\r
+ &Node.DevPath\r
+ );\r
+\r
+ //\r
+ // GetNicType() the SimpleNetwork device\r
+ //\r
+ DEBUG ((DEBUG_NET, "GetNicType()\n"));\r
+\r
+ Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // GetNdisInfo() the SimpleNetwork device\r
+ //\r
+ DEBUG ((DEBUG_NET, "GetNdisInfo()\n"));\r
+\r
+ Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Stop() the SimpleNetwork device\r
+ //\r
+ DEBUG ((DEBUG_NET, "Stop()\n"));\r
+\r
+ Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Print Mode information\r
+ //\r
+ DEBUG ((DEBUG_NET, "Mode->State = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State));\r
+ DEBUG ((DEBUG_NET, "Mode->HwAddressSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize));\r
+ DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable));\r
+ DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported));\r
+ DEBUG ((DEBUG_NET, "Mode->NvRamSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize));\r
+ DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize));\r
+ DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting));\r
+ DEBUG ((DEBUG_NET, "Mode->IfType = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType));\r
+ DEBUG ((DEBUG_NET, "Mode->MCastFilterCount = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount));\r
+ for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) {\r
+ DEBUG ((DEBUG_NET, " Filter[%02d] = ", Index));\r
+ for (Index2 = 0; Index2 < 16; Index2++) {\r
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n"));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "CurrentAddress = "));\r
+ for (Index2 = 0; Index2 < 16; Index2++) {\r
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n"));\r
+\r
+ DEBUG ((DEBUG_NET, "BroadcastAddress = "));\r
+ for (Index2 = 0; Index2 < 16; Index2++) {\r
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n"));\r
+\r
+ DEBUG ((DEBUG_NET, "PermanentAddress = "));\r
+ for (Index2 = 0; Index2 < 16; Index2++) {\r
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n"));\r
+\r
+ //\r
+ // The network device was started, information collected, and stopped.\r
+ // Install protocol interfaces for the SimpleNetwork device.\r
+ //\r
+ DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n"));\r
+\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &SimpleNetworkDevice->Handle,\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ &SimpleNetworkDevice->SimpleNetwork,\r
+ &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
+ &SimpleNetworkDevice->Nii,\r
+ &gEfiDevicePathProtocolGuid,\r
+ SimpleNetworkDevice->DevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Open PCI I/O from the newly created child handle\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ SimpleNetworkDevice->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+\r
+ DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n"));\r
+\r
+Done:\r
+ if (EFI_ERROR (Status)) {\r
+ if (SimpleNetworkDevice != NULL) {\r
+\r
+ Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);\r
+ //\r
+ // CLOSE + SHUTDOWN\r
+ //\r
+ Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);\r
+ //\r
+ // CLEANUP\r
+ //\r
+ Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);\r
+ //\r
+ // STOP\r
+ //\r
+ if (SimpleNetworkDevice->UndiLoaded) {\r
+ Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {\r
+ gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->LegacyBootEvent != NULL) {\r
+ gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);\r
+ }\r
+ \r
+ if (SimpleNetworkDevice->EfiBootEvent != NULL) {\r
+ gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->Xmit != NULL) {\r
+ gBS->FreePages (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,\r
+ sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1\r
+ );\r
+ }\r
+\r
+ if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {\r
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {\r
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->TxDestAddr != NULL) {\r
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);\r
+ }\r
+\r
+ gBS->FreePool (SimpleNetworkDevice);\r
+ \r
+ //\r
+ // Only restore the vector if it was cached.\r
+ //\r
+ if (mCachedInt1A) {\r
+ RestoreCachedVectorAddress (0x1A);\r
+ mCachedInt1A = FALSE;\r
+ }\r
+ }\r
+\r
+ if (PciIo != NULL) {\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationDisable,\r
+ Supports,\r
+ NULL\r
+ );\r
+ }\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ if (Status != EFI_OUT_OF_RESOURCES) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ } \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Stops the device by given device controller.\r
+\r
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param Controller The handle of the controller to test.\r
+ @param NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param ChildHandleBuffer An array of child handles to be freed. May be NULL if\r
+ NumberOfChildren is 0.\r
+ \r
+ @retval EFI_SUCCESS - The device was stopped.\r
+ @retval EFI_DEVICE_ERROR - The device could not be stopped due to a device error.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ BOOLEAN AllChildrenStopped;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Supports;\r
+\r
+ //\r
+ // Complete all outstanding transactions to Controller.\r
+ // Don't allow any new transaction to Controller to be started.\r
+ //\r
+ if (NumberOfChildren == 0) {\r
+ //\r
+ // Close the bus driver\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationDisable,\r
+ Supports,\r
+ NULL\r
+ );\r
+ }\r
+ }\r
+\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ AllChildrenStopped = TRUE;\r
+\r
+ for (Index = 0; Index < NumberOfChildren; Index++) {\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandleBuffer[Index],\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ (VOID **) &SimpleNetwork,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork);\r
+\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ChildHandleBuffer[Index]\r
+ );\r
+\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ SimpleNetworkDevice->Handle,\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ &SimpleNetworkDevice->SimpleNetwork,\r
+ &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
+ &SimpleNetworkDevice->Nii,\r
+ &gEfiDevicePathProtocolGuid,\r
+ SimpleNetworkDevice->DevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ ChildHandleBuffer[Index],\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ } else {\r
+\r
+ Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);\r
+ //\r
+ // CLOSE + SHUTDOWN\r
+ //\r
+ Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);\r
+ //\r
+ // CLEANUP\r
+ //\r
+ Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);\r
+ //\r
+ // STOP\r
+ //\r
+ if (SimpleNetworkDevice->UndiLoaded) {\r
+ Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {\r
+ gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->LegacyBootEvent != NULL) {\r
+ gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);\r
+ }\r
+ \r
+ if (SimpleNetworkDevice->EfiBootEvent != NULL) {\r
+ gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->Xmit != NULL) {\r
+ gBS->FreePages (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,\r
+ sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1\r
+ );\r
+ }\r
+\r
+ if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {\r
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {\r
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);\r
+ }\r
+\r
+ if (SimpleNetworkDevice->TxDestAddr != NULL) {\r
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);\r
+ }\r
+\r
+ gBS->FreePool (SimpleNetworkDevice);\r
+ }\r
+\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ AllChildrenStopped = FALSE;\r
+ }\r
+ }\r
+\r
+ if (!AllChildrenStopped) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// FIFO Support Functions\r
+//\r
+/**\r
+ Judge whether transmit FIFO is full.\r
+\r
+ @param Fifo Point to trasmit FIFO structure.\r
+ \r
+ @return BOOLEAN whether transmit FIFO is full.\r
+**/\r
+BOOLEAN\r
+SimpleNetworkTransmitFifoFull (\r
+ EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo\r
+ )\r
+{\r
+ if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Judge whether transmit FIFO is empty.\r
+\r
+ @param Fifo Point to trasmit FIFO structure.\r
+ \r
+ @return BOOLEAN whether transmit FIFO is empty.\r
+**/\r
+BOOLEAN\r
+SimpleNetworkTransmitFifoEmpty (\r
+ EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo\r
+ )\r
+{\r
+ if (Fifo->Last == Fifo->First) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Add data into transmit buffer.\r
+\r
+ @param Fifo Point to trasmit FIFO structure.\r
+ @param Data The data point want to be added.\r
+ \r
+ @retval EFI_OUT_OF_RESOURCES FIFO is full \r
+ @retval EFI_SUCCESS Success operation. \r
+**/\r
+EFI_STATUS\r
+SimpleNetworkTransmitFifoAdd (\r
+ EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,\r
+ VOID *Data\r
+ )\r
+{\r
+ if (SimpleNetworkTransmitFifoFull (Fifo)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Fifo->Data[Fifo->Last] = Data;\r
+ Fifo->Last = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get a data and remove it from network transmit FIFO.\r
+\r
+ @param Fifo Point to trasmit FIFO structure.\r
+ @param Data On return, point to the data point want to be got and removed.\r
+ \r
+ @retval EFI_OUT_OF_RESOURCES network transmit buffer is empty. \r
+ @retval EFI_SUCCESS Success operation. \r
+**/\r
+EFI_STATUS\r
+SimpleNetworkTransmitFifoRemove (\r
+ EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,\r
+ VOID **Data\r
+ )\r
+{\r
+ if (SimpleNetworkTransmitFifoEmpty (Fifo)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ *Data = Fifo->Data[Fifo->First];\r
+ Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get recive filter setting according to EFI mask value.\r
+\r
+ @param ReceiveFilterSetting filter setting EFI mask value.\r
+ \r
+ @return UINT16 Undi filter setting value.\r
+**/\r
+UINT16\r
+Undi16GetPacketFilterSetting (\r
+ UINTN ReceiveFilterSetting\r
+ )\r
+{\r
+ UINT16 PktFilter;\r
+\r
+ PktFilter = 0;\r
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {\r
+ PktFilter |= FLTR_DIRECTED;\r
+ }\r
+\r
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {\r
+ PktFilter |= FLTR_DIRECTED;\r
+ }\r
+\r
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {\r
+ PktFilter |= FLTR_BRDCST;\r
+ }\r
+\r
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {\r
+ PktFilter |= FLTR_PRMSCS;\r
+ }\r
+\r
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {\r
+ PktFilter |= FLTR_PRMSCS;\r
+ //\r
+ // @bug : Do not know if this is right????\r
+ //\r
+ }\r
+ //\r
+ // @bug : What is FLTR_SRC_RTG?\r
+ //\r
+ return PktFilter;\r
+}\r
+\r
+/**\r
+ Get filter setting from multi cast buffer .\r
+ \r
+ @param Mode Point to mode structure.\r
+ @param McastBuffer The multi cast buffer \r
+ @param HwAddressSize Size of filter value.\r
+ \r
+**/\r
+VOID\r
+Undi16GetMCastFilters (\r
+ IN EFI_SIMPLE_NETWORK_MODE *Mode,\r
+ IN OUT PXENV_UNDI_MCAST_ADDR_T *McastBuffer,\r
+ IN UINTN HwAddressSize\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ //\r
+ // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR?\r
+ //\r
+ McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount;\r
+ for (Index = 0; Index < MAXNUM_MCADDR; Index++) {\r
+ if (Index < McastBuffer->MCastAddrCount) {\r
+ CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize);\r
+ } else {\r
+ ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize);\r
+ }\r
+ }\r
+}\r
+//\r
+// Load 16 bit UNDI Option ROM into memory\r
+//\r
+/**\r
+ Loads the undi driver.\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ \r
+ @retval EFI_SUCCESS - Successfully loads undi driver.\r
+ @retval EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.\r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkLoadUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINTN RomAddress;\r
+ PCI_EXPANSION_ROM_HEADER *PciExpansionRomHeader;\r
+ PCI_DATA_STRUCTURE *PciDataStructure;\r
+ PCI_TYPE00 Pci;\r
+ \r
+ if (!mCachedInt1A) {\r
+ Status = CacheVectorAddress (0x1A);\r
+ if (!EFI_ERROR (Status)) {\r
+ mCachedInt1A = TRUE; \r
+ }\r
+ }\r
+\r
+ PciIo = SimpleNetworkDevice->PciIo;\r
+\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (Pci) / sizeof (UINT32),\r
+ &Pci\r
+ );\r
+\r
+ for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) {\r
+\r
+ PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress;\r
+\r
+ if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+ continue;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress));\r
+\r
+ PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset);\r
+\r
+ if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
+ continue;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure));\r
+\r
+ if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) {\r
+ continue;\r
+ }\r
+\r
+ DEBUG (\r
+ (DEBUG_INIT, \r
+ "PCI device with matchinng VendorId and DeviceId (%d,%d)\n",\r
+ (UINTN) PciDataStructure->VendorId,\r
+ (UINTN) PciDataStructure->DeviceId)\r
+ );\r
+\r
+ Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Unload 16 bit UNDI Option ROM from memory\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ \r
+ @return EFI_STATUS \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkUnloadUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice\r
+ )\r
+{\r
+ if (SimpleNetworkDevice->UndiLoaderTable != NULL) {\r
+ ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT);\r
+ gBS->FreePages (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable,\r
+ SimpleNetworkDevice->UndiLoaderTablePages\r
+ );\r
+ }\r
+\r
+ if (SimpleNetworkDevice->DestinationDataSegment != NULL) {\r
+ ZeroMem (\r
+ SimpleNetworkDevice->DestinationDataSegment,\r
+ SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT\r
+ );\r
+ gBS->FreePages (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment,\r
+ SimpleNetworkDevice->DestinationDataSegmentPages\r
+ );\r
+ }\r
+\r
+ if (SimpleNetworkDevice->DestinationStackSegment != NULL) {\r
+ ZeroMem (\r
+ SimpleNetworkDevice->DestinationStackSegment,\r
+ SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT\r
+ );\r
+ gBS->FreePages (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment,\r
+ SimpleNetworkDevice->DestinationStackSegmentPages\r
+ );\r
+ }\r
+\r
+ if (SimpleNetworkDevice->DestinationCodeSegment != NULL) {\r
+ ZeroMem (\r
+ SimpleNetworkDevice->DestinationCodeSegment,\r
+ SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT\r
+ );\r
+ gBS->FreePages (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment,\r
+ SimpleNetworkDevice->DestinationCodeSegmentPages\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Start the UNDI interface.\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ @param Ax PCI address of Undi device.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM. \r
+ @retval Others Status of start 16 bit UNDI ROM. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkStartUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ UINT16 Ax\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PXENV_START_UNDI_T Start;\r
+\r
+ //\r
+ // Call 16 bit UNDI ROM to start the network interface\r
+ //\r
+ //\r
+ // @bug : What is this state supposed to be???\r
+ //\r
+ Start.Status = INIT_PXE_STATUS;\r
+ Start.Ax = Ax;\r
+ Start.Bx = 0x0000;\r
+ Start.Dx = 0x0000;\r
+ Start.Di = 0x0000;\r
+ Start.Es = 0x0000;\r
+\r
+ Status = PxeStartUndi (SimpleNetworkDevice, &Start);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Start.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop the UNDI interface\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM. \r
+ @retval Others Status of stop 16 bit UNDI ROM. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkStopUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PXENV_STOP_UNDI_T Stop;\r
+\r
+ //\r
+ // Call 16 bit UNDI ROM to start the network interface\r
+ //\r
+ Stop.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiStop (SimpleNetworkDevice, &Stop);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Stop.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Cleanup Unid network interface\r
+\r
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to cleanup 16 bit UNDI ROM. \r
+ @retval Others Status of cleanup 16 bit UNDI ROM. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkCleanupUndi (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PXENV_UNDI_CLEANUP_T Cleanup;\r
+\r
+ //\r
+ // Call 16 bit UNDI ROM to cleanup the network interface\r
+ //\r
+ Cleanup.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Cleanup.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get runtime information for Undi network interface\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_SUCCESS Sucess operation. \r
+ @retval Others Fail to get runtime information for Undi network interface. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkGetInformation (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ UINTN Index;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkStarted:\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to start the network interface\r
+ //\r
+ ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T));\r
+\r
+ SimpleNetworkDevice->GetInformation.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, " GetInformation.Status = %d\n", SimpleNetworkDevice->GetInformation.Status));\r
+ DEBUG ((DEBUG_NET, " GetInformation.BaseIo = %d\n", SimpleNetworkDevice->GetInformation.BaseIo));\r
+ DEBUG ((DEBUG_NET, " GetInformation.IntNumber = %d\n", SimpleNetworkDevice->GetInformation.IntNumber));\r
+ DEBUG ((DEBUG_NET, " GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit));\r
+ DEBUG ((DEBUG_NET, " GetInformation.HwType = %d\n", SimpleNetworkDevice->GetInformation.HwType));\r
+ DEBUG ((DEBUG_NET, " GetInformation.HwAddrLen = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen));\r
+ DEBUG ((DEBUG_NET, " GetInformation.ROMAddress = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress));\r
+ DEBUG ((DEBUG_NET, " GetInformation.RxBufCt = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt));\r
+ DEBUG ((DEBUG_NET, " GetInformation.TxBufCt = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt));\r
+\r
+ DEBUG ((DEBUG_NET, " GetInformation.CurNodeAddr ="));\r
+ for (Index = 0; Index < 16; Index++) {\r
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n"));\r
+\r
+ DEBUG ((DEBUG_NET, " GetInformation.PermNodeAddr ="));\r
+ for (Index = 0; Index < 16; Index++) {\r
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n"));\r
+\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // The information has been retrieved. Fill in Mode data.\r
+ //\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize = SimpleNetworkDevice->GetInformation.HwAddrLen;\r
+\r
+ SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize = SimpleNetworkDevice->GetInformation.MaxTranUnit;\r
+\r
+ SimpleNetworkDevice->SimpleNetworkMode.IfType = (UINT8) SimpleNetworkDevice->GetInformation.HwType;\r
+\r
+ ZeroMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,\r
+ sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress\r
+ );\r
+\r
+ CopyMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,\r
+ &SimpleNetworkDevice->GetInformation.CurrentNodeAddress,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ ZeroMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,\r
+ sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress\r
+ );\r
+\r
+ CopyMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,\r
+ &SimpleNetworkDevice->GetInformation.PermNodeAddress,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ //\r
+ // hard code broadcast address - not avail in PXE2.1\r
+ //\r
+ ZeroMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,\r
+ sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress\r
+ );\r
+\r
+ SetMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,\r
+ 0xff\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get NIC type\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_SUCCESS Sucess operation. \r
+ @retval Others Fail to get NIC type.\r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkGetNicType (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T));\r
+\r
+ SimpleNetworkDevice->GetNicType.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, " GetNicType.Status = %d\n", SimpleNetworkDevice->GetNicType.Status));\r
+ DEBUG ((DEBUG_NET, " GetNicType.NicType = %d\n", SimpleNetworkDevice->GetNicType.NicType));\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // The information has been retrieved. Fill in Mode data.\r
+ //\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get NDIS information\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_SUCCESS Sucess operation. \r
+ @retval Others Fail to get NDIS information.\r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkGetNdisInfo (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T));\r
+\r
+ SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, " GetNdisInfo.Status = %d\n", SimpleNetworkDevice->GetNdisInfo.Status));\r
+ DEBUG ((DEBUG_NET, " GetNdisInfo.IfaceType = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType));\r
+ DEBUG ((DEBUG_NET, " GetNdisInfo.LinkSpeed = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed));\r
+ DEBUG ((DEBUG_NET, " GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags));\r
+\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // The information has been retrieved. Fill in Mode data.\r
+ //\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Call Undi ROM 16bit ISR() to check interrupt cause.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param FrameLength The length of frame buffer.\r
+ @param FrameHeaderLength The length of frame buffer's header if has.\r
+ @param Frame The frame buffer to process network interrupt.\r
+ @param ProtType The type network transmit protocol\r
+ @param PktType The type of package.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM's ISR, or status is invalid. \r
+ @retval EFI_SUCCESS Success operation. \r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkIsr (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ IN UINTN *FrameLength,\r
+ IN UINTN *FrameHeaderLength, OPTIONAL\r
+ IN UINT8 *Frame, OPTIONAL\r
+ IN UINT8 *ProtType, OPTIONAL\r
+ IN UINT8 *PktType OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ BOOLEAN FrameReceived;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ FrameReceived = FALSE;\r
+\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid));\r
+\r
+ if (!SimpleNetworkDevice->IsrValid) {\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));\r
+ SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS;\r
+ SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START;\r
+\r
+ DEBUG ((DEBUG_NET, "Isr() START\n"));\r
+\r
+ Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // There have been no events on this UNDI interface, so return EFI_NOT_READY\r
+ //\r
+ if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // There is data to process, so call until all events processed.\r
+ //\r
+ ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));\r
+ SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS;\r
+ SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;\r
+\r
+ DEBUG ((DEBUG_NET, "Isr() PROCESS\n"));\r
+\r
+ Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ SimpleNetworkDevice->IsrValid = TRUE;\r
+ }\r
+ //\r
+ // Call UNDI GET_NEXT until DONE\r
+ //\r
+ while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) {\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // UNDI is busy. Caller will have to call again.\r
+ // This should never happen with a polled mode driver.\r
+ //\r
+ if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {\r
+ DEBUG ((DEBUG_NET, " BUSY\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Check for invalud UNDI FuncFlag\r
+ //\r
+ if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE &&\r
+ SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT\r
+ ) {\r
+ DEBUG ((DEBUG_NET, " Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Check for Transmit Event\r
+ //\r
+ if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {\r
+ DEBUG ((DEBUG_NET, " TRANSMIT\n"));\r
+ SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;\r
+ }\r
+ //\r
+ // Check for Receive Event\r
+ //\r
+ else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {\r
+ //\r
+ // note - this code will hang on a receive interrupt in a GetStatus loop\r
+ //\r
+ DEBUG ((DEBUG_NET, " RECEIVE\n"));\r
+ SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;\r
+\r
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength = %d\n", SimpleNetworkDevice->Isr.BufferLength));\r
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength = %d\n", SimpleNetworkDevice->Isr.FrameLength));\r
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength));\r
+ DEBUG (\r
+ (\r
+ DEBUG_NET, "SimpleNetworkDevice->Isr.Frame = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel,\r
+ SimpleNetworkDevice->Isr.FrameOffset\r
+ )\r
+ );\r
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));\r
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));\r
+\r
+ if (FrameReceived) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) {\r
+ DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL *FrameLength = %08x\n", *FrameLength));\r
+ *FrameLength = SimpleNetworkDevice->Isr.FrameLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *FrameLength = SimpleNetworkDevice->Isr.FrameLength;\r
+ if (FrameHeaderLength != NULL) {\r
+ *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength;\r
+ }\r
+\r
+ if (ProtType != NULL) {\r
+ *ProtType = SimpleNetworkDevice->Isr.ProtType;\r
+ }\r
+\r
+ if (PktType != NULL) {\r
+ *PktType = SimpleNetworkDevice->Isr.PktType;\r
+ }\r
+\r
+ CopyMem (\r
+ Frame,\r
+ (VOID *)(UINTN) ((SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset),\r
+ SimpleNetworkDevice->Isr.BufferLength\r
+ );\r
+ Frame = Frame + SimpleNetworkDevice->Isr.BufferLength;\r
+ if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) {\r
+ FrameReceived = TRUE;\r
+ }\r
+ }\r
+ //\r
+ // There is data to process, so call until all events processed.\r
+ //\r
+ ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));\r
+ SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS;\r
+ SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;\r
+\r
+ DEBUG ((DEBUG_NET, "Isr() GET NEXT\n"));\r
+\r
+ Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ // if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {\r
+ // return EFI_DEVICE_ERROR;\r
+ // }\r
+ //\r
+ }\r
+\r
+ SimpleNetworkDevice->IsrValid = FALSE;\r
+ return EFI_SUCCESS;\r
+}\r
+//\r
+// ///////////////////////////////////////////////////////////////////////////////////////\r
+// Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs\r
+/////////////////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Start()\r
+//\r
+/**\r
+ Call 16 bit UNDI ROM to start the network interface\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_DEVICE_ERROR Network interface has not be initialized.\r
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.\r
+ @retval EFI_SUCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkStart (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_STARTUP_T Startup;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkStopped:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ case EfiSimpleNetworkInitialized:\r
+ return EFI_ALREADY_STARTED;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to start the network interface\r
+ //\r
+ Startup.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiStartup (SimpleNetworkDevice, &Startup);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Startup.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // The UNDI interface has been started, so update the State.\r
+ //\r
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;\r
+\r
+ //\r
+ //\r
+ //\r
+ SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0;\r
+ SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = 0;\r
+\r
+ return Status;\r
+}\r
+//\r
+// Stop()\r
+//\r
+/**\r
+ Call 16 bit UNDI ROM to stop the network interface\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_DEVICE_ERROR Network interface has not be initialized.\r
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.\r
+ @retval EFI_SUCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkStop (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkStarted:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkInitialized:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;\r
+\r
+ return Status;\r
+}\r
+\r
+//\r
+// Initialize()\r
+//\r
+/**\r
+ Initialize network interface \r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param ExtraRxBufferSize The size of extra request receive buffer.\r
+ @param ExtraTxBufferSize The size of extra request transmit buffer.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.\r
+ @retval EFI_SUCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkInitialize (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN UINTN ExtraRxBufferSize OPTIONAL,\r
+ IN UINTN ExtraTxBufferSize OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_INITIALIZE_T Initialize;\r
+ PXENV_UNDI_OPEN_T Open;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ break;\r
+\r
+ case EfiSimpleNetworkInitialized:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to start the network interface\r
+ //\r
+ Initialize.Status = INIT_PXE_STATUS;\r
+ Initialize.ProtocolIni = 0;\r
+\r
+ Status = PxeUndiInitialize (SimpleNetworkDevice, &Initialize);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status));\r
+\r
+ if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) {\r
+ Status = EFI_NO_MEDIA;\r
+ }\r
+\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Initialize.Status != PXENV_STATUS_SUCCESS) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ Open.Status = INIT_PXE_STATUS;\r
+ Open.OpenFlag = 0;\r
+ Open.PktFilter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);\r
+ Undi16GetMCastFilters (\r
+ &SimpleNetworkDevice->SimpleNetworkMode,\r
+ &Open.McastBuffer,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ Status = PxeUndiOpen (SimpleNetworkDevice, &Open);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Open.Status != PXENV_STATUS_SUCCESS) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // The UNDI interface has been initialized, so update the State.\r
+ //\r
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized;\r
+\r
+ //\r
+ // If initialize succeeds, then assume that media is present.\r
+ //\r
+ SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE;\r
+\r
+ //\r
+ // Reset the recycled transmit buffer FIFO\r
+ //\r
+ SimpleNetworkDevice->TxBufferFifo.First = 0;\r
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;\r
+ SimpleNetworkDevice->IsrValid = FALSE;\r
+\r
+ return Status;\r
+}\r
+//\r
+// Reset()\r
+//\r
+/**\r
+ Reset network interface.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param ExtendedVerification Need extended verfication.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkReset (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_RESET_T Reset;\r
+ UINT16 Rx_filter;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Reset.Status = INIT_PXE_STATUS;\r
+\r
+ Rx_filter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);\r
+\r
+ Undi16GetMCastFilters (\r
+ &SimpleNetworkDevice->SimpleNetworkMode,\r
+ &Reset.R_Mcast_Buf,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Reset.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Reset the recycled transmit buffer FIFO\r
+ //\r
+ SimpleNetworkDevice->TxBufferFifo.First = 0;\r
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;\r
+ SimpleNetworkDevice->IsrValid = FALSE;\r
+\r
+ return Status;\r
+}\r
+//\r
+// Shutdown()\r
+//\r
+/**\r
+ Shutdown network interface.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkShutdown (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_CLOSE_T Close;\r
+ PXENV_UNDI_SHUTDOWN_T Shutdown;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ SimpleNetworkDevice->IsrValid = FALSE;\r
+\r
+ //\r
+ // Call 16 bit UNDI ROM to start the network interface\r
+ //\r
+ Close.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiClose (SimpleNetworkDevice, &Close);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Close.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ Shutdown.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Shutdown.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // The UNDI interface has been initialized, so update the State.\r
+ //\r
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;\r
+\r
+ //\r
+ // If shutdown succeeds, then assume that media is not present.\r
+ //\r
+ SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE;\r
+\r
+ //\r
+ // Reset the recycled transmit buffer FIFO\r
+ //\r
+ SimpleNetworkDevice->TxBufferFifo.First = 0;\r
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;\r
+\r
+ //\r
+ // A short delay. Without this an initialize immediately following\r
+ // a shutdown will cause some versions of UNDI-16 to stop operating.\r
+ //\r
+ gBS->Stall (250000);\r
+\r
+ return Status;\r
+}\r
+//\r
+// ReceiveFilters()\r
+//\r
+/**\r
+ Reset network interface.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param Enable Enable mask value\r
+ @param Disable Disable mask value\r
+ @param ResetMCastFilter Whether reset multi cast filter or not\r
+ @param MCastFilterCnt Count of mutli cast filter for different MAC address\r
+ @param MCastFilter Buffer for mustli cast filter for different MAC address.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkReceiveFilters (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ IN UINT32 Enable,\r
+ IN UINT32 Disable,\r
+ IN BOOLEAN ResetMCastFilter,\r
+ IN UINTN MCastFilterCnt OPTIONAL,\r
+ IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINT32 NewFilter;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_CLOSE_T Close;\r
+ PXENV_UNDI_OPEN_T Open;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // First deal with possible filter setting changes\r
+ //\r
+ if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable;\r
+\r
+ if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {\r
+ if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to close the network interface\r
+ //\r
+ Close.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiClose (SimpleNetworkDevice, &Close);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Close.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ //\r
+ // Reset the recycled transmit buffer FIFO\r
+ //\r
+ SimpleNetworkDevice->TxBufferFifo.First = 0;\r
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;\r
+\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ ZeroMem (&Open, sizeof Open);\r
+\r
+ Open.Status = INIT_PXE_STATUS;\r
+ Open.PktFilter = Undi16GetPacketFilterSetting (NewFilter);\r
+\r
+ if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {\r
+ //\r
+ // Copy the MAC addresses into the UNDI open parameter structure\r
+ //\r
+ Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt;\r
+ for (Index = 0; Index < MCastFilterCnt; ++Index) {\r
+ CopyMem (\r
+ Open.McastBuffer.MCastAddr[Index],\r
+ &MCastFilter[Index],\r
+ sizeof Open.McastBuffer.MCastAddr[Index]\r
+ );\r
+ }\r
+ } else if (!ResetMCastFilter) {\r
+ for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) {\r
+ CopyMem (\r
+ Open.McastBuffer.MCastAddr[Index],\r
+ &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],\r
+ sizeof Open.McastBuffer.MCastAddr[Index]\r
+ );\r
+ }\r
+ }\r
+\r
+ Status = PxeUndiOpen (SimpleNetworkDevice, &Open);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (Open.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ SimpleNetworkDevice->IsrValid = FALSE;\r
+ SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter;\r
+\r
+ if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {\r
+ SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt;\r
+ for (Index = 0; Index < MCastFilterCnt; ++Index) {\r
+ CopyMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],\r
+ &MCastFilter[Index],\r
+ sizeof (EFI_MAC_ADDRESS)\r
+ ); \r
+ }\r
+ }\r
+ //\r
+ // Read back multicast addresses.\r
+ //\r
+ return EFI_SUCCESS;\r
+}\r
+//\r
+// StationAddress()\r
+//\r
+/**\r
+ Set new MAC address.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param Reset Whether reset station MAC address to permenent address\r
+ @param New A pointer to New address\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkStationAddress (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ IN BOOLEAN Reset,\r
+ IN EFI_MAC_ADDRESS * New OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr;\r
+ //\r
+ // EFI_DEVICE_PATH_PROTOCOL *OldDevicePath;\r
+ //\r
+ PXENV_UNDI_CLOSE_T Close;\r
+ PXENV_UNDI_OPEN_T Open;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ SetStationAddr.Status = INIT_PXE_STATUS;\r
+\r
+ if (Reset) {\r
+ //\r
+ // If we are reseting the Station Address to the permanent address, and the\r
+ // Station Address is not programmable, then just return EFI_SUCCESS.\r
+ //\r
+ if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // If the address is already the permanent address, then just return success.\r
+ //\r
+ if (CompareMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,\r
+ &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ ) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Copy the adapters permanent address to the new station address\r
+ //\r
+ CopyMem (\r
+ &SetStationAddr.StationAddress,\r
+ &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+ } else {\r
+ //\r
+ // If we are setting the Station Address, and the\r
+ // Station Address is not programmable, return invalid parameter.\r
+ //\r
+ if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // If the address is already the new address, then just return success.\r
+ //\r
+ if (CompareMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,\r
+ New,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ ) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Copy New to the new station address\r
+ //\r
+ CopyMem (\r
+ &SetStationAddr.StationAddress,\r
+ New,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to stop the network interface\r
+ //\r
+ Close.Status = INIT_PXE_STATUS;\r
+\r
+ PxeUndiClose (SimpleNetworkDevice, &Close);\r
+\r
+ //\r
+ // Call 16-bit UNDI ROM to set the station address\r
+ //\r
+ SetStationAddr.Status = PXENV_STATUS_SUCCESS;\r
+\r
+ Status = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr);\r
+\r
+ //\r
+ // Call 16-bit UNDI ROM to start the network interface\r
+ //\r
+ Open.Status = PXENV_STATUS_SUCCESS;\r
+ Open.OpenFlag = 0;\r
+ Open.PktFilter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);\r
+ Undi16GetMCastFilters (\r
+ &SimpleNetworkDevice->SimpleNetworkMode,\r
+ &Open.McastBuffer,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ PxeUndiOpen (SimpleNetworkDevice, &Open);\r
+\r
+ //\r
+ // Check status from station address change\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ CopyMem (\r
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,\r
+ &SetStationAddr.StationAddress,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+#if 0 /* The device path is based on the permanent address not the current address. */\r
+ //\r
+ // The station address was changed, so update the device path with the new MAC address.\r
+ //\r
+ OldDevicePath = SimpleNetworkDevice->DevicePath;\r
+ SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath);\r
+ SimpleNetworkAppendMacAddressDevicePath (\r
+ &SimpleNetworkDevice->DevicePath,\r
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress\r
+ );\r
+\r
+ Status = LibReinstallProtocolInterfaces (\r
+ SimpleNetworkDevice->Handle,\r
+ &DevicePathProtocol,\r
+ OldDevicePath,\r
+ SimpleNetworkDevice->DevicePath,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n"));\r
+ DEBUG ((DEBUG_ERROR, " Status = %r\n", Status));\r
+ }\r
+\r
+ FreePool (OldDevicePath);\r
+#endif /* 0 */\r
+\r
+ return Status;\r
+}\r
+//\r
+// Statistics()\r
+//\r
+/**\r
+ Resets or collects the statistics on a network interface.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Reset Set to TRUE to reset the statistics for the network interface.\r
+ @param StatisticsSize On input the size, in bytes, of StatisticsTable. On\r
+ output the size, in bytes, of the resulting table of\r
+ statistics.\r
+ @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that\r
+ contains the statistics.\r
+\r
+ @retval EFI_SUCCESS The statistics were collected from the network interface.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer\r
+ size needed to hold the statistics is returned in\r
+ StatisticsSize.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkStatistics (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ IN BOOLEAN Reset,\r
+ IN OUT UINTN *StatisticsSize OPTIONAL,\r
+ OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics;\r
+ PXENV_UNDI_GET_STATISTICS_T GetStatistics;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // If Reset is TRUE, then clear all the statistics.\r
+ //\r
+ if (Reset) {\r
+\r
+ DEBUG ((DEBUG_NET, " RESET Statistics\n"));\r
+\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ ClearStatistics.Status = INIT_PXE_STATUS;\r
+\r
+ Status = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, " RESET Statistics Complete"));\r
+ }\r
+\r
+ if (StatisticsSize != NULL) {\r
+ EFI_NETWORK_STATISTICS LocalStatisticsTable;\r
+\r
+ DEBUG ((DEBUG_NET, " GET Statistics\n"));\r
+\r
+ //\r
+ // If the size if valid, then see if the table is valid\r
+ //\r
+ if (StatisticsTable == NULL) {\r
+ DEBUG ((DEBUG_NET, " StatisticsTable is NULL\n"));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ GetStatistics.Status = INIT_PXE_STATUS;\r
+ GetStatistics.XmtGoodFrames = 0;\r
+ GetStatistics.RcvGoodFrames = 0;\r
+ GetStatistics.RcvCRCErrors = 0;\r
+ GetStatistics.RcvResourceErrors = 0;\r
+\r
+ Status = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (GetStatistics.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Fill in the Statistics Table with the collected values.\r
+ //\r
+ SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff);\r
+\r
+ LocalStatisticsTable.TxGoodFrames = GetStatistics.XmtGoodFrames;\r
+ LocalStatisticsTable.RxGoodFrames = GetStatistics.RcvGoodFrames;\r
+ LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors;\r
+ LocalStatisticsTable.RxDroppedFrames = GetStatistics.RcvResourceErrors;\r
+\r
+ CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize);\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ " Statistics Collected : Size=%d Buf=%08x\n",\r
+ *StatisticsSize,\r
+ StatisticsTable)\r
+ );\r
+\r
+ DEBUG ((DEBUG_NET, " GET Statistics Complete"));\r
+\r
+ if (*StatisticsSize < sizeof LocalStatisticsTable) {\r
+ DEBUG ((DEBUG_NET, " BUFFER TOO SMALL\n"));\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *StatisticsSize = sizeof LocalStatisticsTable;\r
+\r
+ return Status;\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+//\r
+// MCastIpToMac()\r
+//\r
+/**\r
+ Translate IP address to MAC address.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param IPv6 IPv6 or IPv4\r
+ @param IP A pointer to given Ip address.\r
+ @param MAC On return, translated MAC address.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_INVALID_PARAMETER Invalid IP address.\r
+ @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address.\r
+ @retval EFI_UNSUPPORTED Do not support IPv6 \r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkMCastIpToMac (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN BOOLEAN IPv6,\r
+ IN EFI_IP_ADDRESS *IP,\r
+ OUT EFI_MAC_ADDRESS *MAC\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr;\r
+\r
+ if (This == NULL || IP == NULL || MAC == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // 16 bit UNDI Option ROMS do not support IPv6. Check for IPv6 usage.\r
+ //\r
+ if (IPv6) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Call 16 bit UNDI ROM to open the network interface\r
+ //\r
+ GetMcastAddr.Status = INIT_PXE_STATUS;\r
+ CopyMem (&GetMcastAddr.InetAddr, IP, 4);\r
+\r
+ Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Copy the MAC address from the returned data structure.\r
+ //\r
+ CopyMem (\r
+ MAC,\r
+ &GetMcastAddr.MediaAddr,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ return Status;\r
+}\r
+//\r
+// NvData()\r
+//\r
+/**\r
+ Performs read and write operations on the NVRAM device attached to a \r
+ network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param ReadWrite TRUE for read operations, FALSE for write operations.\r
+ @param Offset Byte offset in the NVRAM device at which to start the read or\r
+ write operation. This must be a multiple of NvRamAccessSize and\r
+ less than NvRamSize.\r
+ @param BufferSize The number of bytes to read or write from the NVRAM device.\r
+ This must also be a multiple of NvramAccessSize.\r
+ @param Buffer A pointer to the data buffer.\r
+\r
+ @retval EFI_SUCCESS The NVRAM access was performed.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkNvData (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN BOOLEAN ReadWrite,\r
+ IN UINTN Offset,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+//\r
+// GetStatus()\r
+//\r
+/**\r
+ Reads the current interrupt status and recycled transmit buffer status from \r
+ a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param InterruptStatus A pointer to the bit mask of the currently active interrupts\r
+ If this is NULL, the interrupt status will not be read from\r
+ the device. If this is not NULL, the interrupt status will\r
+ be read from the device. When the interrupt status is read,\r
+ it will also be cleared. Clearing the transmit interrupt\r
+ does not empty the recycled transmit buffer array.\r
+ @param TxBuf Recycled transmit buffer address. The network interface will\r
+ not transmit if its internal recycled transmit buffer array\r
+ is full. Reading the transmit buffer does not clear the\r
+ transmit interrupt. If this is NULL, then the transmit buffer\r
+ status will not be read. If there are no transmit buffers to\r
+ recycle and TxBuf is not NULL, * TxBuf will be set to NULL.\r
+\r
+ @retval EFI_SUCCESS The status of the network interface was retrieved.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkGetStatus (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ OUT UINT32 *InterruptStatus OPTIONAL,\r
+ OUT VOID **TxBuf OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ UINTN FrameLength;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if (InterruptStatus == NULL && TxBuf == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FrameLength = 0;\r
+ Status = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL);\r
+\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ //\r
+ // See if the caller wants interrupt info.\r
+ //\r
+ if (InterruptStatus != NULL) {\r
+ *InterruptStatus = SimpleNetworkDevice->InterruptStatus;\r
+ SimpleNetworkDevice->InterruptStatus = 0;\r
+ }\r
+ //\r
+ // See if the caller wants transmit buffer status info.\r
+ //\r
+ if (TxBuf != NULL) {\r
+ *TxBuf = 0;\r
+ SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Places a packet in the transmit queue of a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param HeaderSize The size, in bytes, of the media header to be filled in by\r
+ the Transmit() function. If HeaderSize is non-zero, then it\r
+ must be equal to This->Mode->MediaHeaderSize and the DestAddr\r
+ and Protocol parameters must not be NULL.\r
+ @param BufferSize The size, in bytes, of the entire packet (media header and\r
+ data) to be transmitted through the network interface.\r
+ @param Buffer A pointer to the packet (media header followed by data) to be\r
+ transmitted. This parameter cannot be NULL. If HeaderSize is zero,\r
+ then the media header in Buffer must already be filled in by the\r
+ caller. If HeaderSize is non-zero, then the media header will be\r
+ filled in by the Transmit() function.\r
+ @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter\r
+ is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then\r
+ This->Mode->CurrentAddress is used for the source HW MAC address.\r
+ @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this\r
+ parameter is ignored.\r
+ @param Protocol The type of header to build. If HeaderSize is zero, then this\r
+ parameter is ignored. See RFC 1700, section "Ether Types", for\r
+ examples.\r
+\r
+ @retval EFI_SUCCESS The packet was placed on the transmit queue.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. \r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkTransmit (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN UINTN HeaderSize,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer,\r
+ IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
+ IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
+ IN UINT16 *Protocol OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ PXENV_UNDI_TRANSMIT_T XmitInfo;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ if (HeaderSize != 0) {\r
+ if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DestAddr == NULL || Protocol == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DestAddr != NULL) {\r
+ CopyMem (\r
+ Buffer,\r
+ DestAddr,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+ }\r
+\r
+ if (SrcAddr == NULL) {\r
+ SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress;\r
+ }\r
+\r
+ CopyMem (\r
+ (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,\r
+ SrcAddr,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ if (Protocol != NULL) {\r
+ *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF));\r
+ }\r
+ }\r
+ //\r
+ // See if the recycled transmit buffer FIFO is full.\r
+ // If it is full, then we can not transmit until the caller calls GetStatus() to pull\r
+ // off recycled transmit buffers.\r
+ //\r
+ if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ //\r
+ // Output debug trace message.\r
+ //\r
+ DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r "));\r
+\r
+ //\r
+ // Initialize UNDI WRITE parameter structure.\r
+ //\r
+ XmitInfo.Status = INIT_PXE_STATUS;\r
+ XmitInfo.Protocol = P_UNKNOWN;\r
+ XmitInfo.XmitFlag = XMT_DESTADDR;\r
+ XmitInfo.DestAddrOffset = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f);\r
+ XmitInfo.DestAddrSegment = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4);\r
+ XmitInfo.TBDOffset = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f);\r
+ XmitInfo.TBDSegment = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4);\r
+ XmitInfo.Reserved[0] = 0;\r
+ XmitInfo.Reserved[1] = 0;\r
+\r
+ CopyMem (\r
+ SimpleNetworkDevice->TxDestAddr,\r
+ Buffer,\r
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize\r
+ );\r
+\r
+ CopyMem (\r
+ SimpleNetworkDevice->TxRealModeMediaHeader,\r
+ Buffer,\r
+ SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize\r
+ );\r
+\r
+ SimpleNetworkDevice->Xmit->ImmedLength = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize;\r
+\r
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength);\r
+\r
+ CopyMem (\r
+ SimpleNetworkDevice->TxRealModeDataBuffer,\r
+ (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize,\r
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen\r
+ );\r
+\r
+ //\r
+ // Make API call to UNDI TRANSMIT\r
+ //\r
+ XmitInfo.Status = 0;\r
+\r
+ Status = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check the status code from the 16 bit UNDI ROM\r
+ //\r
+ switch (XmitInfo.Status) {\r
+ case PXENV_STATUS_OUT_OF_RESOURCES:\r
+ return EFI_NOT_READY;\r
+\r
+ case PXENV_STATUS_SUCCESS:\r
+ break;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Add address of Buffer to the recycled transmit buffer FIFO\r
+ //\r
+ SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Receives a packet from a network interface.\r
+ \r
+ @param This The protocol instance pointer.\r
+ @param HeaderSize The size, in bytes, of the media header received on the network\r
+ interface. If this parameter is NULL, then the media header size\r
+ will not be returned.\r
+ @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in\r
+ bytes, of the packet that was received on the network interface.\r
+ @param Buffer A pointer to the data buffer to receive both the media header and\r
+ the data.\r
+ @param SrcAddr The source HW MAC address. If this parameter is NULL, the\r
+ HW MAC source address will not be extracted from the media\r
+ header.\r
+ @param DestAddr The destination HW MAC address. If this parameter is NULL,\r
+ the HW MAC destination address will not be extracted from the\r
+ media header.\r
+ @param Protocol The media header type. If this parameter is NULL, then the\r
+ protocol will not be extracted from the media header. See\r
+ RFC 1700 section "Ether Types" for examples.\r
+\r
+ @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has\r
+ been updated to the number of bytes received.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit\r
+ request.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkReceive (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ OUT UINTN *HeaderSize OPTIONAL,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer,\r
+ OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
+ OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
+ OUT UINT16 *Protocol OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ UINTN MediaAddrSize;\r
+ UINT8 ProtType;\r
+\r
+ if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = Undi16SimpleNetworkIsr (\r
+ This,\r
+ BufferSize,\r
+ HeaderSize,\r
+ Buffer,\r
+ &ProtType,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) {\r
+ return EFI_NOT_READY;\r
+\r
+ }\r
+\r
+ SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;\r
+\r
+ MediaAddrSize = This->Mode->HwAddressSize;\r
+\r
+ if (SrcAddr != NULL) {\r
+ CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize);\r
+ }\r
+\r
+ if (DestAddr != NULL) {\r
+ CopyMem (DestAddr, Buffer, MediaAddrSize);\r
+ }\r
+\r
+ if (Protocol != NULL) {\r
+ *((UINT8 *) Protocol) = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1);\r
+ *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d HeaderSize = %d\n", *BufferSize, *HeaderSize));\r
+\r
+ return Status;\r
+\r
+}\r
+//\r
+// WaitForPacket()\r
+//\r
+/**\r
+ wait for a packet to be received.\r
+\r
+ @param Event Event used with WaitForEvent() to wait for a packet to be received.\r
+ @param Context Event Context\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+Undi16SimpleNetworkWaitForPacket (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // Someone is waiting on the receive packet event, if there's\r
+ // a packet pending, signal the event\r
+ //\r
+ if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) {\r
+ gBS->SignalEvent (Event);\r
+ }\r
+}\r
+//\r
+// CheckForPacket()\r
+//\r
+/**\r
+ Check whether packet is ready for receive.\r
+\r
+ @param This The protocol instance pointer.\r
+ \r
+ @retval EFI_SUCCESS Receive data is ready.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit\r
+ request.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkCheckForPacket (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;\r
+ UINTN FrameLength;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
+\r
+ if (SimpleNetworkDevice == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Verify that the current state of the adapter is valid for this call.\r
+ //\r
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ FrameLength = 0;\r
+ Status = Undi16SimpleNetworkIsr (\r
+ This,\r
+ &FrameLength,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY;\r
+}\r
+\r
+/**\r
+ Signal handlers for ExitBootServices event.\r
+ \r
+ Clean up any Real-mode UNDI residue from the system \r
+ \r
+ @param Event ExitBootServices event\r
+ @param Context \r
+**/\r
+VOID\r
+EFIAPI\r
+Undi16SimpleNetworkEvent (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // NOTE: This is not the only way to effect this cleanup. The prescribed mechanism\r
+ // would be to perform an UNDI STOP command. This strategam has been attempted\r
+ // but results in problems making some of the EFI core services from TPL_CALLBACK.\r
+ // This issue needs to be resolved, but the other alternative has been to perform\r
+ // the unchain logic explicitly, as done below.\r
+ //\r
+ RestoreCachedVectorAddress (0x1A);\r
+}\r
+\r
+/**\r
+ Allocate buffer below 1M for real mode.\r
+\r
+ @param NumPages The number pages want to be allocated.\r
+ @param Buffer On return, allocated buffer.\r
+ \r
+ @return Status of allocating pages.\r
+**/\r
+EFI_STATUS\r
+BiosSnp16AllocatePagesBelowOneMb (\r
+ UINTN NumPages,\r
+ VOID **Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+\r
+ PhysicalAddress = 0x000fffff;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiRuntimeServicesData,\r
+ NumPages,\r
+ &PhysicalAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ *Buffer = (VOID *) (UINTN) PhysicalAddress;\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BIOS_SNP_16_H_\r
+#define _BIOS_SNP_16_H_\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/SimpleNetwork.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/NetworkInterfaceIdentifier.h>\r
+#include <Protocol/DevicePath.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <Guid/EventGroup.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#include "Pxe.h"\r
+\r
+//\r
+// BIOS Simple Network Protocol Device Structure\r
+//\r
+#define EFI_SIMPLE_NETWORK_DEV_SIGNATURE SIGNATURE_32 ('s', 'n', '1', '6')\r
+\r
+#define INIT_PXE_STATUS 0xabcd\r
+\r
+#define EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE 64\r
+\r
+typedef struct {\r
+ UINT32 First;\r
+ UINT32 Last;\r
+ VOID * Data[EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE];\r
+} EFI_SIMPLE_NETWORK_DEV_FIFO;\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ EFI_HANDLE Handle;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork;\r
+ EFI_SIMPLE_NETWORK_MODE SimpleNetworkMode;\r
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL Nii;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+\r
+ //\r
+ // Local Data for Simple Network Protocol interface goes here\r
+ //\r
+ BOOLEAN UndiLoaded;\r
+ EFI_EVENT EfiBootEvent;\r
+ EFI_EVENT LegacyBootEvent;\r
+ UINT16 PxeEntrySegment;\r
+ UINT16 PxeEntryOffset;\r
+ EFI_SIMPLE_NETWORK_DEV_FIFO TxBufferFifo;\r
+ EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath;\r
+ PXE_T *Pxe; ///< Pointer to !PXE structure\r
+ PXENV_UNDI_GET_INFORMATION_T GetInformation; ///< Data from GET INFORMATION\r
+ PXENV_UNDI_GET_NIC_TYPE_T GetNicType; ///< Data from GET NIC TYPE\r
+ PXENV_UNDI_GET_NDIS_INFO_T GetNdisInfo; ///< Data from GET NDIS INFO\r
+ BOOLEAN IsrValid; ///< TRUE if Isr contains valid data\r
+ PXENV_UNDI_ISR_T Isr; ///< Data from ISR\r
+ PXENV_UNDI_TBD_T *Xmit; //\r
+ VOID *TxRealModeMediaHeader; ///< < 1 MB Size = 0x100\r
+ VOID *TxRealModeDataBuffer; ///< < 1 MB Size = GetInformation.MaxTranUnit\r
+ VOID *TxDestAddr; ///< < 1 MB Size = 16\r
+ UINT8 InterruptStatus; ///< returned/cleared by GetStatus, set in ISR\r
+ UINTN UndiLoaderTablePages;\r
+ UINTN DestinationDataSegmentPages;\r
+ UINTN DestinationStackSegmentPages;\r
+ UINTN DestinationCodeSegmentPages;\r
+ VOID *UndiLoaderTable;\r
+ VOID *DestinationDataSegment;\r
+ VOID *DestinationStackSegment;\r
+ VOID *DestinationCodeSegment;\r
+} EFI_SIMPLE_NETWORK_DEV;\r
+\r
+#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) \\r
+ CR (a, \\r
+ EFI_SIMPLE_NETWORK_DEV, \\r
+ SimpleNetwork, \\r
+ EFI_SIMPLE_NETWORK_DEV_SIGNATURE \\r
+ )\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2;\r
+\r
+\r
+//\r
+// Driver Binding Protocol functions\r
+//\r
+/**\r
+ Tests to see if this driver supports a given controller.\r
+\r
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param Controller The handle of the controller to test.\r
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
+ \r
+ @retval EFI_SUCCESS The driver supports given controller.\r
+ @retval EFI_UNSUPPORT The driver doesn't support given controller.\r
+ @retval Other Other errors prevent driver finishing to test\r
+ if the driver supports given controller.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+;\r
+\r
+/**\r
+ Starts the Snp device controller\r
+\r
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param Controller The handle of the controller to test.\r
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
+ \r
+ @retval EFI_SUCCESS - The device was started. \r
+ @retval EFI_DEVICE_ERROR - The device could not be started due to a device error.\r
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+;\r
+\r
+/**\r
+ Stops the device by given device controller.\r
+\r
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param Controller The handle of the controller to test.\r
+ @param NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param ChildHandleBuffer An array of child handles to be freed. May be NULL if\r
+ NumberOfChildren is 0.\r
+ \r
+ @retval EFI_SUCCESS - The device was stopped.\r
+ @retval EFI_DEVICE_ERROR - The device could not be stopped due to a device error.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+;\r
+\r
+//\r
+// Simple Network Protocol functions\r
+//\r
+/**\r
+ Call 16 bit UNDI ROM to start the network interface\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_DEVICE_ERROR Network interface has not be initialized.\r
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.\r
+ @retval EFI_SUCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkStart (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+;\r
+\r
+/**\r
+ Call 16 bit UNDI ROM to stop the network interface\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_DEVICE_ERROR Network interface has not be initialized.\r
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.\r
+ @retval EFI_SUCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkStop (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+;\r
+\r
+/**\r
+ Initialize network interface \r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param ExtraRxBufferSize The size of extra request receive buffer.\r
+ @param ExtraTxBufferSize The size of extra request transmit buffer.\r
+ \r
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.\r
+ @retval EFI_SUCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkInitialize (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN UINTN ExtraRxBufferSize OPTIONAL,\r
+ IN UINTN ExtraTxBufferSize OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ Reset network interface.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param ExtendedVerification Need extended verfication.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkReset (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+;\r
+\r
+/**\r
+ Shutdown network interface.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkShutdown (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+;\r
+\r
+/**\r
+ Reset network interface.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param Enable Enable mask value\r
+ @param Disable Disable mask value\r
+ @param ResetMCastFilter Whether reset multi cast filter or not\r
+ @param MCastFilterCnt Count of mutli cast filter for different MAC address\r
+ @param MCastFilter Buffer for mustli cast filter for different MAC address.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkReceiveFilters (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ IN UINT32 Enable,\r
+ IN UINT32 Disable,\r
+ IN BOOLEAN ResetMCastFilter,\r
+ IN UINTN MCastFilterCnt OPTIONAL,\r
+ IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ Set new MAC address.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param Reset Whether reset station MAC address to permenent address\r
+ @param New A pointer to New address\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkStationAddress (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ IN BOOLEAN Reset,\r
+ IN EFI_MAC_ADDRESS * New OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ Collect statistics.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param Reset Whether cleanup old statistics data.\r
+ @param StatisticsSize The buffer of statistics table.\r
+ @param StatisticsTable A pointer to statistics buffer.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkStatistics (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ IN BOOLEAN Reset,\r
+ IN OUT UINTN *StatisticsSize OPTIONAL,\r
+ OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ Translate IP address to MAC address.\r
+\r
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
+ @param IPv6 IPv6 or IPv4\r
+ @param IP A pointer to given Ip address.\r
+ @param MAC On return, translated MAC address.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.\r
+ @retval EFI_INVALID_PARAMETER Invalid IP address.\r
+ @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address.\r
+ @retval EFI_UNSUPPORTED Do not support IPv6 \r
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.\r
+ @retval EFI_NOT_STARTED Network device has been stopped.\r
+ @retval EFI_DEVICE_ERROR Invalid status for network device\r
+ @retval EFI_SUCCESS Success operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkMCastIpToMac (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN BOOLEAN IPv6,\r
+ IN EFI_IP_ADDRESS *IP,\r
+ OUT EFI_MAC_ADDRESS *MAC\r
+ )\r
+;\r
+\r
+/**\r
+ Performs read and write operations on the NVRAM device attached to a \r
+ network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param ReadWrite TRUE for read operations, FALSE for write operations.\r
+ @param Offset Byte offset in the NVRAM device at which to start the read or\r
+ write operation. This must be a multiple of NvRamAccessSize and\r
+ less than NvRamSize.\r
+ @param BufferSize The number of bytes to read or write from the NVRAM device.\r
+ This must also be a multiple of NvramAccessSize.\r
+ @param Buffer A pointer to the data buffer.\r
+\r
+ @retval EFI_SUCCESS The NVRAM access was performed.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkNvData (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN BOOLEAN Write,\r
+ IN UINTN Offset,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer\r
+ )\r
+;\r
+\r
+/**\r
+ Reads the current interrupt status and recycled transmit buffer status from \r
+ a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param InterruptStatus A pointer to the bit mask of the currently active interrupts\r
+ If this is NULL, the interrupt status will not be read from\r
+ the device. If this is not NULL, the interrupt status will\r
+ be read from the device. When the interrupt status is read,\r
+ it will also be cleared. Clearing the transmit interrupt\r
+ does not empty the recycled transmit buffer array.\r
+ @param TxBuf Recycled transmit buffer address. The network interface will\r
+ not transmit if its internal recycled transmit buffer array\r
+ is full. Reading the transmit buffer does not clear the\r
+ transmit interrupt. If this is NULL, then the transmit buffer\r
+ status will not be read. If there are no transmit buffers to\r
+ recycle and TxBuf is not NULL, * TxBuf will be set to NULL.\r
+\r
+ @retval EFI_SUCCESS The status of the network interface was retrieved.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkGetStatus (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,\r
+ OUT UINT32 *InterruptStatus OPTIONAL,\r
+ OUT VOID **TxBuf OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ Places a packet in the transmit queue of a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param HeaderSize The size, in bytes, of the media header to be filled in by\r
+ the Transmit() function. If HeaderSize is non-zero, then it\r
+ must be equal to This->Mode->MediaHeaderSize and the DestAddr\r
+ and Protocol parameters must not be NULL.\r
+ @param BufferSize The size, in bytes, of the entire packet (media header and\r
+ data) to be transmitted through the network interface.\r
+ @param Buffer A pointer to the packet (media header followed by data) to be\r
+ transmitted. This parameter cannot be NULL. If HeaderSize is zero,\r
+ then the media header in Buffer must already be filled in by the\r
+ caller. If HeaderSize is non-zero, then the media header will be\r
+ filled in by the Transmit() function.\r
+ @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter\r
+ is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then\r
+ This->Mode->CurrentAddress is used for the source HW MAC address.\r
+ @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this\r
+ parameter is ignored.\r
+ @param Protocol The type of header to build. If HeaderSize is zero, then this\r
+ parameter is ignored. See RFC 1700, section "Ether Types", for\r
+ examples.\r
+\r
+ @retval EFI_SUCCESS The packet was placed on the transmit queue.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. \r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkTransmit (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ IN UINTN HeaderSize,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer,\r
+ IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
+ IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
+ IN UINT16 *Protocol OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ Receives a packet from a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param HeaderSize The size, in bytes, of the media header received on the network\r
+ interface. If this parameter is NULL, then the media header size\r
+ will not be returned.\r
+ @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in\r
+ bytes, of the packet that was received on the network interface.\r
+ @param Buffer A pointer to the data buffer to receive both the media header and\r
+ the data.\r
+ @param SrcAddr The source HW MAC address. If this parameter is NULL, the\r
+ HW MAC source address will not be extracted from the media\r
+ header.\r
+ @param DestAddr The destination HW MAC address. If this parameter is NULL,\r
+ the HW MAC destination address will not be extracted from the\r
+ media header.\r
+ @param Protocol The media header type. If this parameter is NULL, then the\r
+ protocol will not be extracted from the media header. See\r
+ RFC 1700 section "Ether Types" for examples.\r
+\r
+ @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has\r
+ been updated to the number of bytes received.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit\r
+ request.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Undi16SimpleNetworkReceive (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
+ OUT UINTN *HeaderSize OPTIONAL,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer,\r
+ OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
+ OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
+ OUT UINT16 *Protocol OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ wait for a packet to be received.\r
+\r
+ @param Event Event used with WaitForEvent() to wait for a packet to be received.\r
+ @param Context Event Context\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+Undi16SimpleNetworkWaitForPacket (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+;\r
+\r
+/**\r
+ Check whether packet is ready for receive.\r
+\r
+ @param This The protocol instance pointer.\r
+ \r
+ @retval EFI_SUCCESS Receive data is ready.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit\r
+ request.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+**/\r
+EFI_STATUS\r
+Undi16SimpleNetworkCheckForPacket (\r
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
+ )\r
+;\r
+\r
+/**\r
+ Cache Interrupt verctor address converted from IVT number.\r
+\r
+ @param VectorNumber IVT number\r
+ \r
+ @retval EFI_SUCCESS Success to operation.\r
+**/\r
+EFI_STATUS\r
+CacheVectorAddress (\r
+ UINT8 VectorNumber\r
+ )\r
+;\r
+\r
+/**\r
+ Get interrupt vector address according to IVT number. \r
+ \r
+ @param VectorNumber Given IVT number\r
+ \r
+ @return cached interrupt vector address.\r
+**/\r
+EFI_STATUS\r
+RestoreCachedVectorAddress (\r
+ UINT8 VectorNumber\r
+ )\r
+;\r
+\r
+/**\r
+ If available, launch the BaseCode from a NIC option ROM.\r
+ This should install the !PXE and PXENV+ structures in memory for\r
+ subsequent use.\r
+ \r
+\r
+ @param SimpleNetworkDevice Simple network device instance\r
+ @param RomAddress The ROM base address for NIC rom.\r
+ \r
+ @retval EFI_NOT_FOUND The check sum does not match \r
+ @retval EFI_NOT_FOUND Rom ID offset is wrong \r
+ @retval EFI_NOT_FOUND No Rom ID structure is found \r
+**/\r
+EFI_STATUS\r
+LaunchBaseCode (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ UINTN RomAddress\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ START UNDI\r
+ Op-Code: PXENV_START_UNDI (0000h)\r
+ Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is\r
+ responsible for saving the information it needs to communicate with the hardware.\r
+ This service is also responsible for hooking the Int 1Ah service routine\r
+ Note: This API service must be called only once during UNDI Option ROM boot.\r
+ The UNDI driver is responsible for saving this information and using it every time\r
+ PXENV_UNDI_STARTUP is called.\r
+ Service cannot be used in protected mode.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT16 AX;\r
+ UINT16 BX;\r
+ UINT16 DX;\r
+ UINT16 DI;\r
+ UINT16 ES;\r
+ } PXENV_START_UNDI_T;\r
+ Set before calling API service\r
+ AX, BX, DX, DI, ES: BIOS initialization parameter registers. These\r
+ fields should contain the same information passed to the option ROM\r
+ initialization routine by the Host System BIOS. Information about the\r
+ contents of these registers can be found in the [PnP], [PCI] and\r
+ [BBS] specifications.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+\r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeStartUndi (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_START_UNDI_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI STARTUP \r
+ Op-Code: PXENV_UNDI_STARTUP (0001h)\r
+ Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the\r
+ caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper\r
+ operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used\r
+ to complete this initialization. The rest of the UNDI APIs will not be available until this call has\r
+ been completed.\r
+ Note: PXENV_UNDI_STARTUP must not be called again without first calling\r
+ PXENV_UNDI_SHUTDOWN.\r
+ PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for\r
+ chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and\r
+ PXENV_STOP_UNDI API calls.\r
+ This service cannot be used in protected mode.\r
+ typedef struct \r
+ {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_STARTUP_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+\r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiStartup (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI CLEANUP\r
+ Op-Code: PXENV_UNDI_CLEANUP (0002h)\r
+ Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field\r
+ in the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be\r
+ made just before unloading the Universal NIC Driver. The rest of the API will not be available\r
+ after this call executes.\r
+ This service cannot be used in protected mode.\r
+ typedef struct {\r
+ PXENX_STATUS Status;\r
+ } PXENV_UNDI_CLEANUP_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+\r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiCleanup (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI INITIALIZE\r
+ Op-Code: PXENV_UNDI_INITIALIZE (0003h)\r
+ Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the\r
+ caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call resets the adapter and programs it with default parameters. The default parameters used\r
+ are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the\r
+ receive and transmit units of the network adapter to readily receive or transmit packets. The\r
+ application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network.\r
+ This call must be made by an application to establish an interface to the network adapter driver.\r
+ Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for\r
+ the Protocol field in the parameter structure.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ ADDR32 ProtocolIni;\r
+ UINT8 reserved[8];\r
+ } PXENV_UNDI_INITIALIZE_T;\r
+ Set before calling API service\r
+ ProtocolIni: Physical address of a memory copy of the driver\r
+ module from the protocol.ini file obtained from the protocol manager\r
+ driver (refer to the NDIS 2.0 specification). This parameter is\r
+ supported for the universal NDIS driver to pass the information\r
+ contained in the protocol.ini file to the NIC driver for any specific\r
+ configuration of the NIC. (Note that the module identification in the\r
+ protocol.ini file was done by NDIS.) This value can be NULL for any\r
+ other application interfacing to the universal NIC driver\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance.\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiInitialize (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ Wrapper routine for reset adapter.\r
+ \r
+ PXE \r
+ UNDI RESET ADAPTER\r
+ Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h)\r
+ Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized\r
+ by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to\r
+ Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the\r
+ network. This routine cannot be used to replace Initialize or Shutdown calls.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;\r
+ } PXENV_UNDI_RESET_T;\r
+\r
+ #define MAXNUM_MCADDR 8\r
+\r
+ typedef struct {\r
+ UINT16 MCastAddrCount;\r
+ MAC_ADDR McastAddr[MAXNUM_MCADDR];\r
+ } PXENV_UNDI_MCAST_ADDRESS_t;\r
+\r
+ Set before calling API service\r
+ R_Mcast_Buf: This is a structure of MCastAddrCount and\r
+ McastAddr.\r
+ MCastAddrCount: Number of multicast MAC addresses in the\r
+ buffer.\r
+ McastAddr: List of up to MAXNUM_MCADDR multicast MAC\r
+ addresses.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance.\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ @param RxFilter Filter setting mask value for PXE recive . \r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiResetNic (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_RESET_T *PxeUndiTable,\r
+ IN UINT16 RxFilter\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI SHUTDOWN\r
+ Op-Code: PXENV_UNDI_SHUTDOWN (0005h)\r
+ Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call resets the network adapter and leaves it in a safe state for another driver to program it.\r
+ Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the\r
+ Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again.\r
+ typedef struct \r
+ {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_SHUTDOWN_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiShutdown (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI OPEN\r
+ Op-Code: PXENV_UNDI_OPEN (0006h)\r
+ Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call activates the adapter network connection and sets the adapter ready to accept packets\r
+ for transmit and receive.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT16 OpenFlag;\r
+ UINT16 PktFilter;\r
+ #define FLTR_DIRECTED 0x0001\r
+ #define FLTR_BRDCST 0x0002\r
+ #define FLTR_PRMSCS 0x0004\r
+ #define FLTR_SRC_RTG 0x0008\r
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;\r
+ } PXENV_UNDI_OPEN_T;\r
+ Set before calling API service\r
+ OpenFlag: This is an adapter specific input parameter. This is\r
+ supported for the universal NDIS 2.0 driver to pass in the open flags\r
+ provided by the protocol driver. (See the NDIS 2.0 specification.)\r
+ This can be zero.\r
+ PktFilter: Filter for receiving packets. This can be one, or more, of\r
+ the FLTR_xxx constants. Multiple values are arithmetically or-ed\r
+ together.\r
+ directed packets are packets that may come to your MAC address\r
+ or the multicast MAC address.\r
+ R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h).\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiOpen (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI CLOSE\r
+ Op-Code: PXENV_UNDI_CLOSE (0007h)\r
+ Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or\r
+ received until the network adapter is open again.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_CLOSE_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiClose (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI TRANSMIT PACKET\r
+ Op-Code: PXENV_UNDI_TRANSMIT (0008h)\r
+ Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that\r
+ has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX.\r
+ The status code must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call transmits a buffer to the network. The media header\r
+ for the packet can be filled by the calling protocol, but it might not be.\r
+ The network adapter driver will fill it if required by the values in the\r
+ parameter block. The packet is buffered for transmission provided there is\r
+ an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no\r
+ buffer is available the function returns PXENV_EXIT_FAILURE with a status\r
+ code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is\r
+ implementation-dependent. An interrupt is generated on completion of the\r
+ transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is\r
+ permitted in the context of a transmit complete interrupt.\r
+\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT8 Protocol;\r
+ #define P_UNKNOWN 0\r
+ #define P_IP 1\r
+ #define P_ARP 2\r
+ #define P_RARP 3\r
+ UINT8 XmitFlag;\r
+ #define XMT_DESTADDR 0x0000\r
+ #define XMT_BROADCAST 0x0001\r
+ SEGOFF16 DestAddr;\r
+ SEGOFF16 TBD;\r
+ UINT32 Reserved[2];\r
+ } t_PXENV_UNDI_TRANSMIT;\r
+\r
+ #define MAX_DATA_BLKS 8\r
+\r
+ typedef struct {\r
+ UINT16 ImmedLength;\r
+ SEGOFF16 Xmit;\r
+ UINT16 DataBlkCount;\r
+ struct DataBlk {\r
+ UINT8 TDPtrType;\r
+ UINT8 TDRsvdByte;\r
+ UINT16 TDDataLen;\r
+ SEGOFF16 TDDataPtr;\r
+ } DataBlock[MAX_DATA_BLKS];\r
+ } PXENV_UNDI_TBD_T\r
+\r
+ Set before calling API service\r
+ Protocol: This is the protocol of the upper layer that is calling UNDI\r
+ TRANSMIT call. If the upper layer has filled the media header, this\r
+ field must be P_UNKNOWN.\r
+ XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a\r
+ pointer to the destination media address in the field DestAddr. If\r
+ XMT_BROADCAST, the NIC driver fills the broadcast address for the\r
+ destination.\r
+ TBD: Segment:Offset address of the transmit buffer descriptor.\r
+ ImmedLength: Length of the immediate transmit buffer: Xmit.\r
+ Xmit: Segment:Offset of the immediate transmit buffer.\r
+ DataBlkCount: Number of blocks in this transmit buffer.\r
+ TDPtrType:\r
+ 0 => 32-bit physical address in TDDataPtr (not supported in this\r
+ version of PXE)\r
+ 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit\r
+ protected mode pointer\r
+ TDRsvdByte: Reserved must be zero.\r
+ TDDatalen: Data block length in bytes.\r
+ TDDataPtr: Segment:Offset of the transmit block.\r
+ DataBlock: Array of transmit data blocks.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiTransmit (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI SET MULTICAST ADDRESS\r
+ Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h)\r
+ Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call changes the current list of multicast addresses to the input list and resets the network\r
+ adapter to accept it. If the number of multicast addresses is zero, multicast is disabled.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;\r
+ } PXENV_UNDI_SET_MCAST_ADDR_T;\r
+ Set before calling API service\r
+ R_Mcast_Buf: See description in the UNDI RESET ADAPTER\r
+ (0004h) API.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiSetMcastAddr (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI SET STATION ADDRESS\r
+ Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah)\r
+ Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call sets the MAC address to be the input value and is called before opening the network\r
+ adapter. Later, the open call uses this variable as a temporary MAC address to program the\r
+ adapter individual address registers.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ MAC_ADDR StationAddress;\r
+ } PXENV_UNDI_SET_STATION_ADDR_T;\r
+ Set before calling API service\r
+ StationAddress: Temporary MAC address to be used for\r
+ transmit and receive.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiSetStationAddr (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI SET PACKET FILTER\r
+ Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh)\r
+ Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with\r
+ the open call.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT8 filter;\r
+ } PXENV_UNDI_SET_PACKET_FILTER_T;\r
+ Set before calling API service\r
+ Filter: See the receive filter values in the UNDI OPEN\r
+ (0006h) API description.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiSetPacketFilter (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI GET INFORMATION\r
+ Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch)\r
+ Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call copies the network adapter variables, including the MAC address, into the input buffer.\r
+ Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and\r
+ PXENV_UNDI_STARTUP have been issued. All other fields must be valid after\r
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been\r
+ called.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT16 BaseIo;\r
+ UINT16 IntNumber;\r
+ UINT16 MaxTranUnit;\r
+ UINT16 HwType;\r
+ #define ETHER_TYPE 1\r
+ #define EXP_ETHER_TYPE 2\r
+ #define IEEE_TYPE 6\r
+ #define ARCNET_TYPE 7\r
+ UINT16 HwAddrLen;\r
+ MAC_ADDR CurrentNodeAddress;\r
+ MAC_ADDR PermNodeAddress;\r
+ SEGSEL ROMAddress;\r
+ UINT16 RxBufCt;\r
+ UINT16 TxBufCt;\r
+ } PXENV_UNDI_GET_INFORMATION_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ BaseIO: Adapter base I/O address.\r
+ IntNumber: Adapter IRQ number.\r
+ MaxTranUnit: Adapter maximum transmit unit.\r
+ HWType: Type of protocol at the hardware level.\r
+ HWAddrLen: Length of the hardware address.\r
+ CurrentNodeAddress: Current hardware address.\r
+ PermNodeAddress: Permanent hardware address.\r
+ ROMAddress: Real mode ROM segment address.\r
+ RxBufCnt: Receive queue length.\r
+ TxBufCnt: Transmit queue length. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetInformation (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI GET STATISTICS\r
+ Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh)\r
+ Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized\r
+ by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call reads statistical information from the network adapter, and returns.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT32 XmtGoodFrames;\r
+ UINT32 RcvGoodFrames;\r
+ UINT32 RcvCRCErrors;\r
+ UINT32 RcvResourceErrors;\r
+ } PXENV_UNDI_GET_STATISTICS_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ XmtGoodFrames: Number of successful transmissions.\r
+ RcvGoodFrames: Number of good frames received.\r
+ RcvCRCErrors: Number of frames received with CRC\r
+ error.\r
+ RcvResourceErrors: Number of frames discarded\r
+ because receive queue was full.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetStatistics (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI CLEAR STATISTICS\r
+ Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh)\r
+ Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call clears the statistical information from the network adapter.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_CLEAR_STATISTICS_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiClearStatistics (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI INITIATE DIAGS\r
+ Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh)\r
+ Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run\r
+ hardware diagnostics and to update its status information.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_INITIATE_DIAGS_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiInitiateDiags (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI FORCE INTERRUPT\r
+ Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h)\r
+ Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the\r
+ network adapter driver usually queues the packet and calls the application's callback receive\r
+ routine with a pointer to the packet received. Then, the callback routine either can copy the packet\r
+ to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied,\r
+ the network adapter driver does not remove it from the input queue. When the application wants to\r
+ copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive\r
+ interrupt.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_FORCE_INTERRUPT_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiForceInterrupt (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI GET MULTICAST ADDRESS\r
+ Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h)\r
+ Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized\r
+ by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call converts the given IP multicast address to a hardware multicast address.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ IP4 InetAddr;\r
+ MAC_ADDR MediaAddr;\r
+ } PXENV_UNDI_GET_MCAST_ADDR_T;\r
+ Set before calling API service\r
+ InetAddr: IP multicast address.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ MediaAddr: MAC multicast address.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetMcastAddr (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI GET NIC TYPE\r
+ Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h)\r
+ Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE_T parameter structure that has been initialized by\r
+ the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the\r
+ NIC information.\r
+ Description: This call, if successful, provides the NIC-specific information necessary to identify the network\r
+ adapter that is used to boot the system.\r
+ Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if\r
+ the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific\r
+ information can be obtained from the DHCPDISCOVER packet itself.\r
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called\r
+ before the information provided is valid.\r
+ typedef {\r
+ PXENV_STATUS Status;\r
+ UINT8 NicType;\r
+ #define PCI_NIC 2\r
+ #define PnP_NIC 3\r
+ #define CardBus_NIC 4\r
+ Union {\r
+ Struct {\r
+ UINT16 Vendor_ID;\r
+ UINT16 Dev_ID;\r
+ UINT8 Base_Class;\r
+ UINT8 Sub_Class;\r
+ UINT8 Prog_Intf;\r
+ UINT8 Rev;\r
+ UINT16 BusDevFunc;\r
+ UINT16 SubVendor_ID;\r
+ UINT16 SubDevice_ID;\r
+ } pci, cardbus;\r
+ struct {\r
+ UINT32 EISA_Dev_ID;\r
+ UINT8 Base_Class;\r
+ UINT8 Sub_Class;\r
+ UINT8 Prog_Intf;\r
+ UINT16 CardSelNum;\r
+ } pnp;\r
+ } info;\r
+ } PXENV_UNDI_GET_NIC_TYPE_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ NICType: Type of NIC information stored in the parameter\r
+ structure.\r
+ Info: Information about the fields in this union can be found\r
+ in the [PnP] and [PCI] specifications \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetNicType (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI GET IFACE INFO\r
+ Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h)\r
+ Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized\r
+ by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the\r
+ interface specific information.\r
+ Description: This call, if successful, provides the network interface specific information such as the interface\r
+ type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the\r
+ universal drivers such as NDIS or Miniport to communicate to the upper protocol modules.\r
+ Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the\r
+ universal driver to translate/convert this information into a format that is required in its specification\r
+ or to suit the expectation of the upper level protocol modules.\r
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called\r
+ before the information provided is valid.\r
+ typedef struct {\r
+ PXENV_STATUS Status\r
+ UINT8 IfaceType[16];\r
+ UINT32 LinkSpeed;\r
+ UINT32 ServiceFlags;\r
+ UINT32 Reserved[4];\r
+ } PXENV_UNDI_GET_NDIS_INFO_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ IfaceType: Name of MAC type in ASCIIZ format. This is\r
+ used by the universal NDIS driver to specify its driver type\r
+ to the protocol driver.\r
+ LinkSpeed: Defined in the NDIS 2.0 specification.\r
+ ServiceFlags: Defined in the NDIS 2.0 specification.\r
+ Reserved: Must be zero. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetNdisInfo (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI ISR\r
+ Op-Code: PXENV_UNDI_ISR (0014h)\r
+ Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in\r
+ the parameter block indicates the operation to be performed for the call. This field is filled with the\r
+ status of that operation on return.\r
+ Note: Interrupt Service Routine Operation:\r
+ In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the\r
+ application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR\r
+ API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing\r
+ (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT).\r
+ When the Network Interface HW generates an interrupt the protocol driver interrupt service\r
+ routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then\r
+ calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for\r
+ the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface\r
+ level and read any status values required to further process the interrupt. UNDI must return as\r
+ quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or\r
+ PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the\r
+ interrupt was generated by this particular Network Interface or not.\r
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was\r
+ not generated by our NIC, and interrupt processing is complete.\r
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start\r
+ a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is\r
+ now complete.\r
+ The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to\r
+ PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and\r
+ return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the\r
+ first buffer pointer of that frame in the parameter block.\r
+ The protocol driver calls UNDI repeatedly with the FuncFlag equal to\r
+ PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received\r
+ frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l\r
+ remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous\r
+ buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter\r
+ block. Otherwise it must return the first buffer in the next frame.\r
+ If there is no received frame pending to be processed, UNDI processes the transmit completes and\r
+ if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the\r
+ NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag.\r
+ IMPORTANT: It is possible for the protocol driver to be interrupted again while in the\r
+ strategy routine when the UNDI re-enables interrupts. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiIsr (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_ISR_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ STOP UNDI\r
+ Op-Code: PXENV_STOP_UNDI (0015h)\r
+ Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This routine is responsible for unhooking the Int 1Ah service routine.\r
+ Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid\r
+ status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from\r
+ base memory. Also, UNDI must not be removed from base memory if BC is not removed from base\r
+ memory.\r
+ Service cannot be used in protected mode.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_STOP_UNDI_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiStop (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_STOP_UNDI_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ PXE \r
+ UNDI GET STATE\r
+ Op-Code: PXENV_UNDI_GET_STATE (0015h)\r
+ Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state\r
+ constants\r
+ Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call\r
+ sequences\r
+ typedef struct {\r
+ #define PXE_UNDI_GET_STATE_STARTED 1\r
+ #define PXE_UNDI_GET_STATE_INITIALIZED 2\r
+ #define PXE_UNDI_GET_STATE_OPENED 3\r
+ PXENV_STATUS Status;\r
+ UINT8 UNDIstate;\r
+ } PXENV_UNDI_GET_STATE_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ State: See definitions of the state constants.\r
+ Note. UNDI implementation is responsible for maintaining\r
+ internal state machine.\r
+ UNDI ISR\r
+ Op-Code: PXENV_UNDI_ISR (0014h)\r
+ Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in\r
+ the parameter block indicates the operation to be performed for the call. This field is filled with the\r
+ status of that operation on return. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetState (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable\r
+ )\r
+;\r
+\r
+/**\r
+ Effect the Far Call into the PXE Layer\r
+\r
+ Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API\r
+ services will not work, unless there are three 16-bit parameters pushed onto the stack.\r
+ push DS ;Far pointer to parameter structure\r
+ push offset pxe_data_call_struct ;is pushed onto stack.\r
+ push Index ;UINT16 is pushed onto stack.\r
+ call dword ptr (s_PXE ptr es:[di]).EntryPointSP\r
+ add sp, 6 ;Caller cleans up stack. \r
+\r
+ @param SimpleNetworkDevice Device instance for simple network\r
+ @param Table Point to parameter/retun value table for legacy far call\r
+ @param TableSize The size of paramter/return value table\r
+ @param CallIndex The index of legacy call.\r
+ \r
+ @return EFI_STATUS \r
+**/\r
+EFI_STATUS\r
+MakePxeCall (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT VOID *Table,\r
+ IN UINTN TableSize,\r
+ IN UINT16 CallIndex\r
+ )\r
+;\r
+\r
+/**\r
+ Allocate buffer below 1M for real mode.\r
+\r
+ @param NumPages The number pages want to be allocated.\r
+ @param Buffer On return, allocated buffer.\r
+ \r
+ @return Status of allocating pages.\r
+**/\r
+EFI_STATUS\r
+BiosSnp16AllocatePagesBelowOneMb (\r
+ UINTN NumPages,\r
+ VOID **Buffer\r
+ )\r
+;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosSnp16.h"\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16ComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16ComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName = {\r
+ BiosSnp16ComponentNameGetDriverName,\r
+ BiosSnp16ComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosSnp16ComponentNameGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosSnp16ComponentNameGetControllerName,\r
+ "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosSnp16DriverNameTable[] = {\r
+ {\r
+ "eng;en",\r
+ L"BIOS[UNDI] Simple Network Protocol Driver"\r
+ },\r
+ {\r
+ NULL,\r
+ NULL\r
+ }\r
+};\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16ComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mBiosSnp16DriverNameTable,\r
+ DriverName,\r
+ (BOOLEAN)(This == &gBiosSnp16ComponentName)\r
+ );\r
+}\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosSnp16ComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+ Helper Routines that use a PXE-enabled NIC option ROM.\r
+ \r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosSnp16.h"\r
+\r
+#define TO_SEGMENT(x) ((UINT16) (RShiftU64 ((UINT32)(UINTN) (x), 4) & 0xF000))\r
+#define TO_OFFSET(x) ((UINT16) ((UINT32)(UINTN) (x) & 0xFFFF))\r
+#define PARAGRAPH_SIZE 0x10\r
+#define IVT_BASE 0x00000000\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+ UINT16 Signature; ///< 0xaa55\r
+ UINT8 ROMlength; ///< size of this ROM in 512 byte blocks\r
+ UINT8 InitEntryPoint[4]; ///< a jump to the initialization routine\r
+ UINT8 Reserved[0xf]; ///< various\r
+ UINT16 PxeRomIdOffset; ///< offset of UNDI, $BC$, or BUSD ROM ID structure\r
+ UINT16 PcirHeaderOffset; ///< offset of PCI Expansion Header\r
+ UINT16 PnpHeaderOffset; ///< offset of Plug and Play Expansion Header\r
+} OPTION_ROM_HEADER;\r
+#pragma pack()\r
+\r
+UINT32 CachedVectorAddress[0x100];\r
+\r
+/**\r
+ Cache Interrupt verctor address converted from IVT number.\r
+\r
+ @param VectorNumber IVT number\r
+ \r
+ @retval EFI_SUCCESS Success to operation.\r
+**/\r
+EFI_STATUS\r
+CacheVectorAddress (\r
+ UINT8 VectorNumber\r
+ )\r
+{\r
+ UINT32 *Address;\r
+\r
+ Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4);\r
+ CachedVectorAddress[VectorNumber] = *Address;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get interrupt vector address according to IVT number. \r
+ \r
+ @param VectorNumber Given IVT number\r
+ \r
+ @return cached interrupt vector address.\r
+**/\r
+EFI_STATUS\r
+RestoreCachedVectorAddress (\r
+ UINT8 VectorNumber\r
+ )\r
+{\r
+ UINT32 *Address;\r
+\r
+ Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4);\r
+ *Address = CachedVectorAddress[VectorNumber];\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Print Undi loader table. \r
+\r
+ @param UndiLoaderStructure Point to Undi Loader table structure. \r
+ \r
+**/\r
+VOID\r
+Print_Undi_Loader_Table (\r
+ VOID *UndiLoaderStructure\r
+ )\r
+{\r
+ UNDI_LOADER_T *DisplayPointer;\r
+\r
+ DisplayPointer = (UNDI_LOADER_T *) UndiLoaderStructure;\r
+\r
+ DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n"));\r
+ DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) UndiLoaderStructure));\r
+\r
+ DEBUG ((DEBUG_NET, "\n\rStatus = 0x%X\n\r", DisplayPointer->Status));\r
+ DEBUG ((DEBUG_NET, "\t_AX_= 0x%X\n\r", DisplayPointer->Ax));\r
+ DEBUG ((DEBUG_NET, "\t_BX_= 0x%X\n\r", DisplayPointer->Bx));\r
+ DEBUG ((DEBUG_NET, "\t_DX_= 0x%X\n\r", DisplayPointer->Dx));\r
+ DEBUG ((DEBUG_NET, "\t_DI_= 0x%X\n\r", DisplayPointer->Di));\r
+ DEBUG ((DEBUG_NET, "\t_ES_= 0x%X\n\r", DisplayPointer->Es));\r
+ DEBUG ((DEBUG_NET, "\tUNDI_DS= 0x%X\n\r", DisplayPointer->Undi_Ds));\r
+ DEBUG ((DEBUG_NET, "\tUNDI_CS= 0x%X\n\r", DisplayPointer->Undi_Cs));\r
+ DEBUG ((DEBUG_NET, "\tPXEptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Segment));\r
+ DEBUG ((DEBUG_NET, "\tPXEptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Offset));\r
+ DEBUG ((DEBUG_NET, "\tPXENVptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Segment));\r
+ DEBUG ((DEBUG_NET, "\tPXENVptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Offset));\r
+}\r
+\r
+/**\r
+ Simple table dumper. The ROMID table is necessary in order to effect\r
+ the "Early UNDI" trick. Herein, the UNDI layer can be loaded in the\r
+ pre-boot phase without having to download a Network Boot Program \r
+ across the wire. It is required in the implementation in that we\r
+ are not using PXE.\r
+\r
+ @param RomIDStructure Point to RomID structure.\r
+ \r
+**/\r
+VOID\r
+Print_ROMID_Table (\r
+ IN VOID *RomIDStructure\r
+ )\r
+{\r
+ UNDI_ROMID_T *DisplayPointer;\r
+\r
+ DisplayPointer = (UNDI_ROMID_T *) RomIDStructure;\r
+\r
+ DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n"));\r
+ DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) RomIDStructure));\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "\n\rROMID %c%c%c%c\n\r",\r
+ DisplayPointer->Signature[0],\r
+ DisplayPointer->Signature[1],\r
+ DisplayPointer->Signature[2],\r
+ DisplayPointer->Signature[3])\r
+ );\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Length of this structure in bytes = 0x%X\n\r",\r
+ DisplayPointer->StructLength)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Use to make byte checksum of this structure == zero is = 0x%X\n\r",\r
+ DisplayPointer->StructCksum)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Structure format revision number= 0x%X\n\r",\r
+ DisplayPointer->StructRev)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "API Revision number = 0x%X 0x%X 0x%X\n\r",\r
+ DisplayPointer->UNDI_Rev[0],\r
+ DisplayPointer->UNDI_Rev[1],\r
+ DisplayPointer->UNDI_Rev[2])\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Offset of UNDI loader routine in the option ROM image= 0x%X\n\r",\r
+ DisplayPointer->UNDI_Loader)\r
+ );\r
+ DEBUG ((DEBUG_NET, "From the data above, the absolute entry point of the UNDI loader is\n\r"));\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "\tat address 0x%X\n\r",\r
+ (UINT32) (DisplayPointer->UNDI_Loader + ((UINT32) (UINTN)(DisplayPointer - 0x20) & 0xFFFF0)))\r
+ );\r
+ DEBUG ((DEBUG_NET, "Minimum stack segment size, in bytes,\n\r"));\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "needed to load and run the UNDI= 0x%X \n\r",\r
+ DisplayPointer->StackSize)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "UNDI runtime code and data = 0x%X\n\r",\r
+ DisplayPointer->DataSize)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Segment size = 0x%X\n\r",\r
+ DisplayPointer->CodeSize)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "\n\rBus Type = %c%c%c%c\n\r",\r
+ DisplayPointer->BusType[0],\r
+ DisplayPointer->BusType[1],\r
+ DisplayPointer->BusType[2],\r
+ DisplayPointer->BusType[3])\r
+ );\r
+}\r
+\r
+/**\r
+ Print PXE table.\r
+\r
+ @param PxeTable Point to PXE table structure\r
+ \r
+**/\r
+VOID\r
+Print_PXE_Table (\r
+ IN VOID* PxeTable\r
+ )\r
+{\r
+ PXE_T *DisplayPointer;\r
+ UINTN Index;\r
+ UINT8 *Dptr;\r
+\r
+ DisplayPointer = (PXE_T *) PxeTable;\r
+ Dptr = (UINT8 *) PxeTable;\r
+\r
+ DEBUG ((DEBUG_NET, "This is the PXE table at address 0x%X\n\r", PxeTable));\r
+\r
+ DEBUG ((DEBUG_NET, "A dump of the 0x%X bytes is:\n\r", sizeof (PXE_T)));\r
+\r
+ for (Index = 0; Index < sizeof (PXE_T); Index++) {\r
+ if ((Index % 0x10) == 0) {\r
+ DEBUG ((DEBUG_NET, "\t\n\r"));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, " 0x%X ", *Dptr++));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n\r"));\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "\n\rPXE %c%c%c%c%c%c\n\r",\r
+ DisplayPointer->Signature[0],\r
+ DisplayPointer->Signature[1],\r
+ DisplayPointer->Signature[2],\r
+ DisplayPointer->Signature[3])\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Length of this structure in bytes = 0x%X\n\r",\r
+ DisplayPointer->StructLength)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Use to make byte checksum of this structure == zero is = 0x%X\n\r",\r
+ DisplayPointer->StructCksum)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Structure format revision number = 0x%X\n\r",\r
+ DisplayPointer->StructRev)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Must be zero, is equal to 0x%X\n\r",\r
+ DisplayPointer->Reserved1)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Far pointer to UNDI ROMID = 0x%X\n\r",\r
+ (UINT32) (DisplayPointer->Undi.Segment << 0x4 | DisplayPointer->Undi.Offset))\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Far pointer to base-code ROMID = 0x%X\n\r",\r
+ (UINT32) ((DisplayPointer->Base.Segment << 0x04) | DisplayPointer->Base.Offset))\r
+ );\r
+ DEBUG ((DEBUG_NET, "16bit stack segment API entry point. This will be seg:off in \n\r"));\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "real mode and sel:off in 16:16 protected mode = 0x%X:0x%X\n\r",\r
+ DisplayPointer->EntryPointSP.Segment,\r
+ DisplayPointer->EntryPointSP.Offset)\r
+ );\r
+\r
+ DEBUG ((DEBUG_NET, "\n\tNOTE to the implementer\n\tThis is the entry to use for call-ins\n\r"));\r
+\r
+ DEBUG ((DEBUG_NET, "32bit stack Segment API entry point. This will be sel:off. \n\r"));\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "In real mode, sel == 0 = 0x%X:0x%X\n\r",\r
+ DisplayPointer->EntryPointESP.Segment,\r
+ DisplayPointer->EntryPointESP.Offset)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Reserved2 value, must be zero, is equal to 0x%X\n\r",\r
+ DisplayPointer->Reserved2)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Number of segment descriptors in this structur = 0x%X\n\r",\r
+ (UINT8) DisplayPointer->SegDescCnt)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "First segment descriptor in GDT assigned to PXE = 0x%X\n\r",\r
+ (UINT16) DisplayPointer->FirstSelector)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",\r
+ (UINT16) DisplayPointer->Stack.Seg_Addr,\r
+ (UINT32) DisplayPointer->Stack.Phy_Addr,\r
+ (UINT16) DisplayPointer->Stack.Seg_Size)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The UNDIData is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",\r
+ (UINT16) DisplayPointer->UNDIData.Seg_Addr,\r
+ (UINT32) DisplayPointer->UNDIData.Phy_Addr,\r
+ (UINT16) DisplayPointer->UNDIData.Seg_Size)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The UNDICodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",\r
+ (UINT16) DisplayPointer->UNDICode.Seg_Addr,\r
+ (UINT32) DisplayPointer->UNDICode.Phy_Addr,\r
+ (UINT16) DisplayPointer->UNDICode.Seg_Size)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",\r
+ (UINT16) DisplayPointer->UNDICodeWrite.Seg_Addr,\r
+ (UINT32) DisplayPointer->UNDICodeWrite.Phy_Addr,\r
+ (UINT16) DisplayPointer->UNDICodeWrite.Seg_Size)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The BC_Data is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",\r
+ (UINT16) DisplayPointer->BC_Data.Seg_Addr,\r
+ (UINT32) DisplayPointer->BC_Data.Phy_Addr,\r
+ (UINT16) DisplayPointer->BC_Data.Seg_Size)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The BC_Code is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",\r
+ (UINT16) DisplayPointer->BC_Code.Seg_Addr,\r
+ (UINT32) DisplayPointer->BC_Code.Phy_Addr,\r
+ (UINT16) DisplayPointer->BC_Code.Seg_Size)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The BC_CodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",\r
+ (UINT16) DisplayPointer->BC_CodeWrite.Seg_Addr,\r
+ (UINT32) DisplayPointer->BC_CodeWrite.Phy_Addr,\r
+ (UINT16) DisplayPointer->BC_CodeWrite.Seg_Size)\r
+ );\r
+}\r
+\r
+/**\r
+ Print PXENV table.\r
+\r
+ @param PxenvTable Point to PXENV\r
+ \r
+**/\r
+VOID\r
+Print_PXENV_Table (\r
+ IN VOID *PxenvTable\r
+ )\r
+{\r
+ PXENV_T *DisplayPointer;\r
+\r
+ DisplayPointer = (PXENV_T *) PxenvTable;\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "\n\rPXENV+ %c%c%c%c%c%c\n\r",\r
+ DisplayPointer->Signature[0],\r
+ DisplayPointer->Signature[1],\r
+ DisplayPointer->Signature[2],\r
+ DisplayPointer->Signature[3],\r
+ DisplayPointer->Signature[4],\r
+ DisplayPointer->Signature[5])\r
+ );\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "PXE version number. \n\r\tLSB is minor version. \n\r\tMSB is major version = 0x%X\n\r",\r
+ DisplayPointer->Version)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Length of PXE-2.0 Entry Point structure in bytes = 0x%X\n\r",\r
+ DisplayPointer->StructLength)\r
+ );\r
+ DEBUG ((DEBUG_NET, "Used to make structure checksum equal zero is now = 0x%X\n\r", DisplayPointer->StructCksum));\r
+ DEBUG ((DEBUG_NET, "Real mode API entry point segment:Offset. = 0x%X\n\r", DisplayPointer->RMEntry));\r
+ DEBUG ((DEBUG_NET, "Protected mode API entry point = 0x%X\n\r", DisplayPointer->PMEntryOff));\r
+ DEBUG ((DEBUG_NET, " segment:Offset. This will always be zero. \n\r"));\r
+ DEBUG ((DEBUG_NET, "Protected mode API calls = 0x%X\n\r", DisplayPointer->PMEntrySeg));\r
+ DEBUG ((DEBUG_NET, "Real mode stack segment = 0x%X\n\r", DisplayPointer->StackSeg));\r
+ DEBUG ((DEBUG_NET, "Stack segment size in bytes = 0x%X\n\r", DisplayPointer->StackSize));\r
+ DEBUG ((DEBUG_NET, "Real mode base-code code segment = 0x%X\n\r", DisplayPointer->BaseCodeSeg));\r
+ DEBUG ((DEBUG_NET, "Base-code code segment size = 0x%X\n\r", DisplayPointer->BaseCodeSize));\r
+ DEBUG ((DEBUG_NET, "Real mode base-code data segment = 0x%X\n\r", DisplayPointer->BaseDataSeg));\r
+ DEBUG ((DEBUG_NET, "Base-code data segment size = 0x%X\n\r", DisplayPointer->BaseDataSize));\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "UNDI code segment size in bytes = 0x%X\n\r",\r
+ DisplayPointer->UNDICodeSize)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "Real mode segment:Offset pointer \n\r\tto PXE Runtime ID structure, address = 0x%X\n\r",\r
+ DisplayPointer->RuntimePtr)\r
+ );\r
+ DEBUG (\r
+ (\r
+ DEBUG_NET,\r
+ "From above, we have a linear address of 0x%X\n\r",\r
+ (UINT32)\r
+ (\r
+ ((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF) +\r
+ (((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF0000) >> 12)\r
+ )\r
+ )\r
+ );\r
+}\r
+\r
+\r
+#define OPTION_ROM_PTR ((OPTION_ROM_HEADER *) RomAddress)\r
+\r
+/**\r
+ If available, launch the BaseCode from a NIC option ROM.\r
+ This should install the !PXE and PXENV+ structures in memory for\r
+ subsequent use.\r
+ \r
+\r
+ @param SimpleNetworkDevice Simple network device instance\r
+ @param RomAddress The ROM base address for NIC rom.\r
+ \r
+ @retval EFI_NOT_FOUND The check sum does not match \r
+ @retval EFI_NOT_FOUND Rom ID offset is wrong \r
+ @retval EFI_NOT_FOUND No Rom ID structure is found \r
+**/\r
+EFI_STATUS\r
+LaunchBaseCode (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ UINTN RomAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IA32_REGISTER_SET InOutRegs;\r
+ UNDI_ROMID_T *RomIdTableAddress;\r
+ UNDI_LOADER_T *UndiLoaderTable;\r
+ UINT16 Segment;\r
+ UINT16 *StackPointer;\r
+ VOID *Buffer;\r
+ UINTN Size;\r
+ PXE_T *Pxe;\r
+ UINT32 RomLength;\r
+ UINTN PciSegment;\r
+ UINTN Bus;\r
+ UINTN Device;\r
+ UINTN Function;\r
+ BOOLEAN ThunkFailed;\r
+\r
+ DEBUG ((DEBUG_NET, "\n\r\n\rCheck for the UNDI ROMID Signature\n\r"));\r
+\r
+ //\r
+ // paranoia - check structures for validity\r
+ //\r
+ RomLength = OPTION_ROM_PTR->ROMlength << 9;\r
+ if (CalculateSum8 ((UINT8 *) RomAddress, RomLength) != 0) {\r
+ DEBUG ((DEBUG_ERROR, "ROM Header Checksum Error\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ RomIdTableAddress = (UNDI_ROMID_T *) (RomAddress + OPTION_ROM_PTR->PxeRomIdOffset);\r
+\r
+ if ((UINTN) (OPTION_ROM_PTR->PxeRomIdOffset + RomIdTableAddress->StructLength) > RomLength) {\r
+ DEBUG ((DEBUG_ERROR, "ROM ID Offset Error\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // see if this is a header for an UNDI ROM ID structure (vs. a $BC$ or BUSD type)\r
+ //\r
+ if (CompareMem (RomIdTableAddress->Signature, UNDI_ROMID_SIG, sizeof RomIdTableAddress->Signature) != 0) {\r
+ DEBUG ((DEBUG_ERROR, "No ROM ID Structure found....\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ //\r
+ // its not - keep looking\r
+ //\r
+ }\r
+\r
+ if (CalculateSum8 ((UINT8 *) RomIdTableAddress, RomIdTableAddress->StructLength) != 0) {\r
+ DEBUG ((DEBUG_ERROR, "ROM ID Checksum Error\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Print_ROMID_Table (RomIdTableAddress);\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The ROM ID is located at 0x%X\n\r",\r
+ RomIdTableAddress)\r
+ );\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "With an UNDI Loader located at 0x%X\n\r",\r
+ RomAddress + RomIdTableAddress->UNDI_Loader)\r
+ );\r
+\r
+ //\r
+ // found an UNDI ROM ID structure\r
+ //\r
+ SimpleNetworkDevice->Nii.ImageAddr = RomAddress;\r
+ SimpleNetworkDevice->Nii.ImageSize = RomLength;\r
+ SimpleNetworkDevice->Nii.MajorVer = RomIdTableAddress->UNDI_Rev[2];\r
+ SimpleNetworkDevice->Nii.MinorVer = RomIdTableAddress->UNDI_Rev[1];\r
+\r
+ DEBUG ((DEBUG_NET, "Allocate area for the UNDI_LOADER_T structure\n\r"));\r
+ //\r
+ // Allocate 1 page below 1MB to put real mode thunk code in\r
+ //\r
+ // Undi Loader Table is a PXE Specification prescribed data structure\r
+ // that is used to transfer information into and out of the Undi layer.\r
+ // Note how it must be located below 1 MB.\r
+ //\r
+ SimpleNetworkDevice->UndiLoaderTablePages = EFI_SIZE_TO_PAGES (PARAGRAPH_SIZE + sizeof (UNDI_LOADER_T));\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ SimpleNetworkDevice->UndiLoaderTablePages,\r
+ &SimpleNetworkDevice->UndiLoaderTable\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UndiLoaderTable = SimpleNetworkDevice->UndiLoaderTable;\r
+\r
+ DEBUG ((DEBUG_NET, "Allocate area for the real-mode stack whose sole purpose\n\r"));\r
+ DEBUG ((DEBUG_NET, "in life right now is to store a SEG:OFFSET combo pair that\n\r"));\r
+ DEBUG ((DEBUG_NET, "points to an Undi_Loader_t table structure\n\r"));\r
+\r
+ Size = 0x100;\r
+ Status = gBS->AllocatePool (EfiLoaderData, Size, &Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Now we want to put a pointer to the Under Loader Table in our MemPage\r
+ // Buffer. This will be the argument stack for the call into the Undi Loader\r
+ //\r
+ StackPointer = (UINT16 *) Buffer;\r
+ *StackPointer++ = TO_OFFSET (UndiLoaderTable);\r
+ //\r
+ // push the OFFSET\r
+ //\r
+ *StackPointer++ = TO_SEGMENT (UndiLoaderTable);\r
+ //\r
+ // push the SEGMENT\r
+ //\r
+ StackPointer = (UINT16 *) Buffer;\r
+ //\r
+ // reset the stack pointer\r
+ //\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "After the fixups, the stack pointer is 0x%X\n\r",\r
+ (UINT64)(UINTN) StackPointer)\r
+ );\r
+\r
+ //\r
+ // Allocate memory for the Deployed UNDI.\r
+ // The UNDI is essentially telling us how much space it needs, and\r
+ // it is up to the EFI driver to allocate sufficient, boot-time\r
+ // persistent resources for the call\r
+ //\r
+ SimpleNetworkDevice->DestinationDataSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->DataSize);\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ SimpleNetworkDevice->DestinationDataSegmentPages,\r
+ &SimpleNetworkDevice->DestinationDataSegment\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ UndiLoaderTable->Undi_Ds = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationDataSegment >> 4);\r
+\r
+ //\r
+ // Allocate memory for the Deployed UNDI stack\r
+ // The UNDI is essentially telling us how much space it needs, and\r
+ // it is up to the EFI driver to allocate sufficient, boot-time\r
+ // persistent resources for the call\r
+ //\r
+ SimpleNetworkDevice->DestinationStackSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->StackSize);\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ SimpleNetworkDevice->DestinationStackSegmentPages,\r
+ &SimpleNetworkDevice->DestinationStackSegment\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));\r
+ return Status;\r
+ }\r
+ //\r
+ // Allocate memory for the Deployed UNDI.\r
+ // The UNDI is essentially telling us how much space it needs, and\r
+ // it is up to the EFI driver to allocate sufficient, boot-time\r
+ // persistent resources for the call\r
+ //\r
+ SimpleNetworkDevice->DestinationCodeSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->CodeSize);\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ SimpleNetworkDevice->DestinationCodeSegmentPages,\r
+ &SimpleNetworkDevice->DestinationCodeSegment\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ UndiLoaderTable->Undi_Cs = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationCodeSegment >> 4);\r
+\r
+ //\r
+ // these are in the Input and Output Parameter to be sent to the UNDI Loader code\r
+ //\r
+ UndiLoaderTable->Status = 0xAA55;\r
+ //\r
+ // -------------------- Changed by Michael_Huang@3Com.com -----------------\r
+ // UndiLoaderTable->_AX is AX value when UNDI ROM is initialized by BIOS, it is the PCI bus device\r
+ // function of the NIC. Please refer to PXE Spec for detail info.\r
+ // old code is:\r
+ // UndiLoaderTable->Ax = 0x0;\r
+ // -----------------------------------------------------------------------\r
+ //\r
+ SimpleNetworkDevice->PciIo->GetLocation (\r
+ SimpleNetworkDevice->PciIo,\r
+ &PciSegment,\r
+ &Bus,\r
+ &Device,\r
+ &Function\r
+ );\r
+ UndiLoaderTable->Ax = (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function));\r
+ UndiLoaderTable->Bx = 0x0;\r
+ UndiLoaderTable->Dx = 0x0;\r
+ UndiLoaderTable->Di = 0x0;\r
+ UndiLoaderTable->Es = 0x0;\r
+\r
+ //\r
+ // set these OUT values to zero in order to ensure that\r
+ // uninitialized memory is not mistaken for display data\r
+ //\r
+ UndiLoaderTable->PXEptr.Offset = 0;\r
+ UndiLoaderTable->PXEptr.Segment = 0;\r
+ UndiLoaderTable->PXENVptr.Segment = 0;\r
+ UndiLoaderTable->PXENVptr.Offset = 0;\r
+\r
+ DEBUG (\r
+ (DEBUG_INIT,\r
+ "The NIC is located at Bus 0x%X, Device 0x%X, Function 0x%X\n\r",\r
+ Bus,\r
+ Device,\r
+ Function)\r
+ );\r
+\r
+ //\r
+ // These are the values that set up the ACTUAL IA32 machine state, whether in\r
+ // Real16 in EFI32 or the IVE for IA64\r
+ // register values are unused except for CS:IP and SS:SP\r
+ //\r
+ InOutRegs.X.AX = 0;\r
+ InOutRegs.X.BX = 0;\r
+ InOutRegs.X.CX = 0;\r
+ InOutRegs.X.DX = 0;\r
+ InOutRegs.X.SI = 0;\r
+ InOutRegs.X.DI = 0;\r
+ InOutRegs.X.BP = 0;\r
+ InOutRegs.X.DS = 0;\r
+ InOutRegs.X.ES = 0;\r
+ //\r
+ // just to be clean\r
+ //\r
+ DEBUG ((DEBUG_NET, "The way this game works is that the SS:SP +4 should point\n\r"));\r
+ DEBUG ((DEBUG_NET, "to the contents of the UndiLoaderTable\n\r"));\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The Undi Loader Table is at address = 0x%X\n\r",\r
+ (UINT32)(UINTN) UndiLoaderTable)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The segment and offsets are 0x%X and 0x%X, resp\n",\r
+ TO_SEGMENT (UndiLoaderTable),\r
+ TO_OFFSET (UndiLoaderTable))\r
+ );\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The Linear Address of the UNDI Loader entry is 0x%X\n",\r
+ RomAddress + RomIdTableAddress->UNDI_Loader)\r
+ );\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The Address offset of the UNDI Loader entry is 0x%X\n",\r
+ RomIdTableAddress->UNDI_Loader)\r
+ );\r
+\r
+ DEBUG ((DEBUG_NET, "Before the call, we have...\n\r"));\r
+ Print_Undi_Loader_Table (UndiLoaderTable);\r
+\r
+ Segment = ((UINT16) (RShiftU64 (RomAddress, 4) & 0xFFFF));\r
+ DEBUG ((DEBUG_NET, "The Segment of the call is 0x%X\n\r", Segment));\r
+\r
+ //\r
+ // make the call into the UNDI Code\r
+ //\r
+ DEBUG ((DEBUG_INIT, "Make the call into the UNDI code now\n\r"));\r
+\r
+ DEBUG ((DEBUG_NET, "\nThe 20-BIt address of the Call, and the location \n\r"));\r
+ DEBUG ((DEBUG_NET, "\twhere we should be able to set a breakpoint is \n\r"));\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "\t\t0x%X, from SEG:OFF 0x%X:0x%X\n\r\n\r",\r
+ Segment * 0x10 + RomIdTableAddress->UNDI_Loader,\r
+ Segment,\r
+ RomIdTableAddress->UNDI_Loader)\r
+ );\r
+\r
+ ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 (\r
+ SimpleNetworkDevice->LegacyBios,\r
+ Segment, // Input segment\r
+ (UINT16) RomIdTableAddress->UNDI_Loader, // Offset\r
+ &InOutRegs, // Ptr to Regs\r
+ Buffer, // Reference to Stack\r
+ Size // Size of the Stack\r
+ );\r
+ if (ThunkFailed) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "The return code UndiLoaderTable->Status is = 0x%X\n\r",\r
+ UndiLoaderTable->Status)\r
+ );\r
+ DEBUG (\r
+ (DEBUG_NET,\r
+ "This error code should match eax, which is = 0x%X\n\r",\r
+ InOutRegs.X.AX)\r
+ );\r
+\r
+ DEBUG ((DEBUG_NET, "Now returned from the UNDI code\n\r"));\r
+\r
+ DEBUG ((DEBUG_NET, "After the call, we have...\n\r"));\r
+ Print_Undi_Loader_Table (UndiLoaderTable);\r
+\r
+ DEBUG ((DEBUG_NET, "Display the PXENV+ and !PXE tables exported by NIC\n\r"));\r
+ Print_PXENV_Table ((VOID *)(UINTN)((UndiLoaderTable->PXENVptr.Segment << 4) | UndiLoaderTable->PXENVptr.Offset));\r
+ Print_PXE_Table ((VOID *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset));\r
+\r
+ Pxe = (PXE_T *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset);\r
+ SimpleNetworkDevice->Nii.Id = (UINT64)(UINTN) Pxe;\r
+\r
+ //\r
+ // FreePool (Buffer);\r
+ // paranoia - make sure a valid !PXE structure\r
+ //\r
+ if (CompareMem (Pxe->Signature, PXE_SIG, sizeof Pxe->Signature) != 0) {\r
+ DEBUG ((DEBUG_ERROR, "!PXE Structure not found....\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ //\r
+ // its not - keep looking\r
+ //\r
+ }\r
+\r
+ if (CalculateSum8 ((UINT8 *) Pxe, Pxe->StructLength) != 0) {\r
+ DEBUG ((DEBUG_ERROR, "!PXE Checksum Error\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (Pxe->StructLength < (UINT8 *) &Pxe->FirstSelector - (UINT8 *) Pxe->Signature) {\r
+ DEBUG ((DEBUG_ERROR, "!PXE Length Error\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if ((((UINTN) Pxe->Undi.Segment) << 4) + Pxe->Undi.Offset != (UINTN) RomIdTableAddress) {\r
+ DEBUG ((DEBUG_ERROR, "!PXE RomId Address Error\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // This is the magic to bind the global PXE interface\r
+ // This dirtiness is for non-protocol shrouded access\r
+ //\r
+ SimpleNetworkDevice->PxeEntrySegment = Pxe->EntryPointSP.Segment;\r
+\r
+ if (SimpleNetworkDevice->PxeEntrySegment == 0) {\r
+ DEBUG ((DEBUG_ERROR, "!PXE EntryPointSP segment Error\n\r"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ SimpleNetworkDevice->PxeEntryOffset = Pxe->EntryPointSP.Offset;\r
+\r
+ DEBUG (\r
+ (\r
+ DEBUG_NET, "The entry point is 0x%X:0x%X\n\r", SimpleNetworkDevice->PxeEntrySegment, SimpleNetworkDevice->\r
+ PxeEntryOffset\r
+ )\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Effect the Far Call into the PXE Layer\r
+\r
+ Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API\r
+ services will not work, unless there are three 16-bit parameters pushed onto the stack.\r
+ push DS ;Far pointer to parameter structure\r
+ push offset pxe_data_call_struct ;is pushed onto stack.\r
+ push Index ;UINT16 is pushed onto stack.\r
+ call dword ptr (s_PXE ptr es:[di]).EntryPointSP\r
+ add sp, 6 ;Caller cleans up stack. \r
+\r
+ @param SimpleNetworkDevice Device instance for simple network\r
+ @param Table Point to parameter/retun value table for legacy far call\r
+ @param TableSize The size of paramter/return value table\r
+ @param CallIndex The index of legacy call.\r
+ \r
+ @return EFI_STATUS \r
+**/\r
+EFI_STATUS\r
+MakePxeCall (\r
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT VOID *Table,\r
+ IN UINTN TableSize,\r
+ IN UINT16 CallIndex\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IA32_REGISTER_SET InOutRegs;\r
+ UINT16 *BPtr;\r
+ VOID *Buffer;\r
+ UINTN Size;\r
+ VOID *MemPageAddress;\r
+ UINTN Index;\r
+ BOOLEAN ThunkFailed;\r
+\r
+ DEBUG ((DEBUG_NET, "MakePxeCall(CallIndex = %02x, Table = %X, TableSize = %d)\n", CallIndex, Table, TableSize));\r
+\r
+ if (SimpleNetworkDevice->PxeEntrySegment == 0 && SimpleNetworkDevice->PxeEntryOffset == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Allocate a transient data structure for the argument table\r
+ // This table needs to have the input XXX_t structure copied into here.\r
+ // The PXE UNDI can only grab this table when it's below one-MB, and\r
+ // this implementation will not try to push this table on the stack\r
+ // (although this is a possible optimization path since EFI always allocates\r
+ // 4K as a minimum page size...............)\r
+ //\r
+ Status = BiosSnp16AllocatePagesBelowOneMb (\r
+ TableSize / EFI_PAGE_SIZE + 1,\r
+ &MemPageAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));\r
+ return Status;\r
+ }\r
+ //\r
+ // Copy the > 1MB pool table to a sub-1MB buffer\r
+ //\r
+ CopyMem (MemPageAddress, Table, TableSize);\r
+\r
+ //\r
+ // Allocate space for IA-32 register context\r
+ //\r
+ ZeroMem (&InOutRegs, sizeof (InOutRegs));\r
+ InOutRegs.X.ES = SimpleNetworkDevice->PxeEntrySegment;\r
+ InOutRegs.X.DI = SimpleNetworkDevice->PxeEntryOffset;\r
+\r
+ //\r
+ // The game here is to build the stack which will subsequently\r
+ // get copied down below 1 MB by the FarCall primitive.\r
+ // This is now our working stack\r
+ //\r
+ Size = 6;\r
+ Status = gBS->AllocatePool (\r
+ EfiRuntimeServicesData,\r
+ Size,\r
+ &Buffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BPtr = (UINT16 *) Buffer;\r
+ *BPtr++ = CallIndex;\r
+ //\r
+ // SP + 2\r
+ //\r
+ *BPtr++ = TO_OFFSET (MemPageAddress);\r
+ *BPtr++ = TO_SEGMENT (MemPageAddress);\r
+\r
+ DEBUG ((DEBUG_NET, "State before FarCall86\n"));\r
+ DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer));\r
+ BPtr = (UINT16 *) Buffer;\r
+ DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2)));\r
+ DEBUG ((DEBUG_NET, " MemPage = "));\r
+ for (Index = 0; Index < TableSize; Index++) {\r
+ DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index)));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n"));\r
+\r
+ ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 (\r
+ SimpleNetworkDevice->LegacyBios,\r
+ SimpleNetworkDevice->PxeEntrySegment, // Input segment\r
+ SimpleNetworkDevice->PxeEntryOffset,\r
+ &InOutRegs, // Ptr to Regs\r
+ Buffer, // Reference to Stack\r
+ 6 // Size of the Stack\r
+ );\r
+ if (ThunkFailed) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "State after FarCall86\n"));\r
+ DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer));\r
+ BPtr = (UINT16 *) Buffer;\r
+ DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2)));\r
+ DEBUG ((DEBUG_NET, " MemPage = "));\r
+ for (Index = 0; Index < TableSize; Index++) {\r
+ DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index)));\r
+ }\r
+\r
+ DEBUG ((DEBUG_NET, "\n"));\r
+\r
+ //\r
+ // Copy the sub 1MB table to > 1MB table\r
+ //\r
+ CopyMem (Table, MemPageAddress, TableSize);\r
+\r
+ //\r
+ // For PXE UNDI call, AX contains the return status.\r
+ // Convert the PXE UNDI Status to EFI_STATUS type\r
+ //\r
+ if (InOutRegs.X.AX == PXENV_EXIT_SUCCESS) {\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Clean up house\r
+ //\r
+ gBS->FreePool (Buffer);\r
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) MemPageAddress, TableSize / EFI_PAGE_SIZE + 1);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ These are PXE Specification 2.1-compliant data structures and defines.\r
+\r
+ This file relies upon the existence of a PXE-compliant ROM\r
+ in memory, as defined by the Preboot Execution Environment \r
+ Specification (PXE), Version 2.1, located at\r
+\r
+ http://developer.intel.com/ial/wfm/wfmspecs.htm\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _PXEDEF_H_\r
+#define _PXEDEF_H_\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// PXE structure signatures\r
+//\r
+#define BC_ROMID_SIG "$BC$"\r
+#define UNDI_ROMID_SIG "UNDI"\r
+#define BUSD_ROMID_SIG "BUSD"\r
+\r
+#define PXE_SIG "!PXE"\r
+#define PXENV_SIG "PXENV+"\r
+\r
+#define BC_ROMID_REV 0x00\r
+#define UNDI_ROMID_REV 0x00\r
+#define BUSD_ROMID_REV 0x00\r
+\r
+#define PXE_REV 0x00\r
+#define PXENV_REV 0x0201\r
+\r
+#define PXENV_PTR SIGNATURE_32 ('P', 'X', 'E', 'N')\r
+#define PXE_PTR SIGNATURE_32 ('!', 'P', 'X', 'E')\r
+#define UNDI_ROMID_SIG_PTR SIGNATURE_32 ('U', 'N', 'D', 'I')\r
+\r
+typedef UINT16 SEGSEL; // Real mode segment or protected mode selector.\r
+typedef UINT16 OFF16; // Unsigned 16bit offset.\r
+typedef UINT32 ADDR32;\r
+\r
+//\r
+// Bus types\r
+//\r
+#define PXENV_BUS_ISA 0\r
+#define PXENV_BUS_EISA 1\r
+#define PXENV_BUS_MCA 2\r
+#define PXENV_BUS_PCI 3\r
+#define PXENV_BUS_VESA 4\r
+#define PXENV_BUS_PCMCIA 5\r
+\r
+//\r
+//\r
+// Result codes returned in AX by a PXENV API service.\r
+//\r
+#define PXENV_EXIT_SUCCESS 0x0000\r
+#define PXENV_EXIT_FAILURE 0x0001\r
+\r
+//\r
+// Status codes returned in the status word of PXENV API parameter structures.\r
+// \r
+// Generic API errors - these do not match up with the M0x or E0x messages\r
+// that are reported by the loader.\r
+//\r
+#define PXENV_STATUS_SUCCESS 0x00\r
+#define PXENV_STATUS_FAILURE 0x01\r
+#define PXENV_STATUS_BAD_FUNC 0x02\r
+#define PXENV_STATUS_UNSUPPORTED 0x03\r
+#define PXENV_STATUS_KEEP_UNDI 0x04\r
+#define PXENV_STATUS_KEEP_ALL 0x05\r
+#define PXENV_STATUS_OUT_OF_RESOURCES 0x06\r
+\r
+typedef enum {\r
+ PxeEnvStatus_Success,\r
+ PxeEnvStatus_Failure,\r
+ PxeEnvStatus_BadFunc,\r
+ PxeEnvStatus_Unsupported,\r
+ PxeEnvStatus_KeepUndi,\r
+ PxeEnvStatus_KeepAll\r
+} EFI_PXE_STATUS;\r
+\r
+/* Driver errors (0x60 to 0x6F) */\r
+\r
+// These errors are for UNDI compatible NIC drivers. \r
+#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60\r
+#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61\r
+#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62\r
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63\r
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64\r
+#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65\r
+#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66\r
+#define PXENV_STATUS_UNDI_BAD_MAC_ADDR 0x67\r
+#define PXENV_STATUS_UNDI_BAD_EEPROM_CKSUM 0x68\r
+#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69\r
+#define PXENV_STATUS_UNDI_INVALID_STATE 0x6A\r
+#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B\r
+#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C\r
+\r
+typedef struct {\r
+ UINT16 Seg_Addr;\r
+ UINT32 Phy_Addr;\r
+ UINT16 Seg_Size;\r
+} NEWSEGDESC_T;\r
+\r
+typedef struct {\r
+ OFF16 Offset;\r
+ SEGSEL Segment;\r
+} SEGOFF16;\r
+\r
+typedef struct {\r
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.\r
+ UINT8 StructLength; ///< Length of this structure in bytes.\r
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.\r
+ UINT8 StructRev; ///< Structure format revision number.\r
+ UINT8 UNDI_Rev[3]; ///< API revision number stored in Intel order.\r
+ //\r
+ // Revision 2.1.0 == 0x00, 0x01, 0x02\r
+ //\r
+ UINT16 UNDI_Loader; ///< Offset of UNDI loader routine in the option ROM image.\r
+ UINT16 StackSize; ///< Minimum stack segment size, in bytes, needed to load and run the UNDI.\r
+ UINT16 DataSize; ///< UNDI runtime code and data\r
+ UINT16 CodeSize; ///< segment sizes.\r
+ UINT8 BusType[4]; ///< 'ISAR', 'EISA', 'PCIR', 'PCCR'\r
+} UNDI_ROMID_T;\r
+\r
+typedef struct {\r
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.\r
+ UINT8 StructLength; ///< Length of this structure in bytes.\r
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.\r
+ UINT8 StructRev; ///< Structure format revision number.\r
+ UINT8 BC_Rev[3]; ///< API revision number stored in Intel order.\r
+ //\r
+ // Revision 2.1.0 == 0x00, 0x01, 0x02\r
+ //\r
+ UINT16 BC_Loader; ///< Offset of base-code loader routine in the option ROM image.\r
+ UINT16 StackSize; ///< Minimum stack segment size (bytes) needed to load/run base-code.\r
+ UINT16 DataSize; ///< Base-code runtime code and data\r
+ UINT16 CodeSize; ///< segment sizes.\r
+} BC_ROMID_T;\r
+\r
+typedef struct {\r
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.\r
+ UINT8 StructLength; ///< Length of this structure in bytes.\r
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.\r
+ UINT8 StructRev; ///< Structure format revision number.\r
+ UINT8 Reserved1; ///< must be zero\r
+ ///\r
+ /// UNDI_ROMID_T __FAR *UNDI;// Far pointer to UNDI ROMID\r
+ ///\r
+ SEGOFF16 Undi;\r
+\r
+ ///\r
+ /// BC_ROMID_T __FAR *Base; // Far pointer to base-code ROMID\r
+ ///\r
+ SEGOFF16 Base;\r
+\r
+ ///\r
+ /// UINT16 (__FAR __CDECL *EntryPointSP)(UINT16 func, VOID __FAR *param);\r
+ /// 16bit stack segment API entry point. This will be seg:off in\r
+ /// real mode and sel:off in 16:16 protected mode.\r
+ ///\r
+ SEGOFF16 EntryPointSP;\r
+\r
+ ///\r
+ /// UINT16 (__FAR __CDECL *EntryPointESP)(UINT16 func, VOID __FAR *param);\r
+ /// 32bit stack segment API entry point. This will be sel:off.\r
+ /// In real mode, sel == 0\r
+ ///\r
+ SEGOFF16 EntryPointESP;\r
+ ///\r
+ /// UINT16 (__FAR __CDECL *StatusCallout)(UINT16 param);\r
+ /// Address of DHCP/TFTP status callout routine.\r
+ ///\r
+ SEGOFF16 StatusCallout;\r
+ UINT8 Reserved2; ///< must be zero\r
+ UINT8 SegDescCnt; ///< Number of segment descriptors in this structure.\r
+ UINT16 FirstSelector; ///< First segment descriptor in GDT assigned to PXE.\r
+ NEWSEGDESC_T Stack;\r
+ NEWSEGDESC_T UNDIData;\r
+ NEWSEGDESC_T UNDICode;\r
+ NEWSEGDESC_T UNDICodeWrite;\r
+ NEWSEGDESC_T BC_Data;\r
+ NEWSEGDESC_T BC_Code;\r
+ NEWSEGDESC_T BC_CodeWrite;\r
+} PXE_T;\r
+\r
+typedef struct {\r
+ CHAR8 Signature[6]; ///< "PXENV+"\r
+ UINT16 Version; ///< PXE version number. LSB is minor version. MSB is major version.\r
+ UINT8 StructLength; ///< Length of PXE-2.0 Entry Point structure in bytes.\r
+ UINT8 StructCksum; ///< Used to make structure checksum equal zero.\r
+ UINT32 RMEntry; ///< Real mode API entry point segment:offset.\r
+ UINT32 PMEntryOff; ///< Protected mode API entry point\r
+ UINT16 PMEntrySeg; ///< segment:offset. This will always be zero. Protected mode API calls\r
+ ///< must be made through the API entry points in the PXE Runtime ID structure.\r
+\r
+ UINT16 StackSeg; ///< Real mode stack segment.\r
+ UINT16 StackSize; ///< Stack segment size in bytes.\r
+ UINT16 BaseCodeSeg; ///< Real mode base-code code segment.\r
+ UINT16 BaseCodeSize; ///< Base-code code segment size\r
+ UINT16 BaseDataSeg; ///< Real mode base-code data segment.\r
+ UINT16 BaseDataSize; ///< Base-code data segment size\r
+ UINT16 UNDIDataSeg; ///< Real mode UNDI data segment.\r
+ UINT16 UNDIDataSize; ///< UNDI data segment size in bytes.\r
+ UINT16 UNDICodeSeg; ///< Real mode UNDI code segment.\r
+ UINT16 UNDICodeSize; ///< UNDI code segment size in bytes.\r
+ PXE_T *RuntimePtr; ///< Real mode segment:offset pointer to PXE Runtime ID structure.\r
+} PXENV_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status;\r
+ IN OUT UINT16 Ax;\r
+ IN OUT UINT16 Bx;\r
+ IN OUT UINT16 Dx;\r
+ IN OUT UINT16 Di;\r
+ IN OUT UINT16 Es;\r
+ IN OUT UINT16 Undi_Ds;\r
+ IN OUT UINT16 Undi_Cs;\r
+ OUT SEGOFF16 PXEptr;\r
+ OUT SEGOFF16 PXENVptr;\r
+} UNDI_LOADER_T;\r
+\r
+//\r
+// Put in some UNDI-specific arguments\r
+//\r
+#define PXENV_START_UNDI 0x0000\r
+#define PXENV_UNDI_STARTUP 0x0001\r
+#define PXENV_UNDI_CLEANUP 0x0002\r
+#define PXENV_UNDI_INITIALIZE 0x0003\r
+#define PXENV_UNDI_RESET_NIC 0x0004\r
+#define PXENV_UNDI_SHUTDOWN 0x0005\r
+#define PXENV_UNDI_OPEN 0x0006\r
+#define PXENV_UNDI_CLOSE 0x0007\r
+#define PXENV_UNDI_TRANSMIT 0x0008\r
+#define PXENV_UNDI_SET_MCAST_ADDR 0x0009\r
+#define PXENV_UNDI_SET_STATION_ADDR 0x000A\r
+#define PXENV_UNDI_SET_PACKET_FILTER 0x000B\r
+#define PXENV_UNDI_GET_INFORMATION 0x000C\r
+#define PXENV_UNDI_GET_STATISTICS 0x000D\r
+#define PXENV_UNDI_CLEAR_STATISTICS 0x000E\r
+#define PXENV_UNDI_INITIATE_DIAGS 0x000F\r
+#define PXENV_UNDI_FORCE_INTERRUPT 0x0010\r
+#define PXENV_UNDI_GET_MCAST_ADDR 0x0011\r
+#define PXENV_UNDI_GET_NIC_TYPE 0x0012\r
+#define PXENV_UNDI_GET_NDIS_INFO 0x0013\r
+#define PXENV_UNDI_ISR 0x0014\r
+#define PXENV_STOP_UNDI 0x0015\r
+#define PXENV_UNDI_GET_STATE 0x0016\r
+\r
+#define ADDR_LEN 16\r
+#define MAXNUM_MCADDR 8\r
+#define IPLEN 4 ///< length of an IP address \r
+#define XMT_DESTADDR 0x0000 ///< destination address given\r
+#define XMT_BROADCAST 0x0001 ///< use broadcast address\r
+\r
+typedef struct {\r
+ UINT16 MCastAddrCount; ///< In: Number of multi-cast\r
+\r
+ /* addresses. */\r
+ UINT8 MCastAddr[MAXNUM_MCADDR][ADDR_LEN]; /* In: */\r
+\r
+ /* list of multi-cast addresses. */\r
+\r
+ /* Each address can take up to */\r
+\r
+ /* ADDR_LEN bytes and a maximum */\r
+\r
+ /* of MAXNUM_MCADDR address can */\r
+\r
+ /* be provided*/\r
+} PXENV_UNDI_MCAST_ADDR_T;\r
+\r
+/* Definitions of TFTP API parameter structures.\r
+ */\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+ IN UINT16 Ax; ///< In: These register fields must be\r
+ IN UINT16 Bx; ///< filled in with the same data\r
+ IN UINT16 Dx; ///< that was passed to the MLID\r
+ IN UINT16 Di; ///< option ROM boot code by the \r
+ IN UINT16 Es; ///< system BIOS.\r
+} PXENV_START_UNDI_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+} PXENV_UNDI_STARTUP_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+} PXENV_UNDI_CLEANUP_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+ \r
+ ///\r
+ /// This is an input parameter and is a 32-bit physical address of\r
+ /// a memory copy of the driver module in the protocol.ini file\r
+ /// obtained from the Protocol Manager driver(refer to NDIS 2.0\r
+ /// specifications). This parameter is basically supported for\r
+ /// the universal NDIS driver to pass the information contained in\r
+ /// protocol.ini file to the NIC driver for any specific\r
+ /// configuration of the NIC. (Note that the module\r
+ /// identification in the protocol.ini file was done by NDIS\r
+ /// itself.) This value can be NULL for for any other application\r
+ /// interfacing to the Universal NIC Driver.\r
+ ///\r
+ IN UINT32 ProtocolIni; \r
+ UINT8 Reserved[8];\r
+} PXENV_UNDI_INITIALIZE_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+ IN PXENV_UNDI_MCAST_ADDR_T R_Mcast_Buf; ///< multicast address list\r
+ /* see note below */\r
+} PXENV_UNDI_RESET_T;\r
+\r
+/*++\r
+ Note: The NIC driver does not remember the multicast\r
+ addresses provided in any call. So the application must\r
+ provide the multicast address list with all the calls that\r
+ reset the receive unit of the adapter. \r
+ --*/\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+} PXENV_UNDI_SHUTDOWN_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+ \r
+ ///\r
+ /// This is an input parameter and is adapter specific. This is\r
+ /// supported for Universal NDIS 2.0 driver to pass down the Open\r
+ /// flags provided by the protocol driver (See NDIS 2.0\r
+ /// specifications). This can be zero. \r
+ /// \r
+ IN UINT16 OpenFlag; ///< In: See description below \r
+ IN UINT16 PktFilter; ///< In: Filter for receiving \r
+\r
+ /* packet. It takes the following */\r
+\r
+ /* values, multiple values can be */\r
+\r
+ /* ORed together. */\r
+#define FLTR_DIRECTED 0x0001 ///< directed/multicast\r
+#define FLTR_BRDCST 0x0002 ///< broadcast packets\r
+#define FLTR_PRMSCS 0x0004 ///< any packet on LAN\r
+#define FLTR_SRC_RTG 0x0008 ///< source routing packet \r
+ IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; /* In: */\r
+ /* See t_PXENV_UNDI_MCAST_ADDR. */\r
+} PXENV_UNDI_OPEN_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+} PXENV_UNDI_CLOSE_T;\r
+\r
+#define MAX_DATA_BLKS 8\r
+\r
+typedef struct {\r
+ IN UINT16 ImmedLength; ///< In: Data buffer length in\r
+\r
+ /* bytes. */\r
+ UINT16 XmitOffset; ///< 16-bit segment & offset of the \r
+ UINT16 XmitSegment; ///< immediate data buffer. \r
+ UINT16 DataBlkCount; ///< In: Number of data blocks. \r
+ struct DataBlk {\r
+ UINT8 TDPtrType; ///< 0 => 32 bit Phys pointer in TDDataPtr, not supported in this version of LSA \r
+ ///< 1 => seg:offser in TDDataPtr which can be a real mode or 16-bit protected mode pointer\r
+ UINT8 TDRsvdByte; ///< Reserved, must be zero. \r
+ UINT16 TDDataLen; ///< Data block length in bytes. \r
+ UINT16 TDDataPtrOffset; ///< Far pointer to data buffer. \r
+ UINT16 TDDataPtrSegment; ///< Far pointer to data buffer. \r
+ } DataBlock[MAX_DATA_BLKS];\r
+}\r
+PXENV_UNDI_TBD_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+\r
+ ///\r
+ /// This is the protocol of the upper layer that is calling\r
+ /// NICTransmit call. If the upper layer has filled the media\r
+ /// header this field must be 0.\r
+ ///\r
+ IN UINT8 Protocol;\r
+#define P_UNKNOWN 0\r
+#define P_IP 1\r
+#define P_ARP 2\r
+#define P_RARP 3\r
+\r
+ ///\r
+ /// If this flag is 0, the NIC driver expects a pointer to the\r
+ /// destination media address in the field DestMediaAddr. If 1,\r
+ /// the NIC driver fills the broadcast address for the\r
+ /// destination.\r
+ /// \r
+ IN UINT8 XmitFlag; \r
+#define XMT_DESTADDR 0x0000 ///< destination address given \r
+#define XMT_BROADCAST 0x0001 ///< use broadcast address\r
+\r
+ ///\r
+ /// This is a pointer to the hardware address of the destination\r
+ /// media. It can be null if the destination is not known in\r
+ /// which case the XmitFlag contains 1 for broadcast. Destination\r
+ /// media address must be obtained by the upper level protocol\r
+ /// (with Address Resolution Protocol) and NIC driver does not do\r
+ /// any address resolution.\r
+ /// \r
+ IN UINT16 DestAddrOffset; ///< 16-bit segment & offset of the\r
+ IN UINT16 DestAddrSegment; ///< destination media address\r
+\r
+ \r
+ IN UINT16 TBDOffset; ///< 16-bit segment & offset of the \r
+ IN UINT16 TBDSegment; ///< transmit buffer descriptor of type \r
+\r
+ /// XmitBufferDesc \r
+ IN UINT32 Reserved[2];\r
+} PXENV_UNDI_TRANSMIT_T;\r
+\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+ IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; ///< In: \r
+} PXENV_UNDI_SET_MCAST_ADDR_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+ IN UINT8 StationAddress[ADDR_LEN]; ///< new address to be set \r
+} PXENV_UNDI_SET_STATION_ADDR_T;\r
+\r
+typedef struct s_PXENV_UNDI_SET_PACKET_FILTER {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+ IN UINT8 Filter; ///< In: Receive filter value. \r
+} PXENV_UNDI_SET_PACKET_FILTER_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+ OUT UINT16 BaseIo; ///< Out: Adapter's Base IO \r
+ OUT UINT16 IntNumber; ///< Out: IRQ number \r
+ OUT UINT16 MaxTranUnit; ///< Out: MTU \r
+ OUT UINT16 HwType; ///< Out: type of protocol at hardware level \r
+\r
+#define ETHER_TYPE 1\r
+#define EXP_ETHER_TYPE 2\r
+#define IEEE_TYPE 6\r
+#define ARCNET_TYPE 7\r
+ /*++ \r
+ other numbers can be obtained from rfc1010 for "Assigned\r
+ Numbers". This number may not be validated by the application\r
+ and hence adding new numbers to the list should be fine at any\r
+ time. \r
+ --*/\r
+ OUT UINT16 HwAddrLen; ///< Out: actual length of hardware address \r
+ OUT UINT8 CurrentNodeAddress[ADDR_LEN]; ///< Out: Current hardware address\r
+ OUT UINT8 PermNodeAddress[ADDR_LEN]; ///< Out: Permanent hardware address\r
+ OUT UINT16 ROMAddress; ///< Out: ROM address \r
+ OUT UINT16 RxBufCt; ///< Out: receive Queue length \r
+ OUT UINT16 TxBufCt; ///< Out: Transmit Queue length \r
+} PXENV_UNDI_GET_INFORMATION_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+ OUT UINT32 XmtGoodFrames; ///< Out: No. of good transmissions \r
+ OUT UINT32 RcvGoodFrames; ///< Out: No. of good frames received \r
+ OUT UINT32 RcvCRCErrors; ///< Out: No. of frames with CRC error \r
+ OUT UINT32 RcvResourceErrors; ///< Out: no. of frames discarded \r
+ /* Out: receive Queue full */\r
+} PXENV_UNDI_GET_STATISTICS_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+} PXENV_UNDI_CLEAR_STATISTICS_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+} PXENV_UNDI_INITIATE_DIAGS_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx\r
+} PXENV_UNDI_FORCE_INTERRUPT_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+ IN UINT32 InetAddr; ///< In: IP Multicast Address \r
+ OUT UINT8 MediaAddr[ADDR_LEN]; ///< Out: corresponding hardware \r
+ /* multicast address */\r
+} PXENV_UNDI_GET_MCAST_ADDR_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Vendor_ID; ///< OUT: \r
+ OUT UINT16 Dev_ID; ///< OUT: \r
+ OUT UINT8 Base_Class; ///< OUT: \r
+ OUT UINT8 Sub_Class; ///< OUT: \r
+ OUT UINT8 Prog_Intf; ///< OUT: program interface \r
+ OUT UINT8 Rev; ///< OUT: Revision number \r
+ OUT UINT16 BusDevFunc; ///< OUT: Bus, Device & Function numbers \r
+ OUT UINT16 SubVendor_ID; ///< OUT: \r
+ OUT UINT16 SubDevice_ID; ///< OUT: \r
+} PCI_INFO_T;\r
+\r
+typedef struct {\r
+ OUT UINT32 EISA_Dev_ID; ///< Out: \r
+ OUT UINT8 Base_Class; ///< OUT: \r
+ OUT UINT8 Sub_Class; ///< OUT: \r
+ OUT UINT8 Prog_Intf; ///< OUT: program interface \r
+ OUT UINT16 CardSelNum; ///< OUT: Card Selector Number \r
+ OUT UINT8 Reserved; ///< to make it 10 bytes \r
+} PNP_INFO_T;\r
+\r
+\r
+typedef union {\r
+ PCI_INFO_T Pci;\r
+ PNP_INFO_T Pnp;\r
+} PCI_PNP_INFO_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx \r
+ OUT UINT8 NicType; ///< OUT: 2=PCI, 3=PnP \r
+ PCI_PNP_INFO_T PciPnpInfo;\r
+} PXENV_UNDI_GET_NIC_TYPE_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx \r
+ OUT UINT8 IfaceType[16]; ///< OUT: Type name of MAC, AsciiZ \r
+\r
+ /* format. This is used by the */\r
+\r
+ /* Universal NDIS Driver to fill */\r
+\r
+ /* the driver type in it's MAC */\r
+\r
+ /* Service specific */\r
+\r
+ /* characteristic table */\r
+ OUT UINT32 LinkSpeed; ///< OUT: \r
+ OUT UINT32 ServiceFlags; ///< OUT: as defined in NDIS Spec 2.0X \r
+ OUT UINT32 Reserved[4]; ///< OUT: will be filled with 0s till defined\r
+} PXENV_UNDI_GET_NDIS_INFO_T;\r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx \r
+ IN OUT UINT16 FuncFlag; ///< In: PXENV_UNDI_ISR_IN_xxx \r
+\r
+ /* Out: PXENV_UNDI_ISR_OUT_xxx */\r
+ OUT UINT16 BufferLength;\r
+ OUT UINT16 FrameLength;\r
+ OUT UINT16 FrameHeaderLength;\r
+ OUT UINT16 FrameOffset;\r
+ OUT UINT16 FrameSegSel;\r
+ OUT UINT8 ProtType;\r
+ OUT UINT8 PktType;\r
+} PXENV_UNDI_ISR_T;\r
+\r
+#define PXENV_UNDI_ISR_IN_START 1 /* This function must be first */\r
+\r
+/* when an interrupt is received. */\r
+\r
+/* It will tell us if the intr */\r
+\r
+/* was generated by our device. */\r
+#define PXENV_UNDI_ISR_IN_PROCESS 2 /* Call to start processing one of */\r
+\r
+/* our interrupts. */\r
+#define PXENV_UNDI_ISR_IN_GET_NEXT 3 /* Call to start/continue receiving */\r
+\r
+/* data from receive buffer(s). */\r
+\r
+/*++\r
+\r
+ Possible responses from PXENV_UNDI_ISR_IN_START\r
+\r
+ --*/\r
+#define PXENV_UNDI_ISR_OUT_OURS 0 ///< This is our interrupt. Deal with it. \r
+#define PXENV_UNDI_ISR_OUT_NOT_OURS 1 ///< This is not our interrupt.\r
+\r
+/*++\r
+\r
+ Possible responses from PXENV_UNDI_ISR_IN_PROCESS and\r
+ PXENV_UNDI_ISR_IN_PROCESS\r
+\r
+--*/\r
+#define PXENV_UNDI_ISR_OUT_DONE 0 ///< We are done processing this interrupt. \r
+#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 ///< We completed a transmit interrupt. \r
+#define PXENV_UNDI_ISR_OUT_RECEIVE 3 ///< Get data from receive buffer. \r
+\r
+#define PXENV_UNDI_ISR_OUT_BUSY 4 /* ? */\r
+\r
+typedef struct {\r
+ UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+} PXENV_STOP_UNDI_T;\r
+\r
+#define PXENV_UNDI_STARTED 1 ///< not even initialized \r
+#define PXENV_UNDI_INITIALIZED 2 ///< initialized and closed (not opened) \r
+#define PXENV_UNDI_OPENED 3 ///< initialized & opened \r
+\r
+typedef struct {\r
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx \r
+ UINT16 UNDI_State;\r
+} PXENV_UNDI_GET_STATE_T;\r
+\r
+#pragma pack()\r
+\r
+#endif\r
--- /dev/null
+/** @file \r
+ Wrapper routines that use a PXE-enabled NIC option ROM to \r
+ supply internal routines for an EFI SNI (Simple Network \r
+ Interface) Protocol.\r
+\r
+ This file relies upon the existence of a PXE-compliant ROM\r
+ in memory, as defined by the Preboot Execution Environment \r
+ Specification (PXE), Version 2.1, located at\r
+\r
+ http://developer.intel.com/ial/wfm/wfmspecs.htm\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosSnp16.h"\r
+\r
+/**\r
+ PXE \r
+ START UNDI\r
+ Op-Code: PXENV_START_UNDI (0000h)\r
+ Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is\r
+ responsible for saving the information it needs to communicate with the hardware.\r
+ This service is also responsible for hooking the Int 1Ah service routine\r
+ Note: This API service must be called only once during UNDI Option ROM boot.\r
+ The UNDI driver is responsible for saving this information and using it every time\r
+ PXENV_UNDI_STARTUP is called.\r
+ Service cannot be used in protected mode.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT16 AX;\r
+ UINT16 BX;\r
+ UINT16 DX;\r
+ UINT16 DI;\r
+ UINT16 ES;\r
+ } PXENV_START_UNDI_T;\r
+ Set before calling API service\r
+ AX, BX, DX, DI, ES: BIOS initialization parameter registers. These\r
+ fields should contain the same information passed to the option ROM\r
+ initialization routine by the Host System BIOS. Information about the\r
+ contents of these registers can be found in the [PnP], [PCI] and\r
+ [BBS] specifications.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+\r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeStartUndi (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_START_UNDI_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_START_UNDI_T),\r
+ PXENV_START_UNDI\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI STARTUP \r
+ Op-Code: PXENV_UNDI_STARTUP (0001h)\r
+ Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the\r
+ caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper\r
+ operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used\r
+ to complete this initialization. The rest of the UNDI APIs will not be available until this call has\r
+ been completed.\r
+ Note: PXENV_UNDI_STARTUP must not be called again without first calling\r
+ PXENV_UNDI_SHUTDOWN.\r
+ PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for\r
+ chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and\r
+ PXENV_STOP_UNDI API calls.\r
+ This service cannot be used in protected mode.\r
+ typedef struct \r
+ {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_STARTUP_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+\r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiStartup (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_STARTUP_T),\r
+ PXENV_UNDI_STARTUP\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI CLEANUP\r
+ Op-Code: PXENV_UNDI_CLEANUP (0002h)\r
+ Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field\r
+ in the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be\r
+ made just before unloading the Universal NIC Driver. The rest of the API will not be available\r
+ after this call executes.\r
+ This service cannot be used in protected mode.\r
+ typedef struct {\r
+ PXENX_STATUS Status;\r
+ } PXENV_UNDI_CLEANUP_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+\r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiCleanup (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_CLEANUP_T),\r
+ PXENV_UNDI_CLEANUP\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI INITIALIZE\r
+ Op-Code: PXENV_UNDI_INITIALIZE (0003h)\r
+ Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the\r
+ caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call resets the adapter and programs it with default parameters. The default parameters used\r
+ are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the\r
+ receive and transmit units of the network adapter to readily receive or transmit packets. The\r
+ application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network.\r
+ This call must be made by an application to establish an interface to the network adapter driver.\r
+ Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for\r
+ the Protocol field in the parameter structure.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ ADDR32 ProtocolIni;\r
+ UINT8 reserved[8];\r
+ } PXENV_UNDI_INITIALIZE_T;\r
+ Set before calling API service\r
+ ProtocolIni: Physical address of a memory copy of the driver\r
+ module from the protocol.ini file obtained from the protocol manager\r
+ driver (refer to the NDIS 2.0 specification). This parameter is\r
+ supported for the universal NDIS driver to pass the information\r
+ contained in the protocol.ini file to the NIC driver for any specific\r
+ configuration of the NIC. (Note that the module identification in the\r
+ protocol.ini file was done by NDIS.) This value can be NULL for any\r
+ other application interfacing to the universal NIC driver\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiInitialize (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_INITIALIZE_T),\r
+ PXENV_UNDI_INITIALIZE\r
+ );\r
+}\r
+\r
+/**\r
+ Wrapper routine for reset adapter.\r
+ \r
+ PXE \r
+ UNDI RESET ADAPTER\r
+ Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h)\r
+ Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized\r
+ by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to\r
+ Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the\r
+ network. This routine cannot be used to replace Initialize or Shutdown calls.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;\r
+ } PXENV_UNDI_RESET_T;\r
+\r
+ #define MAXNUM_MCADDR 8\r
+\r
+ typedef struct {\r
+ UINT16 MCastAddrCount;\r
+ MAC_ADDR McastAddr[MAXNUM_MCADDR];\r
+ } PXENV_UNDI_MCAST_ADDRESS_t;\r
+\r
+ Set before calling API service\r
+ R_Mcast_Buf: This is a structure of MCastAddrCount and\r
+ McastAddr.\r
+ MCastAddrCount: Number of multicast MAC addresses in the\r
+ buffer.\r
+ McastAddr: List of up to MAXNUM_MCADDR multicast MAC\r
+ addresses.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance.\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ @param RxFilter Filter setting mask value for PXE recive . \r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiResetNic (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_RESET_T *PxeUndiTable,\r
+ IN UINT16 RxFilter\r
+ )\r
+{\r
+ PXENV_UNDI_OPEN_T Open;\r
+ PXENV_UNDI_CLOSE_T Close;\r
+ UINTN Status;\r
+\r
+ Status = MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_RESET_T),\r
+ PXENV_UNDI_RESET_NIC\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Close.Status = PXENV_STATUS_SUCCESS;\r
+\r
+ Status = MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ &Close,\r
+ sizeof (Close),\r
+ PXENV_UNDI_CLOSE\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_RESET_T),\r
+ PXENV_UNDI_RESET_NIC\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Open.Status = PXENV_STATUS_SUCCESS;\r
+ Open.OpenFlag = 0;\r
+ Open.PktFilter = RxFilter;\r
+ CopyMem (\r
+ &Open.McastBuffer,\r
+ &PxeUndiTable->R_Mcast_Buf,\r
+ sizeof (PXENV_UNDI_MCAST_ADDR_T)\r
+ ); \r
+ \r
+\r
+ Status = MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ &Open,\r
+ sizeof (Open),\r
+ PXENV_UNDI_OPEN\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI SHUTDOWN\r
+ Op-Code: PXENV_UNDI_SHUTDOWN (0005h)\r
+ Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call resets the network adapter and leaves it in a safe state for another driver to program it.\r
+ Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the\r
+ Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again.\r
+ typedef struct \r
+ {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_SHUTDOWN_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiShutdown (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_SHUTDOWN_T),\r
+ PXENV_UNDI_SHUTDOWN\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI OPEN\r
+ Op-Code: PXENV_UNDI_OPEN (0006h)\r
+ Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call activates the adapter network connection and sets the adapter ready to accept packets\r
+ for transmit and receive.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT16 OpenFlag;\r
+ UINT16 PktFilter;\r
+ #define FLTR_DIRECTED 0x0001\r
+ #define FLTR_BRDCST 0x0002\r
+ #define FLTR_PRMSCS 0x0004\r
+ #define FLTR_SRC_RTG 0x0008\r
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;\r
+ } PXENV_UNDI_OPEN_T;\r
+ Set before calling API service\r
+ OpenFlag: This is an adapter specific input parameter. This is\r
+ supported for the universal NDIS 2.0 driver to pass in the open flags\r
+ provided by the protocol driver. (See the NDIS 2.0 specification.)\r
+ This can be zero.\r
+ PktFilter: Filter for receiving packets. This can be one, or more, of\r
+ the FLTR_xxx constants. Multiple values are arithmetically or-ed\r
+ together.\r
+ directed packets are packets that may come to your MAC address\r
+ or the multicast MAC address.\r
+ R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h).\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiOpen (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_OPEN_T),\r
+ PXENV_UNDI_OPEN\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI CLOSE\r
+ Op-Code: PXENV_UNDI_CLOSE (0007h)\r
+ Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or\r
+ received until the network adapter is open again.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_CLOSE_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiClose (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_CLOSE_T),\r
+ PXENV_UNDI_CLOSE\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI TRANSMIT PACKET\r
+ Op-Code: PXENV_UNDI_TRANSMIT (0008h)\r
+ Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that\r
+ has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX.\r
+ The status code must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call transmits a buffer to the network. The media header\r
+ for the packet can be filled by the calling protocol, but it might not be.\r
+ The network adapter driver will fill it if required by the values in the\r
+ parameter block. The packet is buffered for transmission provided there is\r
+ an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no\r
+ buffer is available the function returns PXENV_EXIT_FAILURE with a status\r
+ code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is\r
+ implementation-dependent. An interrupt is generated on completion of the\r
+ transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is\r
+ permitted in the context of a transmit complete interrupt.\r
+\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT8 Protocol;\r
+ #define P_UNKNOWN 0\r
+ #define P_IP 1\r
+ #define P_ARP 2\r
+ #define P_RARP 3\r
+ UINT8 XmitFlag;\r
+ #define XMT_DESTADDR 0x0000\r
+ #define XMT_BROADCAST 0x0001\r
+ SEGOFF16 DestAddr;\r
+ SEGOFF16 TBD;\r
+ UINT32 Reserved[2];\r
+ } t_PXENV_UNDI_TRANSMIT;\r
+\r
+ #define MAX_DATA_BLKS 8\r
+\r
+ typedef struct {\r
+ UINT16 ImmedLength;\r
+ SEGOFF16 Xmit;\r
+ UINT16 DataBlkCount;\r
+ struct DataBlk {\r
+ UINT8 TDPtrType;\r
+ UINT8 TDRsvdByte;\r
+ UINT16 TDDataLen;\r
+ SEGOFF16 TDDataPtr;\r
+ } DataBlock[MAX_DATA_BLKS];\r
+ } PXENV_UNDI_TBD_T\r
+\r
+ Set before calling API service\r
+ Protocol: This is the protocol of the upper layer that is calling UNDI\r
+ TRANSMIT call. If the upper layer has filled the media header, this\r
+ field must be P_UNKNOWN.\r
+ XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a\r
+ pointer to the destination media address in the field DestAddr. If\r
+ XMT_BROADCAST, the NIC driver fills the broadcast address for the\r
+ destination.\r
+ TBD: Segment:Offset address of the transmit buffer descriptor.\r
+ ImmedLength: Length of the immediate transmit buffer: Xmit.\r
+ Xmit: Segment:Offset of the immediate transmit buffer.\r
+ DataBlkCount: Number of blocks in this transmit buffer.\r
+ TDPtrType:\r
+ 0 => 32-bit physical address in TDDataPtr (not supported in this\r
+ version of PXE)\r
+ 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit\r
+ protected mode pointer\r
+ TDRsvdByte: Reserved must be zero.\r
+ TDDatalen: Data block length in bytes.\r
+ TDDataPtr: Segment:Offset of the transmit block.\r
+ DataBlock: Array of transmit data blocks.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiTransmit (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_TRANSMIT_T),\r
+ PXENV_UNDI_TRANSMIT\r
+ );\r
+ if (Status == EFI_SUCCESS) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (PxeUndiTable->Status) {\r
+ case PXENV_STATUS_OUT_OF_RESOURCES:\r
+ return EFI_NOT_READY;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI SET MULTICAST ADDRESS\r
+ Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h)\r
+ Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call changes the current list of multicast addresses to the input list and resets the network\r
+ adapter to accept it. If the number of multicast addresses is zero, multicast is disabled.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;\r
+ } PXENV_UNDI_SET_MCAST_ADDR_T;\r
+ Set before calling API service\r
+ R_Mcast_Buf: See description in the UNDI RESET ADAPTER\r
+ (0004h) API.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiSetMcastAddr (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_SET_MCAST_ADDR_T),\r
+ PXENV_UNDI_SET_MCAST_ADDR\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI SET STATION ADDRESS\r
+ Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah)\r
+ Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call sets the MAC address to be the input value and is called before opening the network\r
+ adapter. Later, the open call uses this variable as a temporary MAC address to program the\r
+ adapter individual address registers.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ MAC_ADDR StationAddress;\r
+ } PXENV_UNDI_SET_STATION_ADDR_T;\r
+ Set before calling API service\r
+ StationAddress: Temporary MAC address to be used for\r
+ transmit and receive.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiSetStationAddr (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_SET_STATION_ADDR_T),\r
+ PXENV_UNDI_SET_STATION_ADDR\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI SET PACKET FILTER\r
+ Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh)\r
+ Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with\r
+ the open call.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT8 filter;\r
+ } PXENV_UNDI_SET_PACKET_FILTER_T;\r
+ Set before calling API service\r
+ Filter: See the receive filter values in the UNDI OPEN\r
+ (0006h) API description.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiSetPacketFilter (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_SET_PACKET_FILTER_T),\r
+ PXENV_UNDI_SET_PACKET_FILTER\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI GET INFORMATION\r
+ Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch)\r
+ Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call copies the network adapter variables, including the MAC address, into the input buffer.\r
+ Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and\r
+ PXENV_UNDI_STARTUP have been issued. All other fields must be valid after\r
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been\r
+ called.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT16 BaseIo;\r
+ UINT16 IntNumber;\r
+ UINT16 MaxTranUnit;\r
+ UINT16 HwType;\r
+ #define ETHER_TYPE 1\r
+ #define EXP_ETHER_TYPE 2\r
+ #define IEEE_TYPE 6\r
+ #define ARCNET_TYPE 7\r
+ UINT16 HwAddrLen;\r
+ MAC_ADDR CurrentNodeAddress;\r
+ MAC_ADDR PermNodeAddress;\r
+ SEGSEL ROMAddress;\r
+ UINT16 RxBufCt;\r
+ UINT16 TxBufCt;\r
+ } PXENV_UNDI_GET_INFORMATION_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ BaseIO: Adapter base I/O address.\r
+ IntNumber: Adapter IRQ number.\r
+ MaxTranUnit: Adapter maximum transmit unit.\r
+ HWType: Type of protocol at the hardware level.\r
+ HWAddrLen: Length of the hardware address.\r
+ CurrentNodeAddress: Current hardware address.\r
+ PermNodeAddress: Permanent hardware address.\r
+ ROMAddress: Real mode ROM segment address.\r
+ RxBufCnt: Receive queue length.\r
+ TxBufCnt: Transmit queue length. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetInformation (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_GET_INFORMATION_T),\r
+ PXENV_UNDI_GET_INFORMATION\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI GET STATISTICS\r
+ Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh)\r
+ Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized\r
+ by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call reads statistical information from the network adapter, and returns.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ UINT32 XmtGoodFrames;\r
+ UINT32 RcvGoodFrames;\r
+ UINT32 RcvCRCErrors;\r
+ UINT32 RcvResourceErrors;\r
+ } PXENV_UNDI_GET_STATISTICS_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ XmtGoodFrames: Number of successful transmissions.\r
+ RcvGoodFrames: Number of good frames received.\r
+ RcvCRCErrors: Number of frames received with CRC\r
+ error.\r
+ RcvResourceErrors: Number of frames discarded\r
+ because receive queue was full.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetStatistics (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_GET_STATISTICS_T),\r
+ PXENV_UNDI_GET_STATISTICS\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI CLEAR STATISTICS\r
+ Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh)\r
+ Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call clears the statistical information from the network adapter.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_CLEAR_STATISTICS_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiClearStatistics (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_CLEAR_STATISTICS_T),\r
+ PXENV_UNDI_CLEAR_STATISTICS\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI INITIATE DIAGS\r
+ Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh)\r
+ Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the\r
+ PXENV_STATUS_xxx constants.\r
+ Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run\r
+ hardware diagnostics and to update its status information.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_INITIATE_DIAGS_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiInitiateDiags (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_INITIATE_DIAGS_T),\r
+ PXENV_UNDI_INITIATE_DIAGS\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI FORCE INTERRUPT\r
+ Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h)\r
+ Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been\r
+ initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the\r
+ network adapter driver usually queues the packet and calls the application's callback receive\r
+ routine with a pointer to the packet received. Then, the callback routine either can copy the packet\r
+ to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied,\r
+ the network adapter driver does not remove it from the input queue. When the application wants to\r
+ copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive\r
+ interrupt.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_UNDI_FORCE_INTERRUPT_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiForceInterrupt (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_FORCE_INTERRUPT_T),\r
+ PXENV_UNDI_FORCE_INTERRUPT\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI GET MULTICAST ADDRESS\r
+ Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h)\r
+ Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized\r
+ by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This call converts the given IP multicast address to a hardware multicast address.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ IP4 InetAddr;\r
+ MAC_ADDR MediaAddr;\r
+ } PXENV_UNDI_GET_MCAST_ADDR_T;\r
+ Set before calling API service\r
+ InetAddr: IP multicast address.\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ MediaAddr: MAC multicast address.\r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetMcastAddr (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_GET_MCAST_ADDR_T),\r
+ PXENV_UNDI_GET_MCAST_ADDR\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI GET NIC TYPE\r
+ Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h)\r
+ Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE parameter structure that has been initialized by\r
+ the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the\r
+ NIC information.\r
+ Description: This call, if successful, provides the NIC-specific information necessary to identify the network\r
+ adapter that is used to boot the system.\r
+ Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if\r
+ the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific\r
+ information can be obtained from the DHCPDISCOVER packet itself.\r
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called\r
+ before the information provided is valid.\r
+ typedef {\r
+ PXENV_STATUS Status;\r
+ UINT8 NicType;\r
+ #define PCI_NIC 2\r
+ #define PnP_NIC 3\r
+ #define CardBus_NIC 4\r
+ Union {\r
+ Struct {\r
+ UINT16 Vendor_ID;\r
+ UINT16 Dev_ID;\r
+ UINT8 Base_Class;\r
+ UINT8 Sub_Class;\r
+ UINT8 Prog_Intf;\r
+ UINT8 Rev;\r
+ UINT16 BusDevFunc;\r
+ UINT16 SubVendor_ID;\r
+ UINT16 SubDevice_ID;\r
+ } pci, cardbus;\r
+ struct {\r
+ UINT32 EISA_Dev_ID;\r
+ UINT8 Base_Class;\r
+ UINT8 Sub_Class;\r
+ UINT8 Prog_Intf;\r
+ UINT16 CardSelNum;\r
+ } pnp;\r
+ } info;\r
+ } PXENV_UNDI_GET_NIC_TYPE_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ NICType: Type of NIC information stored in the parameter\r
+ structure.\r
+ Info: Information about the fields in this union can be found\r
+ in the [PnP] and [PCI] specifications \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetNicType (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_GET_NIC_TYPE_T),\r
+ PXENV_UNDI_GET_NIC_TYPE\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI GET IFACE INFO\r
+ Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h)\r
+ Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized\r
+ by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the\r
+ interface specific information.\r
+ Description: This call, if successful, provides the network interface specific information such as the interface\r
+ type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the\r
+ universal drivers such as NDIS or Miniport to communicate to the upper protocol modules.\r
+ Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the\r
+ universal driver to translate/convert this information into a format that is required in its specification\r
+ or to suit the expectation of the upper level protocol modules.\r
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called\r
+ before the information provided is valid.\r
+ typedef struct {\r
+ PXENV_STATUS Status\r
+ UINT8 IfaceType[16];\r
+ UINT32 LinkSpeed;\r
+ UINT32 ServiceFlags;\r
+ UINT32 Reserved[4];\r
+ } PXENV_UNDI_GET_NDIS_INFO_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ IfaceType: Name of MAC type in ASCIIZ format. This is\r
+ used by the universal NDIS driver to specify its driver type\r
+ to the protocol driver.\r
+ LinkSpeed: Defined in the NDIS 2.0 specification.\r
+ ServiceFlags: Defined in the NDIS 2.0 specification.\r
+ Reserved: Must be zero. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetNdisInfo (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_GET_NDIS_INFO_T),\r
+ PXENV_UNDI_GET_NDIS_INFO\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI ISR\r
+ Op-Code: PXENV_UNDI_ISR (0014h)\r
+ Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in\r
+ the parameter block indicates the operation to be performed for the call. This field is filled with the\r
+ status of that operation on return.\r
+ Note: Interrupt Service Routine Operation:\r
+ In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the\r
+ application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR\r
+ API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing\r
+ (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT).\r
+ When the Network Interface HW generates an interrupt the protocol driver interrupt service\r
+ routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then\r
+ calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for\r
+ the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface\r
+ level and read any status values required to further process the interrupt. UNDI must return as\r
+ quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or\r
+ PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the\r
+ interrupt was generated by this particular Network Interface or not.\r
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was\r
+ not generated by our NIC, and interrupt processing is complete.\r
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start\r
+ a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is\r
+ now complete.\r
+ The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to\r
+ PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and\r
+ return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the\r
+ first buffer pointer of that frame in the parameter block.\r
+ The protocol driver calls UNDI repeatedly with the FuncFlag equal to\r
+ PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received\r
+ frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l\r
+ remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous\r
+ buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter\r
+ block. Otherwise it must return the first buffer in the next frame.\r
+ If there is no received frame pending to be processed, UNDI processes the transmit completes and\r
+ if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the\r
+ NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag.\r
+ IMPORTANT: It is possible for the protocol driver to be interrupted again while in the\r
+ strategy routine when the UNDI re-enables interrupts. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiIsr (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_ISR_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_ISR_T),\r
+ PXENV_UNDI_ISR\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ STOP UNDI\r
+ Op-Code: PXENV_STOP_UNDI (0015h)\r
+ Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This routine is responsible for unhooking the Int 1Ah service routine.\r
+ Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid\r
+ status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from\r
+ base memory. Also, UNDI must not be removed from base memory if BC is not removed from base\r
+ memory.\r
+ Service cannot be used in protected mode.\r
+ typedef struct {\r
+ PXENV_STATUS Status;\r
+ } PXENV_STOP_UNDI_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiStop (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_STOP_UNDI_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_STOP_UNDI_T),\r
+ PXENV_STOP_UNDI\r
+ );\r
+}\r
+\r
+/**\r
+ PXE \r
+ UNDI GET STATE\r
+ Op-Code: PXENV_UNDI_GET_STATE (0015h)\r
+ Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state\r
+ constants\r
+ Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call\r
+ sequences\r
+ typedef struct {\r
+ #define PXE_UNDI_GET_STATE_STARTED 1\r
+ #define PXE_UNDI_GET_STATE_INITIALIZED 2\r
+ #define PXE_UNDI_GET_STATE_OPENED 3\r
+ PXENV_STATUS Status;\r
+ UINT8 UNDIstate;\r
+ } PXENV_UNDI_GET_STATE_T;\r
+ Set before calling API service\r
+ N/A\r
+ Returned from API service\r
+ Status: See the PXENV_STATUS_xxx constants.\r
+ State: See definitions of the state constants.\r
+ Note. UNDI implementation is responsible for maintaining\r
+ internal state machine.\r
+ UNDI ISR\r
+ Op-Code: PXENV_UNDI_ISR (0014h)\r
+ Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller.\r
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in\r
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx\r
+ constants.\r
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in\r
+ the parameter block indicates the operation to be performed for the call. This field is filled with the\r
+ status of that operation on return. \r
+ \r
+ @param SimpleNetworkDevice Device instance\r
+ @param PxeUndiTable Point to structure which hold paramter and return value \r
+ for option ROM call.\r
+ \r
+ @return Return value of PXE option ROM far call. \r
+**/\r
+EFI_STATUS\r
+PxeUndiGetState (\r
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,\r
+ IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable\r
+ )\r
+{\r
+ return MakePxeCall (\r
+ SimpleNetworkDevice,\r
+ PxeUndiTable,\r
+ sizeof (PXENV_UNDI_GET_STATE_T),\r
+ PXENV_UNDI_GET_STATE\r
+ );\r
+}\r
--- /dev/null
+## @file\r
+# Thunk wrapper UEFI driver to produce EFI SNP protocol based on legacy 16 NIC ROM.\r
+#\r
+# Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions\r
+# of the BSD License which accompanies this distribution. The\r
+# full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+ BASE_NAME = BiosSnp16\r
+ FILE_GUID = D0CAA91E-2DE4-4b0d-B3DC-09C67E854E34\r
+ MODULE_TYPE = UEFI_DRIVER\r
+ INF_VERSION = 0x00010005\r
+ VERSION_STRING = 1.0\r
+ \r
+ ENTRY_POINT = BiosSnp16DriverEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+# DRIVER_BINDING = gBiosSnp16DriverBinding\r
+# COMPONENT_NAME = gBiosSnp16ComponentName\r
+#\r
+\r
+[Sources]\r
+ BiosSnp16.h\r
+ BiosSnp16.c\r
+ Misc.c\r
+ Pxe.h\r
+ PxeUndi.c\r
+ ComponentName.c\r
+\r
+\r
+[Libraryclasses]\r
+ UefiDriverEntryPoint\r
+ DebugLib\r
+ BaseMemoryLib\r
+ UefiBootServicesTableLib\r
+ UefiLib\r
+ BaseLib\r
+ DevicePathLib\r
+ MemoryAllocationLib\r
+\r
+[Guids]\r
+ gEfiEventExitBootServicesGuid\r
+\r
+[Protocols]\r
+ gEfiNetworkInterfaceIdentifierProtocolGuid\r
+ gEfiDevicePathProtocolGuid\r
+ gEfiSimpleNetworkProtocolGuid\r
+ gEfiPciIoProtocolGuid\r
+ gEfiLegacyBiosProtocolGuid\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
--- /dev/null
+/** @file\r
+ ConsoleOut Routines that speak VGA.\r
+\r
+Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosVideo.h"\r
+\r
+//\r
+// EFI Driver Binding Protocol Instance\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {\r
+ BiosVideoDriverBindingSupported,\r
+ BiosVideoDriverBindingStart,\r
+ BiosVideoDriverBindingStop,\r
+ 0x3,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+//\r
+// Global lookup tables for VGA graphics modes\r
+//\r
+UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };\r
+\r
+UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };\r
+\r
+UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\r
+\r
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = {\r
+ { 0x00, 0x00, 0x00, 0x00 },\r
+ { 0x98, 0x00, 0x00, 0x00 },\r
+ { 0x00, 0x98, 0x00, 0x00 },\r
+ { 0x98, 0x98, 0x00, 0x00 },\r
+ { 0x00, 0x00, 0x98, 0x00 },\r
+ { 0x98, 0x00, 0x98, 0x00 },\r
+ { 0x00, 0x98, 0x98, 0x00 },\r
+ { 0x98, 0x98, 0x98, 0x00 },\r
+ { 0x10, 0x10, 0x10, 0x00 },\r
+ { 0xff, 0x10, 0x10, 0x00 },\r
+ { 0x10, 0xff, 0x10, 0x00 },\r
+ { 0xff, 0xff, 0x10, 0x00 },\r
+ { 0x10, 0x10, 0xff, 0x00 },\r
+ { 0xf0, 0x10, 0xff, 0x00 },\r
+ { 0x10, 0xff, 0xff, 0x00 },\r
+ { 0xff, 0xff, 0xff, 0x00 }\r
+};\r
+\r
+//\r
+// Standard timing defined by VESA EDID\r
+//\r
+VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = {\r
+ //\r
+ // Established Timing I\r
+ //\r
+ {800, 600, 60},\r
+ {800, 600, 56},\r
+ {640, 480, 75},\r
+ {640, 480, 72},\r
+ {640, 480, 67},\r
+ {640, 480, 60},\r
+ {720, 400, 88},\r
+ {720, 400, 70},\r
+ //\r
+ // Established Timing II\r
+ //\r
+ {1280, 1024, 75},\r
+ {1024, 768, 75},\r
+ {1024, 768, 70},\r
+ {1024, 768, 60},\r
+ {1024, 768, 87},\r
+ {832, 624, 75},\r
+ {800, 600, 75},\r
+ {800, 600, 72},\r
+ //\r
+ // Established Timing III\r
+ //\r
+ {1152, 870, 75}\r
+};\r
+\r
+/**\r
+ Supported.\r
+\r
+ @param This Pointer to driver binding protocol\r
+ @param Controller Controller handle to connect\r
+ @param RemainingDevicePath A pointer to the remaining portion of a device\r
+ path\r
+\r
+ @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this\r
+ driver, Otherwise, this controller cannot be\r
+ managed by this driver\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE00 Pci;\r
+ EFI_DEV_PATH *Node;\r
+\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Open the IO Abstraction(s) needed to perform the supported test\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ //\r
+ // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure,\r
+ // because VgaMiniPort protocol is installed on controller handle directly.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiVgaMiniPortProtocolGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+ }\r
+ //\r
+ // See if this is a PCI Graphics Controller by looking at the Command register and\r
+ // Class Code Register\r
+ //\r
+ Status = PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (Pci) / sizeof (UINT32),\r
+ &Pci\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {\r
+\r
+ Status = EFI_SUCCESS;\r
+ //\r
+ // If this is a graphics controller,\r
+ // go further check RemainingDevicePath validation\r
+ //\r
+ if (RemainingDevicePath != NULL) {\r
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
+ //\r
+ // Check if RemainingDevicePath is the End of Device Path Node, \r
+ // if yes, return EFI_SUCCESS\r
+ //\r
+ if (!IsDevicePathEnd (Node)) {\r
+ //\r
+ // If RemainingDevicePath isn't the End of Device Path Node,\r
+ // check its validation\r
+ //\r
+ if (Node->DevPath.Type != ACPI_DEVICE_PATH ||\r
+ Node->DevPath.SubType != ACPI_ADR_DP ||\r
+ DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+Done:\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Install Graphics Output Protocol onto VGA device handles.\r
+\r
+ @param This Pointer to driver binding protocol\r
+ @param Controller Controller handle to connect\r
+ @param RemainingDevicePath A pointer to the remaining portion of a device\r
+ path\r
+\r
+ @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINTN Flags;\r
+ UINT64 OriginalPciAttributes;\r
+ UINT64 Supports;\r
+ BOOLEAN PciAttributesSaved;\r
+\r
+ //\r
+ // Initialize local variables\r
+ //\r
+ PciIo = NULL;\r
+ ParentDevicePath = NULL;\r
+\r
+ //\r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Open the IO Abstraction(s) needed\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
+ return Status;\r
+ }\r
+\r
+ PciAttributesSaved = FALSE;\r
+ //\r
+ // Save original PCI attributes\r
+ //\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationGet,\r
+ 0,\r
+ &OriginalPciAttributes\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ PciAttributesSaved = TRUE;\r
+\r
+ //\r
+ // Get supported PCI attributes\r
+ //\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
+ if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ } \r
+\r
+ //\r
+ // Prepare for status code\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ParentDevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,\r
+ ParentDevicePath\r
+ );\r
+ //\r
+ // Enable the device and make sure VGA cycles are being forwarded to this VGA device\r
+ //\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Supports,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,\r
+ ParentDevicePath\r
+ );\r
+ goto Done;\r
+ }\r
+ //\r
+ // Check to see if there is a legacy option ROM image associated with this PCI device\r
+ //\r
+ Status = LegacyBios->CheckPciRom (\r
+ LegacyBios,\r
+ Controller,\r
+ NULL,\r
+ NULL,\r
+ &Flags\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Post the legacy option ROM if it is available.\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_P_PC_RESET,\r
+ ParentDevicePath\r
+ );\r
+ Status = LegacyBios->InstallPciRom (\r
+ LegacyBios,\r
+ Controller,\r
+ NULL,\r
+ &Flags,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
+ ParentDevicePath\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ if (RemainingDevicePath != NULL) {\r
+ if (IsDevicePathEnd (RemainingDevicePath) && \r
+ (FeaturePcdGet (PcdBiosVideoCheckVbeEnable) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable))) {\r
+ //\r
+ // If RemainingDevicePath is the End of Device Path Node,\r
+ // don't create any child device and return EFI_SUCESS\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Create child handle and install GraphicsOutputProtocol on it\r
+ //\r
+ Status = BiosVideoChildHandleInstall (\r
+ This,\r
+ Controller,\r
+ PciIo,\r
+ LegacyBios,\r
+ ParentDevicePath,\r
+ RemainingDevicePath,\r
+ OriginalPciAttributes\r
+ );\r
+\r
+Done:\r
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,\r
+ ParentDevicePath\r
+ );\r
+\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,\r
+ ParentDevicePath\r
+ );\r
+ if (PciAttributesSaved) {\r
+ //\r
+ // Restore original PCI attributes\r
+ //\r
+ PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSet,\r
+ OriginalPciAttributes,\r
+ NULL\r
+ );\r
+ }\r
+ //\r
+ // Release PCI I/O Protocols on the controller handle.\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop.\r
+\r
+ @param This Pointer to driver binding protocol\r
+ @param Controller Controller handle to connect\r
+ @param NumberOfChildren Number of children handle created by this driver\r
+ @param ChildHandleBuffer Buffer containing child handle created\r
+\r
+ @retval EFI_SUCCESS Driver disconnected successfully from controller\r
+ @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN AllChildrenStopped;\r
+ UINTN Index;\r
+\r
+ AllChildrenStopped = TRUE;\r
+\r
+ if (NumberOfChildren == 0) {\r
+ //\r
+ // Close PCI I/O protocol on the controller handle\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ for (Index = 0; Index < NumberOfChildren; Index++) {\r
+ Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ AllChildrenStopped = FALSE;\r
+ }\r
+ }\r
+\r
+ if (!AllChildrenStopped) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Install child handles if the Handle supports MBR format.\r
+\r
+ @param This Calling context.\r
+ @param ParentHandle Parent Handle\r
+ @param ParentPciIo Parent PciIo interface\r
+ @param ParentLegacyBios Parent LegacyBios interface\r
+ @param ParentDevicePath Parent Device Path\r
+ @param RemainingDevicePath Remaining Device Path\r
+ @param OriginalPciAttributes Original PCI Attributes\r
+\r
+ @retval EFI_SUCCESS If a child handle was added\r
+ @retval other A child handle was not added\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoChildHandleInstall (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ParentHandle,\r
+ IN EFI_PCI_IO_PROTOCOL *ParentPciIo,\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,\r
+ IN UINT64 OriginalPciAttributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate;\r
+ PCI_TYPE00 Pci;\r
+ ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
+ BOOLEAN ProtocolInstalled;\r
+\r
+ //\r
+ // Allocate the private device structure for video device\r
+ //\r
+ BiosVideoPrivate = (BIOS_VIDEO_DEV *) AllocateZeroPool (\r
+ sizeof (BIOS_VIDEO_DEV)\r
+ );\r
+ if (NULL == BiosVideoPrivate) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // See if this is a VGA compatible controller or not\r
+ //\r
+ Status = ParentPciIo->Pci.Read (\r
+ ParentPciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (Pci) / sizeof (UINT32),\r
+ &Pci\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
+ ParentDevicePath\r
+ );\r
+ goto Done;\r
+ }\r
+ BiosVideoPrivate->VgaCompatible = FALSE;\r
+ if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) {\r
+ BiosVideoPrivate->VgaCompatible = TRUE;\r
+ }\r
+\r
+ if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) {\r
+ BiosVideoPrivate->VgaCompatible = TRUE;\r
+ }\r
+\r
+ if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {\r
+ //\r
+ // Create EXIT_BOOT_SERIVES Event\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ BiosVideoNotifyExitBootServices,\r
+ BiosVideoPrivate,\r
+ &gEfiEventExitBootServicesGuid,\r
+ &BiosVideoPrivate->ExitBootServicesEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Initialize the child private structure\r
+ //\r
+ BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;\r
+\r
+ //\r
+ // Fill in Graphics Output specific mode structures\r
+ //\r
+ BiosVideoPrivate->HardwareNeedsStarting = TRUE;\r
+ BiosVideoPrivate->ModeData = NULL;\r
+ BiosVideoPrivate->LineBuffer = NULL;\r
+ BiosVideoPrivate->VgaFrameBuffer = NULL;\r
+ BiosVideoPrivate->VbeFrameBuffer = NULL;\r
+\r
+ //\r
+ // Fill in the Graphics Output Protocol\r
+ //\r
+ BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
+ BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
+\r
+\r
+ //\r
+ // Allocate buffer for Graphics Output Protocol mode information\r
+ //\r
+ BiosVideoPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (\r
+ sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)\r
+ );\r
+ if (NULL == BiosVideoPrivate->GraphicsOutput.Mode) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
+ );\r
+ if (NULL == BiosVideoPrivate->GraphicsOutput.Mode->Info) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Assume that Graphics Output Protocol will be produced until proven otherwise\r
+ //\r
+ BiosVideoPrivate->ProduceGraphicsOutput = TRUE;\r
+\r
+ //\r
+ // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.\r
+ //\r
+ if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {\r
+ if (RemainingDevicePath == NULL) {\r
+ ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
+ AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
+ AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
+ AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
+ SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
+ \r
+ BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (\r
+ ParentDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
+ );\r
+ } else {\r
+ BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
+ }\r
+ \r
+ //\r
+ // Creat child handle and device path protocol firstly\r
+ //\r
+ BiosVideoPrivate->Handle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &BiosVideoPrivate->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ BiosVideoPrivate->GopDevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Fill in the VGA Mini Port Protocol fields\r
+ //\r
+ BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode;\r
+ BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000;\r
+ BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;\r
+ BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5;\r
+ BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
+ BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
+ BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
+\r
+ //\r
+ // Child handle need to consume the Legacy Bios protocol\r
+ //\r
+ BiosVideoPrivate->LegacyBios = ParentLegacyBios;\r
+\r
+ //\r
+ // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally\r
+ //\r
+ BiosVideoPrivate->PciIo = ParentPciIo;\r
+ BiosVideoPrivate->OriginalPciAttributes = OriginalPciAttributes;\r
+\r
+ //\r
+ // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
+ //\r
+ if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable)) {\r
+ Status = BiosVideoCheckForVbe (BiosVideoPrivate);\r
+ DEBUG ((EFI_D_INFO, "BiosVideoCheckForVbe - %r\n", Status));\r
+ } else {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support\r
+ // for the standard 640x480 16 color VGA mode\r
+ //\r
+ DEBUG ((EFI_D_INFO, "VgaCompatible - %x\n", BiosVideoPrivate->VgaCompatible));\r
+ if (BiosVideoPrivate->VgaCompatible) {\r
+ if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable)) {\r
+ Status = BiosVideoCheckForVga (BiosVideoPrivate);\r
+ DEBUG ((EFI_D_INFO, "BiosVideoCheckForVga - %r\n", Status));\r
+ } else {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do\r
+ // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.\r
+ //\r
+ BiosVideoPrivate->ProduceGraphicsOutput = FALSE;\r
+\r
+ //\r
+ // INT services are available, so on the 80x25 and 80x50 text mode are supported\r
+ //\r
+ BiosVideoPrivate->VgaMiniPort.MaxMode = 2;\r
+ }\r
+ }\r
+\r
+ ProtocolInstalled = FALSE;\r
+\r
+ if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
+ //\r
+ // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &BiosVideoPrivate->Handle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &BiosVideoPrivate->GraphicsOutput,\r
+ &gEfiEdidDiscoveredProtocolGuid,\r
+ &BiosVideoPrivate->EdidDiscovered,\r
+ &gEfiEdidActiveProtocolGuid,\r
+ &BiosVideoPrivate->EdidActive,\r
+ NULL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Open the Parent Handle for the child\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ParentHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &BiosVideoPrivate->PciIo,\r
+ This->DriverBindingHandle,\r
+ BiosVideoPrivate->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ ProtocolInstalled = TRUE;\r
+ }\r
+ }\r
+\r
+ if (!ProtocolInstalled) {\r
+ //\r
+ // Install VGA Mini Port Protocol\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ParentHandle,\r
+ &gEfiVgaMiniPortProtocolGuid,\r
+ &BiosVideoPrivate->VgaMiniPort,\r
+ NULL\r
+ );\r
+ }\r
+\r
+Done:\r
+ if (EFI_ERROR (Status)) {\r
+ if ((BiosVideoPrivate != NULL) && (BiosVideoPrivate->ExitBootServicesEvent != NULL)) {\r
+ gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
+ } \r
+ //\r
+ // Free private data structure\r
+ //\r
+ BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Deregister an video child handle and free resources.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Video controller handle\r
+ @param Handle Video child handle\r
+\r
+ @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoChildHandleUninstall (\r
+ EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ EFI_HANDLE Controller,\r
+ EFI_HANDLE Handle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
+ EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ BiosVideoPrivate = NULL;\r
+ GraphicsOutput = NULL;\r
+ PciIo = NULL;\r
+ Status = EFI_UNSUPPORTED;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ (VOID **) &GraphicsOutput,\r
+ This->DriverBindingHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiVgaMiniPortProtocolGuid,\r
+ (VOID **) &VgaMiniPort,\r
+ This->DriverBindingHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);\r
+ }\r
+ }\r
+\r
+ if (BiosVideoPrivate == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Set the 80x25 Text VGA Mode\r
+ //\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.AL = 0x03;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ Regs.H.AH = 0x11;\r
+ Regs.H.AL = 0x14;\r
+ Regs.H.BL = 0;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ //\r
+ // Restore original PCI attributes\r
+ //\r
+ Status = BiosVideoPrivate->PciIo->Attributes (\r
+ BiosVideoPrivate->PciIo,\r
+ EfiPciIoAttributeOperationSet,\r
+ BiosVideoPrivate->OriginalPciAttributes,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Close PCI I/O protocol that opened by child handle\r
+ //\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Handle\r
+ );\r
+\r
+ //\r
+ // Uninstall protocols on child handle\r
+ //\r
+ if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ BiosVideoPrivate->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ BiosVideoPrivate->GopDevicePath,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &BiosVideoPrivate->GraphicsOutput,\r
+ &gEfiEdidDiscoveredProtocolGuid,\r
+ &BiosVideoPrivate->EdidDiscovered,\r
+ &gEfiEdidActiveProtocolGuid,\r
+ &BiosVideoPrivate->EdidActive,\r
+ NULL\r
+ );\r
+ }\r
+ if (!BiosVideoPrivate->ProduceGraphicsOutput) {\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Controller,\r
+ &gEfiVgaMiniPortProtocolGuid,\r
+ &BiosVideoPrivate->VgaMiniPort,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {\r
+ //\r
+ // Close EXIT_BOOT_SERIVES Event\r
+ //\r
+ gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
+ }\r
+\r
+ //\r
+ // Release all allocated resources\r
+ //\r
+ BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Release resource for biso video instance.\r
+\r
+ @param BiosVideoPrivate Video child device private data structure\r
+\r
+**/\r
+VOID\r
+BiosVideoDeviceReleaseResource (\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate\r
+ )\r
+{\r
+ if (BiosVideoPrivate == NULL) {\r
+ return ;\r
+ }\r
+\r
+ //\r
+ // Release all the resourses occupied by the BIOS_VIDEO_DEV\r
+ //\r
+\r
+ //\r
+ // Free VGA Frame Buffer\r
+ //\r
+ if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
+ FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
+ }\r
+ //\r
+ // Free VBE Frame Buffer\r
+ //\r
+ if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
+ FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
+ }\r
+ //\r
+ // Free line buffer\r
+ //\r
+ if (BiosVideoPrivate->LineBuffer != NULL) {\r
+ FreePool (BiosVideoPrivate->LineBuffer);\r
+ }\r
+ //\r
+ // Free mode data\r
+ //\r
+ if (BiosVideoPrivate->ModeData != NULL) {\r
+ FreePool (BiosVideoPrivate->ModeData);\r
+ }\r
+ //\r
+ // Free memory allocated below 1MB\r
+ //\r
+ if (BiosVideoPrivate->PagesBelow1MB != 0) {\r
+ gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);\r
+ }\r
+\r
+ if (BiosVideoPrivate->VbeSaveRestorePages != 0) {\r
+ gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);\r
+ }\r
+\r
+ //\r
+ // Free graphics output protocol occupied resource\r
+ //\r
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
+ }\r
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
+ }\r
+ //\r
+ // Free EDID discovered protocol occupied resource\r
+ //\r
+ if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {\r
+ FreePool (BiosVideoPrivate->EdidDiscovered.Edid);\r
+ }\r
+ //\r
+ // Free EDID active protocol occupied resource\r
+ //\r
+ if (BiosVideoPrivate->EdidActive.Edid != NULL) {\r
+ FreePool (BiosVideoPrivate->EdidActive.Edid);\r
+ }\r
+\r
+ if (BiosVideoPrivate->GopDevicePath!= NULL) {\r
+ FreePool (BiosVideoPrivate->GopDevicePath);\r
+ }\r
+\r
+ FreePool (BiosVideoPrivate);\r
+\r
+ return ;\r
+}\r
+\r
+\r
+/**\r
+ Generate a search key for a specified timing data.\r
+\r
+ @param EdidTiming Pointer to EDID timing\r
+\r
+ @return The 32 bit unique key for search.\r
+\r
+**/\r
+UINT32\r
+CalculateEdidKey (\r
+ VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
+ )\r
+{\r
+ UINT32 Key;\r
+\r
+ //\r
+ // Be sure no conflicts for all standard timing defined by VESA.\r
+ //\r
+ Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;\r
+ return Key;\r
+}\r
+\r
+\r
+/**\r
+ Parse the Established Timing and Standard Timing in EDID data block.\r
+\r
+ @param EdidBuffer Pointer to EDID data block\r
+ @param ValidEdidTiming Valid EDID timing information\r
+\r
+ @retval TRUE The EDID data is valid.\r
+ @retval FALSE The EDID data is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+ParseEdidData (\r
+ UINT8 *EdidBuffer,\r
+ VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming\r
+ )\r
+{\r
+ UINT8 CheckSum;\r
+ UINT32 Index;\r
+ UINT32 ValidNumber;\r
+ UINT32 TimingBits;\r
+ UINT8 *BufferIndex;\r
+ UINT16 HorizontalResolution;\r
+ UINT16 VerticalResolution;\r
+ UINT8 AspectRatio;\r
+ UINT8 RefreshRate;\r
+ VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming;\r
+ VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock;\r
+\r
+ EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer;\r
+\r
+ //\r
+ // Check the checksum of EDID data\r
+ //\r
+ CheckSum = 0;\r
+ for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) {\r
+ CheckSum = (UINT8) (CheckSum + EdidBuffer[Index]);\r
+ }\r
+ if (CheckSum != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ ValidNumber = 0;\r
+ gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0);\r
+\r
+ if ((EdidDataBlock->EstablishedTimings[0] != 0) ||\r
+ (EdidDataBlock->EstablishedTimings[1] != 0) ||\r
+ (EdidDataBlock->EstablishedTimings[2] != 0)\r
+ ) {\r
+ //\r
+ // Established timing data\r
+ //\r
+ TimingBits = EdidDataBlock->EstablishedTimings[0] |\r
+ (EdidDataBlock->EstablishedTimings[1] << 8) |\r
+ ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;\r
+ for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {\r
+ if ((TimingBits & 0x1) != 0) {\r
+ ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);\r
+ ValidNumber ++;\r
+ }\r
+ TimingBits = TimingBits >> 1;\r
+ }\r
+ } else {\r
+ //\r
+ // If no Established timing data, read the standard timing data\r
+ //\r
+ BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];\r
+ for (Index = 0; Index < 8; Index ++) {\r
+ if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){\r
+ //\r
+ // A valid Standard Timing\r
+ //\r
+ HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);\r
+ AspectRatio = (UINT8) (BufferIndex[1] >> 6);\r
+ switch (AspectRatio) {\r
+ case 0:\r
+ VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);\r
+ break;\r
+ case 1:\r
+ VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
+ break;\r
+ case 2:\r
+ VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);\r
+ break;\r
+ case 3:\r
+ VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);\r
+ break;\r
+ default:\r
+ VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
+ break;\r
+ }\r
+ RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);\r
+ TempTiming.HorizontalResolution = HorizontalResolution;\r
+ TempTiming.VerticalResolution = VerticalResolution;\r
+ TempTiming.RefreshRate = RefreshRate;\r
+ ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
+ ValidNumber ++;\r
+ }\r
+ BufferIndex += 2;\r
+ }\r
+ }\r
+\r
+ ValidEdidTiming->ValidNumber = ValidNumber;\r
+ return TRUE;\r
+}\r
+\r
+\r
+/**\r
+ Search a specified Timing in all the valid EDID timings.\r
+\r
+ @param ValidEdidTiming All valid EDID timing information.\r
+ @param EdidTiming The Timing to search for.\r
+\r
+ @retval TRUE Found.\r
+ @retval FALSE Not found.\r
+\r
+**/\r
+BOOLEAN\r
+SearchEdidTiming (\r
+ VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming,\r
+ VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
+ )\r
+{\r
+ UINT32 Index;\r
+ UINT32 Key;\r
+\r
+ Key = CalculateEdidKey (EdidTiming);\r
+\r
+ for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {\r
+ if (Key == ValidEdidTiming->Key[Index]) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Check for VBE device.\r
+\r
+ @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
+\r
+ @retval EFI_SUCCESS VBE device found\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoCheckForVbe (\r
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT16 *ModeNumberPtr;\r
+ BOOLEAN ModeFound;\r
+ BOOLEAN EdidFound;\r
+ BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
+ BIOS_VIDEO_MODE_DATA *CurrentModeData;\r
+ UINTN PreferMode;\r
+ UINTN ModeNumber;\r
+ VESA_BIOS_EXTENSIONS_EDID_TIMING Timing;\r
+ VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming;\r
+ EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride;\r
+ UINT32 EdidAttributes;\r
+ BOOLEAN EdidOverrideFound;\r
+ UINTN EdidOverrideDataSize;\r
+ UINT8 *EdidOverrideDataBlock;\r
+ UINTN EdidActiveDataSize;\r
+ UINT8 *EdidActiveDataBlock;\r
+\r
+ EdidFound = TRUE;\r
+ EdidOverrideFound = FALSE;\r
+ EdidOverrideDataBlock = NULL;\r
+ EdidActiveDataSize = 0;\r
+ EdidActiveDataBlock = NULL;\r
+\r
+ //\r
+ // Allocate buffer under 1MB for VBE data structures\r
+ //\r
+ BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (\r
+ sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +\r
+ sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +\r
+ sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +\r
+ sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)\r
+ );\r
+\r
+ BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;\r
+\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiBootServicesData,\r
+ BiosVideoPrivate->NumberOfPagesBelow1MB,\r
+ &BiosVideoPrivate->PagesBelow1MB\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));\r
+ \r
+ //\r
+ // Fill in the VBE related data structures\r
+ //\r
+ BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);\r
+ BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);\r
+ BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);\r
+ BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1);\r
+ BiosVideoPrivate->VbeSaveRestorePages = 0;\r
+ BiosVideoPrivate->VbeSaveRestoreBuffer = 0;\r
+\r
+ //\r
+ // Test to see if the Video Adapter is compliant with VBE 3.0\r
+ //\r
+ gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;\r
+ gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);\r
+ BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;\r
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
+\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ Status = EFI_DEVICE_ERROR;\r
+\r
+ //\r
+ // See if the VESA call succeeded\r
+ //\r
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check for 'VESA' signature\r
+ //\r
+ if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check to see if this is VBE 2.0 or higher\r
+ //\r
+ if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {\r
+ return Status;\r
+ }\r
+\r
+ EdidFound = FALSE;\r
+ EdidAttributes = 0xff;\r
+ EdidOverrideDataSize = 0;\r
+\r
+ //\r
+ // Find EDID Override protocol firstly, this protocol is installed by platform if needed.\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiEdidOverrideProtocolGuid,\r
+ NULL,\r
+ (VOID **) &EdidOverride\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow\r
+ //\r
+ EdidOverrideDataBlock = AllocatePool (sizeof (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2));\r
+ if (NULL == EdidOverrideDataBlock) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ Status = EdidOverride->GetEdid (\r
+ EdidOverride,\r
+ BiosVideoPrivate->Handle,\r
+ &EdidAttributes,\r
+ &EdidOverrideDataSize,\r
+ (UINT8 **) &EdidOverrideDataBlock\r
+ );\r
+ if (!EFI_ERROR (Status) &&\r
+ EdidAttributes == 0 &&\r
+ EdidOverrideDataSize != 0) {\r
+ //\r
+ // Succeeded to get EDID Override Data\r
+ //\r
+ EdidOverrideFound = TRUE;\r
+ }\r
+ }\r
+\r
+ if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) {\r
+ //\r
+ // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,\r
+ // read EDID information through INT10 call\r
+ //\r
+\r
+ gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;\r
+ Regs.X.BX = 1;\r
+ Regs.X.CX = 0;\r
+ Regs.X.DX = 0;\r
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
+\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+ //\r
+ // See if the VESA call succeeded\r
+ //\r
+ if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
+ //\r
+ // Set EDID Discovered Data\r
+ //\r
+ BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
+ BiosVideoPrivate->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool (\r
+ VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
+ BiosVideoPrivate->VbeEdidDataBlock\r
+ );\r
+\r
+ if (NULL == BiosVideoPrivate->EdidDiscovered.Edid) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ EdidFound = TRUE;\r
+ }\r
+ }\r
+\r
+ if (EdidFound) {\r
+ EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
+ EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid;\r
+ } else if (EdidOverrideFound) {\r
+ EdidActiveDataSize = EdidOverrideDataSize;\r
+ EdidActiveDataBlock = EdidOverrideDataBlock;\r
+ EdidFound = TRUE;\r
+ }\r
+\r
+ if (EdidFound) {\r
+ //\r
+ // Parse EDID data structure to retrieve modes supported by monitor\r
+ //\r
+ if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) {\r
+ //\r
+ // Copy EDID Override Data to EDID Active Data\r
+ //\r
+ BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize;\r
+ BiosVideoPrivate->EdidActive.Edid = (UINT8 *) AllocateCopyPool (\r
+ EdidActiveDataSize,\r
+ EdidActiveDataBlock\r
+ );\r
+ if (NULL == BiosVideoPrivate->EdidActive.Edid) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ }\r
+ } else {\r
+ BiosVideoPrivate->EdidActive.SizeOfEdid = 0;\r
+ BiosVideoPrivate->EdidActive.Edid = NULL;\r
+ EdidFound = FALSE;\r
+ }\r
+\r
+ //\r
+ // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode\r
+ //\r
+ ModeNumberPtr = (UINT16 *)\r
+ (\r
+ (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |\r
+ ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)\r
+ );\r
+\r
+ PreferMode = 0;\r
+ ModeNumber = 0;\r
+\r
+ for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {\r
+ //\r
+ // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.\r
+ //\r
+ if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
+ continue;\r
+ }\r
+ //\r
+ // Get the information about the mode\r
+ //\r
+ gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
+ Regs.X.CX = *ModeNumberPtr;\r
+ gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
+\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ //\r
+ // See if the call succeeded. If it didn't, then try the next mode.\r
+ //\r
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
+ continue;\r
+ }\r
+ //\r
+ // See if the mode supports color. If it doesn't then try the next mode.\r
+ //\r
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {\r
+ continue;\r
+ }\r
+ //\r
+ // See if the mode supports graphics. If it doesn't then try the next mode.\r
+ //\r
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {\r
+ continue;\r
+ }\r
+ //\r
+ // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.\r
+ //\r
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {\r
+ continue;\r
+ }\r
+ //\r
+ // See if the mode supports 32 bit color. If it doesn't then try the next mode.\r
+ // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the\r
+ // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel\r
+ //\r
+ if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {\r
+ continue;\r
+ }\r
+\r
+ if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {\r
+ continue;\r
+ }\r
+\r
+ if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {\r
+ continue;\r
+ }\r
+ //\r
+ // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.\r
+ //\r
+ if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {\r
+ continue;\r
+ }\r
+\r
+ if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {\r
+ //\r
+ // EDID exist, check whether this mode match with any mode in EDID\r
+ //\r
+ Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
+ Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
+ if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Select a reasonable mode to be set for current display mode\r
+ //\r
+ ModeFound = FALSE;\r
+\r
+ if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&\r
+ BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768\r
+ ) {\r
+ ModeFound = TRUE;\r
+ }\r
+ if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&\r
+ BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600\r
+ ) {\r
+ ModeFound = TRUE;\r
+ PreferMode = ModeNumber;\r
+ }\r
+ if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&\r
+ BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480\r
+ ) {\r
+ ModeFound = TRUE;\r
+ }\r
+\r
+ if ((!EdidFound) && (!ModeFound)) {\r
+ //\r
+ // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480\r
+ //\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Add mode to the list of available modes\r
+ //\r
+ ModeNumber ++;\r
+ ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (\r
+ ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA)\r
+ );\r
+ if (NULL == ModeBuffer) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ if (ModeNumber > 1) {\r
+ CopyMem (\r
+ ModeBuffer,\r
+ BiosVideoPrivate->ModeData,\r
+ (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
+ );\r
+ }\r
+\r
+ if (BiosVideoPrivate->ModeData != NULL) {\r
+ FreePool (BiosVideoPrivate->ModeData);\r
+ }\r
+\r
+ CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
+ CurrentModeData->VbeModeNumber = *ModeNumberPtr;\r
+ if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
+ CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
+ CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
+ CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);\r
+ CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;\r
+ CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);\r
+ CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;\r
+ CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);\r
+ CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;\r
+ CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);\r
+ } else {\r
+ CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;\r
+ CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;\r
+ CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);\r
+ CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;\r
+ CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);\r
+ CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;\r
+ CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);\r
+ CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;\r
+ CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);\r
+ }\r
+\r
+ CurrentModeData->PixelFormat = PixelBitMask;\r
+ if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&\r
+ (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
+ if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
+ CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
+ } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
+ CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
+ }\r
+ }\r
+\r
+ CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;\r
+ CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;\r
+ CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;\r
+ CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;\r
+ CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;\r
+\r
+ CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
+ CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
+ CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
+\r
+ CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
+\r
+ BiosVideoPrivate->ModeData = ModeBuffer;\r
+ }\r
+ //\r
+ // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT\r
+ //\r
+ if (ModeNumber == 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Assign Gop's Blt function\r
+ //\r
+ BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;\r
+\r
+ BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = (UINT32) ModeNumber;\r
+ //\r
+ // Current mode is unknow till now, set it to an invalid mode.\r
+ //\r
+ BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
+\r
+ //\r
+ // Find the best mode to initialize\r
+ //\r
+ Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);\r
+ if (EFI_ERROR (Status)) {\r
+ for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {\r
+ Status = BiosVideoGraphicsOutputSetMode (\r
+ &BiosVideoPrivate->GraphicsOutput,\r
+ (UINT32) PreferMode\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+ if (PreferMode == ModeNumber) {\r
+ //\r
+ // None mode is set successfully.\r
+ //\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+Done:\r
+ //\r
+ // If there was an error, then free the mode structure\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ if (BiosVideoPrivate->ModeData != NULL) {\r
+ FreePool (BiosVideoPrivate->ModeData);\r
+ BiosVideoPrivate->ModeData = NULL;\r
+ BiosVideoPrivate->MaxMode = 0;\r
+ }\r
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;\r
+ }\r
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
+ BiosVideoPrivate->GraphicsOutput.Mode= NULL;\r
+ }\r
+ if (EdidOverrideDataBlock != NULL) {\r
+ FreePool (EdidOverrideDataBlock);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Check for VGA device.\r
+\r
+ @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
+\r
+ @retval EFI_SUCCESS Standard VGA device found\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoCheckForVga (\r
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+\r
+ //\r
+ // Assign Gop's Blt function\r
+ //\r
+ BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;\r
+\r
+ //\r
+ // Add mode to the list of available modes\r
+ // caller should guarantee that Mode has been allocated.\r
+ //\r
+ ASSERT (BiosVideoPrivate->GraphicsOutput.Mode != NULL);\r
+ BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
+\r
+ ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (\r
+ sizeof (BIOS_VIDEO_MODE_DATA)\r
+ );\r
+ if (NULL == ModeBuffer) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ ModeBuffer->VbeModeNumber = 0x0012;\r
+ ModeBuffer->BytesPerScanLine = 640;\r
+ ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);\r
+ ModeBuffer->HorizontalResolution = 640;\r
+ ModeBuffer->VerticalResolution = 480;\r
+ ModeBuffer->PixelFormat = PixelBltOnly;\r
+ ModeBuffer->BitsPerPixel = 8;\r
+ ModeBuffer->ColorDepth = 32;\r
+ ModeBuffer->RefreshRate = 60;\r
+\r
+ BiosVideoPrivate->ModeData = ModeBuffer;\r
+\r
+ //\r
+ // Test to see if the Video Adapter support the 640x480 16 color mode\r
+ //\r
+ BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
+ Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);\r
+\r
+Done:\r
+ //\r
+ // If there was an error, then free the mode structure\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ if (BiosVideoPrivate->ModeData != NULL) {\r
+ FreePool (BiosVideoPrivate->ModeData);\r
+ BiosVideoPrivate->ModeData = NULL;\r
+ }\r
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;\r
+ }\r
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
+ BiosVideoPrivate->GraphicsOutput.Mode = NULL;\r
+ }\r
+ }\r
+ return Status;\r
+}\r
+\r
+//\r
+// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
+//\r
+\r
+/**\r
+ Graphics Output protocol interface to get video mode.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ModeNumber The mode number to return information on.\r
+ @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
+ buffer.\r
+ @param Info Caller allocated buffer that returns information\r
+ about ModeNumber.\r
+\r
+ @retval EFI_SUCCESS Mode information returned.\r
+ @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
+ video mode.\r
+ @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
+ @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoGraphicsOutputQueryMode (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN UINT32 ModeNumber,\r
+ OUT UINTN *SizeOfInfo,\r
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
+ )\r
+{\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate;\r
+ BIOS_VIDEO_MODE_DATA *ModeData;\r
+\r
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
+\r
+ if (BiosVideoPrivate->HardwareNeedsStarting) {\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,\r
+ BiosVideoPrivate->GopDevicePath\r
+ );\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
+ );\r
+ if (NULL == *Info) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
+\r
+ ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
+ (*Info)->Version = 0;\r
+ (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
+ (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
+ (*Info)->PixelFormat = ModeData->PixelFormat;\r
+ CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));\r
+\r
+ (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Worker function to set video mode.\r
+\r
+ @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV.\r
+ @param ModeData The mode data to be set.\r
+ @param DevicePath Pointer to Device Path Protocol.\r
+\r
+ @retval EFI_SUCCESS Graphics mode was changed.\r
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
+ request.\r
+ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoSetModeWorker (\r
+ IN BIOS_VIDEO_DEV *BiosVideoPrivate,\r
+ IN BIOS_VIDEO_MODE_DATA *ModeData,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+\r
+ if (BiosVideoPrivate->LineBuffer != NULL) {\r
+ FreePool (BiosVideoPrivate->LineBuffer);\r
+ }\r
+\r
+ if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
+ FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
+ }\r
+\r
+ if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
+ FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
+ }\r
+\r
+ BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool (\r
+ ModeData->BytesPerScanLine\r
+ );\r
+ if (NULL == BiosVideoPrivate->LineBuffer) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Clear all registers\r
+ //\r
+ ZeroMem (&Regs, sizeof (Regs));\r
+\r
+ if (ModeData->VbeModeNumber < 0x100) {\r
+ //\r
+ // Allocate a working buffer for BLT operations to the VGA frame buffer\r
+ //\r
+ BiosVideoPrivate->VgaFrameBuffer = (UINT8 *) AllocatePool (4 * 480 * 80);\r
+ if (NULL == BiosVideoPrivate->VgaFrameBuffer) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Set VGA Mode\r
+ //\r
+ Regs.X.AX = ModeData->VbeModeNumber;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ } else {\r
+ //\r
+ // Allocate a working buffer for BLT operations to the VBE frame buffer\r
+ //\r
+ BiosVideoPrivate->VbeFrameBuffer =\r
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (\r
+ ModeData->BytesPerScanLine * ModeData->VerticalResolution\r
+ );\r
+ if (NULL == BiosVideoPrivate->VbeFrameBuffer) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Set VBE mode\r
+ //\r
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;\r
+ Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);\r
+ ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK));\r
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ //\r
+ // Check to see if the call succeeded\r
+ //\r
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,\r
+ DevicePath\r
+ );\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Initialize the state of the VbeFrameBuffer\r
+ //\r
+ Status = BiosVideoPrivate->PciIo->Mem.Read (\r
+ BiosVideoPrivate->PciIo,\r
+ EfiPciIoWidthUint32,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) ModeData->LinearFrameBuffer,\r
+ (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,\r
+ BiosVideoPrivate->VbeFrameBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Graphics Output protocol interface to set video mode.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ModeNumber The mode number to be set.\r
+\r
+ @retval EFI_SUCCESS Graphics mode was changed.\r
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
+ request.\r
+ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoGraphicsOutputSetMode (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
+ IN UINT32 ModeNumber\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate;\r
+ BIOS_VIDEO_MODE_DATA *ModeData;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
+\r
+ ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
+\r
+ if (ModeNumber >= This->Mode->MaxMode) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ if (ModeNumber == This->Mode->Mode) {\r
+ //\r
+ // Clear screen to black\r
+ // \r
+ ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ BiosVideoGraphicsOutputVbeBlt (\r
+ This,\r
+ &Background,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ ModeData->HorizontalResolution,\r
+ ModeData->VerticalResolution,\r
+ 0\r
+ );\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->GopDevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ This->Mode->Mode = ModeNumber;\r
+ This->Mode->Info->Version = 0;\r
+ This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
+ This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
+ This->Mode->Info->PixelFormat = ModeData->PixelFormat;\r
+ CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask));\r
+ This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
+ This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
+\r
+ //\r
+ // Frame BufferSize remain unchanged\r
+ //\r
+ This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer;\r
+ This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
+\r
+ BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
+\r
+ @param PciIo The pointer of EFI_PCI_IO_PROTOCOL\r
+ @param VbeBuffer The data to transfer to screen\r
+ @param MemAddress Physical frame buffer base address\r
+ @param DestinationX The X coordinate of the destination for BltOperation\r
+ @param DestinationY The Y coordinate of the destination for BltOperation\r
+ @param TotalBytes The total bytes of copy\r
+ @param VbePixelWidth Bytes per pixel\r
+ @param BytesPerScanLine Bytes per scan line\r
+\r
+**/\r
+VOID\r
+CopyVideoBuffer (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT8 *VbeBuffer,\r
+ IN VOID *MemAddress,\r
+ IN UINTN DestinationX,\r
+ IN UINTN DestinationY,\r
+ IN UINTN TotalBytes,\r
+ IN UINT32 VbePixelWidth,\r
+ IN UINTN BytesPerScanLine\r
+ )\r
+{\r
+ UINTN FrameBufferAddr;\r
+ UINTN CopyBlockNum;\r
+ UINTN RemainingBytes;\r
+ UINTN UnalignedBytes;\r
+ EFI_STATUS Status;\r
+\r
+ FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
+\r
+ //\r
+ // If TotalBytes is less than 4 bytes, only start byte copy.\r
+ //\r
+ if (TotalBytes < 4) {\r
+ Status = PciIo->Mem.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) FrameBufferAddr,\r
+ TotalBytes,\r
+ VbeBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // If VbeBuffer is not 4-byte aligned, start byte copy.\r
+ //\r
+ UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
+\r
+ if (UnalignedBytes != 0) {\r
+ Status = PciIo->Mem.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) FrameBufferAddr,\r
+ UnalignedBytes,\r
+ VbeBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ FrameBufferAddr += UnalignedBytes;\r
+ VbeBuffer += UnalignedBytes;\r
+ }\r
+\r
+ //\r
+ // Calculate 4-byte block count and remaining bytes.\r
+ //\r
+ CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
+ RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
+\r
+ //\r
+ // Copy 4-byte block and remaining bytes to physical frame buffer.\r
+ //\r
+ if (CopyBlockNum != 0) {\r
+ Status = PciIo->Mem.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) FrameBufferAddr,\r
+ CopyBlockNum,\r
+ VbeBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ if (RemainingBytes != 0) {\r
+ FrameBufferAddr += (CopyBlockNum << 2);\r
+ VbeBuffer += (CopyBlockNum << 2);\r
+ Status = PciIo->Mem.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) FrameBufferAddr,\r
+ RemainingBytes,\r
+ VbeBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+}\r
+\r
+/**\r
+ Worker function to block transfer for VBE device.\r
+\r
+ @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV\r
+ @param BltBuffer The data to transfer to screen\r
+ @param BltOperation The operation to perform\r
+ @param SourceX The X coordinate of the source for BltOperation\r
+ @param SourceY The Y coordinate of the source for BltOperation\r
+ @param DestinationX The X coordinate of the destination for\r
+ BltOperation\r
+ @param DestinationY The Y coordinate of the destination for\r
+ BltOperation\r
+ @param Width The width of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Height The height of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Delta Not used for EfiBltVideoFill and\r
+ EfiBltVideoToVideo operation. If a Delta of 0 is\r
+ used, the entire BltBuffer will be operated on. If\r
+ a subrectangle of the BltBuffer is used, then\r
+ Delta represents the number of bytes in a row of\r
+ the BltBuffer.\r
+ @param Mode Mode data.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
+ @retval EFI_SUCCESS Blt operation success\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoVbeBltWorker (\r
+ IN BIOS_VIDEO_DEV *BiosVideoPrivate,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
+ IN UINTN SourceX,\r
+ IN UINTN SourceY,\r
+ IN UINTN DestinationX,\r
+ IN UINTN DestinationY,\r
+ IN UINTN Width,\r
+ IN UINTN Height,\r
+ IN UINTN Delta,\r
+ IN BIOS_VIDEO_MODE_DATA *Mode\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_TPL OriginalTPL;\r
+ UINTN DstY;\r
+ UINTN SrcY;\r
+ UINTN DstX;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+ VOID *MemAddress;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
+ UINTN BytesPerScanLine;\r
+ UINTN Index;\r
+ UINT8 *VbeBuffer;\r
+ UINT8 *VbeBuffer1;\r
+ UINT8 *BltUint8;\r
+ UINT32 VbePixelWidth;\r
+ UINT32 Pixel;\r
+ UINTN TotalBytes;\r
+\r
+ PciIo = BiosVideoPrivate->PciIo;\r
+\r
+ VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;\r
+ MemAddress = Mode->LinearFrameBuffer;\r
+ BytesPerScanLine = Mode->BytesPerScanLine;\r
+ VbePixelWidth = Mode->BitsPerPixel / 8;\r
+ BltUint8 = (UINT8 *) BltBuffer;\r
+ TotalBytes = Width * VbePixelWidth;\r
+\r
+ if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Width == 0 || Height == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // We need to fill the Virtual Screen buffer with the blt data.\r
+ // The virtual screen is upside down, as the first row is the bootom row of\r
+ // the image.\r
+ //\r
+ if (BltOperation == EfiBltVideoToBltBuffer) {\r
+ //\r
+ // Video to BltBuffer: Source is Video, destination is BltBuffer\r
+ //\r
+ if (SourceY + Height > Mode->VerticalResolution) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (SourceX + Width > Mode->HorizontalResolution) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ //\r
+ // BltBuffer to Video: Source is BltBuffer, destination is Video\r
+ //\r
+ if (DestinationY + Height > Mode->VerticalResolution) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DestinationX + Width > Mode->HorizontalResolution) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ //\r
+ // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
+ // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
+ // the number of bytes in each row can be computed.\r
+ //\r
+ if (Delta == 0) {\r
+ Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+ }\r
+ //\r
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
+ // We would not want a timer based event (Cursor, ...) to come in while we are\r
+ // doing this operation.\r
+ //\r
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ switch (BltOperation) {\r
+ case EfiBltVideoToBltBuffer:\r
+ for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ //\r
+ // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
+ //\r
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
+ for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
+ Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;\r
+ Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
+ Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
+ Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
+ Blt->Reserved = 0;\r
+ Blt++;\r
+ VbeBuffer += VbePixelWidth;\r
+ }\r
+\r
+ }\r
+ break;\r
+\r
+ case EfiBltVideoToVideo:\r
+ for (Index = 0; Index < Height; Index++) {\r
+ if (DestinationY <= SourceY) {\r
+ SrcY = SourceY + Index;\r
+ DstY = DestinationY + Index;\r
+ } else {\r
+ SrcY = SourceY + Height - Index - 1;\r
+ DstY = DestinationY + Height - Index - 1;\r
+ }\r
+\r
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
+ VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
+\r
+ gBS->CopyMem (\r
+ VbeBuffer,\r
+ VbeBuffer1,\r
+ TotalBytes\r
+ );\r
+\r
+ //\r
+ // Update physical frame buffer.\r
+ //\r
+ CopyVideoBuffer (\r
+ PciIo,\r
+ VbeBuffer,\r
+ MemAddress,\r
+ DestinationX,\r
+ DstY,\r
+ TotalBytes,\r
+ VbePixelWidth,\r
+ BytesPerScanLine\r
+ );\r
+ }\r
+ break;\r
+\r
+ case EfiBltVideoFill:\r
+ VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
+ //\r
+ // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
+ //\r
+ Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
+ (\r
+ (Blt->Green & Mode->Green.Mask) <<\r
+ Mode->Green.Position\r
+ ) |\r
+ ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
+\r
+ for (Index = 0; Index < Width; Index++) {\r
+ gBS->CopyMem (\r
+ VbeBuffer,\r
+ &Pixel,\r
+ VbePixelWidth\r
+ );\r
+ VbeBuffer += VbePixelWidth;\r
+ }\r
+\r
+ VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
+ for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
+ gBS->CopyMem (\r
+ (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
+ VbeBuffer,\r
+ TotalBytes\r
+ );\r
+ }\r
+\r
+ for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
+ //\r
+ // Update physical frame buffer.\r
+ //\r
+ CopyVideoBuffer (\r
+ PciIo,\r
+ VbeBuffer,\r
+ MemAddress,\r
+ DestinationX,\r
+ DstY,\r
+ TotalBytes,\r
+ VbePixelWidth,\r
+ BytesPerScanLine\r
+ );\r
+ }\r
+ break;\r
+\r
+ case EfiBltBufferToVideo:\r
+ for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
+ for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
+ //\r
+ // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
+ //\r
+ Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
+ ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
+ ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
+ gBS->CopyMem (\r
+ VbeBuffer,\r
+ &Pixel,\r
+ VbePixelWidth\r
+ );\r
+ Blt++;\r
+ VbeBuffer += VbePixelWidth;\r
+ }\r
+\r
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
+\r
+ //\r
+ // Update physical frame buffer.\r
+ //\r
+ CopyVideoBuffer (\r
+ PciIo,\r
+ VbeBuffer,\r
+ MemAddress,\r
+ DestinationX,\r
+ DstY,\r
+ TotalBytes,\r
+ VbePixelWidth,\r
+ BytesPerScanLine\r
+ );\r
+ }\r
+ break;\r
+\r
+ default: ;\r
+ }\r
+\r
+ gBS->RestoreTPL (OriginalTPL);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Graphics Output protocol instance to block transfer for VBE device.\r
+\r
+ @param This Pointer to Graphics Output protocol instance\r
+ @param BltBuffer The data to transfer to screen\r
+ @param BltOperation The operation to perform\r
+ @param SourceX The X coordinate of the source for BltOperation\r
+ @param SourceY The Y coordinate of the source for BltOperation\r
+ @param DestinationX The X coordinate of the destination for\r
+ BltOperation\r
+ @param DestinationY The Y coordinate of the destination for\r
+ BltOperation\r
+ @param Width The width of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Height The height of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Delta Not used for EfiBltVideoFill and\r
+ EfiBltVideoToVideo operation. If a Delta of 0 is\r
+ used, the entire BltBuffer will be operated on. If\r
+ a subrectangle of the BltBuffer is used, then\r
+ Delta represents the number of bytes in a row of\r
+ the BltBuffer.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
+ @retval EFI_SUCCESS Blt operation success\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoGraphicsOutputVbeBlt (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
+ IN UINTN SourceX,\r
+ IN UINTN SourceY,\r
+ IN UINTN DestinationX,\r
+ IN UINTN DestinationY,\r
+ IN UINTN Width,\r
+ IN UINTN Height,\r
+ IN UINTN Delta\r
+ )\r
+{\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate;\r
+ BIOS_VIDEO_MODE_DATA *Mode;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
+ Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];\r
+\r
+ return BiosVideoVbeBltWorker (\r
+ BiosVideoPrivate,\r
+ BltBuffer,\r
+ BltOperation,\r
+ SourceX,\r
+ SourceY,\r
+ DestinationX,\r
+ DestinationY,\r
+ Width,\r
+ Height,\r
+ Delta,\r
+ Mode\r
+ );\r
+}\r
+\r
+/**\r
+ Write graphics controller registers.\r
+\r
+ @param PciIo Pointer to PciIo protocol instance of the\r
+ controller\r
+ @param Address Register address\r
+ @param Data Data to be written to register\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+WriteGraphicsController (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINTN Address,\r
+ IN UINTN Data\r
+ )\r
+{\r
+ Address = Address | (Data << 8);\r
+ PciIo->Io.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,\r
+ 1,\r
+ &Address\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Read the four bit plane of VGA frame buffer.\r
+\r
+ @param PciIo Pointer to PciIo protocol instance of the\r
+ controller\r
+ @param HardwareBuffer Hardware VGA frame buffer address\r
+ @param MemoryBuffer Memory buffer address\r
+ @param WidthInBytes Number of bytes in a line to read\r
+ @param Height Height of the area to read\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+VgaReadBitPlanes (\r
+ EFI_PCI_IO_PROTOCOL *PciIo,\r
+ UINT8 *HardwareBuffer,\r
+ UINT8 *MemoryBuffer,\r
+ UINTN WidthInBytes,\r
+ UINTN Height\r
+ )\r
+{\r
+ UINTN BitPlane;\r
+ UINTN Rows;\r
+ UINTN FrameBufferOffset;\r
+ UINT8 *Source;\r
+ UINT8 *Destination;\r
+\r
+ //\r
+ // Program the Mode Register Write mode 0, Read mode 0\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0\r
+ );\r
+\r
+ for (BitPlane = 0, FrameBufferOffset = 0;\r
+ BitPlane < VGA_NUMBER_OF_BIT_PLANES;\r
+ BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE\r
+ ) {\r
+ //\r
+ // Program the Read Map Select Register to select the correct bit plane\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,\r
+ BitPlane\r
+ );\r
+\r
+ Source = HardwareBuffer;\r
+ Destination = MemoryBuffer + FrameBufferOffset;\r
+\r
+ for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {\r
+ PciIo->Mem.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) Source,\r
+ WidthInBytes,\r
+ (VOID *) Destination\r
+ );\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Internal routine to convert VGA color to Grahpics Output color.\r
+\r
+ @param MemoryBuffer Buffer containing VGA color\r
+ @param CoordinateX The X coordinate of pixel on screen\r
+ @param CoordinateY The Y coordinate of pixel on screen\r
+ @param BltBuffer Buffer to contain converted Grahpics Output color\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+VgaConvertToGraphicsOutputColor (\r
+ UINT8 *MemoryBuffer,\r
+ UINTN CoordinateX,\r
+ UINTN CoordinateY,\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
+ )\r
+{\r
+ UINTN Mask;\r
+ UINTN Bit;\r
+ UINTN Color;\r
+\r
+ MemoryBuffer += ((CoordinateY << 6) + (CoordinateY << 4) + (CoordinateX >> 3));\r
+ Mask = mVgaBitMaskTable[CoordinateX & 0x07];\r
+ for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
+ if ((*MemoryBuffer & Mask) != 0) {\r
+ Color |= Bit;\r
+ }\r
+ }\r
+\r
+ *BltBuffer = mVgaColorToGraphicsOutputColor[Color];\r
+}\r
+\r
+/**\r
+ Internal routine to convert Grahpics Output color to VGA color.\r
+\r
+ @param BltBuffer buffer containing Grahpics Output color\r
+\r
+ @return Converted VGA color\r
+\r
+**/\r
+UINT8\r
+VgaConvertColor (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
+ )\r
+{\r
+ UINT8 Color;\r
+\r
+ Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));\r
+ if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {\r
+ Color |= 0x08;\r
+ }\r
+\r
+ return Color;\r
+}\r
+\r
+\r
+/**\r
+ Grahpics Output protocol instance to block transfer for VGA device.\r
+\r
+ @param This Pointer to Grahpics Output protocol instance\r
+ @param BltBuffer The data to transfer to screen\r
+ @param BltOperation The operation to perform\r
+ @param SourceX The X coordinate of the source for BltOperation\r
+ @param SourceY The Y coordinate of the source for BltOperation\r
+ @param DestinationX The X coordinate of the destination for\r
+ BltOperation\r
+ @param DestinationY The Y coordinate of the destination for\r
+ BltOperation\r
+ @param Width The width of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Height The height of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Delta Not used for EfiBltVideoFill and\r
+ EfiBltVideoToVideo operation. If a Delta of 0 is\r
+ used, the entire BltBuffer will be operated on. If\r
+ a subrectangle of the BltBuffer is used, then\r
+ Delta represents the number of bytes in a row of\r
+ the BltBuffer.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
+ @retval EFI_SUCCESS Blt operation success\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoGraphicsOutputVgaBlt (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
+ IN UINTN SourceX,\r
+ IN UINTN SourceY,\r
+ IN UINTN DestinationX,\r
+ IN UINTN DestinationY,\r
+ IN UINTN Width,\r
+ IN UINTN Height,\r
+ IN UINTN Delta\r
+ )\r
+{\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate;\r
+ EFI_TPL OriginalTPL;\r
+ UINT8 *MemAddress;\r
+ UINTN BytesPerScanLine;\r
+ UINTN Bit;\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ UINTN StartAddress;\r
+ UINTN Bytes;\r
+ UINTN Offset;\r
+ UINT8 LeftMask;\r
+ UINT8 RightMask;\r
+ UINTN Address;\r
+ UINTN AddressFix;\r
+ UINT8 *Address1;\r
+ UINT8 *SourceAddress;\r
+ UINT8 *DestinationAddress;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 Data;\r
+ UINT8 PixelColor;\r
+ UINT8 *VgaFrameBuffer;\r
+ UINTN SourceOffset;\r
+ UINTN SourceWidth;\r
+ UINTN Rows;\r
+ UINTN Columns;\r
+ UINTN CoordinateX;\r
+ UINTN CoordinateY;\r
+ UINTN CurrentMode;\r
+\r
+ if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
+\r
+ CurrentMode = This->Mode->Mode;\r
+ PciIo = BiosVideoPrivate->PciIo;\r
+ MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;\r
+ BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;\r
+ VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;\r
+\r
+\r
+ if (Width == 0 || Height == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // We need to fill the Virtual Screen buffer with the blt data.\r
+ // The virtual screen is upside down, as the first row is the bootom row of\r
+ // the image.\r
+ //\r
+ if (BltOperation == EfiBltVideoToBltBuffer) {\r
+ //\r
+ // Video to BltBuffer: Source is Video, destination is BltBuffer\r
+ //\r
+ if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ //\r
+ // BltBuffer to Video: Source is BltBuffer, destination is Video\r
+ //\r
+ if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ //\r
+ // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
+ // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
+ // the number of bytes in each row can be computed.\r
+ //\r
+ if (Delta == 0) {\r
+ Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+ }\r
+ //\r
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
+ // We would not want a timer based event (Cursor, ...) to come in while we are\r
+ // doing this operation.\r
+ //\r
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ //\r
+ // Compute some values we need for VGA\r
+ //\r
+ switch (BltOperation) {\r
+ case EfiBltVideoToBltBuffer:\r
+\r
+ SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
+ SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
+\r
+ //\r
+ // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
+ //\r
+ VgaReadBitPlanes (\r
+ PciIo,\r
+ MemAddress + SourceOffset,\r
+ VgaFrameBuffer + SourceOffset,\r
+ SourceWidth,\r
+ Height\r
+ );\r
+\r
+ //\r
+ // Convert VGA Bit Planes to a Graphics Output 32-bit color value\r
+ //\r
+ BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);\r
+ for (Rows = 0, CoordinateY = SourceY; Rows < Height; Rows++, CoordinateY++, BltBuffer += (Delta >> 2)) {\r
+ for (Columns = 0, CoordinateX = SourceX; Columns < Width; Columns++, CoordinateX++, BltBuffer++) {\r
+ VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, CoordinateY, BltBuffer);\r
+ }\r
+\r
+ BltBuffer -= Width;\r
+ }\r
+\r
+ break;\r
+\r
+ case EfiBltVideoToVideo:\r
+ //\r
+ // Check for an aligned Video to Video operation\r
+ //\r
+ if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {\r
+ //\r
+ // Program the Mode Register Write mode 1, Read mode 0\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1\r
+ );\r
+\r
+ SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));\r
+ DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
+ Bytes = Width >> 3;\r
+ for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {\r
+ PciIo->CopyMem (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) (DestinationAddress + Offset),\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) (SourceAddress + Offset),\r
+ Bytes\r
+ );\r
+ }\r
+ } else {\r
+ SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
+ SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
+\r
+ //\r
+ // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
+ //\r
+ VgaReadBitPlanes (\r
+ PciIo,\r
+ MemAddress + SourceOffset,\r
+ VgaFrameBuffer + SourceOffset,\r
+ SourceWidth,\r
+ Height\r
+ );\r
+ }\r
+\r
+ break;\r
+\r
+ case EfiBltVideoFill:\r
+ StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
+ Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);\r
+ LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];\r
+ RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];\r
+ if (Bytes == 0) {\r
+ LeftMask = (UINT8) (LeftMask & RightMask);\r
+ RightMask = 0;\r
+ }\r
+\r
+ if (LeftMask == 0xff) {\r
+ StartAddress--;\r
+ Bytes++;\r
+ LeftMask = 0;\r
+ }\r
+\r
+ if (RightMask == 0xff) {\r
+ Bytes++;\r
+ RightMask = 0;\r
+ }\r
+\r
+ PixelColor = VgaConvertColor (BltBuffer);\r
+\r
+ //\r
+ // Program the Mode Register Write mode 2, Read mode 0\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
+ );\r
+\r
+ //\r
+ // Program the Data Rotate/Function Select Register to replace\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
+ VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
+ );\r
+\r
+ if (LeftMask != 0) {\r
+ //\r
+ // Program the BitMask register with the Left column mask\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
+ LeftMask\r
+ );\r
+\r
+ for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
+ //\r
+ // Read data from the bit planes into the latches\r
+ //\r
+ PciIo->Mem.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) Address,\r
+ 1,\r
+ &Data\r
+ );\r
+ //\r
+ // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
+ //\r
+ PciIo->Mem.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) Address,\r
+ 1,\r
+ &PixelColor\r
+ );\r
+ }\r
+ }\r
+\r
+ if (Bytes > 1) {\r
+ //\r
+ // Program the BitMask register with the middle column mask of 0xff\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
+ 0xff\r
+ );\r
+\r
+ for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {\r
+ PciIo->Mem.Write (\r
+ PciIo,\r
+ EfiPciIoWidthFillUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) Address,\r
+ Bytes - 1,\r
+ &PixelColor\r
+ );\r
+ }\r
+ }\r
+\r
+ if (RightMask != 0) {\r
+ //\r
+ // Program the BitMask register with the Right column mask\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
+ RightMask\r
+ );\r
+\r
+ for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {\r
+ //\r
+ // Read data from the bit planes into the latches\r
+ //\r
+ PciIo->Mem.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) Address,\r
+ 1,\r
+ &Data\r
+ );\r
+ //\r
+ // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
+ //\r
+ PciIo->Mem.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) Address,\r
+ 1,\r
+ &PixelColor\r
+ );\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EfiBltBufferToVideo:\r
+ StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
+ LeftMask = mVgaBitMaskTable[DestinationX & 0x07];\r
+\r
+ //\r
+ // Program the Mode Register Write mode 2, Read mode 0\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
+ );\r
+\r
+ //\r
+ // Program the Data Rotate/Function Select Register to replace\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
+ VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
+ );\r
+\r
+ for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
+ for (Index1 = 0; Index1 < Width; Index1++) {\r
+ BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);\r
+ }\r
+ AddressFix = Address;\r
+\r
+ for (Bit = 0; Bit < 8; Bit++) {\r
+ //\r
+ // Program the BitMask register with the Left column mask\r
+ //\r
+ WriteGraphicsController (\r
+ PciIo,\r
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
+ LeftMask\r
+ );\r
+\r
+ for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {\r
+ //\r
+ // Read data from the bit planes into the latches\r
+ //\r
+ PciIo->Mem.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) Address1,\r
+ 1,\r
+ &Data\r
+ );\r
+\r
+ PciIo->Mem.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_IO_PASS_THROUGH_BAR,\r
+ (UINT64) (UINTN) Address1,\r
+ 1,\r
+ &BiosVideoPrivate->LineBuffer[Index1]\r
+ );\r
+ }\r
+\r
+ LeftMask = (UINT8) (LeftMask >> 1);\r
+ if (LeftMask == 0) {\r
+ LeftMask = 0x80;\r
+ AddressFix++;\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ default: ;\r
+ }\r
+\r
+ gBS->RestoreTPL (OriginalTPL);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// VGA Mini Port Protocol Functions\r
+//\r
+\r
+/**\r
+ VgaMiniPort protocol interface to set mode.\r
+\r
+ @param This Pointer to VgaMiniPort protocol instance\r
+ @param ModeNumber The index of the mode\r
+\r
+ @retval EFI_UNSUPPORTED The requested mode is not supported\r
+ @retval EFI_SUCCESS The requested mode is set successfully\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoVgaMiniPortSetMode (\r
+ IN EFI_VGA_MINI_PORT_PROTOCOL *This,\r
+ IN UINTN ModeNumber\r
+ )\r
+{\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Make sure the ModeNumber is a valid value\r
+ //\r
+ if (ModeNumber >= This->MaxMode) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Get the device structure for this device\r
+ //\r
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);\r
+\r
+ switch (ModeNumber) {\r
+ case 0:\r
+ //\r
+ // Set the 80x25 Text VGA Mode\r
+ //\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.AL = 0x83;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ Regs.H.AH = 0x11;\r
+ Regs.H.AL = 0x14;\r
+ Regs.H.BL = 0;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+ break;\r
+\r
+ case 1:\r
+ //\r
+ // Set the 80x50 Text VGA Mode\r
+ //\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.AL = 0x83;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+ Regs.H.AH = 0x11;\r
+ Regs.H.AL = 0x12;\r
+ Regs.H.BL = 0;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Event handler for Exit Boot Service.\r
+\r
+ @param Event The event that be siganlled when exiting boot service.\r
+ @param Context Pointer to instance of BIOS_VIDEO_DEV.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BiosVideoNotifyExitBootServices (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+\r
+ BiosVideoPrivate = (BIOS_VIDEO_DEV *)Context;\r
+\r
+ //\r
+ // Set the 80x25 Text VGA Mode\r
+ //\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.AL = 0x03;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.AL = 0x83;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+\r
+ Regs.H.AH = 0x11;\r
+ Regs.H.AL = 0x04;\r
+ Regs.H.BL = 0;\r
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
+}\r
+\r
+/**\r
+ The user Entry Point for module UefiBiosVideo. The user code starts with this function.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoEntryPoint(\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Install driver model protocol(s).\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gBiosVideoDriverBinding,\r
+ ImageHandle,\r
+ &gBiosVideoComponentName,\r
+ &gBiosVideoComponentName2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver\r
+ //\r
+ return gBS->InstallMultipleProtocolInterfaces (\r
+ &ImageHandle,\r
+ &gEfiLegacyBiosGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+}\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BIOS_GRAPHICS_OUTPUT_H_\r
+#define _BIOS_GRAPHICS_OUTPUT_H_\r
+\r
+#include <FrameworkDxe.h>\r
+\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/EdidActive.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/EdidDiscovered.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/VgaMiniPort.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/EdidOverride.h>\r
+\r
+#include <Guid/StatusCodeDataTypeId.h>\r
+#include <Guid/LegacyBios.h>\r
+#include <Guid/EventGroup.h>\r
+\r
+#include <Library/PcdLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include "VesaBiosExtensions.h"\r
+\r
+//\r
+// Packed format support: The number of bits reserved for each of the colors and the actual\r
+// position of RGB in the frame buffer is specified in the VBE Mode information\r
+//\r
+typedef struct {\r
+ UINT8 Position; // Position of the color\r
+ UINT8 Mask; // The number of bits expressed as a mask\r
+} BIOS_VIDEO_COLOR_PLACEMENT;\r
+\r
+//\r
+// BIOS Graphics Output Graphical Mode Data\r
+//\r
+typedef struct {\r
+ UINT16 VbeModeNumber;\r
+ UINT16 BytesPerScanLine;\r
+ VOID *LinearFrameBuffer;\r
+ UINTN FrameBufferSize;\r
+ UINT32 HorizontalResolution;\r
+ UINT32 VerticalResolution;\r
+ UINT32 ColorDepth;\r
+ UINT32 RefreshRate;\r
+ UINT32 BitsPerPixel;\r
+ BIOS_VIDEO_COLOR_PLACEMENT Red;\r
+ BIOS_VIDEO_COLOR_PLACEMENT Green;\r
+ BIOS_VIDEO_COLOR_PLACEMENT Blue;\r
+ BIOS_VIDEO_COLOR_PLACEMENT Reserved;\r
+ EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;\r
+ EFI_PIXEL_BITMASK PixelBitMask;\r
+} BIOS_VIDEO_MODE_DATA;\r
+\r
+//\r
+// BIOS video child handle private data Structure\r
+//\r
+#define BIOS_VIDEO_DEV_SIGNATURE SIGNATURE_32 ('B', 'V', 'M', 'p')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ EFI_HANDLE Handle;\r
+\r
+ //\r
+ // Consumed Protocols\r
+ //\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ //\r
+ // Original PCI attributes\r
+ //\r
+ UINT64 OriginalPciAttributes;\r
+\r
+ //\r
+ // Produced Protocols\r
+ //\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput;\r
+ EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered;\r
+ EFI_EDID_ACTIVE_PROTOCOL EdidActive;\r
+ EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort;\r
+\r
+ //\r
+ // General fields\r
+ //\r
+ BOOLEAN VgaCompatible;\r
+ BOOLEAN ProduceGraphicsOutput;\r
+\r
+ //\r
+ // Graphics Output Protocol related fields\r
+ //\r
+ BOOLEAN HardwareNeedsStarting;\r
+ UINTN CurrentMode;\r
+ UINTN MaxMode;\r
+ BIOS_VIDEO_MODE_DATA *ModeData;\r
+ UINT8 *LineBuffer;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
+ UINT8 *VgaFrameBuffer;\r
+\r
+ //\r
+ // VESA Bios Extensions related fields\r
+ //\r
+ UINTN NumberOfPagesBelow1MB; // Number of 4KB pages in PagesBelow1MB\r
+ EFI_PHYSICAL_ADDRESS PagesBelow1MB; // Buffer for all VBE Information Blocks\r
+ VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *VbeInformationBlock; // 0x200 bytes. Must be allocated below 1MB\r
+ VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; // 0x100 bytes. Must be allocated below 1MB\r
+ VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *VbeEdidDataBlock; // 0x80 bytes. Must be allocated below 1MB\r
+ VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; // 59 bytes. Must be allocated below 1MB\r
+ UINTN VbeSaveRestorePages; // Number of 4KB pages in VbeSaveRestoreBuffer\r
+ EFI_PHYSICAL_ADDRESS VbeSaveRestoreBuffer; // Must be allocated below 1MB\r
+ //\r
+ // Status code\r
+ //\r
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
+\r
+ EFI_EVENT ExitBootServicesEvent;\r
+} BIOS_VIDEO_DEV;\r
+\r
+#define BIOS_VIDEO_DEV_FROM_PCI_IO_THIS(a) CR (a, BIOS_VIDEO_DEV, PciIo, BIOS_VIDEO_DEV_SIGNATURE)\r
+#define BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS(a) CR (a, BIOS_VIDEO_DEV, GraphicsOutput, BIOS_VIDEO_DEV_SIGNATURE)\r
+#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV, VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE)\r
+\r
+#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2;\r
+\r
+//\r
+// Driver Binding Protocol functions\r
+//\r
+\r
+/**\r
+ Supported.\r
+\r
+ @param This Pointer to driver binding protocol\r
+ @param Controller Controller handle to connect\r
+ @param RemainingDevicePath A pointer to the remaining portion of a device\r
+ path\r
+\r
+ @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this\r
+ driver, Otherwise, this controller cannot be\r
+ managed by this driver\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+\r
+/**\r
+ Install Graphics Output Protocol onto VGA device handles.\r
+\r
+ @param This Pointer to driver binding protocol\r
+ @param Controller Controller handle to connect\r
+ @param RemainingDevicePath A pointer to the remaining portion of a device\r
+ path\r
+\r
+ @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+\r
+/**\r
+ Stop.\r
+\r
+ @param This Pointer to driver binding protocol\r
+ @param Controller Controller handle to connect\r
+ @param NumberOfChildren Number of children handle created by this driver\r
+ @param ChildHandleBuffer Buffer containing child handle created\r
+\r
+ @retval EFI_SUCCESS Driver disconnected successfully from controller\r
+ @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ );\r
+\r
+//\r
+// Private worker functions\r
+//\r
+\r
+/**\r
+ Check for VBE device.\r
+\r
+ @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
+\r
+ @retval EFI_SUCCESS VBE device found\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoCheckForVbe (\r
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
+ );\r
+\r
+\r
+/**\r
+ Check for VGA device.\r
+\r
+ @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
+\r
+ @retval EFI_SUCCESS Standard VGA device found\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoCheckForVga (\r
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
+ );\r
+\r
+\r
+\r
+\r
+/**\r
+ Release resource for biso video instance.\r
+\r
+ @param BiosVideoPrivate Video child device private data structure\r
+\r
+**/\r
+VOID\r
+BiosVideoDeviceReleaseResource (\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate\r
+ );\r
+\r
+//\r
+// BIOS Graphics Output Protocol functions\r
+//\r
+\r
+/**\r
+ Graphics Output protocol interface to get video mode.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ModeNumber The mode number to return information on.\r
+ @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
+ buffer.\r
+ @param Info Caller allocated buffer that returns information\r
+ about ModeNumber.\r
+\r
+ @retval EFI_SUCCESS Mode information returned.\r
+ @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.\r
+ @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
+ video mode.\r
+ @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
+ @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoGraphicsOutputQueryMode (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN UINT32 ModeNumber,\r
+ OUT UINTN *SizeOfInfo,\r
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
+ );\r
+\r
+\r
+/**\r
+ Graphics Output protocol interface to set video mode.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ModeNumber The mode number to be set.\r
+\r
+ @retval EFI_SUCCESS Graphics mode was changed.\r
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
+ request.\r
+ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoGraphicsOutputSetMode (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
+ IN UINT32 ModeNumber\r
+ );\r
+\r
+\r
+/**\r
+ Graphics Output protocol instance to block transfer for VBE device.\r
+\r
+ @param This Pointer to Graphics Output protocol instance\r
+ @param BltBuffer The data to transfer to screen\r
+ @param BltOperation The operation to perform\r
+ @param SourceX The X coordinate of the source for BltOperation\r
+ @param SourceY The Y coordinate of the source for BltOperation\r
+ @param DestinationX The X coordinate of the destination for\r
+ BltOperation\r
+ @param DestinationY The Y coordinate of the destination for\r
+ BltOperation\r
+ @param Width The width of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Height The height of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Delta Not used for EfiBltVideoFill and\r
+ EfiBltVideoToVideo operation. If a Delta of 0 is\r
+ used, the entire BltBuffer will be operated on. If\r
+ a subrectangle of the BltBuffer is used, then\r
+ Delta represents the number of bytes in a row of\r
+ the BltBuffer.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
+ @retval EFI_SUCCESS Blt operation success\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoGraphicsOutputVbeBlt (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
+ IN UINTN SourceX,\r
+ IN UINTN SourceY,\r
+ IN UINTN DestinationX,\r
+ IN UINTN DestinationY,\r
+ IN UINTN Width,\r
+ IN UINTN Height,\r
+ IN UINTN Delta\r
+ );\r
+\r
+\r
+/**\r
+ Grahpics Output protocol instance to block transfer for VGA device.\r
+\r
+ @param This Pointer to Grahpics Output protocol instance\r
+ @param BltBuffer The data to transfer to screen\r
+ @param BltOperation The operation to perform\r
+ @param SourceX The X coordinate of the source for BltOperation\r
+ @param SourceY The Y coordinate of the source for BltOperation\r
+ @param DestinationX The X coordinate of the destination for\r
+ BltOperation\r
+ @param DestinationY The Y coordinate of the destination for\r
+ BltOperation\r
+ @param Width The width of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Height The height of a rectangle in the blt rectangle in\r
+ pixels\r
+ @param Delta Not used for EfiBltVideoFill and\r
+ EfiBltVideoToVideo operation. If a Delta of 0 is\r
+ used, the entire BltBuffer will be operated on. If\r
+ a subrectangle of the BltBuffer is used, then\r
+ Delta represents the number of bytes in a row of\r
+ the BltBuffer.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
+ @retval EFI_SUCCESS Blt operation success\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoGraphicsOutputVgaBlt (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
+ IN UINTN SourceX,\r
+ IN UINTN SourceY,\r
+ IN UINTN DestinationX,\r
+ IN UINTN DestinationY,\r
+ IN UINTN Width,\r
+ IN UINTN Height,\r
+ IN UINTN Delta\r
+ );\r
+\r
+//\r
+// BIOS VGA Mini Port Protocol functions\r
+//\r
+\r
+/**\r
+ VgaMiniPort protocol interface to set mode.\r
+\r
+ @param This Pointer to VgaMiniPort protocol instance\r
+ @param ModeNumber The index of the mode\r
+\r
+ @retval EFI_UNSUPPORTED The requested mode is not supported\r
+ @retval EFI_SUCCESS The requested mode is set successfully\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoVgaMiniPortSetMode (\r
+ IN EFI_VGA_MINI_PORT_PROTOCOL *This,\r
+ IN UINTN ModeNumber\r
+ );\r
+\r
+/**\r
+ Event handler for Exit Boot Service.\r
+\r
+ @param Event The event that be siganlled when exiting boot service.\r
+ @param Context Pointer to instance of BIOS_VIDEO_DEV.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BiosVideoNotifyExitBootServices (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
+//\r
+// Standard VGA Definitions\r
+//\r
+#define VGA_HORIZONTAL_RESOLUTION 640\r
+#define VGA_VERTICAL_RESOLUTION 480\r
+#define VGA_NUMBER_OF_BIT_PLANES 4\r
+#define VGA_PIXELS_PER_BYTE 8\r
+#define VGA_BYTES_PER_SCAN_LINE (VGA_HORIZONTAL_RESOLUTION / VGA_PIXELS_PER_BYTE)\r
+#define VGA_BYTES_PER_BIT_PLANE (VGA_VERTICAL_RESOLUTION * VGA_BYTES_PER_SCAN_LINE)\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER 0x3ce\r
+#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER 0x3cf\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER 0x00\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER 0x02\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER 0x03\r
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE 0x00\r
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND 0x08\r
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR 0x10\r
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR 0x18\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER 0x04\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER 0x05\r
+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0 0x00\r
+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1 0x08\r
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 0x00\r
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 0x01\r
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 0x02\r
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3 0x03\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER 0x06\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER 0x07\r
+\r
+#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER 0x08\r
+\r
+/**\r
+ Install child handles if the Handle supports MBR format.\r
+\r
+ @param This Calling context.\r
+ @param ParentHandle Parent Handle\r
+ @param ParentPciIo Parent PciIo interface\r
+ @param ParentLegacyBios Parent LegacyBios interface\r
+ @param ParentDevicePath Parent Device Path\r
+ @param RemainingDevicePath Remaining Device Path\r
+ @param OriginalPciAttributes Original PCI Attributes\r
+\r
+ @retval EFI_SUCCESS If a child handle was added\r
+ @retval other A child handle was not added\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoChildHandleInstall (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ParentHandle,\r
+ IN EFI_PCI_IO_PROTOCOL *ParentPciIo,\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,\r
+ IN UINT64 OriginalPciAttributes\r
+ );\r
+\r
+/**\r
+ Deregister an video child handle and free resources.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Video controller handle\r
+ @param Handle Video child handle\r
+\r
+ @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+BiosVideoChildHandleUninstall (\r
+ EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ EFI_HANDLE Controller,\r
+ EFI_HANDLE Handle\r
+ );\r
+\r
+/**\r
+ Release resource for biso video instance.\r
+\r
+ @param BiosVideoPrivate Video child device private data structure\r
+\r
+**/\r
+VOID\r
+BiosVideoDeviceReleaseResource (\r
+ BIOS_VIDEO_DEV *BiosVideoPrivate\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BiosVideo.h"\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName = {\r
+ BiosVideoComponentNameGetDriverName,\r
+ BiosVideoComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosVideoComponentNameGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosVideoComponentNameGetControllerName,\r
+ "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = {\r
+ {\r
+ "eng;en",\r
+ L"BIOS[INT10] Video Driver"\r
+ },\r
+ {\r
+ NULL,\r
+ NULL\r
+ }\r
+};\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mBiosVideoDriverNameTable,\r
+ DriverName,\r
+ (BOOLEAN)(This == &gBiosVideoComponentName)\r
+ );\r
+}\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BiosVideoComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _VESA_BIOS_EXTENSIONS_H_\r
+#define _VESA_BIOS_EXTENSIONS_H_\r
+\r
+//\r
+// Turn on byte packing of data structures\r
+//\r
+#pragma pack(1)\r
+//\r
+// VESA BIOS Extensions status codes\r
+//\r
+#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f\r
+\r
+//\r
+// VESA BIOS Extensions Services\r
+//\r
+#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION 0x4f00\r
+\r
+/*++\r
+\r
+ Routine Description:\r
+ Function 00 : Return Controller Information\r
+\r
+ Arguments:\r
+ Inputs:\r
+ AX = 0x4f00\r
+ ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure\r
+ Outputs:\r
+ AX = Return Status\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION 0x4f01\r
+\r
+/*++\r
+\r
+ Routine Description:\r
+ Function 01 : Return Mode Information\r
+\r
+ Arguments:\r
+ Inputs:\r
+ AX = 0x4f01\r
+ CX = Mode Number\r
+ ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure\r
+ Outputs:\r
+ AX = Return Status\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02\r
+\r
+/*++\r
+\r
+ Routine Description:\r
+ Function 02 : Set Mode\r
+\r
+ Arguments:\r
+ Inputs:\r
+ AX = 0x4f02\r
+ BX = Desired mode to set\r
+ D0-D8 = Mode Number\r
+ D9-D10 = Reserved (must be 0)\r
+ D11 = 0 - Use current default refresh rate\r
+ = 1 - Use user specfieid CRTC values for refresh rate\r
+ D12-D13 = Reserved (must be 0)\r
+ D14 = 0 - Use windowed frame buffer model\r
+ = 1 - Use linear/flat frame buffer model\r
+ D15 = 0 - Clear display memory\r
+ = 1 - Don't clear display memory\r
+ ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure\r
+ Outputs:\r
+ AX = Return Status\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE 0x4f03\r
+\r
+/*++\r
+\r
+ Routine Description:\r
+ Function 03 : Return Current Mode\r
+\r
+ Arguments:\r
+ Inputs:\r
+ AX = 0x4f03\r
+ Outputs:\r
+ AX = Return Status\r
+ BX = Current mode\r
+ D0-D13 = Mode Number\r
+ D14 = 0 - Windowed frame buffer model\r
+ = 1 - Linear/flat frame buffer model\r
+ D15 = 0 - Memory cleared at last mode set\r
+ = 1 - Memory not cleared at last mode set\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04\r
+\r
+/*++\r
+\r
+ Routine Description:\r
+ Function 04 : Save/Restore State\r
+\r
+ Arguments:\r
+ Inputs:\r
+ AX = 0x4f03\r
+ DL = 0x00 - Return Save/Restore State buffer size\r
+ = 0x01 - Save State\r
+ = 0x02 - Restore State\r
+ CX = Requested Status\r
+ D0 = Save/Restore controller hardware state\r
+ D1 = Save/Restore BIOS data state\r
+ D2 = Save/Restore DAC state\r
+ D3 = Save/Restore Regsiter state\r
+ ES:BX = Pointer to buffer if DL=1 or DL=2\r
+ Outputs:\r
+ AX = Return Status\r
+ BX = Number of 64 byte blocks to hold the state buffer if DL=0\r
+\r
+--*/\r
+#define VESA_BIOS_EXTENSIONS_EDID 0x4f15\r
+\r
+/*++\r
+\r
+ Routine Description:\r
+ Function 15 : implement VBE/DDC service\r
+\r
+ Arguments:\r
+ Inputs:\r
+ AX = 0x4f15\r
+ BL = 0x00 - Report VBE/DDC Capabilities\r
+ CX = 0x00 - Controller unit number (00 = primary controller)\r
+ ES:DI = Null pointer, must be 0:0 in version 1.0\r
+ Outputs:\r
+ AX = Return Status\r
+ BH = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes)\r
+ BL = DDC level supported\r
+ D0 = 0 DDC1 not supported\r
+ = 1 DDC1 supported\r
+ D1 = 0 DDC2 not supported\r
+ = 1 DDC2 supported\r
+ D2 = 0 Screen not blanked during data transfer\r
+ = 1 Screen blanked during data transfer\r
+\r
+ Inputs:\r
+ AX = 0x4f15\r
+ BL = 0x01 - Read EDID\r
+ CX = 0x00 - Controller unit number (00 = primary controller)\r
+ DX = 0x00 - EDID block number\r
+ ES:DI = Pointer to buffer in which the EDID block is returned\r
+ Outputs:\r
+ AX = Return Status\r
+--*/\r
+\r
+//\r
+// Timing data from EDID data block\r
+//\r
+#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE 128\r
+#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17\r
+\r
+typedef struct {\r
+ UINT16 HorizontalResolution;\r
+ UINT16 VerticalResolution;\r
+ UINT16 RefreshRate;\r
+} VESA_BIOS_EXTENSIONS_EDID_TIMING;\r
+\r
+typedef struct {\r
+ UINT32 ValidNumber;\r
+ UINT32 Key[VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER];\r
+} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING;\r
+\r
+typedef struct {\r
+ UINT8 Header[8]; //EDID header "00 FF FF FF FF FF FF 00"\r
+ UINT16 ManufactureName; //EISA 3-character ID\r
+ UINT16 ProductCode; //Vendor assigned code\r
+ UINT32 SerialNumber; //32-bit serial number\r
+ UINT8 WeekOfManufacture; //Week number\r
+ UINT8 YearOfManufacture; //Year\r
+ UINT8 EdidVersion; //EDID Structure Version\r
+ UINT8 EdidRevision; //EDID Structure Revision\r
+ UINT8 VideoInputDefinition;\r
+ UINT8 MaxHorizontalImageSize; //cm\r
+ UINT8 MaxVerticalImageSize; //cm\r
+ UINT8 DisplayTransferCharacteristic;\r
+ UINT8 FeatureSupport;\r
+ UINT8 RedGreenLowBits; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0\r
+ UINT8 BlueWhiteLowBits; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0\r
+ UINT8 RedX; //Red-x Bits 9 - 2\r
+ UINT8 RedY; //Red-y Bits 9 - 2\r
+ UINT8 GreenX; //Green-x Bits 9 - 2\r
+ UINT8 GreenY; //Green-y Bits 9 - 2\r
+ UINT8 BlueX; //Blue-x Bits 9 - 2\r
+ UINT8 BlueY; //Blue-y Bits 9 - 2\r
+ UINT8 WhiteX; //White-x Bits 9 - 2\r
+ UINT8 WhiteY; //White-x Bits 9 - 2\r
+ UINT8 EstablishedTimings[3];\r
+ UINT8 StandardTimingIdentification[16];\r
+ UINT8 DetailedTimingDescriptions[72];\r
+ UINT8 ExtensionFlag; //Number of (optional) 128-byte EDID extension blocks to follow\r
+ UINT8 Checksum;\r
+} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK;\r
+\r
+//\r
+// Super VGA Information Block\r
+//\r
+typedef struct {\r
+ UINT32 VESASignature; // 'VESA' 4 byte signature\r
+ UINT16 VESAVersion; // VBE version number\r
+ UINT32 OEMStringPtr; // Pointer to OEM string\r
+ UINT32 Capabilities; // Capabilities of video card\r
+ UINT32 VideoModePtr; // Pointer to an array of 16-bit supported modes values terminated by 0xFFFF\r
+ UINT16 TotalMemory; // Number of 64kb memory blocks\r
+ UINT16 OemSoftwareRev; // VBE implementation Software revision\r
+ UINT32 OemVendorNamePtr; // VbeFarPtr to Vendor Name String\r
+ UINT32 OemProductNamePtr; // VbeFarPtr to Product Name String\r
+ UINT32 OemProductRevPtr; // VbeFarPtr to Product Revision String\r
+ UINT8 Reserved[222]; // Reserved for VBE implementation scratch area\r
+ UINT8 OemData[256]; // Data area for OEM strings. Pad to 512 byte block size\r
+} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK;\r
+\r
+//\r
+// Super VGA Information Block VESASignature values\r
+//\r
+#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE SIGNATURE_32 ('V', 'E', 'S', 'A')\r
+#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE SIGNATURE_32 ('V', 'B', 'E', '2')\r
+\r
+//\r
+// Super VGA Information Block VESAVersion values\r
+//\r
+#define VESA_BIOS_EXTENSIONS_VERSION_1_2 0x0102\r
+#define VESA_BIOS_EXTENSIONS_VERSION_2_0 0x0200\r
+#define VESA_BIOS_EXTENSIONS_VERSION_3_0 0x0300\r
+\r
+//\r
+// Super VGA Information Block Capabilities field bit defintions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01 // 0: DAC width is fixed at 6 bits/color\r
+// 1: DAC width switchable to 8 bits/color\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02 // 0: Controller is VGA compatible\r
+// 1: Controller is not VGA compatible\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04 // 0: Normal RAMDAC operation\r
+// 1: Use blank bit in function 9 to program RAMDAC\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC 0x08 // 0: No hardware stereoscopic signal support\r
+// 1: Hardware stereoscopic signal support\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC 0x10 // 0: Stero signaling supported via external VESA stereo connector\r
+// 1: Stero signaling supported via VESA EVC connector\r
+//\r
+// Super VGA mode number bite field definitions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100 // 0: Not a VESA defined VBE mode\r
+// 1: A VESA defined VBE mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800 // 0: Use current BIOS default referesh rate\r
+// 1: Use the user specified CRTC values for refresh rate\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER 0x4000 // 0: Use a banked/windowed frame buffer\r
+// 1: Use a linear/flat frame buffer\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY 0x8000 // 0: Clear display memory\r
+// 1: Preseve display memory\r
+//\r
+// Super VGA Information Block mode list terminator value\r
+//\r
+#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff\r
+\r
+//\r
+// Window Function\r
+//\r
+typedef\r
+VOID\r
+(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) (\r
+ VOID\r
+ );\r
+\r
+//\r
+// Super VGA Mode Information Block\r
+//\r
+typedef struct {\r
+ //\r
+ // Manadory fields for all VESA Bios Extensions revisions\r
+ //\r
+ UINT16 ModeAttributes; // Mode attributes\r
+ UINT8 WinAAttributes; // Window A attributes\r
+ UINT8 WinBAttributes; // Window B attributes\r
+ UINT16 WinGranularity; // Window granularity in k\r
+ UINT16 WinSize; // Window size in k\r
+ UINT16 WinASegment; // Window A segment\r
+ UINT16 WinBSegment; // Window B segment\r
+ UINT32 WindowFunction; // Pointer to window function\r
+ UINT16 BytesPerScanLine; // Bytes per scanline\r
+ //\r
+ // Manadory fields for VESA Bios Extensions 1.2 and above\r
+ //\r
+ UINT16 XResolution; // Horizontal resolution\r
+ UINT16 YResolution; // Vertical resolution\r
+ UINT8 XCharSize; // Character cell width\r
+ UINT8 YCharSize; // Character cell height\r
+ UINT8 NumberOfPlanes; // Number of memory planes\r
+ UINT8 BitsPerPixel; // Bits per pixel\r
+ UINT8 NumberOfBanks; // Number of CGA style banks\r
+ UINT8 MemoryModel; // Memory model type\r
+ UINT8 BankSize; // Size of CGA style banks\r
+ UINT8 NumberOfImagePages; // Number of images pages\r
+ UINT8 Reserved1; // Reserved\r
+ UINT8 RedMaskSize; // Size of direct color red mask\r
+ UINT8 RedFieldPosition; // Bit posn of lsb of red mask\r
+ UINT8 GreenMaskSize; // Size of direct color green mask\r
+ UINT8 GreenFieldPosition; // Bit posn of lsb of green mask\r
+ UINT8 BlueMaskSize; // Size of direct color blue mask\r
+ UINT8 BlueFieldPosition; // Bit posn of lsb of blue mask\r
+ UINT8 RsvdMaskSize; // Size of direct color res mask\r
+ UINT8 RsvdFieldPosition; // Bit posn of lsb of res mask\r
+ UINT8 DirectColorModeInfo; // Direct color mode attributes\r
+ //\r
+ // Manadory fields for VESA Bios Extensions 2.0 and above\r
+ //\r
+ UINT32 PhysBasePtr; // Physical Address for flat memory frame buffer\r
+ UINT32 Reserved2; // Reserved\r
+ UINT16 Reserved3; // Reserved\r
+ //\r
+ // Manadory fields for VESA Bios Extensions 3.0 and above\r
+ //\r
+ UINT16 LinBytesPerScanLine; // Bytes/scan line for linear modes\r
+ UINT8 BnkNumberOfImagePages; // Number of images for banked modes\r
+ UINT8 LinNumberOfImagePages; // Number of images for linear modes\r
+ UINT8 LinRedMaskSize; // Size of direct color red mask (linear mode)\r
+ UINT8 LinRedFieldPosition; // Bit posiiton of lsb of red mask (linear modes)\r
+ UINT8 LinGreenMaskSize; // Size of direct color green mask (linear mode)\r
+ UINT8 LinGreenFieldPosition; // Bit posiiton of lsb of green mask (linear modes)\r
+ UINT8 LinBlueMaskSize; // Size of direct color blue mask (linear mode)\r
+ UINT8 LinBlueFieldPosition; // Bit posiiton of lsb of blue mask (linear modes)\r
+ UINT8 LinRsvdMaskSize; // Size of direct color reserved mask (linear mode)\r
+ UINT8 LinRsvdFieldPosition; // Bit posiiton of lsb of reserved mask (linear modes)\r
+ UINT32 MaxPixelClock; // Maximum pixel clock (in Hz) for graphics mode\r
+ UINT8 Pad[190]; // Pad to 256 byte block size\r
+} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK;\r
+\r
+//\r
+// Super VGA Mode Information Block ModeAttributes field bit defintions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE 0x0001 // 0: Mode not supported in handware\r
+// 1: Mode supported in handware\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004 // 0: TTY Output functions not supported by BIOS\r
+// 1: TTY Output functions supported by BIOS\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008 // 0: Monochrome mode\r
+// 1: Color mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS 0x0010 // 0: Text mode\r
+// 1: Graphics mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020 // 0: VGA compatible mode\r
+// 1: Not a VGA compatible mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED 0x0040 // 0: VGA compatible windowed memory mode\r
+// 1: Not a VGA compatible windowed memory mode\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080 // 0: No linear fram buffer mode available\r
+// 1: Linear frame buffer mode available\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100 // 0: No double scan mode available\r
+// 1: Double scan mode available\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED 0x0200 // 0: No interlaced mode is available\r
+// 1: Interlaced mode is available\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400 // 0: No hardware triple buffer mode support available\r
+// 1: Hardware triple buffer mode support available\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC 0x0800 // 0: No hardware steroscopic display support\r
+// 1: Hardware steroscopic display support\r
+//\r
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY 0x1000 // 0: No dual display start address support\r
+// 1: Dual display start address support\r
+//\r
+// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit defintions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01 // 0: Single non-relocatable window only\r
+// 1: Relocatable window(s) are supported\r
+//\r
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE 0x02 // 0: Window is not readable\r
+// 1: Window is readable\r
+//\r
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE 0x04 // 0: Window is not writable\r
+// 1: Window is writable\r
+//\r
+// Super VGA Mode Information Block DirectColorMode field bit defintions\r
+//\r
+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP 0x01 // 0: Color ram is fixed\r
+// 1: Color ramp is programmable\r
+//\r
+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE 0x02 // 0: Bits in Rsvd field are reserved\r
+// 1: Bits in Rsdv field are usable\r
+//\r
+// Super VGA Memory Models\r
+//\r
+typedef enum {\r
+ MemPL = 3, // Planar memory model\r
+ MemPK = 4, // Packed pixel memory model\r
+ MemRGB= 6, // Direct color RGB memory model\r
+ MemYUV= 7 // Direct color YUV memory model\r
+} VESA_BIOS_EXTENSIONS_MEMORY_MODELS;\r
+\r
+//\r
+// Super VGA CRTC Information Block\r
+//\r
+typedef struct {\r
+ UINT16 HorizontalTotal; // Horizontal total in pixels\r
+ UINT16 HorizontalSyncStart; // Horizontal sync start in pixels\r
+ UINT16 HorizontalSyncEnd; // Horizontal sync end in pixels\r
+ UINT16 VericalTotal; // Vertical total in pixels\r
+ UINT16 VericalSyncStart; // Vertical sync start in pixels\r
+ UINT16 VericalSyncEnd; // Vertical sync end in pixels\r
+ UINT8 Flags; // Flags (Interlaced/DoubleScan/etc).\r
+ UINT32 PixelClock; // Pixel clock in units of Hz\r
+ UINT16 RefreshRate; // Refresh rate in units of 0.01 Hz\r
+ UINT8 Reserved[40]; // Pad\r
+} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK;\r
+\r
+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01 // 0: Graphics mode is not souble scanned\r
+// 1: Graphics mode is double scanned\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02 // 0: Graphics mode is not interlaced\r
+// 1: Graphics mode is interlaced\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE 0x04 // 0: Horizontal sync polarity is positive(+)\r
+// 0: Horizontal sync polarity is negative(-)\r
+//\r
+#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08 // 0: Verical sync polarity is positive(+)\r
+// 0: Verical sync polarity is negative(-)\r
+//\r
+// Turn off byte packing of data structures\r
+//\r
+#pragma pack()\r
+\r
+#endif\r
--- /dev/null
+## @file\r
+# Video driver based on legacy bios.\r
+#\r
+# This driver by using Legacy Bios protocol service to support csm Video\r
+# and produce Graphics Output Protocol.\r
+#\r
+# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions\r
+# of the BSD License which accompanies this distribution. The\r
+# full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = BiosVideoDxe\r
+ FILE_GUID = 0B04B2ED-861C-42cd-A22F-C3AAFACCB896\r
+ MODULE_TYPE = UEFI_DRIVER\r
+ VERSION_STRING = 1.0\r
+\r
+ ENTRY_POINT = BiosVideoEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+# DRIVER_BINDING = gBiosVideoDriverBinding\r
+# COMPONENT_NAME = gBiosVideoComponentName\r
+#\r
+\r
+[Sources]\r
+ BiosVideo.c\r
+ BiosVideo.h\r
+ ComponentName.c\r
+ VesaBiosExtensions.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ DevicePathLib\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ BaseMemoryLib\r
+ ReportStatusCodeLib\r
+ DebugLib\r
+ PcdLib\r
+\r
+\r
+[Guids]\r
+ gEfiLegacyBiosGuid # ALWAYS_PRODUCED\r
+ gEfiEventExitBootServicesGuid\r
+\r
+[Protocols]\r
+ gEfiVgaMiniPortProtocolGuid # PROTOCOL BY_START\r
+ gEfiEdidDiscoveredProtocolGuid # PROTOCOL BY_START\r
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL BY_START\r
+ gEfiEdidActiveProtocolGuid # PROTOCOL BY_START\r
+ gEfiLegacyBiosProtocolGuid # PROTOCOL TO_START\r
+ gEfiPciIoProtocolGuid # PROTOCOL TO_START\r
+ gEfiDevicePathProtocolGuid # PROTOCOL TO_START\r
+ gEfiEdidOverrideProtocolGuid # PROTOCOL TO_START\r
+\r
+[Pcd]\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable\r
--- /dev/null
+## @file\r
+# Interrupt Redirection Template\r
+#\r
+# Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions\r
+# of the BSD License which accompanies this distribution. The\r
+# full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+ASM_GLOBAL ASM_PFX(InterruptRedirectionTemplate)\r
+\r
+#----------------------------------------------------------------------------\r
+# Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F \r
+#\r
+# Input: None\r
+#\r
+# Output: None\r
+#\r
+# Prototype: VOID\r
+# InterruptRedirectionTemplate ( \r
+# VOID\r
+# );\r
+#\r
+# Saves: None\r
+#\r
+# Modified: None\r
+#\r
+# Description: Contains the code that is copied into low memory (below 640K).\r
+# This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.\r
+# This template must be copied into low memory, and the IDT entries\r
+# 0x68-0x6F must be point to the low memory copy of this code. Each\r
+# entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily \r
+# computed.\r
+#\r
+#----------------------------------------------------------------------------\r
+ASM_PFX(InterruptRedirectionTemplate):\r
+ int $0x8\r
+ .byte 0xcf\r
+ nop\r
+ int $0x9\r
+ .byte 0xcf\r
+ nop\r
+ int $0xa\r
+ .byte 0xcf\r
+ nop\r
+ int $0xb\r
+ .byte 0xcf\r
+ nop\r
+ int $0xc\r
+ .byte 0xcf\r
+ nop\r
+ int $0xd\r
+ .byte 0xcf\r
+ nop\r
+ int $0xe\r
+ .byte 0xcf\r
+ nop\r
+ int $0xf\r
+ .byte 0xcf\r
+ nop\r
--- /dev/null
+;; @file\r
+; Interrupt Redirection Template\r
+;\r
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
+;\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions\r
+; of the BSD License which accompanies this distribution. The\r
+; full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+;;\r
+\r
+.686P\r
+.MODEL FLAT, C\r
+.CODE\r
+\r
+;----------------------------------------------------------------------------\r
+; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F \r
+;\r
+; Input: None\r
+;\r
+; Output: None\r
+;\r
+; Prototype: VOID\r
+; InterruptRedirectionTemplate ( \r
+; VOID\r
+; );\r
+;\r
+; Saves: None\r
+;\r
+; Modified: None\r
+;\r
+; Description: Contains the code that is copied into low memory (below 640K).\r
+; This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.\r
+; This template must be copied into low memory, and the IDT entries\r
+; 0x68-0x6F must be point to the low memory copy of this code. Each\r
+; entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily \r
+; computed.\r
+;\r
+;----------------------------------------------------------------------------\r
+\r
+InterruptRedirectionTemplate PROC C\r
+ int 08h\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 09h\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0ah\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0bh\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0ch\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0dh\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0eh\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0fh\r
+ DB 0cfh ; IRET\r
+ nop\r
+InterruptRedirectionTemplate ENDP\r
+\r
+END
\ No newline at end of file
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+\r
+/**\r
+ Assign drive number to legacy HDD drives prior to booting an EFI\r
+ aware OS so the OS can access drives without an EFI driver.\r
+ Note: BBS compliant drives ARE NOT available until this call by\r
+ either shell or EFI.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BbsCount Number of BBS_TABLE structures\r
+ @param BbsTable List BBS entries\r
+\r
+ @retval EFI_SUCCESS Drive numbers assigned\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosPrepareToBootEfi (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ OUT UINT16 *BbsCount,\r
+ OUT BBS_TABLE **BbsTable\r
+ )\r
+{\r
+ //\r
+ // Shadow All Opion ROM\r
+ //\r
+ LegacyBiosShadowAllLegacyOproms (This);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ To boot from an unconventional device like parties and/or execute\r
+ HDD diagnostics.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Attributes How to interpret the other input parameters\r
+ @param BbsEntry The 0-based index into the BbsTable for the\r
+ parent device.\r
+ @param BeerData Pointer to the 128 bytes of ram BEER data.\r
+ @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data.\r
+ The caller must provide a pointer to the specific\r
+ Service Area and not the start all Service Areas.\r
+ EFI_INVALID_PARAMETER if error. Does NOT return if no error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosBootUnconventionalDevice (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UDC_ATTRIBUTES Attributes,\r
+ IN UINTN BbsEntry,\r
+ IN VOID *BeerData,\r
+ IN VOID *ServiceAreaData\r
+ )\r
+{\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+\r
+/**\r
+ Attempt to legacy boot the BootOption. If the EFI contexted has been\r
+ compromised this function will not return.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BbsDevicePath EFI Device Path from BootXXXX variable.\r
+ @param LoadOptionsSize Size of LoadOption in size.\r
+ @param LoadOptions LoadOption from BootXXXX variable\r
+\r
+ @retval EFI_SUCCESS Removable media not present\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosLegacyBoot (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN BBS_BBS_DEVICE_PATH *BbsDevicePath,\r
+ IN UINT32 LoadOptionsSize,\r
+ IN VOID *LoadOptions\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Build the E820 table.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param Size Size of E820 Table\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildE820 (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ OUT UINTN *Size\r
+ )\r
+{\r
+ *Size = 0;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get all BBS info\r
+\r
+ @param This Protocol instance pointer.\r
+ @param HddCount Number of HDD_INFO structures\r
+ @param HddInfo Onboard IDE controller information\r
+ @param BbsCount Number of BBS_TABLE structures\r
+ @param BbsTable List BBS entries\r
+\r
+ @retval EFI_SUCCESS Tables returned\r
+ @retval EFI_NOT_FOUND resource not found\r
+ @retval EFI_DEVICE_ERROR can not get BBS table\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosGetBbsInfo (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ OUT UINT16 *HddCount,\r
+ OUT HDD_INFO **HddInfo,\r
+ OUT UINT16 *BbsCount,\r
+ OUT BBS_TABLE **BbsTable\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Fill in the standard BDA for Keyboard LEDs\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Leds Current LED status\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosUpdateKeyboardLedStatus (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT8 Leds\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Relocate this image under 4G memory for IPF.\r
+\r
+ @param ImageHandle Handle of driver image.\r
+ @param SystemTable Pointer to system table.\r
+\r
+ @retval EFI_SUCCESS Image successfully relocated.\r
+ @retval EFI_ABORTED Failed to relocate image.\r
+\r
+**/\r
+EFI_STATUS\r
+RelocateImageUnder4GIfNeeded (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+ UINTN NumberOfPages;\r
+ EFI_PHYSICAL_ADDRESS LoadedImageBase;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+ EFI_PHYSICAL_ADDRESS MemoryAddress;\r
+ EFI_HANDLE NewImageHandle;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ ImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID *) &LoadedImage\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ LoadedImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImage->ImageBase;\r
+ if (LoadedImageBase > 0xffffffff) {\r
+ NumberOfPages = (UINTN) (DivU64x32(LoadedImage->ImageSize, EFI_PAGE_SIZE) + 1);\r
+\r
+ //\r
+ // Allocate buffer below 4GB here\r
+ //\r
+ Status = AllocateLegacyMemory (\r
+ AllocateMaxAddress,\r
+ 0x7FFFFFFF,\r
+ NumberOfPages, // do we have to convert this to pages??\r
+ &MemoryAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ZeroMem (&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
+ ImageContext.Handle = (VOID *)(UINTN)LoadedImageBase;\r
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
+\r
+ //\r
+ // Get information about the image being loaded\r
+ //\r
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)MemoryAddress;\r
+ //\r
+ // Align buffer on section boundry\r
+ //\r
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
+ ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);\r
+\r
+ //\r
+ // Load the image to our new buffer\r
+ //\r
+ Status = PeCoffLoaderLoadImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (MemoryAddress, NumberOfPages);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Relocate the image in our new buffer\r
+ //\r
+ Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (MemoryAddress, NumberOfPages);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create a new handle with gEfiCallerIdGuid to be used as the ImageHandle fore the reloaded image\r
+ // \r
+ NewImageHandle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &NewImageHandle,\r
+ &gEfiCallerIdGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // Flush the instruction cache so the image data is written before we execute it\r
+ //\r
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+\r
+ Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (MemoryAddress, NumberOfPages);\r
+ return Status;\r
+ }\r
+ //\r
+ // return error directly the BS will unload this image\r
+ //\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _IPF_THUNK_H_\r
+#define _IPF_THUNK_H_\r
+\r
+#include "LegacyBiosInterface.h"\r
+#include <IndustryStandard/Sal.h>\r
+\r
+/**\r
+ Template of real mode code.\r
+\r
+ @param CodeStart Start address of code.\r
+ @param CodeEnd End address of code\r
+ @param ReverseThunkStart Start of reverse thunk.\r
+ @param IntThunk Low memory thunk.\r
+\r
+**/\r
+VOID\r
+RealModeTemplate (\r
+ OUT UINTN *CodeStart,\r
+ OUT UINTN *CodeEnd,\r
+ OUT UINTN *ReverseThunkStart,\r
+ LOW_MEMORY_THUNK *IntThunk\r
+ );\r
+\r
+/**\r
+ Register physical address of Esal Data Area\r
+\r
+ @param ReverseThunkCodeAddress Reverse Thunk Address\r
+ @param IntThunkAddress IntThunk Address\r
+\r
+ @retval EFI_SUCCESS ESAL data area set successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EsalSetSalDataArea (\r
+ IN UINTN ReverseThunkCodeAddress,\r
+ IN UINTN IntThunkAddress\r
+ );\r
+\r
+/**\r
+ Get address of reverse thunk.\r
+\r
+ @retval EFI_SAL_SUCCESS Address of reverse thunk returned successfully.\r
+\r
+**/\r
+SAL_RETURN_REGS\r
+EsalGetReverseThunkAddress (\r
+ VOID\r
+ );\r
+\r
+typedef struct {\r
+ UINT32 Eax; // 0\r
+ UINT32 Ecx; // 4\r
+ UINT32 Edx; // 8\r
+ UINT32 Ebx; // 12\r
+ UINT32 Esp; // 16\r
+ UINT32 Ebp; // 20\r
+ UINT32 Esi; // 24\r
+ UINT32 Edi; // 28\r
+ UINT32 Eflag; // 32\r
+ UINT32 Eip; // 36\r
+ UINT16 Cs; // 40\r
+ UINT16 Ds; // 42\r
+ UINT16 Es; // 44\r
+ UINT16 Fs; // 46\r
+ UINT16 Gs; // 48\r
+ UINT16 Ss; // 50\r
+} IPF_DWORD_REGS;\r
+\r
+/**\r
+ Entrypoint of IA32 code.\r
+\r
+ @param CallTypeData Data of call type\r
+ @param DwordRegister Register set of IA32 general registers\r
+ and segment registers\r
+ @param StackPointer Stack pointer.\r
+ @param StackSize Size of stack.\r
+\r
+**/\r
+VOID\r
+EfiIaEntryPoint (\r
+ UINT64 CallTypeData,\r
+ IPF_DWORD_REGS *DwordRegister,\r
+ UINT64 StackPointer,\r
+ UINT64 StackSize\r
+ );\r
+\r
+#endif\r
--- /dev/null
+//// @file\r
+//\r
+// Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions\r
+// of the BSD License which accompanies this distribution. The\r
+// full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+////\r
+\r
+#define NUM_REAL_GDT_ENTRIES 3\r
+#define LOW_STACK_SIZE (8*1024) // 8k?\r
+\r
+//\r
+// Low memory Thunk Structure\r
+//\r
+#define Code 0\r
+#define LowReverseThunkStart Code + 4096\r
+#define GdtDesc LowReverseThunkStart + 4\r
+#define IdtDesc GdtDesc + 6\r
+#define FlatSs IdtDesc + 6\r
+#define FlatEsp FlatSs + 4\r
+#define LowCodeSelector FlatEsp + 4\r
+#define LowDataSelector LowCodeSelector + 4\r
+#define LowStack LowDataSelector + 4\r
+#define RealModeIdtDesc LowStack + 4\r
+#define RealModeGdt RealModeIdtDesc + 6\r
+#define RealModeGdtDesc RealModeGdt + (8 * NUM_REAL_GDT_ENTRIES)\r
+#define RevRealDs RealModeGdtDesc + 6\r
+#define RevRealSs RevRealDs + 2\r
+#define RevRealEsp RevRealSs + 2\r
+#define RevRealIdtDesc RevRealEsp + 4\r
+#define RevFlatDataSelector RevRealIdtDesc + 6\r
+#define RevFlatStack RevFlatDataSelector + 2\r
+#define Stack RevFlatStack + 4\r
+#define RevThunkStack Stack + LOW_STACK_SIZE\r
+\r
+#define EfiToLegacy16InitTable RevThunkStack + LOW_STACK_SIZE\r
+#define InitTableBiosLessThan1MB EfiToLegacy16InitTable\r
+#define InitTableHiPmmMemory InitTableBiosLessThan1MB + 4\r
+#define InitTablePmmMemorySizeInBytes InitTableHiPmmMemory + 4\r
+#define InitTableReverseThunkCallSegment InitTablePmmMemorySizeInBytes + 4\r
+#define InitTableReverseThunkCallOffset InitTableReverseThunkCallSegment + 2\r
+#define InitTableNumberE820Entries InitTableReverseThunkCallOffset + 2\r
+#define InitTableOsMemoryAbove1Mb InitTableNumberE820Entries + 4\r
+#define InitTableThunkStart InitTableOsMemoryAbove1Mb + 4\r
+#define InitTableThunkSizeInBytes InitTableThunkStart + 4\r
+#define InitTable16InitTableEnd InitTableThunkSizeInBytes + 4\r
+\r
+#define EfiToLegacy16BootTable InitTable16InitTableEnd\r
+#define BootTableBiosLessThan1MB EfiToLegacy16BootTable\r
+#define BootTableHiPmmMemory BootTableBiosLessThan1MB + 4\r
+#define BootTablePmmMemorySizeInBytes BootTableHiPmmMemory + 4\r
+#define BootTableReverseThunkCallSegment BootTablePmmMemorySizeInBytes + 4\r
+#define BootTableReverseThunkCallOffset BootTableReverseThunkCallSegment + 2\r
+#define BootTableNumberE820Entries BootTableReverseThunkCallOffset + 2\r
+#define BootTableOsMemoryAbove1Mb BootTableNumberE820Entries + 4\r
+#define BootTableThunkStart BootTableOsMemoryAbove1Mb + 4\r
+#define BootTableThunkSizeInBytes BootTableThunkStart + 4\r
+#define EfiToLegacy16BootTableEnd BootTableThunkSizeInBytes + 4\r
+\r
+#define InterruptRedirectionCode EfiToLegacy16BootTableEnd\r
+#define PciHandler InterruptRedirectionCode + 32\r
+\r
+\r
+//\r
+// Register Sets (16 Bit)\r
+//\r
+\r
+#define AX 0\r
+#define BX 2\r
+#define CX 4\r
+#define DX 6\r
+#define SI 8\r
+#define DI 10\r
+#define Flags 12\r
+#define ES 14\r
+#define CS 16\r
+#define SS 18\r
+#define DS 20\r
+#define BP 22\r
+\r
+\r
+\r
--- /dev/null
+//// @file
+//
+// Copyright (c) 1999 - 2008, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions
+// of the BSD License which accompanies this distribution. The
+// full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+////
+
+.file "IpfThunk.s"
+
+#include "IpfMacro.i"
+#include "Ipf/IpfThunk.i"
+
+.align 0x10
+//-----------------------------------------------------------------------------
+//++
+// EfiIaEntryPoint
+//
+// Register physical address of Esal Data Area
+//
+// On Entry :
+// in1 = ptr to legacy bios reg
+// in2 = ptr to Call Stack
+// in3 = Call Stack Size
+//
+// Return Value:
+// r8 = SAL_SUCCESS
+//
+// As per static calling conventions.
+//
+//--
+//---------------------------------------------------------------------------
+PROCEDURE_ENTRY(EfiIaEntryPoint)
+
+ alloc loc0 = 8,10,8,0;;
+
+ mov out0 = r0;;
+ mov out1 = r0;;
+ mov out2 = r0;;
+ mov out3 = r0;;
+ mov out4 = r0;;
+ mov out5 = r0;;
+ mov out6 = r0;;
+ mov out7 = r0;;
+
+ mov loc1 = b0;; // save efi (b0)
+ mov loc2 = psr;; // save efi (PSR)
+ mov loc3 = gp;; // save efi (GP)
+ mov loc4 = pr;; // save efi (PR)
+ mov loc5 = sp;; // save efi (SP)
+ mov loc6 = r13;; // save efi (TP)
+ mov loc7 = ar.lc;; // save efi (LC)
+ mov loc8 = ar.fpsr;; // save efi (FPSR)
+
+ mov r8 = r0;; // return status
+ mov r9 = r0;; // return value
+ mov r10 = r0;; // return value
+ mov r11 = r0;; // return value
+
+bios_int_func::
+ rsm 0x4000;; // i(14)=0, disable interrupt
+ srlz.d;;
+ srlz.i;;
+
+//---------------------//
+// save fp registers //
+//---------------------//
+
+ dep sp = 0,sp,0,4;; // align 16
+ add sp = -16,sp;; // post decrement
+
+int_ip_1x::
+ mov r2 = ip;;
+ add r2 = (int_ip_1y - int_ip_1x),r2;;
+ mov b7 = r2;;
+ br save_fp_registers;;
+
+int_ip_1y::
+ add sp = 16,sp;; // adjust (SP)
+ mov loc9 = sp;; // save (SP)
+ adds sp = 0x10,in1;; // in1 + 0x10 = SP
+ ld4 sp = [sp];; // SP
+ adds r17 = 0x32,in1;; // in1 + 0x32 = SS
+ ld2 r17 = [r17];; // SS
+ movl r2 = 0xffffffff;; // if no SS:SP, then define new SS:SP
+ cmp.ne p6,p0 = sp,r2;;
+ movl r2 = 0xffff;;
+ cmp.ne.or p6,p0 = r17,r2;;
+ (p6) br.sptk bif_1;;
+
+ mov sp = in3;; // 16-bit stack pointer
+ mov r2 = psr;;
+ tbit.z p6,p7 = r2,17;; // psr.dt (Physical OR Virtual)
+
+bif_ip1x::
+ mov r2 = in2;; // ia32 callback stack top
+ mov r3 = in3;; // 16-bit stack pointer
+ sub r2 = r2,r3;;
+ shr.u r17 = r2,4;; // 16-bit stack segment
+
+bif_1::
+ extr.u sp = sp,0,16;; // SP (16-bit sp for legacy code)
+ dep sp = 0,sp,0,3;; // align 8
+ cmp.eq p6,p0 = 0,sp;; // if SP=0000 then wrap to 0x10000
+ (p6) dep sp = -1,sp,16,1;;
+ shladd r2 = r17,4,sp;; // ESP = SS<<4+SP
+ add r2 = -8,r2;; // post decrement 64 bit pointer
+ add sp = -8,sp;; // post decrement SP
+
+sale_ip1x::
+ mov r18 = ip;;
+ adds r18 = (sale_ip1y - sale_ip1x),r18;;
+ sub r18 = r18,r2;; // return address - CS base
+ add r18 = r18,sp;; // adjustment for stack
+ shl r18 = r18,32;;
+ movl r19 = 0xb80f66fa;; // CLI, JMPE xxxxxxxx
+ or r18 = r18,r19;;
+ st8 [r2] = r18;; // (FA,66,0F,B8,xx,xx,xx,xx)
+
+ cmp.eq p6,p0 = 0,sp;; // if SP=0000 then wrap to 0x10000
+ (p6) dep sp = -1,sp,16,1;;
+ shladd r2 = r17,4,sp;; // ESP=SS<<4+SP
+ add r2 = -2,r2;; // post decrement 64 bit pointer
+ add sp = -2,sp;; // post decrement SP
+
+ movl r18 = 0x8000000000000100;; // CALL FAR function
+ cmp.eq p6,p7 = in0,r18;;
+ (p6) add r19 = 0x28,in1;; // in1 + 0x28 = CS
+ (p6) ld2 r18 = [r19],-4;; // CS
+ (p6) st2 [r2] = r18,-2;; // in1 + 0x24 = EIP
+ (p6) ld2 r18 = [r19];; // EIP
+ (p6) st2 [r2] = r18,-2;; //
+ (p6) movl r18 = 0x9a90;; // nop, CALLFAR xxxx:yyyy
+
+ (p7) movl r18 = 0xcd;; // INT xx
+ (p7) dep r18 = in0,r18,8,8;;
+ st2 [r2] = r18;; // (CD,xx)
+
+ mov r18 = r2;; // EIP for legacy execution
+
+//------------------------------//
+// flush 32 bytes legacy code //
+//------------------------------//
+
+ dep r2 = 0,r2,0,5;; // align to 32
+ fc r2;;
+ sync.i;;
+ srlz.i;;
+ srlz.d;;
+
+//------------------------------//
+// load legacy registers //
+//------------------------------//
+ mov r2 = in1;; // IA32 BIOS register state
+ ld4 r8 = [r2],4;; // in1 + 0 = EAX
+ ld4 r9 = [r2],4;; // in1 + 4 = ECX
+ ld4 r10 = [r2],4;; // in1 + 8 = EDX
+ ld4 r11 = [r2],4;; // in1 + 12 = EBX
+
+ add r2 = 4,r2;; // in1 + 16 = ESP (skip)
+
+ ld4 r13 = [r2],4;; // in1 + 20 = EBP
+ ld4 r14 = [r2],4;; // in1 + 24 = ESI
+ ld4 r15 = [r2],4;; // in1 + 28 = EDI
+ ld4 r3 = [r2],4;; // in1 + 32 = EFLAGS
+ mov ar.eflag = r3;;
+
+ add r2 = 4,r2;; // in1 + 36 = EIP (skip)
+ add r2 = 2,r2;; // in1 + 40 = CS (skip)
+
+ ld2 r16 = [r2],2;; // in1 + 42 = DS, (r16 = GS,FS,ES,DS)
+ movl r27 = 0xc93fffff00000000;;
+ dep r27 = r16,r27,4,16;; // r27 = DSD
+
+ ld2 r19 = [r2],2;; // in1 + 44 = ES
+ dep r16 = r19,r16,16,16;;
+ movl r24 = 0xc93fffff00000000;;
+ dep r24 = r19,r24,4,16;; // r24 = ESD
+
+ ld2 r19 = [r2],2;; // in1 + 46 = FS
+ dep r16 = r19,r16,32,16;;
+ movl r28 = 0xc93fffff00000000;;
+ dep r28 = r19,r28,4,16;; // r28 = FSD
+
+ ld2 r19 = [r2],2;; // in1 + 48 = GS
+ dep r16 = r19,r16,48,16;;
+ movl r29 = 0xc93fffff00000000;;
+ dep r29 = r19,r29,4,16;; // r29 = GSD
+
+ mov r30 = r0;; // r30 = LDTD, clear NaT
+ mov r31 = r0;; // r31 = GDTD, clear NaT
+
+ dep r17 = r17,r17,16,16;; // CS = SS, (r17 = TSS,LDT,SS,CS)
+
+ movl r3 = 0x0930ffff00000000;;
+ dep r3 = r17,r3,4,16;;
+ mov ar.csd = r3;; // ar25 = CSD
+ mov ar.ssd = r3;; // ar26 = SSD
+
+//------------------------------//
+// give control to INT function //
+//------------------------------//
+
+ br.call.sptk b0 = execute_int_function;;
+
+//------------------------------//
+// store legacy registers //
+//------------------------------//
+
+ mov r2 = in1;;
+ st4 [r2] = r8,4;; // EAX
+ st4 [r2] = r9,4;; // ECX
+ st4 [r2] = r10,4;; // EDX
+ st4 [r2] = r11,4;; // EBX
+
+ add r2 = 4,r2;; // ESP (skip)
+
+ st4 [r2] = r13,4;; // EBP
+ st4 [r2] = r14,4;; // ESI
+ st4 [r2] = r15,4;; // EDI
+
+ mov r3 = ar.eflag;;
+ st4 [r2] = r3,4;; // EFLAGS
+
+ add r2 = 4,r2;; // EIP (skip)
+ add r2 = 2,r2;; // CS (skip)
+
+ st2 [r2] = r16,2;; // DS, (r16 = GS,FS,ES,DS)
+
+ extr.u r3 = r16,16,16;;
+ st2 [r2] = r3,2;; // ES
+
+ extr.u r3 = r16,32,16;;
+ st2 [r2] = r3,2;; // FS
+
+ extr.u r3 = r16,48,16;;
+ st2 [r2] = r3,2;; // GS
+
+//------------------------------//
+// restore fp registers //
+//------------------------------//
+ mov sp = loc9;; // restore (SP)
+int_ip_2x::
+ mov r2 = ip;;
+ add r2 = (int_ip_2y - int_ip_2x),r2;;
+ mov b7 = r2;;
+ br restore_fp_registers;;
+
+int_ip_2y::
+ mov r8 = r0;; // return status
+ mov r9 = r0;; // return value
+ mov r10 = r0;; // return value
+ mov r11 = r0;; // return value
+
+ mov ar.fpsr = loc8;; // restore efi (FPSR)
+ mov ar.lc = loc7;; // restore efi (LC)
+ mov r13 = loc6;; // restore efi (TP)
+ mov sp = loc5;; // restore efi (SP)
+ mov pr = loc4;; // restore efi (PR)
+ mov gp = loc3;; // restore efi (GP)
+ mov psr.l = loc2;; // restore efi (PSR)
+ srlz.d;;
+ srlz.i;;
+ mov b0 = loc1;; // restore efi (b0)
+ mov ar.pfs = loc0;;
+ br.ret.sptk b0;; // return to efi
+
+PROCEDURE_EXIT (EfiIaEntryPoint)
+
+//==============================//
+// EXECUTE_INT_FUNCTION //
+//==============================//
+// switch to virtual address //
+//------------------------------//
+
+execute_int_function::
+
+ alloc r2 = 0,0,0,0;; // cfm.sof=0
+ flushrs;;
+
+ rsm 0x2000;; // ic(13)=0 for control register programming
+ srlz.d;;
+ srlz.i;;
+
+ mov r2 = psr;;
+ dep r2 = -1,r2,34,1;; // set is(34)
+ dep r2 = -1,r2,44,1;; // set bn(44)
+ dep r2 = -1,r2,36,1;; // set it(36)
+ dep r2 = -1,r2,27,1;; // set rt(27)
+ dep r2 = -1,r2,17,1;; // set dt(17)
+ dep r2 = 0,r2,3,1;; // reset ac(3)
+ dep r2 = -1,r2,13,1;; // set ic(13)
+
+ mov cr.ipsr = r2;;
+ mov cr.ifs = r0;; // clear interruption function state register
+ mov cr.iip = r18;;
+
+ rfi;; // go to legacy code execution
+
+//------------------------------//
+// back from legacy code //
+//------------------------------//
+// switch to physical address //
+//------------------------------//
+
+sale_ip1y::
+ rsm 0x6000;; // i(14)=0,ic(13)=0 for control reg programming
+ srlz.d;;
+ srlz.i;;
+
+ mov r2 = psr;;
+ dep r2 = -1,r2,44,1;; // set bn(44)
+ dep r2 = 0,r2,36,1;; // reset it(36)
+ dep r2 = 0,r2,27,1;; // reset rt(27)
+ dep r2 = 0,r2,17,1;; // reset dt(17)
+ dep r2 = -1,r2,13,1;; // set ic(13)
+ mov cr.ipsr = r2;;
+
+sale_ip2x::
+ mov r2 = ip;;
+ add r2 = (sale_ip2y - sale_ip2x),r2;;
+ mov cr.ifs = r0;; // clear interruption function state register
+ mov cr.iip = r2;;
+ rfi;;
+
+sale_ip2y::
+ br.ret.sptk b0;; // return to SAL
+
+//------------------------------//
+// store fp registers //
+//------------------------------//
+save_fp_registers::
+ stf.spill [sp]=f2,-16;; stf.spill [sp]=f3,-16;;
+ stf.spill [sp]=f4,-16;; stf.spill [sp]=f5,-16;; stf.spill [sp]=f6,-16;; stf.spill [sp]=f7,-16;;
+ stf.spill [sp]=f8,-16;; stf.spill [sp]=f9,-16;; stf.spill [sp]=f10,-16;; stf.spill [sp]=f11,-16;;
+ stf.spill [sp]=f12,-16;; stf.spill [sp]=f13,-16;; stf.spill [sp]=f14,-16;; stf.spill [sp]=f15,-16;;
+ stf.spill [sp]=f16,-16;; stf.spill [sp]=f17,-16;; stf.spill [sp]=f18,-16;; stf.spill [sp]=f19,-16;;
+ stf.spill [sp]=f20,-16;; stf.spill [sp]=f21,-16;; stf.spill [sp]=f22,-16;; stf.spill [sp]=f23,-16;;
+ stf.spill [sp]=f24,-16;; stf.spill [sp]=f25,-16;; stf.spill [sp]=f26,-16;; stf.spill [sp]=f27,-16;;
+ stf.spill [sp]=f28,-16;; stf.spill [sp]=f29,-16;; stf.spill [sp]=f30,-16;; stf.spill [sp]=f31,-16;;
+ stf.spill [sp]=f32,-16;; stf.spill [sp]=f33,-16;; stf.spill [sp]=f34,-16;; stf.spill [sp]=f35,-16;;
+ stf.spill [sp]=f36,-16;; stf.spill [sp]=f37,-16;; stf.spill [sp]=f38,-16;; stf.spill [sp]=f39,-16;;
+ stf.spill [sp]=f40,-16;; stf.spill [sp]=f41,-16;; stf.spill [sp]=f42,-16;; stf.spill [sp]=f43,-16;;
+ stf.spill [sp]=f44,-16;; stf.spill [sp]=f45,-16;; stf.spill [sp]=f46,-16;; stf.spill [sp]=f47,-16;;
+ stf.spill [sp]=f48,-16;; stf.spill [sp]=f49,-16;; stf.spill [sp]=f50,-16;; stf.spill [sp]=f51,-16;;
+ stf.spill [sp]=f52,-16;; stf.spill [sp]=f53,-16;; stf.spill [sp]=f54,-16;; stf.spill [sp]=f55,-16;;
+ stf.spill [sp]=f56,-16;; stf.spill [sp]=f57,-16;; stf.spill [sp]=f58,-16;; stf.spill [sp]=f59,-16;;
+ stf.spill [sp]=f60,-16;; stf.spill [sp]=f61,-16;; stf.spill [sp]=f62,-16;; stf.spill [sp]=f63,-16;;
+ stf.spill [sp]=f64,-16;; stf.spill [sp]=f65,-16;; stf.spill [sp]=f66,-16;; stf.spill [sp]=f67,-16;;
+ stf.spill [sp]=f68,-16;; stf.spill [sp]=f69,-16;; stf.spill [sp]=f70,-16;; stf.spill [sp]=f71,-16;;
+ stf.spill [sp]=f72,-16;; stf.spill [sp]=f73,-16;; stf.spill [sp]=f74,-16;; stf.spill [sp]=f75,-16;;
+ stf.spill [sp]=f76,-16;; stf.spill [sp]=f77,-16;; stf.spill [sp]=f78,-16;; stf.spill [sp]=f79,-16;;
+ stf.spill [sp]=f80,-16;; stf.spill [sp]=f81,-16;; stf.spill [sp]=f82,-16;; stf.spill [sp]=f83,-16;;
+ stf.spill [sp]=f84,-16;; stf.spill [sp]=f85,-16;; stf.spill [sp]=f86,-16;; stf.spill [sp]=f87,-16;;
+ stf.spill [sp]=f88,-16;; stf.spill [sp]=f89,-16;; stf.spill [sp]=f90,-16;; stf.spill [sp]=f91,-16;;
+ stf.spill [sp]=f92,-16;; stf.spill [sp]=f93,-16;; stf.spill [sp]=f94,-16;; stf.spill [sp]=f95,-16;;
+ stf.spill [sp]=f96,-16;; stf.spill [sp]=f97,-16;; stf.spill [sp]=f98,-16;; stf.spill [sp]=f99,-16;;
+ stf.spill [sp]=f100,-16;;stf.spill [sp]=f101,-16;;stf.spill [sp]=f102,-16;;stf.spill [sp]=f103,-16;;
+ stf.spill [sp]=f104,-16;;stf.spill [sp]=f105,-16;;stf.spill [sp]=f106,-16;;stf.spill [sp]=f107,-16;;
+ stf.spill [sp]=f108,-16;;stf.spill [sp]=f109,-16;;stf.spill [sp]=f110,-16;;stf.spill [sp]=f111,-16;;
+ stf.spill [sp]=f112,-16;;stf.spill [sp]=f113,-16;;stf.spill [sp]=f114,-16;;stf.spill [sp]=f115,-16;;
+ stf.spill [sp]=f116,-16;;stf.spill [sp]=f117,-16;;stf.spill [sp]=f118,-16;;stf.spill [sp]=f119,-16;;
+ stf.spill [sp]=f120,-16;;stf.spill [sp]=f121,-16;;stf.spill [sp]=f122,-16;;stf.spill [sp]=f123,-16;;
+ stf.spill [sp]=f124,-16;;stf.spill [sp]=f125,-16;;stf.spill [sp]=f126,-16;;stf.spill [sp]=f127,-16;;
+ invala;;
+ br b7;;
+
+//------------------------------//
+// restore fp registers //
+//------------------------------//
+restore_fp_registers::
+ ldf.fill f127=[sp],16;;ldf.fill f126=[sp],16;;ldf.fill f125=[sp],16;;ldf.fill f124=[sp],16;;
+ ldf.fill f123=[sp],16;;ldf.fill f122=[sp],16;;ldf.fill f121=[sp],16;;ldf.fill f120=[sp],16;;
+ ldf.fill f119=[sp],16;;ldf.fill f118=[sp],16;;ldf.fill f117=[sp],16;;ldf.fill f116=[sp],16;;
+ ldf.fill f115=[sp],16;;ldf.fill f114=[sp],16;;ldf.fill f113=[sp],16;;ldf.fill f112=[sp],16;;
+ ldf.fill f111=[sp],16;;ldf.fill f110=[sp],16;;ldf.fill f109=[sp],16;;ldf.fill f108=[sp],16;;
+ ldf.fill f107=[sp],16;;ldf.fill f106=[sp],16;;ldf.fill f105=[sp],16;;ldf.fill f104=[sp],16;;
+ ldf.fill f103=[sp],16;;ldf.fill f102=[sp],16;;ldf.fill f101=[sp],16;;ldf.fill f100=[sp],16;;
+ ldf.fill f99=[sp],16;; ldf.fill f98=[sp],16;; ldf.fill f97=[sp],16;; ldf.fill f96=[sp],16;;
+ ldf.fill f95=[sp],16;; ldf.fill f94=[sp],16;; ldf.fill f93=[sp],16;; ldf.fill f92=[sp],16;;
+ ldf.fill f91=[sp],16;; ldf.fill f90=[sp],16;; ldf.fill f89=[sp],16;; ldf.fill f88=[sp],16;;
+ ldf.fill f87=[sp],16;; ldf.fill f86=[sp],16;; ldf.fill f85=[sp],16;; ldf.fill f84=[sp],16;;
+ ldf.fill f83=[sp],16;; ldf.fill f82=[sp],16;; ldf.fill f81=[sp],16;; ldf.fill f80=[sp],16;;
+ ldf.fill f79=[sp],16;; ldf.fill f78=[sp],16;; ldf.fill f77=[sp],16;; ldf.fill f76=[sp],16;;
+ ldf.fill f75=[sp],16;; ldf.fill f74=[sp],16;; ldf.fill f73=[sp],16;; ldf.fill f72=[sp],16;;
+ ldf.fill f71=[sp],16;; ldf.fill f70=[sp],16;; ldf.fill f69=[sp],16;; ldf.fill f68=[sp],16;;
+ ldf.fill f67=[sp],16;; ldf.fill f66=[sp],16;; ldf.fill f65=[sp],16;; ldf.fill f64=[sp],16;;
+ ldf.fill f63=[sp],16;; ldf.fill f62=[sp],16;; ldf.fill f61=[sp],16;; ldf.fill f60=[sp],16;;
+ ldf.fill f59=[sp],16;; ldf.fill f58=[sp],16;; ldf.fill f57=[sp],16;; ldf.fill f56=[sp],16;;
+ ldf.fill f55=[sp],16;; ldf.fill f54=[sp],16;; ldf.fill f53=[sp],16;; ldf.fill f52=[sp],16;;
+ ldf.fill f51=[sp],16;; ldf.fill f50=[sp],16;; ldf.fill f49=[sp],16;; ldf.fill f48=[sp],16;;
+ ldf.fill f47=[sp],16;; ldf.fill f46=[sp],16;; ldf.fill f45=[sp],16;; ldf.fill f44=[sp],16;;
+ ldf.fill f43=[sp],16;; ldf.fill f42=[sp],16;; ldf.fill f41=[sp],16;; ldf.fill f40=[sp],16;;
+ ldf.fill f39=[sp],16;; ldf.fill f38=[sp],16;; ldf.fill f37=[sp],16;; ldf.fill f36=[sp],16;;
+ ldf.fill f35=[sp],16;; ldf.fill f34=[sp],16;; ldf.fill f33=[sp],16;; ldf.fill f32=[sp],16;;
+ ldf.fill f31=[sp],16;; ldf.fill f30=[sp],16;; ldf.fill f29=[sp],16;; ldf.fill f28=[sp],16;;
+ ldf.fill f27=[sp],16;; ldf.fill f26=[sp],16;; ldf.fill f25=[sp],16;; ldf.fill f24=[sp],16;;
+ ldf.fill f23=[sp],16;; ldf.fill f22=[sp],16;; ldf.fill f21=[sp],16;; ldf.fill f20=[sp],16;;
+ ldf.fill f19=[sp],16;; ldf.fill f18=[sp],16;; ldf.fill f17=[sp],16;; ldf.fill f16=[sp],16;;
+ ldf.fill f15=[sp],16;; ldf.fill f14=[sp],16;; ldf.fill f13=[sp],16;; ldf.fill f12=[sp],16;;
+ ldf.fill f11=[sp],16;; ldf.fill f10=[sp],16;; ldf.fill f9=[sp],16;; ldf.fill f8=[sp],16;;
+ ldf.fill f7=[sp],16;; ldf.fill f6=[sp],16;; ldf.fill f5=[sp],16;; ldf.fill f4=[sp],16;;
+ ldf.fill f3=[sp],16;; ldf.fill f2=[sp],16;;
+ invala;;
+ br b7;;
+
+//-----------------------------------------------------------------------------
+//++
+// EsalSetSalDataArea
+//
+// Register physical address of Esal Data Area
+//
+// On Entry :
+// in0 = Reverse Thunk Address
+// in1 = IntThunk Address
+//
+// Return Value:
+// r8 = SAL_SUCCESS
+//
+// As per static calling conventions.
+//
+//--
+//---------------------------------------------------------------------------
+
+PROCEDURE_ENTRY (EsalSetSalDataArea)
+
+ NESTED_SETUP (4,8,0,0)
+
+EsalCalcStart1_3::
+ mov r8 = ip;;
+ add r8 = (ReverseThunkAddress - EsalCalcStart1_3), r8;;
+ st8 [r8] = in0;;
+
+EsalCalcStart1_4::
+ mov r8 = ip;;
+ add r8 = (IntThunkAddress - EsalCalcStart1_4), r8;;
+ st8 [r8] = in1;;
+
+ mov r8 = r0;;
+
+ NESTED_RETURN
+
+PROCEDURE_EXIT (EsalSetSalDataArea)
+
+//-----------------------------------------------------------------------------
+//++
+// EsagGetReverseThunkAddress
+//
+// Register physical address of Esal Data Area
+//
+// On Entry :
+// out0 = CodeStart
+// out1 = CodeEnd
+// out1 = ReverseThunkCode
+//
+// Return Value:
+// r8 = SAL_SUCCESS
+//
+// As per static calling conventions.
+//
+//--
+//---------------------------------------------------------------------------
+
+PROCEDURE_ENTRY (EsalGetReverseThunkAddress)
+
+ NESTED_SETUP (4,8,0,0)
+
+EsalCalcStart1_31::
+ mov r8 = ip;;
+ add r8 = (Ia32CodeStart - EsalCalcStart1_31), r8;;
+ mov r9 = r8;;
+
+EsalCalcStart1_41::
+ mov r8 = ip;;
+ add r8 = (Ia32CodeEnd - EsalCalcStart1_41), r8;;
+ mov r10 = r8;;
+
+EsalCalcStart1_51::
+ mov r8 = ip;;
+ add r8 = (ReverseThunkAddress - EsalCalcStart1_51), r8;;
+ mov r11 = r8;;
+ mov r8 = r0;;
+
+ NESTED_RETURN
+
+PROCEDURE_EXIT (EsalGetReverseThunkAddress)
+
+
+.align 16
+PROCEDURE_ENTRY (InterruptRedirectionTemplate)
+ data8 0x90CFCD08
+ data8 0x90CFCD09
+ data8 0x90CFCD0A
+ data8 0x90CFCD0B
+ data8 0x90CFCD0C
+ data8 0x90CFCD0D
+ data8 0x90CFCD0E
+ data8 0x90CFCD0F
+PROCEDURE_EXIT (InterruptRedirectionTemplate)
+
+//------------------------------//
+// Reverse Thunk Code //
+//------------------------------//
+
+Ia32CodeStart::
+ br.sptk.few Ia32CodeStart;; // IPF CSM integration -Bug (Write This Code)
+ReverseThunkCode::
+ data8 0xb80f66fa // CLI, JMPE xxxx
+ReverseThunkAddress::
+ data8 0 // Return Address
+IntThunkAddress::
+ data8 0 // IntThunk Address
+Ia32CodeEnd::
+
+
+
+
--- /dev/null
+/** @file\r
+ Call into 16-bit BIOS code\r
+\r
+ BugBug: Thunker does A20 gate. Can we get rid of this code or\r
+ put it into Legacy16 code.\r
+\r
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+#include "IpfThunk.h"\r
+\r
+/**\r
+ Gets the current flat GDT and IDT descriptors and store them in\r
+ Private->IntThunk. These values are used by the Thunk code.\r
+ This method must be called before every thunk in order to assure\r
+ that the correct GDT and IDT are restored after the thunk.\r
+\r
+ @param Private Private context for Legacy BIOS\r
+\r
+ @retval EFI_SUCCESS Should only pass.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosGetFlatDescs (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ BIOS interrupt call function.\r
+\r
+ @param BiosInt Int number of BIOS call\r
+ @param Segment Segment number\r
+ @param Offset Offset in segment\r
+ @param Regs IA32 Register set.\r
+ @param Stack Base address of stack\r
+ @param StackSize Size of stack\r
+\r
+ @retval EFI_SUCCESS BIOS interrupt call succeeds.\r
+\r
+**/\r
+EFI_STATUS\r
+BiosIntCall (\r
+ IN UINT16 BiosInt,\r
+ IN UINT16 Segment,\r
+ IN UINT16 Offset,\r
+ IN EFI_IA32_REGISTER_SET *Regs,\r
+ IN VOID *Stack,\r
+ IN UINTN StackSize\r
+ )\r
+{\r
+ IPF_DWORD_REGS DwordRegs;\r
+ UINT64 IntTypeVariable;\r
+\r
+ IntTypeVariable = 0x8000000000000000;\r
+ IntTypeVariable |= BiosInt;\r
+\r
+ DwordRegs.Cs = Segment;\r
+ DwordRegs.Eip = Offset;\r
+\r
+ DwordRegs.Ds = Regs->X.DS;\r
+ DwordRegs.Es = Regs->X.ES;\r
+ DwordRegs.Fs = Regs->X.ES;\r
+ DwordRegs.Gs = Regs->X.ES;\r
+ DwordRegs.Ss = 0xFFFF;\r
+\r
+ DwordRegs.Eax = Regs->X.AX;\r
+ DwordRegs.Ebx = Regs->X.BX;\r
+ //\r
+ // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, AX = B10Dh is\r
+ // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to write.\r
+ //\r
+ DwordRegs.Ecx = Regs->E.ECX;\r
+ DwordRegs.Edx = Regs->X.DX;\r
+\r
+ DwordRegs.Ebp = Regs->X.BP;\r
+ DwordRegs.Eflag = *((UINT16 *) &Regs->X.Flags);\r
+\r
+ DwordRegs.Edi = Regs->X.DI;\r
+ DwordRegs.Esi = Regs->X.SI;\r
+ DwordRegs.Esp = 0xFFFFFFFF;\r
+\r
+ EfiIaEntryPoint (IntTypeVariable, &DwordRegs, ((UINTN) Stack + StackSize), StackSize);\r
+\r
+ Regs->X.CS = DwordRegs.Cs;\r
+\r
+ Regs->X.DS = (UINT16) DwordRegs.Ds;\r
+ Regs->X.SS = (UINT16) DwordRegs.Ss;\r
+\r
+ Regs->E.EAX = DwordRegs.Eax;\r
+ Regs->E.EBX = DwordRegs.Ebx;\r
+ Regs->E.ECX = DwordRegs.Ecx;\r
+ Regs->E.EDX = DwordRegs.Edx;\r
+\r
+ Regs->E.EBP = DwordRegs.Ebp;\r
+ CopyMem (&Regs->X.Flags, &DwordRegs.Eflag, sizeof (EFI_FLAGS_REG));\r
+\r
+ Regs->E.EDI = DwordRegs.Edi;\r
+ Regs->E.ESI = DwordRegs.Esi;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Template of real mode code.\r
+\r
+ @param CodeStart Start address of code.\r
+ @param CodeEnd End address of code\r
+ @param ReverseThunkStart Start of reverse thunk.\r
+ @param IntThunk Low memory thunk.\r
+\r
+**/\r
+VOID\r
+RealModeTemplate (\r
+ OUT UINTN *CodeStart,\r
+ OUT UINTN *CodeEnd,\r
+ OUT UINTN *ReverseThunkStart,\r
+ LOW_MEMORY_THUNK *IntThunk\r
+ )\r
+{\r
+ SAL_RETURN_REGS SalStatus;\r
+\r
+ SalStatus = EsalGetReverseThunkAddress ();\r
+\r
+ *CodeStart = SalStatus.r9;\r
+ *CodeEnd = SalStatus.r10;\r
+ *ReverseThunkStart = SalStatus.r11;\r
+\r
+}\r
+\r
+\r
+/**\r
+ Allocate memory < 1 MB and copy the thunker code into low memory. Se up\r
+ all the descriptors.\r
+\r
+ @param Private Private context for Legacy BIOS\r
+\r
+ @retval EFI_SUCCESS Should only pass.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosInitializeThunk (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ GDT32 *CodeGdt;\r
+ GDT32 *DataGdt;\r
+ UINTN CodeStart;\r
+ UINTN CodeEnd;\r
+ UINTN ReverseThunkStart;\r
+ UINT32 Base;\r
+ LOW_MEMORY_THUNK *IntThunk;\r
+ UINTN TempData;\r
+\r
+ ASSERT (Private);\r
+\r
+ IntThunk = Private->IntThunk;\r
+\r
+ //\r
+ // Clear the reserved descriptor\r
+ //\r
+ ZeroMem (&(IntThunk->RealModeGdt[0]), sizeof (GDT32));\r
+\r
+ //\r
+ // Setup a descriptor for real-mode code\r
+ //\r
+ CodeGdt = &(IntThunk->RealModeGdt[1]);\r
+\r
+ //\r
+ // Fill in the descriptor with our real-mode segment value\r
+ //\r
+ CodeGdt->Type = 0xA;\r
+ //\r
+ // code/read\r
+ //\r
+ CodeGdt->System = 1;\r
+ CodeGdt->Dpl = 0;\r
+ CodeGdt->Present = 1;\r
+ CodeGdt->Software = 0;\r
+ CodeGdt->Reserved = 0;\r
+ CodeGdt->DefaultSize = 0;\r
+ //\r
+ // 16 bit operands\r
+ //\r
+ CodeGdt->Granularity = 0;\r
+\r
+ CodeGdt->LimitHi = 0;\r
+ CodeGdt->LimitLo = 0xffff;\r
+\r
+ Base = (*((UINT32 *) &IntThunk->Code));\r
+ CodeGdt->BaseHi = (Base >> 24) & 0xFF;\r
+ CodeGdt->BaseMid = (Base >> 16) & 0xFF;\r
+ CodeGdt->BaseLo = Base & 0xFFFF;\r
+\r
+ //\r
+ // Setup a descriptor for read-mode data\r
+ //\r
+ DataGdt = &(IntThunk->RealModeGdt[2]);\r
+ CopyMem (DataGdt, CodeGdt, sizeof (GDT32));\r
+\r
+ DataGdt->Type = 0x2;\r
+ //\r
+ // read/write data\r
+ //\r
+ DataGdt->BaseHi = 0x0;\r
+ //\r
+ // Base = 0\r
+ //\r
+ DataGdt->BaseMid = 0x0;\r
+ //\r
+ DataGdt->BaseLo = 0x0;\r
+ //\r
+ DataGdt->LimitHi = 0x0F;\r
+ //\r
+ // Limit = 4Gb\r
+ //\r
+ DataGdt->LimitLo = 0xFFFF;\r
+ //\r
+ DataGdt->Granularity = 0x1;\r
+ //\r
+ //\r
+ // Compute selector value\r
+ //\r
+ IntThunk->RealModeGdtDesc.Limit = (UINT16) (sizeof (IntThunk->RealModeGdt) - 1);\r
+ CopyMem (&IntThunk->RealModeGdtDesc.Base, (UINT32 *) &IntThunk->RealModeGdt, sizeof (UINT32));\r
+ //\r
+ // IntThunk->RealModeGdtDesc.Base = *((UINT32*) &IntThunk->RealModeGdt);\r
+ //\r
+ IntThunk->RealModeIdtDesc.Limit = 0xFFFF;\r
+ IntThunk->RealModeIdtDesc.Base = 0;\r
+ IntThunk->LowCodeSelector = (UINT32) ((UINTN) CodeGdt - IntThunk->RealModeGdtDesc.Base);\r
+ IntThunk->LowDataSelector = (UINT32) ((UINTN) DataGdt - IntThunk->RealModeGdtDesc.Base);\r
+\r
+ //\r
+ // Initialize low real-mode code thunk\r
+ //\r
+ RealModeTemplate (&CodeStart, &CodeEnd, &ReverseThunkStart, IntThunk);\r
+\r
+ TempData = (UINTN) &(IntThunk->Code);\r
+ IntThunk->LowReverseThunkStart = ((UINT32) TempData + (UINT32) (ReverseThunkStart - CodeStart));\r
+\r
+ EsalSetSalDataArea (TempData, (UINTN) IntThunk);\r
+ CopyMem (IntThunk->Code, (VOID *) CodeStart, CodeEnd - CodeStart);\r
+\r
+ IntThunk->EfiToLegacy16InitTable.ReverseThunkCallSegment = EFI_SEGMENT (*((UINT32 *) &IntThunk->LowReverseThunkStart));\r
+ IntThunk->EfiToLegacy16InitTable.ReverseThunkCallOffset = EFI_OFFSET (*((UINT32 *) &IntThunk->LowReverseThunkStart));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Thunk to 16-bit real mode and execute a software interrupt with a vector\r
+ of BiosInt. Regs will contain the 16-bit register context on entry and\r
+ exit.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BiosInt Processor interrupt vector to invoke\r
+ @param Regs Register contexted passed into (and returned) from\r
+ thunk to 16-bit mode\r
+\r
+ @retval FALSE Thunk completed, and there were no BIOS errors in the\r
+ target code. See Regs for status.\r
+ @retval TRUE There was a BIOS erro in the target code.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosInt86 (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT8 BiosInt,\r
+ IN EFI_IA32_REGISTER_SET *Regs\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ LOW_MEMORY_THUNK *IntThunk;\r
+ UINT16 *Stack16;\r
+ EFI_TPL OriginalTpl;\r
+ UINTN IaSegment;\r
+ UINTN IaOffset;\r
+ UINTN *Address;\r
+ UINTN TempData;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ IntThunk = Private->IntThunk;\r
+\r
+ //\r
+ // Get the current flat GDT, IDT, and SS and store them in Private->IntThunk.\r
+ //\r
+ Status = LegacyBiosGetFlatDescs (Private);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Regs->X.Flags.Reserved1 = 1;\r
+ Regs->X.Flags.Reserved2 = 0;\r
+ Regs->X.Flags.Reserved3 = 0;\r
+ Regs->X.Flags.Reserved4 = 0;\r
+ Regs->X.Flags.IOPL = 3;\r
+ Regs->X.Flags.NT = 0;\r
+ Regs->X.Flags.IF = 1;\r
+ Regs->X.Flags.TF = 0;\r
+ Regs->X.Flags.CF = 0;\r
+ //\r
+ // Clear the error flag; thunk code may set it.\r
+ //\r
+ Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE);\r
+\r
+ //\r
+ // Copy regs to low memory stack\r
+ //\r
+ Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16);\r
+ CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ //\r
+ // Provide low stack esp\r
+ //\r
+ TempData = ((UINTN) Stack16) - ((UINTN) IntThunk);\r
+ IntThunk->LowStack = *((UINT32 *) &TempData);\r
+\r
+ //\r
+ // Stack for reverse thunk flat mode.\r
+ // It must point to top of stack (end of stack space).\r
+ //\r
+ TempData = ((UINTN) IntThunk->RevThunkStack) + LOW_STACK_SIZE;\r
+ IntThunk->RevFlatStack = *((UINT32 *) &TempData);\r
+\r
+ //\r
+ // The call to Legacy16 is a critical section to EFI\r
+ //\r
+ OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ //\r
+ // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.\r
+ //\r
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Call the real mode thunk code\r
+ //\r
+ TempData = BiosInt * 4;\r
+ Address = (UINTN *) TempData;\r
+ IaOffset = 0xFFFF & (*Address);\r
+ IaSegment = 0xFFFF & ((*Address) >> 16);\r
+\r
+ Status = BiosIntCall (\r
+ BiosInt,\r
+ (UINT16) IaSegment,\r
+ (UINT16) IaOffset,\r
+ (EFI_IA32_REGISTER_SET *) Stack16,\r
+ IntThunk,\r
+ IntThunk->LowStack\r
+ );\r
+\r
+ //\r
+ // Check for errors with the thunk\r
+ //\r
+ switch (Status) {\r
+ case THUNK_OK:\r
+ break;\r
+\r
+ case THUNK_ERR_A20_UNSUP:\r
+ case THUNK_ERR_A20_FAILED:\r
+ default:\r
+ //\r
+ // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error).\r
+ //\r
+ Regs->X.Flags.CF = 1;\r
+ break;\r
+ }\r
+\r
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // End critical section\r
+ //\r
+ gBS->RestoreTPL (OriginalTpl);\r
+\r
+ //\r
+ // Return the resulting registers\r
+ //\r
+ CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ return (BOOLEAN) (Regs->X.Flags.CF != 0);\r
+}\r
+\r
+\r
+/**\r
+ Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the\r
+ 16-bit register context on entry and exit. Arguments can be passed on\r
+ the Stack argument\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Segment Segemnt of 16-bit mode call\r
+ @param Offset Offset of 16-bit mdoe call\r
+ @param Regs Register contexted passed into (and returned) from\r
+ thunk to 16-bit mode\r
+ @param Stack Caller allocated stack used to pass arguments\r
+ @param StackSize Size of Stack in bytes\r
+\r
+ @retval FALSE Thunk completed, and there were no BIOS errors in the\r
+ target code. See Regs for status.\r
+ @retval TRUE There was a BIOS erro in the target code.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosFarCall86 (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT16 Segment,\r
+ IN UINT16 Offset,\r
+ IN EFI_IA32_REGISTER_SET *Regs,\r
+ IN VOID *Stack,\r
+ IN UINTN StackSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ LOW_MEMORY_THUNK *IntThunk;\r
+ UINT16 *Stack16;\r
+ EFI_TPL OriginalTpl;\r
+ UINTN IaSegment;\r
+ UINTN IaOffset;\r
+ UINTN TempData;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ IntThunk = Private->IntThunk;\r
+ IaSegment = Segment;\r
+ IaOffset = Offset;\r
+\r
+ //\r
+ // Get the current flat GDT and IDT and store them in Private->IntThunk.\r
+ //\r
+ Status = LegacyBiosGetFlatDescs (Private);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Regs->X.Flags.Reserved1 = 1;\r
+ Regs->X.Flags.Reserved2 = 0;\r
+ Regs->X.Flags.Reserved3 = 0;\r
+ Regs->X.Flags.Reserved4 = 0;\r
+ Regs->X.Flags.IOPL = 3;\r
+ Regs->X.Flags.NT = 0;\r
+ Regs->X.Flags.IF = 1;\r
+ Regs->X.Flags.TF = 0;\r
+ Regs->X.Flags.CF = 0;\r
+ //\r
+ // Clear the error flag; thunk code may set it.\r
+ //\r
+ Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE);\r
+ if (Stack != NULL && StackSize != 0) {\r
+ //\r
+ // Copy Stack to low memory stack\r
+ //\r
+ Stack16 -= StackSize / sizeof (UINT16);\r
+ CopyMem (Stack16, Stack, StackSize);\r
+ }\r
+ //\r
+ // Copy regs to low memory stack\r
+ //\r
+ Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16);\r
+ CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ //\r
+ // Provide low stack esp\r
+ //\r
+ TempData = ((UINTN) Stack16) - ((UINTN) IntThunk);\r
+ IntThunk->LowStack = *((UINT32 *) &TempData);\r
+\r
+ //\r
+ // The call to Legacy16 is a critical section to EFI\r
+ //\r
+ OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ //\r
+ // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.\r
+ //\r
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Call the real mode thunk code\r
+ //\r
+ Status = BiosIntCall (\r
+ 0x100,\r
+ (UINT16) IaSegment,\r
+ (UINT16) IaOffset,\r
+ (EFI_IA32_REGISTER_SET *) Stack16,\r
+ IntThunk,\r
+ IntThunk->LowStack\r
+ );\r
+\r
+ //\r
+ // Check for errors with the thunk\r
+ //\r
+ switch (Status) {\r
+ case THUNK_OK:\r
+ break;\r
+\r
+ case THUNK_ERR_A20_UNSUP:\r
+ case THUNK_ERR_A20_FAILED:\r
+ default:\r
+ //\r
+ // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error).\r
+ //\r
+ Regs->X.Flags.CF = 1;\r
+ break;\r
+ }\r
+ //\r
+ // Restore protected mode interrupt state\r
+ //\r
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // End critical section\r
+ //\r
+ gBS->RestoreTPL (OriginalTpl);\r
+\r
+ //\r
+ // Return the resulting registers\r
+ //\r
+ CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET));\r
+ Stack16 += sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16);\r
+\r
+ if (Stack != NULL && StackSize != 0) {\r
+ //\r
+ // Copy low memory stack to Stack\r
+ //\r
+ CopyMem (Stack, Stack16, StackSize);\r
+ Stack16 += StackSize / sizeof (UINT16);\r
+ }\r
+\r
+ return (BOOLEAN) (Regs->X.Flags.CF != 0);\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+#include <IndustryStandard/Pci.h>\r
+\r
+// Give floppy 3 states\r
+// FLOPPY_PRESENT_WITH_MEDIA = Floppy controller present and media is inserted\r
+// FLOPPY_NOT_PRESENT = No floppy controller present\r
+// FLOPPY_PRESENT_NO_MEDIA = Floppy controller present but no media inserted\r
+//\r
+#define FLOPPY_NOT_PRESENT 0\r
+#define FLOPPY_PRESENT_WITH_MEDIA 1\r
+#define FLOPPY_PRESENT_NO_MEDIA 2\r
+\r
+BBS_TABLE *mBbsTable;\r
+BOOLEAN mBbsTableDoneFlag = FALSE;\r
+BOOLEAN IsHaveMediaInFloppy = TRUE;\r
+\r
+/**\r
+ Checks the state of the floppy and if media is inserted.\r
+ \r
+ This routine checks the state of the floppy and if media is inserted.\r
+ There are 3 cases:\r
+ No floppy present - Set BBS entry to ignore\r
+ Floppy present & no media - Set BBS entry to lowest priority. We cannot\r
+ set it to ignore since 16-bit CSM will\r
+ indicate no floppy and thus drive A: is\r
+ unusable. CSM-16 will not try floppy since\r
+ lowest priority and thus not incur boot\r
+ time penality.\r
+ Floppy present & media - Set BBS entry to some priority.\r
+\r
+ @return State of floppy media\r
+\r
+**/\r
+UINT8\r
+HasMediaInFloppy (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ EFI_ISA_IO_PROTOCOL *IsaIo;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+\r
+ HandleBuffer = NULL;\r
+ HandleCount = 0;\r
+\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiIsaIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ //\r
+ // If don't find any ISA/IO protocol assume no floppy. Need for floppy\r
+ // free system\r
+ //\r
+ if (HandleCount == 0) {\r
+ return FLOPPY_NOT_PRESENT;\r
+ }\r
+\r
+ ASSERT (HandleBuffer != NULL);\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiIsaIoProtocolGuid,\r
+ (VOID **) &IsaIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {\r
+ continue;\r
+ }\r
+ //\r
+ // Update blockio in case the floppy is inserted in during BdsTimeout\r
+ //\r
+ Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ if (BlkIo->Media->MediaPresent) {\r
+ FreePool (HandleBuffer);\r
+ return FLOPPY_PRESENT_WITH_MEDIA;\r
+ } else {\r
+ FreePool (HandleBuffer);\r
+ return FLOPPY_PRESENT_NO_MEDIA;\r
+ }\r
+ }\r
+\r
+ FreePool (HandleBuffer);\r
+\r
+ return FLOPPY_NOT_PRESENT;\r
+\r
+}\r
+\r
+\r
+/**\r
+ Complete build of BBS TABLE.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param BbsTable BBS Table passed to 16-bit code\r
+\r
+ @retval EFI_SUCCESS Removable media not present\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildBbs (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN BBS_TABLE *BbsTable\r
+ )\r
+{\r
+ UINTN BbsIndex;\r
+ HDD_INFO *HddInfo;\r
+ UINTN HddIndex;\r
+ UINTN Index;\r
+\r
+ //\r
+ // First entry is floppy.\r
+ // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE.\r
+ // Next n entries are filled in after each ROM is dispatched.\r
+ // Entry filled in if follow BBS spec. See LegacyPci.c\r
+ // Next entries are for non-BBS compliant ROMS. They are filled in by\r
+ // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority\r
+ // occurs after that invocation.\r
+ //\r
+ // Floppy\r
+ // Set default state.\r
+ //\r
+ IsHaveMediaInFloppy = HasMediaInFloppy ();\r
+ if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) {\r
+ BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+ } else {\r
+ if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) {\r
+ BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY;\r
+ } else {\r
+ BbsTable[0].BootPriority = BBS_IGNORE_ENTRY;\r
+ }\r
+ }\r
+\r
+ BbsTable[0].Bus = 0xff;\r
+ BbsTable[0].Device = 0xff;\r
+ BbsTable[0].Function = 0xff;\r
+ BbsTable[0].DeviceType = BBS_FLOPPY;\r
+ BbsTable[0].Class = 01;\r
+ BbsTable[0].SubClass = 02;\r
+ BbsTable[0].StatusFlags.OldPosition = 0;\r
+ BbsTable[0].StatusFlags.Reserved1 = 0;\r
+ BbsTable[0].StatusFlags.Enabled = 0;\r
+ BbsTable[0].StatusFlags.Failed = 0;\r
+ BbsTable[0].StatusFlags.MediaPresent = 0;\r
+ BbsTable[0].StatusFlags.Reserved2 = 0;\r
+\r
+ //\r
+ // Onboard HDD - Note Each HDD controller controls 2 drives\r
+ // Master & Slave\r
+ //\r
+ HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];\r
+ //\r
+ // Get IDE Drive Info\r
+ //\r
+ LegacyBiosBuildIdeData (Private, &HddInfo, 0);\r
+\r
+ for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) {\r
+\r
+ BbsIndex = HddIndex * 2 + 1;\r
+ for (Index = 0; Index < 2; ++Index) {\r
+\r
+ BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus;\r
+ BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device;\r
+ BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function;\r
+ BbsTable[BbsIndex + Index].Class = 01;\r
+ BbsTable[BbsIndex + Index].SubClass = 01;\r
+ BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0;\r
+ BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0;\r
+ BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0;\r
+ BbsTable[BbsIndex + Index].StatusFlags.Failed = 0;\r
+ BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0;\r
+ BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0;\r
+\r
+ //\r
+ // If no controller found or no device found set to ignore\r
+ // else set to unprioritized and set device type\r
+ //\r
+ if (HddInfo[HddIndex].CommandBaseAddress == 0) {\r
+ BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;\r
+ } else {\r
+ if (Index == 0) {\r
+ if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) {\r
+ BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+ if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) {\r
+ BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;\r
+ } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) {\r
+ BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;\r
+ } else {\r
+ //\r
+ // for ZIPDISK\r
+ //\r
+ BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;\r
+ }\r
+ } else {\r
+ BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;\r
+ }\r
+ } else {\r
+ if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) {\r
+ BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+ if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) {\r
+ BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;\r
+ } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) {\r
+ BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;\r
+ } else {\r
+ //\r
+ // for ZIPDISK\r
+ //\r
+ BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;\r
+ }\r
+ } else {\r
+ BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+ Get all BBS info\r
+\r
+ @param This Protocol instance pointer.\r
+ @param HddCount Number of HDD_INFO structures\r
+ @param HddInfo Onboard IDE controller information\r
+ @param BbsCount Number of BBS_TABLE structures\r
+ @param BbsTable List BBS entries\r
+\r
+ @retval EFI_SUCCESS Tables returned\r
+ @retval EFI_NOT_FOUND resource not found\r
+ @retval EFI_DEVICE_ERROR can not get BBS table\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosGetBbsInfo (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ OUT UINT16 *HddCount,\r
+ OUT HDD_INFO **HddInfo,\r
+ OUT UINT16 *BbsCount,\r
+ OUT BBS_TABLE **BbsTable\r
+ )\r
+{\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
+// HDD_INFO *LocalHddInfo;\r
+// IN BBS_TABLE *LocalBbsTable;\r
+ UINTN NumHandles;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ UINTN TempData;\r
+ UINT32 Granularity;\r
+\r
+ HandleBuffer = NULL;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
+// LocalHddInfo = EfiToLegacy16BootTable->HddInfo;\r
+// LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;\r
+\r
+ if (!mBbsTableDoneFlag) {\r
+ mBbsTable = Private->BbsTablePtr;\r
+\r
+ //\r
+ // Always enable disk controllers so 16-bit CSM code has valid information for all\r
+ // drives.\r
+ //\r
+ //\r
+ // Get PciRootBridgeIO protocol\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ NULL,\r
+ &NumHandles,\r
+ &HandleBuffer\r
+ );\r
+\r
+ if (NumHandles == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ mBbsTableDoneFlag = TRUE;\r
+ for (Index = 0; Index < NumHandles; Index++) {\r
+ //\r
+ // Connect PciRootBridgeIO protocol handle with FALSE parameter to let\r
+ // PCI bus driver enumerate all subsequent handles\r
+ //\r
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);\r
+\r
+ }\r
+\r
+ LegacyBiosBuildBbs (Private, mBbsTable);\r
+\r
+ Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);\r
+\r
+ //\r
+ // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs.\r
+ //\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16UpdateBbs;\r
+\r
+ //\r
+ // Pass in handoff data\r
+ //\r
+ TempData = (UINTN) EfiToLegacy16BootTable;\r
+ Regs.X.ES = EFI_SEGMENT ((UINT32) TempData);\r
+ Regs.X.BX = EFI_OFFSET ((UINT32) TempData);\r
+\r
+ Private->LegacyBios.FarCall86 (\r
+ This,\r
+ Private->Legacy16CallSegment,\r
+ Private->Legacy16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);\r
+ Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);\r
+\r
+ if (Regs.X.AX != 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ *HddCount = MAX_IDE_CONTROLLER;\r
+ *HddInfo = EfiToLegacy16BootTable->HddInfo;\r
+ *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;\r
+ *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ This code fills in BDA (0x400) and EBDA (pointed to by 0x4xx)\r
+ information. There is support for doing initializeation before\r
+ Legacy16 is loaded and before a legacy boot is attempted.\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+\r
+/**\r
+ Fill in the standard BDA and EBDA stuff before Legacy16 load\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosInitBda (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ BDA_STRUC *Bda;\r
+ UINT8 *Ebda;\r
+\r
+ Bda = (BDA_STRUC *) ((UINTN) 0x400);\r
+ Ebda = (UINT8 *) ((UINTN) 0x9fc00);\r
+\r
+ ZeroMem (Bda, 0x100);\r
+ ZeroMem (Ebda, 0x400);\r
+ //\r
+ // 640k-1k for EBDA\r
+ //\r
+ Bda->MemSize = 0x27f;\r
+ Bda->KeyHead = 0x1e;\r
+ Bda->KeyTail = 0x1e;\r
+ Bda->FloppyData = 0x00;\r
+ Bda->FloppyTimeout = 0xff;\r
+\r
+ Bda->KeyStart = 0x001E;\r
+ Bda->KeyEnd = 0x003E;\r
+ Bda->KeyboardStatus = 0x10;\r
+ Bda->Ebda = 0x9fc0;\r
+\r
+ //\r
+ // Move LPT time out here and zero out LPT4 since some SCSI OPROMS\r
+ // use this as scratch pad (LPT4 is Reserved)\r
+ //\r
+ Bda->Lpt1_2Timeout = 0x1414;\r
+ Bda->Lpt3_4Timeout = 0x1400;\r
+\r
+ *Ebda = 0x01;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+\r
+#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address))\r
+\r
+//\r
+// define maximum number of HDD system supports\r
+//\r
+#define MAX_HDD_ENTRIES 0x30\r
+\r
+//\r
+// Module Global:\r
+// Since this driver will only ever produce one instance of the Private Data\r
+// protocol you are not required to dynamically allocate the PrivateData.\r
+//\r
+LEGACY_BIOS_INSTANCE mPrivateData;\r
+\r
+//\r
+// The end of OPROM shadow address\r
+//\r
+UINTN mEndOpromShadowAddress = 0;\r
+\r
+/**\r
+ Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode\r
+ memory.\r
+\r
+ @param AllocateType Allocated Legacy Memory Type\r
+ @param StartPageAddress Start address of range\r
+ @param Pages Number of pages to allocate\r
+ @param Result Result of allocation\r
+\r
+ @retval EFI_SUCCESS Legacy16 code loaded\r
+ @retval Other No protocol installed, unload driver.\r
+\r
+**/\r
+EFI_STATUS\r
+AllocateLegacyMemory (\r
+ IN EFI_ALLOCATE_TYPE AllocateType,\r
+ IN EFI_PHYSICAL_ADDRESS StartPageAddress,\r
+ IN UINTN Pages,\r
+ OUT EFI_PHYSICAL_ADDRESS *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS MemPage;\r
+\r
+ //\r
+ // Allocate Pages of memory less <= StartPageAddress\r
+ //\r
+ MemPage = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPageAddress;\r
+ Status = gBS->AllocatePages (\r
+ AllocateType,\r
+ EfiBootServicesCode,\r
+ Pages,\r
+ &MemPage\r
+ );\r
+ //\r
+ // Do not ASSERT on Status error but let caller decide since some cases\r
+ // memory is already taken but that is ok.\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ *Result = (EFI_PHYSICAL_ADDRESS) (UINTN) MemPage;\r
+ }\r
+ //\r
+ // If reach here the status = EFI_SUCCESS\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function is called when EFI needs to reserve an area in the 0xE0000 or 0xF0000\r
+ 64 KB blocks.\r
+\r
+ Note: inconsistency with the Framework CSM spec. Per the spec, this function may be\r
+ invoked only once. This limitation is relaxed to allow multiple calls in this implemenation.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param LegacyMemorySize Size of required region\r
+ @param Region Region to use. 00 = Either 0xE0000 or 0xF0000\r
+ block Bit0 = 1 0xF0000 block Bit1 = 1 0xE0000\r
+ block\r
+ @param Alignment Address alignment. Bit mapped. First non-zero\r
+ bit from right is alignment.\r
+ @param LegacyMemoryAddress Region Assigned\r
+\r
+ @retval EFI_SUCCESS Region assigned\r
+ @retval EFI_ACCESS_DENIED Procedure previously invoked\r
+ @retval Other Region not assigned\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosGetLegacyRegion (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINTN LegacyMemorySize,\r
+ IN UINTN Region,\r
+ IN UINTN Alignment,\r
+ OUT VOID **LegacyMemoryAddress\r
+ )\r
+{\r
+\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ EFI_STATUS Status;\r
+ UINT32 Granularity;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity);\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16GetTableAddress;\r
+ Regs.X.BX = (UINT16) Region;\r
+ Regs.X.CX = (UINT16) LegacyMemorySize;\r
+ Regs.X.DX = (UINT16) Alignment;\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Private->Legacy16CallSegment,\r
+ Private->Legacy16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ if (Regs.X.AX == 0) {\r
+ *LegacyMemoryAddress = (VOID *) (UINTN) ((Regs.X.DS << 4) + Regs.X.BX);\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);\r
+ Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function is called when copying data to the region assigned by\r
+ EFI_LEGACY_BIOS_PROTOCOL.GetLegacyRegion().\r
+\r
+ @param This Protocol instance pointer.\r
+ @param LegacyMemorySize Size of data to copy\r
+ @param LegacyMemoryAddress Legacy Region destination address Note: must\r
+ be in region assigned by\r
+ LegacyBiosGetLegacyRegion\r
+ @param LegacyMemorySourceAddress Source of data\r
+\r
+ @retval EFI_SUCCESS The data was copied successfully.\r
+ @retval EFI_ACCESS_DENIED Either the starting or ending address is out of bounds.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosCopyLegacyRegion (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINTN LegacyMemorySize,\r
+ IN VOID *LegacyMemoryAddress,\r
+ IN VOID *LegacyMemorySourceAddress\r
+ )\r
+{\r
+\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ UINT32 Granularity;\r
+\r
+ if ((LegacyMemoryAddress < (VOID *)(UINTN)0xE0000 ) ||\r
+ ((UINTN) LegacyMemoryAddress + LegacyMemorySize > (UINTN) 0x100000)\r
+ ) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ //\r
+ // There is no protection from writes over lapping if this function is\r
+ // called multiple times.\r
+ //\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity);\r
+ CopyMem (LegacyMemoryAddress, LegacyMemorySourceAddress, LegacyMemorySize);\r
+\r
+ Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);\r
+ Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Find Legacy16 BIOS image in the FLASH device and shadow it into memory. Find\r
+ the $EFI table in the shadow area. Thunk into the Legacy16 code after it had\r
+ been shadowed.\r
+\r
+ @param Private Legacy BIOS context data\r
+\r
+ @retval EFI_SUCCESS Legacy16 code loaded\r
+ @retval Other No protocol installed, unload driver.\r
+\r
+**/\r
+EFI_STATUS\r
+ShadowAndStartLegacy16 (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *Ptr;\r
+ UINT8 *PtrEnd;\r
+ BOOLEAN Done;\r
+ EFI_COMPATIBILITY16_TABLE *Table;\r
+ UINT8 CheckSum;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable;\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
+ VOID *LegacyBiosImage;\r
+ UINTN LegacyBiosImageSize;\r
+ UINTN E820Size;\r
+ UINT32 *ClearPtr;\r
+ BBS_TABLE *BbsTable;\r
+ LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable;\r
+ UINTN Index;\r
+ UINT32 TpmPointer;\r
+ VOID *TpmBinaryImage;\r
+ UINTN TpmBinaryImageSize;\r
+ UINTN Location;\r
+ UINTN Alignment;\r
+ UINTN TempData;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+ UINT16 OldMask;\r
+ UINT16 NewMask;\r
+ UINT32 Granularity;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
+\r
+ Location = 0;\r
+ Alignment = 0;\r
+\r
+ //\r
+ // we allocate the C/D/E/F segment as RT code so no one will use it any more.\r
+ //\r
+ Address = 0xC0000;\r
+ gDS->GetMemorySpaceDescriptor (Address, &Descriptor);\r
+ if (Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
+ //\r
+ // If it is already reserved, we should be safe, or else we allocate it.\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateAddress,\r
+ EfiRuntimeServicesCode,\r
+ 0x40000/EFI_PAGE_SIZE,\r
+ &Address\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Bugbug: need to figure out whether C/D/E/F segment should be marked as reserved memory.\r
+ // \r
+ DEBUG ((DEBUG_ERROR, "Failed to allocate the C/D/E/F segment Status = %r", Status));\r
+ }\r
+ }\r
+\r
+ //\r
+ // start testtest\r
+ // GetTimerValue (&Ticker);\r
+ //\r
+ // gRT->SetVariable (L"StartLegacy",\r
+ // &gEfiGlobalVariableGuid,\r
+ // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ // sizeof (UINT64),\r
+ // (VOID *)&Ticker\r
+ // );\r
+ // end testtest\r
+ //\r
+ EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
+ Status = Private->LegacyBiosPlatform->GetPlatformInfo (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformBinarySystemRom,\r
+ &LegacyBiosImage,\r
+ &LegacyBiosImageSize,\r
+ &Location,\r
+ &Alignment,\r
+ 0,\r
+ 0\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Private->BiosStart = (UINT32) (0x100000 - LegacyBiosImageSize);\r
+ Private->OptionRom = 0xc0000;\r
+ Private->LegacyBiosImageSize = (UINT32) LegacyBiosImageSize;\r
+\r
+ //\r
+ // Can only shadow into memory allocated for legacy useage.\r
+ //\r
+ ASSERT (Private->BiosStart > Private->OptionRom);\r
+\r
+ //\r
+ // Shadow Legacy BIOS. Turn on memory and copy image\r
+ //\r
+ Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity);\r
+\r
+ ClearPtr = (VOID *) ((UINTN) 0xc0000);\r
+\r
+ //\r
+ // Initialize region from 0xc0000 to start of BIOS to all ffs. This allows unused\r
+ // regions to be used by EMM386 etc.\r
+ //\r
+ SetMem ((VOID *) ClearPtr, (UINTN) (0x40000 - LegacyBiosImageSize), 0xff);\r
+\r
+ TempData = Private->BiosStart;\r
+\r
+ CopyMem (\r
+ (VOID *) TempData,\r
+ LegacyBiosImage,\r
+ (UINTN) LegacyBiosImageSize\r
+ );\r
+\r
+ Private->Cpu->FlushDataCache (Private->Cpu, 0xc0000, 0x40000, EfiCpuFlushTypeWriteBackInvalidate);\r
+\r
+ //\r
+ // Search for Legacy16 table in Shadowed ROM\r
+ //\r
+ Done = FALSE;\r
+ Table = NULL;\r
+ for (Ptr = (UINT8 *) TempData; Ptr < (UINT8 *) ((UINTN) 0x100000) && !Done; Ptr += 0x10) {\r
+ if (*(UINT32 *) Ptr == SIGNATURE_32 ('I', 'F', 'E', '$')) {\r
+ Table = (EFI_COMPATIBILITY16_TABLE *) Ptr;\r
+ PtrEnd = Ptr + Table->TableLength;\r
+ for (CheckSum = 0; Ptr < PtrEnd; Ptr++) {\r
+ CheckSum = (UINT8) (CheckSum +*Ptr);\r
+ }\r
+\r
+ Done = TRUE;\r
+ }\r
+ }\r
+\r
+ if (Table == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "No Legacy16 table found\n"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (!Done) {\r
+ //\r
+ // Legacy16 table header checksum error.\r
+ //\r
+ DEBUG ((EFI_D_ERROR, "Legacy16 table found with bad talbe header checksum\n"));\r
+ }\r
+\r
+ //\r
+ // Remember location of the Legacy16 table\r
+ //\r
+ Private->Legacy16Table = Table;\r
+ Private->Legacy16CallSegment = Table->Compatibility16CallSegment;\r
+ Private->Legacy16CallOffset = Table->Compatibility16CallOffset;\r
+ EfiToLegacy16InitTable = &Private->IntThunk->EfiToLegacy16InitTable;\r
+ Private->Legacy16InitPtr = EfiToLegacy16InitTable;\r
+ Private->Legacy16BootPtr = &Private->IntThunk->EfiToLegacy16BootTable;\r
+ Private->InternalIrqRoutingTable = NULL;\r
+ Private->NumberIrqRoutingEntries = 0;\r
+ Private->BbsTablePtr = NULL;\r
+ Private->LegacyEfiHddTable = NULL;\r
+ Private->DiskEnd = 0;\r
+ Private->Disk4075 = 0;\r
+ Private->HddTablePtr = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo;\r
+ Private->NumberHddControllers = MAX_IDE_CONTROLLER;\r
+ Private->Dump[0] = 'D';\r
+ Private->Dump[1] = 'U';\r
+ Private->Dump[2] = 'M';\r
+ Private->Dump[3] = 'P';\r
+\r
+ ZeroMem (\r
+ Private->Legacy16BootPtr,\r
+ sizeof (EFI_TO_COMPATIBILITY16_BOOT_TABLE)\r
+ );\r
+\r
+ //\r
+ // Store away a copy of the EFI System Table\r
+ //\r
+ Table->EfiSystemTable = (UINT32) (UINTN) gST;\r
+\r
+ //\r
+ // Get the end of OPROM shadow address\r
+ //\r
+ Status = Private->LegacyBiosPlatform->GetPlatformInfo (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformEndOpromShadowAddr,\r
+ NULL,\r
+ NULL,\r
+ &mEndOpromShadowAddress,\r
+ NULL,\r
+ 0,\r
+ 0\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ mEndOpromShadowAddress = 0xDFFFF;\r
+ }\r
+\r
+ //\r
+ // IPF CSM integration -Bug\r
+ //\r
+ // Construct the Legacy16 boot memory map. This sets up number of\r
+ // E820 entries.\r
+ //\r
+ LegacyBiosBuildE820 (Private, &E820Size);\r
+ //\r
+ // Initialize BDA and EBDA standard values needed to load Legacy16 code\r
+ //\r
+ LegacyBiosInitBda (Private);\r
+ LegacyBiosInitCmos (Private);\r
+\r
+ //\r
+ // All legacy interrupt should be masked when do initialization work from legacy 16 code.\r
+ //\r
+ Private->Legacy8259->GetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL);\r
+ NewMask = 0xFFFF;\r
+ Private->Legacy8259->SetMask(Private->Legacy8259, &NewMask, NULL, NULL, NULL);\r
+ \r
+ //\r
+ // Call into Legacy16 code to do an INIT\r
+ //\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16InitializeYourself;\r
+ Regs.X.ES = EFI_SEGMENT (*((UINT32 *) &EfiToLegacy16InitTable));\r
+ Regs.X.BX = EFI_OFFSET (*((UINT32 *) &EfiToLegacy16InitTable));\r
+\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Table->Compatibility16CallSegment,\r
+ Table->Compatibility16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ //\r
+ // Restore original legacy interrupt mask value\r
+ //\r
+ Private->Legacy8259->SetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL);\r
+ \r
+ if (Regs.X.AX != 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // start testtest\r
+ // GetTimerValue (&Ticker);\r
+ //\r
+ // gRT->SetVariable (L"BackFromInitYourself",\r
+ // &gEfiGlobalVariableGuid,\r
+ // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ // sizeof (UINT64),\r
+ // (VOID *)&Ticker\r
+ // );\r
+ // end testtest\r
+ //\r
+ // Copy E820 table after InitializeYourself is completed\r
+ //\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16GetTableAddress;\r
+ Regs.X.CX = (UINT16) E820Size;\r
+ Regs.X.DX = 1;\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Table->Compatibility16CallSegment,\r
+ Table->Compatibility16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
+ Table->E820Length = (UINT32) E820Size;\r
+ if (Regs.X.AX != 0) {\r
+ DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n"));\r
+ } else {\r
+ TempData = Table->E820Pointer;\r
+ CopyMem ((VOID *) TempData, Private->E820Table, E820Size);\r
+ }\r
+ //\r
+ // Get PnPInstallationCheck Info.\r
+ //\r
+ Private->PnPInstallationCheckSegment = Table->PnPInstallationCheckSegment;\r
+ Private->PnPInstallationCheckOffset = Table->PnPInstallationCheckOffset;\r
+\r
+ //\r
+ // Check if PCI Express is supported. If yes, Save base address.\r
+ //\r
+ Status = Private->LegacyBiosPlatform->GetPlatformInfo (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformPciExpressBase,\r
+ NULL,\r
+ NULL,\r
+ &Location,\r
+ &Alignment,\r
+ 0,\r
+ 0\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Private->Legacy16Table->PciExpressBase = (UINT32)Location;\r
+ Location = 0;\r
+ }\r
+ //\r
+ // Check if TPM is supported. If yes get a region in E0000,F0000 to copy it\r
+ // into, copy it and update pointer to binary image. This needs to be\r
+ // done prior to any OPROM for security purposes.\r
+ //\r
+ Status = Private->LegacyBiosPlatform->GetPlatformInfo (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformBinaryTpmBinary,\r
+ &TpmBinaryImage,\r
+ &TpmBinaryImageSize,\r
+ &Location,\r
+ &Alignment,\r
+ 0,\r
+ 0\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16GetTableAddress;\r
+ Regs.X.CX = (UINT16) TpmBinaryImageSize;\r
+ Regs.X.DX = 1;\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Table->Compatibility16CallSegment,\r
+ Table->Compatibility16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ TpmPointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
+ if (Regs.X.AX != 0) {\r
+ DEBUG ((EFI_D_ERROR, "TPM cannot be loaded\n"));\r
+ } else {\r
+ CopyMem ((VOID *) (UINTN)TpmPointer, TpmBinaryImage, TpmBinaryImageSize);\r
+ Table->TpmSegment = Regs.X.DS;\r
+ Table->TpmOffset = Regs.X.BX;\r
+\r
+ }\r
+ }\r
+ //\r
+ // Lock the Legacy BIOS region\r
+ //\r
+ Private->Cpu->FlushDataCache (Private->Cpu, Private->BiosStart, (UINT32) LegacyBiosImageSize, EfiCpuFlushTypeWriteBackInvalidate);\r
+ Private->LegacyRegion->Lock (Private->LegacyRegion, Private->BiosStart, (UINT32) LegacyBiosImageSize, &Granularity);\r
+\r
+ //\r
+ // Get the BbsTable from LOW_MEMORY_THUNK\r
+ //\r
+ BbsTable = (BBS_TABLE *)(UINTN)Private->IntThunk->BbsTable;\r
+ ZeroMem ((VOID *)BbsTable, sizeof (Private->IntThunk->BbsTable));\r
+\r
+ EfiToLegacy16BootTable->BbsTable = (UINT32)(UINTN)BbsTable;\r
+ Private->BbsTablePtr = (VOID *) BbsTable;\r
+ //\r
+ // Skip Floppy and possible onboard IDE drives\r
+ //\r
+ EfiToLegacy16BootTable->NumberBbsEntries = 1 + 2 * MAX_IDE_CONTROLLER;\r
+\r
+ for (Index = 0; Index < (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); Index++) {\r
+ BbsTable[Index].BootPriority = BBS_IGNORE_ENTRY;\r
+ }\r
+ //\r
+ // Allocate space for Legacy HDD table\r
+ //\r
+ LegacyEfiHddTable = (LEGACY_EFI_HDD_TABLE *) AllocateZeroPool ((UINTN) MAX_HDD_ENTRIES * sizeof (LEGACY_EFI_HDD_TABLE));\r
+ ASSERT (LegacyEfiHddTable);\r
+\r
+ Private->LegacyEfiHddTable = LegacyEfiHddTable;\r
+ Private->LegacyEfiHddTableIndex = 0x00;\r
+\r
+ //\r
+ // start testtest\r
+ // GetTimerValue (&Ticker);\r
+ //\r
+ // gRT->SetVariable (L"EndOfLoadFv",\r
+ // &gEfiGlobalVariableGuid,\r
+ // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ // sizeof (UINT64),\r
+ // (VOID *)&Ticker\r
+ // );\r
+ // end testtest\r
+ //\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Shadow all legacy16 OPROMs that haven't been shadowed.\r
+ Warning: Use this with caution. This routine disconnects all EFI\r
+ drivers. If used externally then caller must re-connect EFI\r
+ drivers.\r
+\r
+ @param This Protocol instance pointer.\r
+\r
+ @retval EFI_SUCCESS OPROMs shadowed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosShadowAllLegacyOproms (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This\r
+ )\r
+{\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+\r
+ //\r
+ // EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;\r
+ // EFI_LEGACY16_TABLE *Legacy16Table;\r
+ //\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+\r
+ //\r
+ // LegacyBiosPlatform = Private->LegacyBiosPlatform;\r
+ // Legacy16Table = Private->Legacy16Table;\r
+ //\r
+ // Shadow PCI ROMs. We must do this near the end since this will kick\r
+ // of Native EFI drivers that may be needed to collect info for Legacy16\r
+ //\r
+ // WARNING: PciIo is gone after this call.\r
+ //\r
+ PciProgramAllInterruptLineRegisters (Private);\r
+\r
+ PciShadowRoms (Private);\r
+\r
+ //\r
+ // Shadow PXE base code, BIS etc.\r
+ //\r
+ // LegacyBiosPlatform->ShadowServiceRoms (LegacyBiosPlatform,\r
+ // &Private->OptionRom,\r
+ // Legacy16Table);\r
+ //\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get the PCI BIOS interface version.\r
+\r
+ @param Private Driver private data.\r
+\r
+ @return The PCI interface version number in Binary Coded Decimal (BCD) format.\r
+ E.g.: 0x0210 indicates 2.10, 0x0300 indicates 3.00\r
+\r
+**/\r
+UINT16\r
+GetPciInterfaceVersion (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_IA32_REGISTER_SET Reg;\r
+ BOOLEAN ThunkFailed;\r
+ UINT16 PciInterfaceVersion;\r
+\r
+ PciInterfaceVersion = 0;\r
+ \r
+ Reg.X.AX = 0xB101;\r
+ Reg.E.EDI = 0;\r
+\r
+ ThunkFailed = Private->LegacyBios.Int86 (&Private->LegacyBios, 0x1A, &Reg);\r
+ if (!ThunkFailed) {\r
+ //\r
+ // From PCI Firmware 3.0 Specification:\r
+ // If the CARRY FLAG [CF] is cleared and AH is set to 00h, it is still necessary to examine the\r
+ // contents of [EDX] for the presence of the string "PCI" + (trailing space) to fully validate the\r
+ // presence of the PCI function set. [BX] will further indicate the version level, with enough\r
+ // granularity to allow for incremental changes in the code that don't affect the function interface.\r
+ // Version numbers are stored as Binary Coded Decimal (BCD) values. For example, Version 2.10\r
+ // would be returned as a 02h in the [BH] registers and 10h in the [BL] registers.\r
+ //\r
+ if ((Reg.X.Flags.CF == 0) && (Reg.H.AH == 0) && (Reg.E.EDX == SIGNATURE_32 ('P', 'C', 'I', ' '))) {\r
+ PciInterfaceVersion = Reg.X.BX;\r
+ }\r
+ }\r
+ return PciInterfaceVersion;\r
+}\r
+\r
+/**\r
+ Install Driver to produce Legacy BIOS protocol.\r
+\r
+ @param ImageHandle Handle of driver image.\r
+ @param SystemTable Pointer to system table.\r
+\r
+ @retval EFI_SUCCESS Legacy BIOS protocol installed\r
+ @retval No protocol installed, unload driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosInstall (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable;\r
+ EFI_PHYSICAL_ADDRESS MemoryAddress;\r
+ VOID *MemoryPtr;\r
+ EFI_PHYSICAL_ADDRESS MemoryAddressUnder1MB;\r
+ UINTN Index;\r
+ UINT32 *BaseVectorMaster;\r
+ EFI_PHYSICAL_ADDRESS StartAddress;\r
+ UINT32 *ClearPtr;\r
+ EFI_PHYSICAL_ADDRESS MemStart;\r
+ UINT32 IntRedirCode;\r
+ UINT32 Granularity;\r
+ BOOLEAN DecodeOn;\r
+ UINT32 MemorySize;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
+ UINT64 Length;\r
+\r
+ //\r
+ // Load this driver's image to memory\r
+ //\r
+ Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Private = &mPrivateData;\r
+ ZeroMem (Private, sizeof (LEGACY_BIOS_INSTANCE));\r
+\r
+ //\r
+ // Grab a copy of all the protocols we depend on. Any error would\r
+ // be a dispatcher bug!.\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Private->Cpu);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->LocateProtocol (&gEfiLegacyRegion2ProtocolGuid, NULL, (VOID **) &Private->LegacyRegion);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosPlatformProtocolGuid, NULL, (VOID **) &Private->LegacyBiosPlatform);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &Private->Legacy8259);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, (VOID **) &Private->LegacyInterrupt);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Locate Memory Test Protocol if exists\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiGenericMemTestProtocolGuid,\r
+ NULL,\r
+ (VOID **) &Private->GenericMemoryTest\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Make sure all memory from 0-640K is tested\r
+ //\r
+ for (StartAddress = 0; StartAddress < 0xa0000; ) {\r
+ gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor);\r
+ if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) {\r
+ StartAddress = Descriptor.BaseAddress + Descriptor.Length;\r
+ continue;\r
+ }\r
+ Length = MIN (Descriptor.Length, 0xa0000 - StartAddress);\r
+ Private->GenericMemoryTest->CompatibleRangeTest (\r
+ Private->GenericMemoryTest,\r
+ StartAddress,\r
+ Length\r
+ );\r
+ StartAddress = StartAddress + Length;\r
+ }\r
+ //\r
+ // Make sure all memory from 1MB to 16MB is tested and added to memory map\r
+ //\r
+ for (StartAddress = BASE_1MB; StartAddress < BASE_16MB; ) {\r
+ gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor);\r
+ if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) {\r
+ StartAddress = Descriptor.BaseAddress + Descriptor.Length;\r
+ continue;\r
+ }\r
+ Length = MIN (Descriptor.Length, BASE_16MB - StartAddress);\r
+ Private->GenericMemoryTest->CompatibleRangeTest (\r
+ Private->GenericMemoryTest,\r
+ StartAddress,\r
+ Length\r
+ );\r
+ StartAddress = StartAddress + Length;\r
+ }\r
+\r
+ Private->Signature = LEGACY_BIOS_INSTANCE_SIGNATURE;\r
+\r
+ Private->LegacyBios.Int86 = LegacyBiosInt86;\r
+ Private->LegacyBios.FarCall86 = LegacyBiosFarCall86;\r
+ Private->LegacyBios.CheckPciRom = LegacyBiosCheckPciRom;\r
+ Private->LegacyBios.InstallPciRom = LegacyBiosInstallPciRom;\r
+ Private->LegacyBios.LegacyBoot = LegacyBiosLegacyBoot;\r
+ Private->LegacyBios.UpdateKeyboardLedStatus = LegacyBiosUpdateKeyboardLedStatus;\r
+ Private->LegacyBios.GetBbsInfo = LegacyBiosGetBbsInfo;\r
+ Private->LegacyBios.ShadowAllLegacyOproms = LegacyBiosShadowAllLegacyOproms;\r
+ Private->LegacyBios.PrepareToBootEfi = LegacyBiosPrepareToBootEfi;\r
+ Private->LegacyBios.GetLegacyRegion = LegacyBiosGetLegacyRegion;\r
+ Private->LegacyBios.CopyLegacyRegion = LegacyBiosCopyLegacyRegion;\r
+ Private->LegacyBios.BootUnconventionalDevice = LegacyBiosBootUnconventionalDevice;\r
+\r
+ Private->ImageHandle = ImageHandle;\r
+\r
+ //\r
+ // Enable read attribute of legacy region.\r
+ //\r
+ DecodeOn = TRUE;\r
+ Private->LegacyRegion->Decode (\r
+ Private->LegacyRegion,\r
+ 0xc0000,\r
+ 0x40000,\r
+ &Granularity,\r
+ &DecodeOn\r
+ );\r
+ //\r
+ // Set Cachebility for legacy region\r
+ // BUGBUG: Comments about this legacy region cacheability setting\r
+ // This setting will make D865GCHProduction CSM Unhappy\r
+ //\r
+ if (PcdGetBool (PcdLegacyBiosCacheLegacyRegion)) {\r
+ gDS->SetMemorySpaceAttributes (\r
+ 0x0,\r
+ 0xA0000,\r
+ EFI_MEMORY_WB\r
+ );\r
+ gDS->SetMemorySpaceAttributes (\r
+ 0xc0000,\r
+ 0x40000,\r
+ EFI_MEMORY_WB\r
+ );\r
+ }\r
+\r
+ gDS->SetMemorySpaceAttributes (\r
+ 0xA0000,\r
+ 0x20000,\r
+ EFI_MEMORY_UC\r
+ );\r
+\r
+ //\r
+ // Allocate 0 - 4K for real mode interupt vectors and BDA.\r
+ //\r
+ AllocateLegacyMemory (\r
+ AllocateAddress,\r
+ 0,\r
+ 1,\r
+ &MemoryAddress\r
+ );\r
+ ASSERT (MemoryAddress == 0x000000000);\r
+\r
+ ClearPtr = (VOID *) ((UINTN) 0x0000);\r
+\r
+ //\r
+ // Initialize region from 0x0000 to 4k. This initializes interrupt vector\r
+ // range.\r
+ //\r
+ gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);\r
+ ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);\r
+\r
+ //\r
+ // Allocate pages for OPROM usage\r
+ //\r
+ MemorySize = PcdGet32 (PcdEbdaReservedMemorySize);\r
+ ASSERT ((MemorySize & 0xFFF) == 0);\r
+\r
+ Status = AllocateLegacyMemory (\r
+ AllocateAddress,\r
+ CONVENTIONAL_MEMORY_TOP - MemorySize,\r
+ EFI_SIZE_TO_PAGES (MemorySize),\r
+ &MemoryAddress\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ ZeroMem ((VOID *) ((UINTN) MemoryAddress), MemorySize);\r
+\r
+ //\r
+ // Allocate all 32k chunks from 0x60000 ~ 0x88000 for Legacy OPROMs that\r
+ // don't use PMM but look for zeroed memory. Note that various non-BBS\r
+ // SCSIs expect different areas to be free\r
+ //\r
+ for (MemStart = 0x60000; MemStart < 0x88000; MemStart += 0x1000) {\r
+ Status = AllocateLegacyMemory (\r
+ AllocateAddress,\r
+ MemStart,\r
+ 1,\r
+ &MemoryAddress\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ MemoryPtr = (VOID *) ((UINTN) MemoryAddress);\r
+ ZeroMem (MemoryPtr, 0x1000);\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "WARNING: Allocate legacy memory fail for SCSI card - %x\n", MemStart));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Allocate a 64k area (16 4k pages) for 16-bit code for scratch pad and zero it out\r
+ //\r
+ Status = AllocateLegacyMemory (\r
+ AllocateMaxAddress,\r
+ CONVENTIONAL_MEMORY_TOP,\r
+ 16,\r
+ &MemoryAddressUnder1MB\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ ZeroMem ((VOID *) ((UINTN) MemoryAddressUnder1MB), 0x10000);\r
+\r
+ //\r
+ // Allocate space for thunker and Init Thunker\r
+ //\r
+ Status = AllocateLegacyMemory (\r
+ AllocateMaxAddress,\r
+ CONVENTIONAL_MEMORY_TOP,\r
+ (sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 2,\r
+ &MemoryAddress\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ Private->IntThunk = (LOW_MEMORY_THUNK *) (UINTN) MemoryAddress;\r
+ EfiToLegacy16InitTable = &Private->IntThunk->EfiToLegacy16InitTable;\r
+ EfiToLegacy16InitTable->ThunkStart = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress;\r
+ EfiToLegacy16InitTable->ThunkSizeInBytes = (UINT32) (sizeof (LOW_MEMORY_THUNK));\r
+\r
+ Status = LegacyBiosInitializeThunk (Private);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Init the legacy memory map in memory < 1 MB.\r
+ //\r
+ EfiToLegacy16InitTable->BiosLessThan1MB = (UINT32) MemoryAddressUnder1MB;\r
+ EfiToLegacy16InitTable->LowPmmMemory = (UINT32) MemoryAddressUnder1MB;\r
+ EfiToLegacy16InitTable->LowPmmMemorySizeInBytes = 0x10000;\r
+\r
+ //\r
+ // Allocate 4 MB of PMM Memory under 16 MB\r
+ //\r
+ Status = AllocateLegacyMemory (\r
+ AllocateMaxAddress,\r
+ 0x1000000,\r
+ 0x400,\r
+ &MemoryAddress\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ EfiToLegacy16InitTable->HiPmmMemory = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress;\r
+ EfiToLegacy16InitTable->HiPmmMemorySizeInBytes = PMM_MEMORY_SIZE;\r
+ }\r
+\r
+ //\r
+ // ShutdownAPs();\r
+ //\r
+ // Start the Legacy BIOS;\r
+ //\r
+ Status = ShadowAndStartLegacy16 (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Initialize interrupt redirection code and entries;\r
+ // IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.\r
+ //\r
+ CopyMem (\r
+ Private->IntThunk->InterruptRedirectionCode,\r
+ (VOID *) (UINTN) InterruptRedirectionTemplate,\r
+ sizeof (Private->IntThunk->InterruptRedirectionCode)\r
+ );\r
+\r
+ //\r
+ // Save Unexpected interrupt vector so can restore it just prior to boot\r
+ //\r
+ BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);\r
+ Private->BiosUnexpectedInt = BaseVectorMaster[0];\r
+ IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode;\r
+ for (Index = 0; Index < 8; Index++) {\r
+ BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4);\r
+ }\r
+ //\r
+ // Save EFI value\r
+ //\r
+ Private->ThunkSeg = (UINT16) (EFI_SEGMENT (IntRedirCode));\r
+\r
+ //\r
+ // Make a new handle and install the protocol\r
+ //\r
+ Private->Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Private->Handle,\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &Private->LegacyBios\r
+ );\r
+ Private->Csm16PciInterfaceVersion = GetPciInterfaceVersion (Private);\r
+ \r
+ DEBUG ((EFI_D_INFO, "CSM16 PCI BIOS Interface Version: %02x.%02x\n", \r
+ (UINT8) (Private->Csm16PciInterfaceVersion >> 8), \r
+ (UINT8) Private->Csm16PciInterfaceVersion\r
+ ));\r
+ ASSERT (Private->Csm16PciInterfaceVersion != 0);\r
+ return Status;\r
+}\r
--- /dev/null
+## @file\r
+# Legacy Bios Module to support CSM.\r
+#\r
+# This driver installs Legacy Bios Protocol to support CSM module work in EFI system.\r
+#\r
+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions\r
+# of the BSD License which accompanies this distribution. The\r
+# full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = LegacyBiosDxe\r
+ FILE_GUID = F122A15C-C10B-4d54-8F48-60F4F06DD1AD\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+\r
+ ENTRY_POINT = LegacyBiosInstall\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF\r
+#\r
+\r
+[Sources]\r
+ LegacyCmos.c\r
+ LegacyIde.c\r
+ LegacyBios.c\r
+ LegacyBda.c\r
+ LegacyBiosInterface.h\r
+ LegacyPci.c\r
+\r
+[Sources.Ia32]\r
+ IA32/InterruptTable.S\r
+ IA32/InterruptTable.asm\r
+ Thunk.c\r
+ LegacyBootSupport.c\r
+ LegacyBbs.c\r
+ LegacySio.c\r
+\r
+[Sources.X64]\r
+ X64/InterruptTable.asm\r
+ X64/InterruptTable.S\r
+ Thunk.c\r
+ LegacyBootSupport.c\r
+ LegacyBbs.c\r
+ LegacySio.c\r
+\r
+[Sources.IPF]\r
+ Ipf/IpfThunk.s\r
+ Ipf/Thunk.c\r
+ Ipf/IpfThunk.i\r
+ Ipf/IpfBootSupport.c\r
+ Ipf/IpfThunk.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ DevicePathLib\r
+ UefiBootServicesTableLib\r
+ MemoryAllocationLib\r
+ UefiDriverEntryPoint\r
+ BaseMemoryLib\r
+ UefiLib\r
+ DebugLib\r
+ DxeServicesTableLib\r
+ PcdLib\r
+ ReportStatusCodeLib\r
+ PeCoffLib\r
+ CacheMaintenanceLib\r
+ DebugAgentLib\r
+\r
+[LibraryClasses.IA32]\r
+ IoLib\r
+ HobLib\r
+ UefiRuntimeServicesTableLib\r
+ BaseLib\r
+\r
+[LibraryClasses.X64]\r
+ IoLib\r
+ HobLib\r
+ UefiRuntimeServicesTableLib\r
+ BaseLib\r
+\r
+[LibraryClasses.IPF]\r
+ IoLib\r
+ UefiRuntimeServicesTableLib\r
+\r
+\r
+[Guids]\r
+ gEfiDiskInfoIdeInterfaceGuid # ALWAYS_CONSUMED\r
+ gEfiLegacyBiosGuid # ALWAYS_PRODUCED\r
+\r
+[Guids.IA32]\r
+ gEfiSmbiosTableGuid # ALWAYS_CONSUMED\r
+ gEfiAcpi20TableGuid # ALWAYS_CONSUMED\r
+ gEfiAcpi10TableGuid # ALWAYS_CONSUMED\r
+\r
+[Guids.X64]\r
+ gEfiSmbiosTableGuid # ALWAYS_CONSUMED\r
+ gEfiAcpi20TableGuid # ALWAYS_CONSUMED\r
+ gEfiAcpi10TableGuid # ALWAYS_CONSUMED\r
+\r
+\r
+[Protocols]\r
+ gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiPciRootBridgeIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiCpuArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiIsaIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiGenericMemTestProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDiskInfoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacy8259ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacyBiosPlatformProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacyInterruptProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacyRegion2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
+ gEfiTimerArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
+\r
+[Pcd]\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize\r
+\r
+[Depex]\r
+ gEfiLegacyRegion2ProtocolGuid AND gEfiLegacyInterruptProtocolGuid AND gEfiLegacyBiosPlatformProtocolGuid AND gEfiLegacy8259ProtocolGuid AND gEfiGenericMemTestProtocolGuid AND gEfiCpuArchProtocolGuid\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LEGACY_BIOS_INTERFACE_\r
+#define _LEGACY_BIOS_INTERFACE_\r
+\r
+\r
+#include <FrameworkDxe.h>\r
+\r
+#include <Guid/SmBios.h>\r
+#include <Guid/Acpi.h>\r
+#include <Guid/DxeServices.h>\r
+#include <Guid/LegacyBios.h>\r
+#include <Guid/StatusCodeDataTypeId.h>\r
+\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/Cpu.h>\r
+#include <Protocol/IsaIo.h>\r
+#include <Protocol/LegacyRegion2.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/LegacyInterrupt.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/DiskInfo.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+#include <Protocol/LegacyBiosPlatform.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/Legacy8259.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/Timer.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/CacheMaintenanceLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+\r
+//\r
+// System Tickers\r
+//\r
+#define DEFAULT_LAGACY_TIMER_TICK_DURATION 549254\r
+// BUGBUG: This entry maybe changed to PCD in future and wait for\r
+// redesign of BDS library\r
+//\r
+#define MAX_BBS_ENTRIES 0x100\r
+\r
+//\r
+// Thunk Status Codes\r
+// (These apply only to errors with the thunk and not to the code that was\r
+// thunked to.)\r
+//\r
+#define THUNK_OK 0x00\r
+#define THUNK_ERR_A20_UNSUP 0x01\r
+#define THUNK_ERR_A20_FAILED 0x02\r
+\r
+//\r
+// Vector base definitions\r
+//\r
+//\r
+// 8259 Hardware definitions\r
+//\r
+#define LEGACY_MODE_BASE_VECTOR_MASTER 0x08\r
+#define LEGACY_MODE_BASE_VECTOR_SLAVE 0x70\r
+\r
+//\r
+// The original PC used INT8-F for master PIC. Since these mapped over\r
+// processor exceptions TIANO moved the master PIC to INT68-6F.\r
+//\r
+// The vector base for slave PIC is set as 0x70 for PC-AT compatibility.\r
+//\r
+#define PROTECTED_MODE_BASE_VECTOR_MASTER 0x68\r
+#define PROTECTED_MODE_BASE_VECTOR_SLAVE 0x70\r
+\r
+//\r
+// Trace defines\r
+//\r
+//\r
+#define LEGACY_BDA_TRACE 0x000\r
+#define LEGACY_BIOS_TRACE 0x040\r
+#define LEGACY_BOOT_TRACE 0x080\r
+#define LEGACY_CMOS_TRACE 0x0C0\r
+#define LEGACY_IDE_TRACE 0x100\r
+#define LEGACY_MP_TRACE 0x140\r
+#define LEGACY_PCI_TRACE 0x180\r
+#define LEGACY_SIO_TRACE 0x1C0\r
+\r
+#define LEGACY_PCI_TRACE_000 LEGACY_PCI_TRACE + 0x00\r
+#define LEGACY_PCI_TRACE_001 LEGACY_PCI_TRACE + 0x01\r
+#define LEGACY_PCI_TRACE_002 LEGACY_PCI_TRACE + 0x02\r
+#define LEGACY_PCI_TRACE_003 LEGACY_PCI_TRACE + 0x03\r
+#define LEGACY_PCI_TRACE_004 LEGACY_PCI_TRACE + 0x04\r
+#define LEGACY_PCI_TRACE_005 LEGACY_PCI_TRACE + 0x05\r
+#define LEGACY_PCI_TRACE_006 LEGACY_PCI_TRACE + 0x06\r
+#define LEGACY_PCI_TRACE_007 LEGACY_PCI_TRACE + 0x07\r
+#define LEGACY_PCI_TRACE_008 LEGACY_PCI_TRACE + 0x08\r
+#define LEGACY_PCI_TRACE_009 LEGACY_PCI_TRACE + 0x09\r
+#define LEGACY_PCI_TRACE_00A LEGACY_PCI_TRACE + 0x0A\r
+#define LEGACY_PCI_TRACE_00B LEGACY_PCI_TRACE + 0x0B\r
+#define LEGACY_PCI_TRACE_00C LEGACY_PCI_TRACE + 0x0C\r
+#define LEGACY_PCI_TRACE_00D LEGACY_PCI_TRACE + 0x0D\r
+#define LEGACY_PCI_TRACE_00E LEGACY_PCI_TRACE + 0x0E\r
+#define LEGACY_PCI_TRACE_00F LEGACY_PCI_TRACE + 0x0F\r
+\r
+\r
+typedef struct {\r
+ UINTN PciSegment;\r
+ UINTN PciBus;\r
+ UINTN PciDevice;\r
+ UINTN PciFunction;\r
+ UINT32 ShadowAddress;\r
+ UINT32 ShadowedSize;\r
+ UINT8 DiskStart;\r
+ UINT8 DiskEnd;\r
+} ROM_INSTANCE_ENTRY;\r
+\r
+//\r
+// Values for RealModeGdt\r
+//\r
+#if defined (MDE_CPU_IA32)\r
+\r
+#define NUM_REAL_GDT_ENTRIES 3\r
+#define CONVENTIONAL_MEMORY_TOP 0xA0000 // 640 KB\r
+#define INITIAL_VALUE_BELOW_1K 0x0\r
+\r
+#elif defined (MDE_CPU_X64)\r
+\r
+#define NUM_REAL_GDT_ENTRIES 8\r
+#define CONVENTIONAL_MEMORY_TOP 0xA0000 // 640 KB\r
+#define INITIAL_VALUE_BELOW_1K 0x0\r
+\r
+#elif defined (MDE_CPU_IPF)\r
+\r
+#define NUM_REAL_GDT_ENTRIES 3\r
+#define CONVENTIONAL_MEMORY_TOP 0x80000 // 512 KB\r
+#define INITIAL_VALUE_BELOW_1K 0xff\r
+\r
+#endif\r
+\r
+//\r
+// Miscellaneous numbers\r
+//\r
+#define PMM_MEMORY_SIZE 0x400000 // 4 MB\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// Define what a processor GDT looks like\r
+//\r
+typedef struct {\r
+ UINT32 LimitLo : 16;\r
+ UINT32 BaseLo : 16;\r
+ UINT32 BaseMid : 8;\r
+ UINT32 Type : 4;\r
+ UINT32 System : 1;\r
+ UINT32 Dpl : 2;\r
+ UINT32 Present : 1;\r
+ UINT32 LimitHi : 4;\r
+ UINT32 Software : 1;\r
+ UINT32 Reserved : 1;\r
+ UINT32 DefaultSize : 1;\r
+ UINT32 Granularity : 1;\r
+ UINT32 BaseHi : 8;\r
+} GDT32;\r
+\r
+typedef struct {\r
+ UINT16 LimitLow;\r
+ UINT16 BaseLow;\r
+ UINT8 BaseMid;\r
+ UINT8 Attribute;\r
+ UINT8 LimitHi;\r
+ UINT8 BaseHi;\r
+} GDT64;\r
+\r
+//\r
+// Define what a processor descriptor looks like\r
+// This data structure must be kept in sync with ASM STRUCT in Thunk.inc\r
+//\r
+typedef struct {\r
+ UINT16 Limit;\r
+ UINT64 Base;\r
+} DESCRIPTOR64;\r
+\r
+typedef struct {\r
+ UINT16 Limit;\r
+ UINT32 Base;\r
+} DESCRIPTOR32;\r
+\r
+//\r
+// Low stub lay out\r
+//\r
+#define LOW_STACK_SIZE (8 * 1024) // 8k?\r
+#define EFI_MAX_E820_ENTRY 100\r
+#define FIRST_INSTANCE 1\r
+#define NOT_FIRST_INSTANCE 0\r
+\r
+#if defined (MDE_CPU_IA32)\r
+typedef struct {\r
+ //\r
+ // Space for the code\r
+ // The address of Code is also the beginning of the relocated Thunk code\r
+ //\r
+ CHAR8 Code[4096]; // ?\r
+ //\r
+ // The address of the Reverse Thunk code\r
+ // Note that this member CONTAINS the address of the relocated reverse thunk\r
+ // code unlike the member variable 'Code', which IS the address of the Thunk\r
+ // code.\r
+ //\r
+ UINT32 LowReverseThunkStart;\r
+\r
+ //\r
+ // Data for the code (cs releative)\r
+ //\r
+ DESCRIPTOR32 GdtDesc; // Protected mode GDT\r
+ DESCRIPTOR32 IdtDesc; // Protected mode IDT\r
+ UINT32 FlatSs;\r
+ UINT32 FlatEsp;\r
+\r
+ UINT32 LowCodeSelector; // Low code selector in GDT\r
+ UINT32 LowDataSelector; // Low data selector in GDT\r
+ UINT32 LowStack;\r
+ DESCRIPTOR32 RealModeIdtDesc;\r
+\r
+ //\r
+ // real-mode GDT (temporary GDT with two real mode segment descriptors)\r
+ //\r
+ GDT32 RealModeGdt[NUM_REAL_GDT_ENTRIES];\r
+ DESCRIPTOR32 RealModeGdtDesc;\r
+\r
+ //\r
+ // Members specifically for the reverse thunk\r
+ // The RevReal* members are used to store the current state of real mode\r
+ // before performing the reverse thunk. The RevFlat* members must be set\r
+ // before calling the reverse thunk assembly code.\r
+ //\r
+ UINT16 RevRealDs;\r
+ UINT16 RevRealSs;\r
+ UINT32 RevRealEsp;\r
+ DESCRIPTOR32 RevRealIdtDesc;\r
+ UINT16 RevFlatDataSelector; // Flat data selector in GDT\r
+ UINT32 RevFlatStack;\r
+\r
+ //\r
+ // A low memory stack\r
+ //\r
+ CHAR8 Stack[LOW_STACK_SIZE];\r
+\r
+ //\r
+ // Stack for flat mode after reverse thunk\r
+ // @bug - This may no longer be necessary if the reverse thunk interface\r
+ // is changed to have the flat stack in a different location.\r
+ //\r
+ CHAR8 RevThunkStack[LOW_STACK_SIZE];\r
+\r
+ //\r
+ // Legacy16 Init memory map info\r
+ //\r
+ EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable;\r
+\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable;\r
+\r
+ CHAR8 InterruptRedirectionCode[32];\r
+ EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler;\r
+ EFI_DISPATCH_OPROM_TABLE DispatchOpromTable;\r
+ BBS_TABLE BbsTable[MAX_BBS_ENTRIES];\r
+} LOW_MEMORY_THUNK;\r
+\r
+#elif defined (MDE_CPU_X64)\r
+\r
+typedef struct {\r
+ //\r
+ // Space for the code\r
+ // The address of Code is also the beginning of the relocated Thunk code\r
+ //\r
+ CHAR8 Code[4096]; // ?\r
+\r
+ //\r
+ // Data for the code (cs releative)\r
+ //\r
+ DESCRIPTOR64 X64GdtDesc; // Protected mode GDT\r
+ DESCRIPTOR64 X64IdtDesc; // Protected mode IDT\r
+ UINTN X64Ss;\r
+ UINTN X64Esp;\r
+\r
+ UINTN RealStack;\r
+ DESCRIPTOR32 RealModeIdtDesc;\r
+ DESCRIPTOR32 RealModeGdtDesc;\r
+\r
+ //\r
+ // real-mode GDT (temporary GDT with two real mode segment descriptors)\r
+ //\r
+ GDT64 RealModeGdt[NUM_REAL_GDT_ENTRIES];\r
+ UINT64 PageMapLevel4;\r
+\r
+ //\r
+ // A low memory stack\r
+ //\r
+ CHAR8 Stack[LOW_STACK_SIZE];\r
+\r
+ //\r
+ // Legacy16 Init memory map info\r
+ //\r
+ EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable;\r
+\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable;\r
+\r
+ CHAR8 InterruptRedirectionCode[32];\r
+ EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler;\r
+ EFI_DISPATCH_OPROM_TABLE DispatchOpromTable;\r
+ BBS_TABLE BbsTable[MAX_BBS_ENTRIES];\r
+} LOW_MEMORY_THUNK;\r
+\r
+#elif defined (MDE_CPU_IPF)\r
+\r
+typedef struct {\r
+ //\r
+ // Space for the code\r
+ // The address of Code is also the beginning of the relocated Thunk code\r
+ //\r
+ CHAR8 Code[4096]; // ?\r
+ //\r
+ // The address of the Reverse Thunk code\r
+ // Note that this member CONTAINS the address of the relocated reverse thunk\r
+ // code unlike the member variable 'Code', which IS the address of the Thunk\r
+ // code.\r
+ //\r
+ UINT32 LowReverseThunkStart;\r
+\r
+ //\r
+ // Data for the code (cs releative)\r
+ //\r
+ DESCRIPTOR32 GdtDesc; // Protected mode GDT\r
+ DESCRIPTOR32 IdtDesc; // Protected mode IDT\r
+ UINT32 FlatSs;\r
+ UINT32 FlatEsp;\r
+\r
+ UINT32 LowCodeSelector; // Low code selector in GDT\r
+ UINT32 LowDataSelector; // Low data selector in GDT\r
+ UINT32 LowStack;\r
+ DESCRIPTOR32 RealModeIdtDesc;\r
+\r
+ //\r
+ // real-mode GDT (temporary GDT with two real mode segment descriptors)\r
+ //\r
+ GDT32 RealModeGdt[NUM_REAL_GDT_ENTRIES];\r
+ DESCRIPTOR32 RealModeGdtDesc;\r
+\r
+ //\r
+ // Members specifically for the reverse thunk\r
+ // The RevReal* members are used to store the current state of real mode\r
+ // before performing the reverse thunk. The RevFlat* members must be set\r
+ // before calling the reverse thunk assembly code.\r
+ //\r
+ UINT16 RevRealDs;\r
+ UINT16 RevRealSs;\r
+ UINT32 RevRealEsp;\r
+ DESCRIPTOR32 RevRealIdtDesc;\r
+ UINT16 RevFlatDataSelector; // Flat data selector in GDT\r
+ UINT32 RevFlatStack;\r
+\r
+ //\r
+ // A low memory stack\r
+ //\r
+ CHAR8 Stack[LOW_STACK_SIZE];\r
+\r
+ //\r
+ // Stack for flat mode after reverse thunk\r
+ // @bug - This may no longer be necessary if the reverse thunk interface\r
+ // is changed to have the flat stack in a different location.\r
+ //\r
+ CHAR8 RevThunkStack[LOW_STACK_SIZE];\r
+\r
+ //\r
+ // Legacy16 Init memory map info\r
+ //\r
+ EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable;\r
+\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable;\r
+\r
+ CHAR8 InterruptRedirectionCode[32];\r
+ EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler;\r
+ EFI_DISPATCH_OPROM_TABLE DispatchOpromTable;\r
+ BBS_TABLE BbsTable[MAX_BBS_ENTRIES];\r
+} LOW_MEMORY_THUNK;\r
+\r
+#endif\r
+\r
+//\r
+// PnP Expansion Header\r
+//\r
+typedef struct {\r
+ UINT32 PnpSignature;\r
+ UINT8 Revision;\r
+ UINT8 Length;\r
+ UINT16 NextHeader;\r
+ UINT8 Reserved1;\r
+ UINT8 Checksum;\r
+ UINT32 DeviceId;\r
+ UINT16 MfgPointer;\r
+ UINT16 ProductNamePointer;\r
+ UINT8 Class;\r
+ UINT8 SubClass;\r
+ UINT8 Interface;\r
+ UINT8 DeviceIndicators;\r
+ UINT16 Bcv;\r
+ UINT16 DisconnectVector;\r
+ UINT16 Bev;\r
+ UINT16 Reserved2;\r
+ UINT16 StaticResourceVector;\r
+} LEGACY_PNP_EXPANSION_HEADER;\r
+\r
+typedef struct {\r
+ UINT8 PciSegment;\r
+ UINT8 PciBus;\r
+ UINT8 PciDevice;\r
+ UINT8 PciFunction;\r
+ UINT16 Vid;\r
+ UINT16 Did;\r
+ UINT16 SysSid;\r
+ UINT16 SVid;\r
+ UINT8 Class;\r
+ UINT8 SubClass;\r
+ UINT8 Interface;\r
+ UINT8 Reserved;\r
+ UINTN RomStart;\r
+ UINTN ManufacturerString;\r
+ UINTN ProductNameString;\r
+} LEGACY_ROM_AND_BBS_TABLE;\r
+\r
+//\r
+// Structure how EFI has mapped a devices HDD drive numbers.\r
+// Boot to EFI aware OS or shell requires this mapping when\r
+// 16-bit CSM assigns drive numbers.\r
+// This mapping is ignored booting to a legacy OS.\r
+//\r
+typedef struct {\r
+ UINT8 PciSegment;\r
+ UINT8 PciBus;\r
+ UINT8 PciDevice;\r
+ UINT8 PciFunction;\r
+ UINT8 StartDriveNumber;\r
+ UINT8 EndDriveNumber;\r
+} LEGACY_EFI_HDD_TABLE;\r
+\r
+//\r
+// This data is passed to Leacy16Boot\r
+//\r
+typedef enum {\r
+ EfiAcpiAddressRangeMemory = 1,\r
+ EfiAcpiAddressRangeReserved = 2,\r
+ EfiAcpiAddressRangeACPI = 3,\r
+ EfiAcpiAddressRangeNVS = 4\r
+} EFI_ACPI_MEMORY_TYPE;\r
+\r
+typedef struct {\r
+ UINT64 BaseAddr;\r
+ UINT64 Length;\r
+ EFI_ACPI_MEMORY_TYPE Type;\r
+} EFI_E820_ENTRY64;\r
+\r
+typedef struct {\r
+ UINT32 BassAddrLow;\r
+ UINT32 BaseAddrHigh;\r
+ UINT32 LengthLow;\r
+ UINT32 LengthHigh;\r
+ EFI_ACPI_MEMORY_TYPE Type;\r
+} EFI_E820_ENTRY;\r
+\r
+#pragma pack()\r
+\r
+extern BBS_TABLE *mBbsTable;\r
+\r
+extern EFI_GENERIC_MEMORY_TEST_PROTOCOL *gGenMemoryTest;\r
+\r
+extern UINTN mEndOpromShadowAddress;\r
+\r
+#define PORT_70 0x70\r
+#define PORT_71 0x71\r
+\r
+#define CMOS_0A 0x0a ///< Status register A\r
+#define CMOS_0D 0x0d ///< Status register D\r
+#define CMOS_0E 0x0e ///< Diagnostic Status\r
+#define CMOS_0F 0x0f ///< Shutdown status\r
+#define CMOS_10 0x10 ///< Floppy type\r
+#define CMOS_12 0x12 ///< IDE type\r
+#define CMOS_14 0x14 ///< Same as BDA 40:10\r
+#define CMOS_15 0x15 ///< Low byte of base memory in 1k increments\r
+#define CMOS_16 0x16 ///< High byte of base memory in 1k increments\r
+#define CMOS_17 0x17 ///< Low byte of 1MB+ memory in 1k increments - max 15 MB\r
+#define CMOS_18 0x18 ///< High byte of 1MB+ memory in 1k increments - max 15 MB\r
+#define CMOS_19 0x19 ///< C: extended drive type\r
+#define CMOS_1A 0x1a ///< D: extended drive type\r
+#define CMOS_2E 0x2e ///< Most significient byte of standard checksum\r
+#define CMOS_2F 0x2f ///< Least significient byte of standard checksum\r
+#define CMOS_30 0x30 ///< CMOS 0x17\r
+#define CMOS_31 0x31 ///< CMOS 0x18\r
+#define CMOS_32 0x32 ///< Century byte\r
+\r
+\r
+#define LEGACY_BIOS_INSTANCE_SIGNATURE SIGNATURE_32 ('L', 'B', 'I', 'T')\r
+typedef struct {\r
+ UINTN Signature;\r
+\r
+ EFI_HANDLE Handle;\r
+ EFI_LEGACY_BIOS_PROTOCOL LegacyBios;\r
+\r
+ EFI_HANDLE ImageHandle;\r
+\r
+ //\r
+ // CPU Architectural Protocol \r
+ //\r
+ EFI_CPU_ARCH_PROTOCOL *Cpu;\r
+\r
+ //\r
+ // Protocol to Lock and Unlock 0xc0000 - 0xfffff\r
+ //\r
+ EFI_LEGACY_REGION2_PROTOCOL *LegacyRegion;\r
+\r
+ EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;\r
+\r
+ //\r
+ // Interrupt control for thunk and PCI IRQ\r
+ //\r
+ EFI_LEGACY_8259_PROTOCOL *Legacy8259;\r
+\r
+ //\r
+ // PCI Interrupt PIRQ control\r
+ //\r
+ EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;\r
+\r
+ //\r
+ // Generic Memory Test\r
+ //\r
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenericMemoryTest;\r
+\r
+ //\r
+ // TRUE if PCI Interupt Line registers have been programmed.\r
+ //\r
+ BOOLEAN PciInterruptLine;\r
+\r
+ //\r
+ // Code space below 1MB needed by thunker to transition to real mode.\r
+ // Contains stack and real mode code fragments\r
+ //\r
+ LOW_MEMORY_THUNK *IntThunk;\r
+\r
+ //\r
+ // Starting shadow address of the Legacy BIOS\r
+ //\r
+ UINT32 BiosStart;\r
+ UINT32 LegacyBiosImageSize;\r
+\r
+ //\r
+ // Start of variables used by CsmItp.mac ITP macro file and/os LegacyBios\r
+ //\r
+ UINT8 Dump[4];\r
+\r
+ //\r
+ // $EFI Legacy16 code entry info in memory < 1 MB;\r
+ //\r
+ EFI_COMPATIBILITY16_TABLE *Legacy16Table;\r
+ VOID *Legacy16InitPtr;\r
+ VOID *Legacy16BootPtr;\r
+ VOID *InternalIrqRoutingTable;\r
+ UINT32 NumberIrqRoutingEntries;\r
+ VOID *BbsTablePtr;\r
+ VOID *HddTablePtr;\r
+ UINT32 NumberHddControllers;\r
+\r
+ //\r
+ // Cached copy of Legacy16 entry point\r
+ //\r
+ UINT16 Legacy16CallSegment;\r
+ UINT16 Legacy16CallOffset;\r
+\r
+ //\r
+ // Returned from $EFI and passed in to OPROMS\r
+ //\r
+ UINT16 PnPInstallationCheckSegment;\r
+ UINT16 PnPInstallationCheckOffset;\r
+\r
+ //\r
+ // E820 table\r
+ //\r
+ EFI_E820_ENTRY E820Table[EFI_MAX_E820_ENTRY];\r
+ UINT32 NumberE820Entries;\r
+\r
+ //\r
+ // True if legacy VGA INT 10h handler installed\r
+ //\r
+ BOOLEAN VgaInstalled;\r
+\r
+ //\r
+ // Number of IDE drives\r
+ //\r
+ UINT8 IdeDriveCount;\r
+\r
+ //\r
+ // Current Free Option ROM space. An option ROM must NOT go past\r
+ // BiosStart.\r
+ //\r
+ UINT32 OptionRom;\r
+\r
+ //\r
+ // Save Legacy16 unexpected interrupt vector. Reprogram INT 68-6F from\r
+ // EFI values to legacy value just before boot.\r
+ //\r
+ UINT32 BiosUnexpectedInt;\r
+ UINT32 ThunkSavedInt[8];\r
+ UINT16 ThunkSeg;\r
+ LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable;\r
+ UINT16 LegacyEfiHddTableIndex;\r
+ UINT8 DiskEnd;\r
+ UINT8 Disk4075;\r
+ UINT16 TraceIndex;\r
+ UINT16 Trace[0x200];\r
+\r
+ //\r
+ // Indicate that whether GenericLegacyBoot is entered or not\r
+ //\r
+ BOOLEAN LegacyBootEntered; \r
+\r
+ //\r
+ // CSM16 PCI Interface Version\r
+ //\r
+ UINT16 Csm16PciInterfaceVersion;\r
+\r
+} LEGACY_BIOS_INSTANCE;\r
+\r
+\r
+#pragma pack(1)\r
+\r
+/*\r
+ 40:00-01 Com1\r
+ 40:02-03 Com2\r
+ 40:04-05 Com3\r
+ 40:06-07 Com4\r
+ 40:08-09 Lpt1\r
+ 40:0A-0B Lpt2\r
+ 40:0C-0D Lpt3\r
+ 40:0E-0E Ebda segment\r
+ 40:10-11 MachineConfig\r
+ 40:12 Bda12 - skip\r
+ 40:13-14 MemSize below 1MB\r
+ 40:15-16 Bda15_16 - skip\r
+ 40:17 Keyboard Shift status\r
+ 40:18-19 Bda18_19 - skip\r
+ 40:1A-1B Key buffer head\r
+ 40:1C-1D Key buffer tail\r
+ 40:1E-3D Bda1E_3D- key buffer -skip\r
+ 40:3E-3F FloppyData 3E = Calibration status 3F = Motor status\r
+ 40:40 FloppyTimeout\r
+ 40:41-74 Bda41_74 - skip\r
+ 40:75 Number of HDD drives\r
+ 40:76-77 Bda76_77 - skip\r
+ 40:78-79 78 = Lpt1 timeout, 79 = Lpt2 timeout\r
+ 40:7A-7B 7A = Lpt3 timeout, 7B = Lpt4 timeout\r
+ 40:7C-7D 7C = Com1 timeout, 7D = Com2 timeout\r
+ 40:7E-7F 7E = Com3 timeout, 7F = Com4 timeout\r
+ 40:80-81 Pointer to start of key buffer\r
+ 40:82-83 Pointer to end of key buffer\r
+ 40:84-87 Bda84_87 - skip\r
+ 40:88 HDD Data Xmit rate\r
+ 40:89-8f skip\r
+ 40:90 Floppy data rate\r
+ 40:91-95 skip\r
+ 40:96 Keyboard Status\r
+ 40:97 LED Status\r
+ 40:98-101 skip\r
+*/\r
+typedef struct {\r
+ UINT16 Com1;\r
+ UINT16 Com2;\r
+ UINT16 Com3;\r
+ UINT16 Com4;\r
+ UINT16 Lpt1;\r
+ UINT16 Lpt2;\r
+ UINT16 Lpt3;\r
+ UINT16 Ebda;\r
+ UINT16 MachineConfig;\r
+ UINT8 Bda12;\r
+ UINT16 MemSize;\r
+ UINT8 Bda15_16[0x02];\r
+ UINT8 ShiftStatus;\r
+ UINT8 Bda18_19[0x02];\r
+ UINT16 KeyHead;\r
+ UINT16 KeyTail;\r
+ UINT16 Bda1E_3D[0x10];\r
+ UINT16 FloppyData;\r
+ UINT8 FloppyTimeout;\r
+ UINT8 Bda41_74[0x34];\r
+ UINT8 NumberOfDrives;\r
+ UINT8 Bda76_77[0x02];\r
+ UINT16 Lpt1_2Timeout;\r
+ UINT16 Lpt3_4Timeout;\r
+ UINT16 Com1_2Timeout;\r
+ UINT16 Com3_4Timeout;\r
+ UINT16 KeyStart;\r
+ UINT16 KeyEnd;\r
+ UINT8 Bda84_87[0x4];\r
+ UINT8 DataXmit;\r
+ UINT8 Bda89_8F[0x07];\r
+ UINT8 FloppyXRate;\r
+ UINT8 Bda91_95[0x05];\r
+ UINT8 KeyboardStatus;\r
+ UINT8 LedStatus;\r
+} BDA_STRUC;\r
+#pragma pack()\r
+\r
+#define LEGACY_BIOS_INSTANCE_FROM_THIS(this) CR (this, LEGACY_BIOS_INSTANCE, LegacyBios, LEGACY_BIOS_INSTANCE_SIGNATURE)\r
+\r
+/**\r
+ Thunk to 16-bit real mode and execute a software interrupt with a vector\r
+ of BiosInt. Regs will contain the 16-bit register context on entry and\r
+ exit.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BiosInt Processor interrupt vector to invoke\r
+ @param Regs Register contexted passed into (and returned) from thunk to\r
+ 16-bit mode\r
+\r
+ @retval FALSE Thunk completed, and there were no BIOS errors in the target code.\r
+ See Regs for status.\r
+ @retval TRUE There was a BIOS erro in the target code.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosInt86 (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT8 BiosInt,\r
+ IN EFI_IA32_REGISTER_SET *Regs\r
+ );\r
+\r
+\r
+/**\r
+ Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the\r
+ 16-bit register context on entry and exit. Arguments can be passed on\r
+ the Stack argument\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Segment Segemnt of 16-bit mode call\r
+ @param Offset Offset of 16-bit mdoe call\r
+ @param Regs Register contexted passed into (and returned) from\r
+ thunk to 16-bit mode\r
+ @param Stack Caller allocated stack used to pass arguments\r
+ @param StackSize Size of Stack in bytes\r
+\r
+ @retval FALSE Thunk completed, and there were no BIOS errors in\r
+ the target code. See Regs for status.\r
+ @retval TRUE There was a BIOS erro in the target code.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosFarCall86 (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT16 Segment,\r
+ IN UINT16 Offset,\r
+ IN EFI_IA32_REGISTER_SET *Regs,\r
+ IN VOID *Stack,\r
+ IN UINTN StackSize\r
+ );\r
+\r
+\r
+/**\r
+ Test to see if a legacy PCI ROM exists for this device. Optionally return\r
+ the Legacy ROM instance for this PCI device.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will\r
+ be loaded\r
+ @param RomImage Return the legacy PCI ROM for this device\r
+ @param RomSize Size of ROM Image\r
+ @param Flags Indicates if ROM found and if PC-AT.\r
+\r
+ @retval EFI_SUCCESS Legacy Option ROM availible for this device\r
+ @retval EFI_UNSUPPORTED Legacy Option ROM not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosCheckPciRom (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN EFI_HANDLE PciHandle,\r
+ OUT VOID **RomImage, OPTIONAL\r
+ OUT UINTN *RomSize, OPTIONAL\r
+ OUT UINTN *Flags\r
+ );\r
+\r
+\r
+/**\r
+ Assign drive number to legacy HDD drives prior to booting an EFI\r
+ aware OS so the OS can access drives without an EFI driver.\r
+ Note: BBS compliant drives ARE NOT available until this call by\r
+ either shell or EFI.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BbsCount Number of BBS_TABLE structures\r
+ @param BbsTable List BBS entries\r
+\r
+ @retval EFI_SUCCESS Drive numbers assigned\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosPrepareToBootEfi (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ OUT UINT16 *BbsCount,\r
+ OUT BBS_TABLE **BbsTable\r
+ );\r
+\r
+\r
+/**\r
+ To boot from an unconventional device like parties and/or execute\r
+ HDD diagnostics.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Attributes How to interpret the other input parameters\r
+ @param BbsEntry The 0-based index into the BbsTable for the parent\r
+ device.\r
+ @param BeerData Pointer to the 128 bytes of ram BEER data.\r
+ @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data.\r
+ The caller must provide a pointer to the specific\r
+ Service Area and not the start all Service Areas.\r
+ EFI_INVALID_PARAMETER if error. Does NOT return if no error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosBootUnconventionalDevice (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UDC_ATTRIBUTES Attributes,\r
+ IN UINTN BbsEntry,\r
+ IN VOID *BeerData,\r
+ IN VOID *ServiceAreaData\r
+ );\r
+\r
+\r
+/**\r
+ Load a legacy PC-AT OPROM on the PciHandle device. Return information\r
+ about how many disks were added by the OPROM and the shadow address and\r
+ size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C:\r
+\r
+ @param This Protocol instance pointer.\r
+ @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will\r
+ be loaded. This value is NULL if RomImage is\r
+ non-NULL. This is the normal case.\r
+ @param RomImage A PCI PC-AT ROM image. This argument is non-NULL\r
+ if there is no hardware associated with the ROM\r
+ and thus no PciHandle, otherwise is must be NULL.\r
+ Example is PXE base code.\r
+ @param Flags Indicates if ROM found and if PC-AT.\r
+ @param DiskStart Disk number of first device hooked by the ROM. If\r
+ DiskStart is the same as DiskEnd no disked were\r
+ hooked.\r
+ @param DiskEnd Disk number of the last device hooked by the ROM.\r
+ @param RomShadowAddress Shadow address of PC-AT ROM\r
+ @param RomShadowedSize Size of RomShadowAddress in bytes\r
+\r
+ @retval EFI_SUCCESS Legacy ROM loaded for this device\r
+ @retval EFI_INVALID_PARAMETER PciHandle not found\r
+ @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no onboard\r
+ ROM\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosInstallPciRom (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL * This,\r
+ IN EFI_HANDLE PciHandle,\r
+ IN VOID **RomImage,\r
+ OUT UINTN *Flags,\r
+ OUT UINT8 *DiskStart, OPTIONAL\r
+ OUT UINT8 *DiskEnd, OPTIONAL\r
+ OUT VOID **RomShadowAddress, OPTIONAL\r
+ OUT UINT32 *RomShadowedSize OPTIONAL\r
+ );\r
+\r
+\r
+/**\r
+ Fill in the standard BDA for Keyboard LEDs\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Leds Current LED status\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosUpdateKeyboardLedStatus (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT8 Leds\r
+ );\r
+\r
+\r
+/**\r
+ Get all BBS info\r
+\r
+ @param This Protocol instance pointer.\r
+ @param HddCount Number of HDD_INFO structures\r
+ @param HddInfo Onboard IDE controller information\r
+ @param BbsCount Number of BBS_TABLE structures\r
+ @param BbsTable List BBS entries\r
+\r
+ @retval EFI_SUCCESS Tables returned\r
+ @retval EFI_NOT_FOUND resource not found\r
+ @retval EFI_DEVICE_ERROR can not get BBS table\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosGetBbsInfo (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ OUT UINT16 *HddCount,\r
+ OUT HDD_INFO **HddInfo,\r
+ OUT UINT16 *BbsCount,\r
+ OUT BBS_TABLE **BbsTable\r
+ );\r
+\r
+\r
+/**\r
+ Shadow all legacy16 OPROMs that haven't been shadowed.\r
+ Warning: Use this with caution. This routine disconnects all EFI\r
+ drivers. If used externally then caller must re-connect EFI\r
+ drivers.\r
+\r
+ @param This Protocol instance pointer.\r
+\r
+ @retval EFI_SUCCESS OPROMs shadowed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosShadowAllLegacyOproms (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This\r
+ );\r
+\r
+\r
+/**\r
+ Attempt to legacy boot the BootOption. If the EFI contexted has been\r
+ compromised this function will not return.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BbsDevicePath EFI Device Path from BootXXXX variable.\r
+ @param LoadOptionsSize Size of LoadOption in size.\r
+ @param LoadOptions LoadOption from BootXXXX variable\r
+\r
+ @retval EFI_SUCCESS Removable media not present\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosLegacyBoot (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN BBS_BBS_DEVICE_PATH *BbsDevicePath,\r
+ IN UINT32 LoadOptionsSize,\r
+ IN VOID *LoadOptions\r
+ );\r
+\r
+\r
+/**\r
+ Allocate memory < 1 MB and copy the thunker code into low memory. Se up\r
+ all the descriptors.\r
+\r
+ @param Private Private context for Legacy BIOS\r
+\r
+ @retval EFI_SUCCESS Should only pass.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosInitializeThunk (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ Fill in the standard BDA and EBDA stuff before Legacy16 load\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosInitBda (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ Collect IDE Inquiry data from the IDE disks\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param HddInfo Hdd Information\r
+ @param Flag Reconnect IdeController or not\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildIdeData (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN HDD_INFO **HddInfo,\r
+ IN UINT16 Flag\r
+ );\r
+\r
+\r
+/**\r
+ Enable ide controller. This gets disabled when LegacyBoot.c is about\r
+ to run the Option ROMs.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+\r
+**/\r
+VOID\r
+EnableIdeController (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ If the IDE channel is in compatibility (legacy) mode, remove all\r
+ PCI I/O BAR addresses from the controller.\r
+\r
+ @param IdeController The handle of target IDE controller\r
+\r
+\r
+**/\r
+VOID\r
+InitLegacyIdeController (\r
+ IN EFI_HANDLE IdeController\r
+ );\r
+\r
+\r
+/**\r
+ Program the interrupt routing register in all the PCI devices. On a PC AT system\r
+ this register contains the 8259 IRQ vector that matches it's PCI interrupt.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_ALREADY_STARTED All PCI devices have been processed.\r
+\r
+**/\r
+EFI_STATUS\r
+PciProgramAllInterruptLineRegisters (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ Collect EFI Info about legacy devices.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildSioData (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol\r
+ to chose the order. Skip any devices that have already have legacy\r
+ BIOS run.\r
+\r
+ @param Private Protocol instance pointer.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_UNSUPPORTED Cannot get VGA device handle.\r
+\r
+**/\r
+EFI_STATUS\r
+PciShadowRoms (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ Fill in the standard BDA and EBDA stuff prior to legacy Boot\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosCompleteBdaBeforeBoot (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ Fill in the standard CMOS stuff before Legacy16 load\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosInitCmos (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ Fill in the standard CMOS stuff prior to legacy Boot\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosCompleteStandardCmosBeforeBoot (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+\r
+/**\r
+ Contains the code that is copied into low memory (below 640K).\r
+ This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.\r
+ This template must be copied into low memory, and the IDT entries\r
+ 0x68-0x6F must be point to the low memory copy of this code. Each\r
+ entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily\r
+ computed.\r
+\r
+**/\r
+VOID\r
+InterruptRedirectionTemplate (\r
+ VOID\r
+ );\r
+\r
+\r
+/**\r
+ Build the E820 table.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param Size Size of E820 Table\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildE820 (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ OUT UINTN *Size\r
+ );\r
+\r
+/**\r
+ This function is to put all AP in halt state.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+**/\r
+VOID\r
+ShutdownAPs (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+/**\r
+ Worker function for LegacyBiosGetFlatDescs, retrieving content of\r
+ specific registers.\r
+\r
+ @param IntThunk Pointer to IntThunk of Legacy BIOS context.\r
+\r
+**/\r
+VOID\r
+GetRegisters (\r
+ LOW_MEMORY_THUNK *IntThunk\r
+ );\r
+\r
+/**\r
+ Routine for calling real thunk code.\r
+\r
+ @param RealCode The address of thunk code.\r
+ @param BiosInt The Bios interrupt vector number.\r
+ @param CallAddress The address of 16-bit mode call.\r
+\r
+ @return Status returned by real thunk code\r
+\r
+**/\r
+UINTN\r
+CallRealThunkCode (\r
+ UINT8 *RealCode,\r
+ UINT8 BiosInt,\r
+ UINT32 CallAddress\r
+ );\r
+\r
+/**\r
+ Routine for generating soft interrupt.\r
+\r
+ @param Vector The interrupt vector number.\r
+\r
+**/\r
+VOID\r
+GenerateSoftInit (\r
+ UINT8 Vector\r
+ );\r
+\r
+/**\r
+ Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode\r
+ memory.\r
+\r
+ @param AllocateType Allocated Legacy Memory Type\r
+ @param StartPageAddress Start address of range\r
+ @param Pages Number of pages to allocate\r
+ @param Result Result of allocation\r
+\r
+ @retval EFI_SUCCESS Legacy16 code loaded\r
+ @retval Other No protocol installed, unload driver.\r
+\r
+**/\r
+EFI_STATUS\r
+AllocateLegacyMemory (\r
+ IN EFI_ALLOCATE_TYPE AllocateType,\r
+ IN EFI_PHYSICAL_ADDRESS StartPageAddress,\r
+ IN UINTN Pages,\r
+ OUT EFI_PHYSICAL_ADDRESS *Result\r
+ );\r
+\r
+/**\r
+ Get a region from the LegacyBios for Tiano usage. Can only be invoked once.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param LegacyMemorySize Size of required region\r
+ @param Region Region to use. 00 = Either 0xE0000 or 0xF0000\r
+ block Bit0 = 1 0xF0000 block Bit1 = 1 0xE0000\r
+ block\r
+ @param Alignment Address alignment. Bit mapped. First non-zero\r
+ bit from right is alignment.\r
+ @param LegacyMemoryAddress Region Assigned\r
+\r
+ @retval EFI_SUCCESS Region assigned\r
+ @retval EFI_ACCESS_DENIED Procedure previously invoked\r
+ @retval Other Region not assigned\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosGetLegacyRegion (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINTN LegacyMemorySize,\r
+ IN UINTN Region,\r
+ IN UINTN Alignment,\r
+ OUT VOID **LegacyMemoryAddress\r
+ );\r
+\r
+/**\r
+ Get a region from the LegacyBios for Tiano usage. Can only be invoked once.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param LegacyMemorySize Size of data to copy\r
+ @param LegacyMemoryAddress Legacy Region destination address Note: must\r
+ be in region assigned by\r
+ LegacyBiosGetLegacyRegion\r
+ @param LegacyMemorySourceAddress Source of data\r
+\r
+ @retval EFI_SUCCESS Region assigned\r
+ @retval EFI_ACCESS_DENIED Destination outside assigned region\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosCopyLegacyRegion (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINTN LegacyMemorySize,\r
+ IN VOID *LegacyMemoryAddress,\r
+ IN VOID *LegacyMemorySourceAddress\r
+ );\r
+\r
+/**\r
+ Find Legacy16 BIOS image in the FLASH device and shadow it into memory. Find\r
+ the $EFI table in the shadow area. Thunk into the Legacy16 code after it had\r
+ been shadowed.\r
+\r
+ @param Private Legacy BIOS context data\r
+\r
+ @retval EFI_SUCCESS Legacy16 code loaded\r
+ @retval Other No protocol installed, unload driver.\r
+\r
+**/\r
+EFI_STATUS\r
+ShadowAndStartLegacy16 (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ );\r
+\r
+/**\r
+ Checks the state of the floppy and if media is inserted.\r
+ \r
+ This routine checks the state of the floppy and if media is inserted.\r
+ There are 3 cases:\r
+ No floppy present - Set BBS entry to ignore\r
+ Floppy present & no media - Set BBS entry to lowest priority. We cannot\r
+ set it to ignore since 16-bit CSM will\r
+ indicate no floppy and thus drive A: is\r
+ unusable. CSM-16 will not try floppy since\r
+ lowest priority and thus not incur boot\r
+ time penality.\r
+ Floppy present & media - Set BBS entry to some priority.\r
+\r
+ @return State of floppy media\r
+\r
+**/\r
+UINT8\r
+HasMediaInFloppy (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Identify drive data must be updated to actual parameters before boot.\r
+ This requires updating the checksum, if it exists.\r
+\r
+ @param IdentifyDriveData ATA Identify Data\r
+ @param Checksum checksum of the ATA Identify Data\r
+\r
+ @retval EFI_SUCCESS checksum calculated\r
+ @retval EFI_SECURITY_VIOLATION IdentifyData invalid\r
+\r
+**/\r
+EFI_STATUS\r
+CalculateIdentifyDriveChecksum (\r
+ IN UINT8 *IdentifyDriveData,\r
+ OUT UINT8 *Checksum\r
+ );\r
+\r
+/**\r
+ Identify drive data must be updated to actual parameters before boot.\r
+\r
+ @param IdentifyDriveData ATA Identify Data\r
+\r
+**/\r
+VOID\r
+UpdateIdentifyDriveData (\r
+ IN UINT8 *IdentifyDriveData\r
+ );\r
+\r
+/**\r
+ Complete build of BBS TABLE.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param BbsTable BBS Table passed to 16-bit code\r
+\r
+ @retval EFI_SUCCESS Removable media not present\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildBbs (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN BBS_TABLE *BbsTable\r
+ );\r
+\r
+/**\r
+ Read CMOS register through index/data port.\r
+\r
+ @param[in] Index The index of the CMOS register to read.\r
+\r
+ @return The data value from the CMOS register specified by Index.\r
+\r
+**/\r
+UINT8\r
+LegacyReadStandardCmos (\r
+ IN UINT8 Index\r
+ );\r
+\r
+/**\r
+ Write CMOS register through index/data port.\r
+\r
+ @param[in] Index The index of the CMOS register to write.\r
+ @param[in] Value The value of CMOS register to write.\r
+\r
+ @return The value written to the CMOS register specified by Index.\r
+\r
+**/\r
+UINT8\r
+LegacyWriteStandardCmos (\r
+ IN UINT8 Index,\r
+ IN UINT8 Value\r
+ );\r
+\r
+/**\r
+ Calculate the new standard CMOS checksum and write it.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS Calculate 16-bit checksum successfully\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyCalculateWriteStandardCmosChecksum (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Test to see if a legacy PCI ROM exists for this device. Optionally return\r
+ the Legacy ROM instance for this PCI device.\r
+\r
+ @param[in] This Protocol instance pointer.\r
+ @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded\r
+ @param[out] RomImage Return the legacy PCI ROM for this device\r
+ @param[out] RomSize Size of ROM Image\r
+ @param[out] RuntimeImageLength Runtime size of ROM Image\r
+ @param[out] Flags Indicates if ROM found and if PC-AT.\r
+ @param[out] OpromRevision Revision of the PCI Rom\r
+ @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header\r
+\r
+ @return EFI_SUCCESS Legacy Option ROM availible for this device\r
+ @return EFI_ALREADY_STARTED This device is already managed by its Oprom\r
+ @return EFI_UNSUPPORTED Legacy Option ROM not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosCheckPciRomEx (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN EFI_HANDLE PciHandle,\r
+ OUT VOID **RomImage, OPTIONAL\r
+ OUT UINTN *RomSize, OPTIONAL\r
+ OUT UINTN *RuntimeImageLength, OPTIONAL\r
+ OUT UINTN *Flags, OPTIONAL\r
+ OUT UINT8 *OpromRevision, OPTIONAL\r
+ OUT VOID **ConfigUtilityCodeHeader OPTIONAL\r
+ );\r
+\r
+/**\r
+ Relocate this image under 4G memory for IPF.\r
+\r
+ @param ImageHandle Handle of driver image.\r
+ @param SystemTable Pointer to system table.\r
+\r
+ @retval EFI_SUCCESS Image successfully relocated.\r
+ @retval EFI_ABORTED Failed to relocate image.\r
+\r
+**/\r
+EFI_STATUS\r
+RelocateImageUnder4GIfNeeded (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ );\r
+\r
+/**\r
+ Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the\r
+ 16-bit register context on entry and exit. Arguments can be passed on\r
+ the Stack argument\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Segment Segemnt of 16-bit mode call\r
+ @param Offset Offset of 16-bit mdoe call\r
+ @param Regs Register contexted passed into (and returned) from thunk to\r
+ 16-bit mode\r
+ @param Stack Caller allocated stack used to pass arguments\r
+ @param StackSize Size of Stack in bytes\r
+\r
+ @retval FALSE Thunk completed, and there were no BIOS errors in the target code.\r
+ See Regs for status.\r
+ @retval TRUE There was a BIOS erro in the target code.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalLegacyBiosFarCall (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT16 Segment,\r
+ IN UINT16 Offset,\r
+ IN EFI_IA32_REGISTER_SET *Regs,\r
+ IN VOID *Stack,\r
+ IN UINTN StackSize\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#define BOOT_LEGACY_OS 0\r
+#define BOOT_EFI_OS 1\r
+#define BOOT_UNCONVENTIONAL_DEVICE 2\r
+\r
+UINT32 mLoadOptionsSize = 0;\r
+UINTN mBootMode = BOOT_LEGACY_OS;\r
+VOID *mLoadOptions = NULL;\r
+BBS_BBS_DEVICE_PATH *mBbsDevicePathPtr = NULL;\r
+BBS_BBS_DEVICE_PATH mBbsDevicePathNode;\r
+UDC_ATTRIBUTES mAttributes = { 0, 0, 0, 0 };\r
+UINTN mBbsEntry = 0;\r
+VOID *mBeerData = NULL;\r
+VOID *mServiceAreaData = NULL;\r
+UINT64 mLowWater = 0xffffffffffffffffULL;\r
+\r
+extern BBS_TABLE *mBbsTable;\r
+\r
+/**\r
+ Print the BBS Table.\r
+\r
+ @param BbsTable The BBS table.\r
+\r
+\r
+**/\r
+VOID\r
+PrintBbsTable (\r
+ IN BBS_TABLE *BbsTable\r
+ )\r
+{\r
+ UINT16 Index;\r
+ UINT16 SubIndex;\r
+ CHAR8 *String;\r
+\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+ DEBUG ((EFI_D_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs mfgs:mfgo dess:deso\n"));\r
+ DEBUG ((EFI_D_INFO, "=================================================================\n"));\r
+ for (Index = 0; Index < MAX_BBS_ENTRIES; Index++) {\r
+ //\r
+ // Filter\r
+ //\r
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+ continue;\r
+ }\r
+\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x",\r
+ (UINTN) Index,\r
+ (UINTN) BbsTable[Index].BootPriority,\r
+ (UINTN) BbsTable[Index].Bus,\r
+ (UINTN) BbsTable[Index].Device,\r
+ (UINTN) BbsTable[Index].Function,\r
+ (UINTN) BbsTable[Index].Class,\r
+ (UINTN) BbsTable[Index].SubClass,\r
+ (UINTN) BbsTable[Index].DeviceType,\r
+ (UINTN) * (UINT16 *) &BbsTable[Index].StatusFlags\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ " %04x:%04x %04x:%04x %04x:%04x",\r
+ (UINTN) BbsTable[Index].BootHandlerSegment,\r
+ (UINTN) BbsTable[Index].BootHandlerOffset,\r
+ (UINTN) BbsTable[Index].MfgStringSegment,\r
+ (UINTN) BbsTable[Index].MfgStringOffset,\r
+ (UINTN) BbsTable[Index].DescStringSegment,\r
+ (UINTN) BbsTable[Index].DescStringOffset\r
+ ));\r
+\r
+ //\r
+ // Print DescString\r
+ //\r
+ String = (CHAR8 *)(UINTN)((BbsTable[Index].DescStringSegment << 4) + BbsTable[Index].DescStringOffset);\r
+ if (String != NULL) {\r
+ DEBUG ((EFI_D_INFO," ("));\r
+ for (SubIndex = 0; String[SubIndex] != 0; SubIndex++) {\r
+ DEBUG ((EFI_D_INFO, "%c", String[SubIndex]));\r
+ }\r
+ DEBUG ((EFI_D_INFO,")"));\r
+ }\r
+ DEBUG ((EFI_D_INFO,"\n"));\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Print the BBS Table.\r
+\r
+ @param HddInfo The HddInfo table.\r
+\r
+\r
+**/\r
+VOID\r
+PrintHddInfo (\r
+ IN HDD_INFO *HddInfo\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+ for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {\r
+ DEBUG ((EFI_D_INFO, "Index - %04x\n", Index));\r
+ DEBUG ((EFI_D_INFO, " Status - %04x\n", (UINTN)HddInfo[Index].Status));\r
+ DEBUG ((EFI_D_INFO, " B/D/F - %02x/%02x/%02x\n", (UINTN)HddInfo[Index].Bus, (UINTN)HddInfo[Index].Device, (UINTN)HddInfo[Index].Function));\r
+ DEBUG ((EFI_D_INFO, " Command - %04x\n", HddInfo[Index].CommandBaseAddress));\r
+ DEBUG ((EFI_D_INFO, " Control - %04x\n", HddInfo[Index].ControlBaseAddress));\r
+ DEBUG ((EFI_D_INFO, " BusMaster - %04x\n", HddInfo[Index].BusMasterAddress));\r
+ DEBUG ((EFI_D_INFO, " HddIrq - %02x\n", HddInfo[Index].HddIrq));\r
+ DEBUG ((EFI_D_INFO, " IdentifyDrive[0].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[0].Raw[0]));\r
+ DEBUG ((EFI_D_INFO, " IdentifyDrive[1].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[1].Raw[0]));\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Identify drive data must be updated to actual parameters before boot.\r
+\r
+ @param IdentifyDriveData ATA Identify Data\r
+\r
+**/\r
+VOID\r
+UpdateIdentifyDriveData (\r
+ IN UINT8 *IdentifyDriveData\r
+ );\r
+\r
+/**\r
+ Update SIO data.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS Removable media not present\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateSioData (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ UINT8 LegacyInterrupts[16];\r
+ EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable;\r
+ UINTN RoutingTableEntries;\r
+ EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY *IrqPriorityTable;\r
+ UINTN NumberPriorityEntries;\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
+ UINT8 HddIrq;\r
+ UINT16 LegacyInt;\r
+ UINT16 LegMask;\r
+ UINT32 Register;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ EFI_ISA_IO_PROTOCOL *IsaIo;\r
+\r
+ LegacyInt = 0;\r
+ HandleBuffer = NULL;\r
+\r
+ EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
+ LegacyBiosBuildSioData (Private);\r
+ SetMem (LegacyInterrupts, sizeof (LegacyInterrupts), 0);\r
+\r
+ //\r
+ // Create list of legacy interrupts.\r
+ //\r
+ for (Index = 0; Index < 4; Index++) {\r
+ LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Serial[Index].Irq;\r
+ }\r
+\r
+ for (Index = 4; Index < 7; Index++) {\r
+ LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Parallel[Index - 4].Irq;\r
+ }\r
+\r
+ LegacyInterrupts[7] = EfiToLegacy16BootTable->SioData.Floppy.Irq;\r
+\r
+ //\r
+ // Get Legacy Hdd IRQs. If native mode treat as PCI\r
+ //\r
+ for (Index = 0; Index < 2; Index++) {\r
+ HddIrq = EfiToLegacy16BootTable->HddInfo[Index].HddIrq;\r
+ if ((HddIrq != 0) && ((HddIrq == 15) || (HddIrq == 14))) {\r
+ LegacyInterrupts[Index + 8] = HddIrq;\r
+ }\r
+ }\r
+\r
+ Private->LegacyBiosPlatform->GetRoutingTable (\r
+ Private->LegacyBiosPlatform,\r
+ (VOID *) &RoutingTable,\r
+ &RoutingTableEntries,\r
+ NULL,\r
+ NULL,\r
+ (VOID **) &IrqPriorityTable,\r
+ &NumberPriorityEntries\r
+ );\r
+ //\r
+ // Remove legacy interrupts from the list of PCI interrupts available.\r
+ //\r
+ for (Index = 0; Index <= 0x0b; Index++) {\r
+ for (Index1 = 0; Index1 <= NumberPriorityEntries; Index1++) {\r
+ if (LegacyInterrupts[Index] != 0) {\r
+ LegacyInt = (UINT16) (LegacyInt | (1 << LegacyInterrupts[Index]));\r
+ if (LegacyInterrupts[Index] == IrqPriorityTable[Index1].Irq) {\r
+ IrqPriorityTable[Index1].Used = LEGACY_USED;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ Private->Legacy8259->GetMask (\r
+ Private->Legacy8259,\r
+ &LegMask,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // Set SIO interrupts and disable mouse. Let mouse driver\r
+ // re-enable it.\r
+ //\r
+ LegMask = (UINT16) ((LegMask &~LegacyInt) | 0x1000);\r
+ Private->Legacy8259->SetMask (\r
+ Private->Legacy8259,\r
+ &LegMask,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // Disable mouse in keyboard controller\r
+ //\r
+ Register = 0xA7;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiIsaIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiIsaIoProtocolGuid,\r
+ (VOID **) &IsaIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, 0x64, 1, &Register);\r
+\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Identify drive data must be updated to actual parameters before boot.\r
+ This requires updating the checksum, if it exists.\r
+\r
+ @param IdentifyDriveData ATA Identify Data\r
+ @param Checksum checksum of the ATA Identify Data\r
+\r
+ @retval EFI_SUCCESS checksum calculated\r
+ @retval EFI_SECURITY_VIOLATION IdentifyData invalid\r
+\r
+**/\r
+EFI_STATUS\r
+CalculateIdentifyDriveChecksum (\r
+ IN UINT8 *IdentifyDriveData,\r
+ OUT UINT8 *Checksum\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 LocalChecksum;\r
+ LocalChecksum = 0;\r
+ *Checksum = 0;\r
+ if (IdentifyDriveData[510] != 0xA5) {\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+\r
+ for (Index = 0; Index < 512; Index++) {\r
+ LocalChecksum = (UINT8) (LocalChecksum + IdentifyDriveData[Index]);\r
+ }\r
+\r
+ *Checksum = LocalChecksum;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Identify drive data must be updated to actual parameters before boot.\r
+\r
+ @param IdentifyDriveData ATA Identify Data\r
+\r
+\r
+**/\r
+VOID\r
+UpdateIdentifyDriveData (\r
+ IN UINT8 *IdentifyDriveData\r
+ )\r
+{\r
+ UINT16 NumberCylinders;\r
+ UINT16 NumberHeads;\r
+ UINT16 NumberSectorsTrack;\r
+ UINT32 CapacityInSectors;\r
+ UINT8 OriginalChecksum;\r
+ UINT8 FinalChecksum;\r
+ EFI_STATUS Status;\r
+ ATAPI_IDENTIFY *ReadInfo;\r
+\r
+ //\r
+ // Status indicates if Integrity byte is correct. Checksum should be\r
+ // 0 if valid.\r
+ //\r
+ ReadInfo = (ATAPI_IDENTIFY *) IdentifyDriveData;\r
+ Status = CalculateIdentifyDriveChecksum (IdentifyDriveData, &OriginalChecksum);\r
+ if (OriginalChecksum != 0) {\r
+ Status = EFI_SECURITY_VIOLATION;\r
+ }\r
+ //\r
+ // If NumberCylinders = 0 then do data(Controller present but don drive attached).\r
+ //\r
+ NumberCylinders = ReadInfo->Raw[1];\r
+ if (NumberCylinders != 0) {\r
+ ReadInfo->Raw[54] = NumberCylinders;\r
+\r
+ NumberHeads = ReadInfo->Raw[3];\r
+ ReadInfo->Raw[55] = NumberHeads;\r
+\r
+ NumberSectorsTrack = ReadInfo->Raw[6];\r
+ ReadInfo->Raw[56] = NumberSectorsTrack;\r
+\r
+ //\r
+ // Copy Multisector info and set valid bit.\r
+ //\r
+ ReadInfo->Raw[59] = (UINT16) (ReadInfo->Raw[47] + 0x100);\r
+ CapacityInSectors = (UINT32) ((UINT32) (NumberCylinders) * (UINT32) (NumberHeads) * (UINT32) (NumberSectorsTrack));\r
+ ReadInfo->Raw[57] = (UINT16) (CapacityInSectors >> 16);\r
+ ReadInfo->Raw[58] = (UINT16) (CapacityInSectors & 0xffff);\r
+ if (Status == EFI_SUCCESS) {\r
+ //\r
+ // Forece checksum byte to 0 and get new checksum.\r
+ //\r
+ ReadInfo->Raw[255] &= 0xff;\r
+ CalculateIdentifyDriveChecksum (IdentifyDriveData, &FinalChecksum);\r
+\r
+ //\r
+ // Force new checksum such that sum is 0.\r
+ //\r
+ FinalChecksum = (UINT8) ((UINT8)0 - FinalChecksum);\r
+ ReadInfo->Raw[255] = (UINT16) (ReadInfo->Raw[255] | (FinalChecksum << 8));\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Identify drive data must be updated to actual parameters before boot.\r
+ Do for all drives.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+\r
+**/\r
+VOID\r
+UpdateAllIdentifyDriveData (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ UINTN Index;\r
+ HDD_INFO *HddInfo;\r
+\r
+ HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];\r
+\r
+ for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {\r
+ //\r
+ // Each controller can have 2 devices. Update for each device\r
+ //\r
+ if ((HddInfo[Index].Status & HDD_MASTER_IDE) != 0) {\r
+ UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[0].Raw[0]));\r
+ }\r
+\r
+ if ((HddInfo[Index].Status & HDD_SLAVE_IDE) != 0) {\r
+ UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[1].Raw[0]));\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Enable ide controller. This gets disabled when LegacyBoot.c is about\r
+ to run the Option ROMs.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+\r
+**/\r
+VOID\r
+EnableIdeController (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE IdeController;\r
+ UINT8 ByteBuffer;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+\r
+ Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformIdeHandle,\r
+ 0,\r
+ &HandleBuffer,\r
+ &HandleCount,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ IdeController = HandleBuffer[0];\r
+ Status = gBS->HandleProtocol (\r
+ IdeController,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ ByteBuffer = 0x1f;\r
+ if (!EFI_ERROR (Status)) {\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x04, 1, &ByteBuffer);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Enable ide controller. This gets disabled when LegacyBoot.c is about\r
+ to run the Option ROMs.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+\r
+**/\r
+VOID\r
+EnableAllControllers (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE01 PciConfigHeader;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ //\r
+ //\r
+ EnableIdeController (Private);\r
+\r
+ //\r
+ // Assumption is table is built from low bus to high bus numbers.\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (PciConfigHeader) / sizeof (UINT32),\r
+ &PciConfigHeader\r
+ );\r
+\r
+ //\r
+ // We do not enable PPB here. This is for HotPlug Consideration.\r
+ // The Platform HotPlug Driver is responsible for Padding enough hot plug\r
+ // resources. It is also responsible for enable this bridge. If it\r
+ // does not pad it. It will cause some early Windows fail to installation.\r
+ // If the platform driver does not pad resource for PPB, PPB should be in\r
+ // un-enabled state to let Windows know that this PPB is not configured by\r
+ // BIOS. So Windows will allocate default resource for PPB.\r
+ //\r
+ // The reason for why we enable the command register is:\r
+ // The CSM will use the IO bar to detect some IRQ status, if the command\r
+ // is disabled, the IO resource will be out of scope.\r
+ // For example:\r
+ // We installed a legacy IRQ handle for a PCI IDE controller. When IRQ\r
+ // comes up, the handle will check the IO space to identify is the\r
+ // controller generated the IRQ source.\r
+ // If the IO command is not enabled, the IRQ handler will has wrong\r
+ // information. It will cause IRQ storm when the correctly IRQ handler fails\r
+ // to run.\r
+ //\r
+ if (!(IS_PCI_VGA (&PciConfigHeader) ||\r
+ IS_PCI_OLD_VGA (&PciConfigHeader) ||\r
+ IS_PCI_IDE (&PciConfigHeader) ||\r
+ IS_PCI_P2P (&PciConfigHeader) ||\r
+ IS_PCI_P2P_SUB (&PciConfigHeader) ||\r
+ IS_PCI_LPC (&PciConfigHeader) )) {\r
+\r
+ PciConfigHeader.Hdr.Command |= 0x1f;\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 4, 1, &PciConfigHeader.Hdr.Command);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ The following routines are identical in operation, so combine\r
+ for code compaction:\r
+ EfiGetPlatformBinaryGetMpTable\r
+ EfiGetPlatformBinaryGetOemIntData\r
+ EfiGetPlatformBinaryGetOem32Data\r
+ EfiGetPlatformBinaryGetOem16Data\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Id Table/Data identifier\r
+\r
+ @retval EFI_SUCCESS Success\r
+ @retval EFI_INVALID_PARAMETER Invalid ID\r
+ @retval EFI_OUT_OF_RESOURCES no resource to get data or table\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyGetDataOrTable (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN EFI_GET_PLATFORM_INFO_MODE Id\r
+ )\r
+{\r
+ VOID *Table;\r
+ UINT32 TablePtr;\r
+ UINTN TableSize;\r
+ UINTN Alignment;\r
+ UINTN Location;\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;\r
+ EFI_COMPATIBILITY16_TABLE *Legacy16Table;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+\r
+ LegacyBiosPlatform = Private->LegacyBiosPlatform;\r
+ Legacy16Table = Private->Legacy16Table;\r
+\r
+ //\r
+ // Phase 1 - get an address allocated in 16-bit code\r
+ //\r
+ while (TRUE) {\r
+ switch (Id) {\r
+ case EfiGetPlatformBinaryMpTable:\r
+ case EfiGetPlatformBinaryOemIntData:\r
+ case EfiGetPlatformBinaryOem32Data:\r
+ case EfiGetPlatformBinaryOem16Data:\r
+ {\r
+ Status = LegacyBiosPlatform->GetPlatformInfo (\r
+ LegacyBiosPlatform,\r
+ Id,\r
+ (VOID *) &Table,\r
+ &TableSize,\r
+ &Location,\r
+ &Alignment,\r
+ 0,\r
+ 0\r
+ );\r
+ DEBUG ((EFI_D_INFO, "LegacyGetDataOrTable - ID: %x, %r\n", (UINTN)Id, Status));\r
+ DEBUG ((EFI_D_INFO, " Table - %x, Size - %x, Location - %x, Alignment - %x\n", (UINTN)Table, (UINTN)TableSize, (UINTN)Location, (UINTN)Alignment));\r
+ break;\r
+ }\r
+\r
+ default:\r
+ {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16GetTableAddress;\r
+ Regs.X.CX = (UINT16) TableSize;\r
+ Regs.X.BX = (UINT16) Location;\r
+ Regs.X.DX = (UINT16) Alignment;\r
+ Private->LegacyBios.FarCall86 (\r
+ This,\r
+ Private->Legacy16CallSegment,\r
+ Private->Legacy16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ if (Regs.X.AX != 0) {\r
+ DEBUG ((EFI_D_ERROR, "Table ID %x length insufficient\n", Id));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Phase 2 Call routine second time with address to allow address adjustment\r
+ //\r
+ Status = LegacyBiosPlatform->GetPlatformInfo (\r
+ LegacyBiosPlatform,\r
+ Id,\r
+ (VOID *) &Table,\r
+ &TableSize,\r
+ &Location,\r
+ &Alignment,\r
+ Regs.X.DS,\r
+ Regs.X.BX\r
+ );\r
+ switch (Id) {\r
+ case EfiGetPlatformBinaryMpTable:\r
+ {\r
+ Legacy16Table->MpTablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
+ Legacy16Table->MpTableLength = (UINT32)TableSize;\r
+ DEBUG ((EFI_D_INFO, "MP table in legacy region - %x\n", (UINTN)Legacy16Table->MpTablePtr));\r
+ break;\r
+ }\r
+\r
+ case EfiGetPlatformBinaryOemIntData:\r
+ {\r
+\r
+ Legacy16Table->OemIntSegment = Regs.X.DS;\r
+ Legacy16Table->OemIntOffset = Regs.X.BX;\r
+ DEBUG ((EFI_D_INFO, "OemInt table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->OemIntSegment, (UINTN)Legacy16Table->OemIntOffset));\r
+ break;\r
+ }\r
+\r
+ case EfiGetPlatformBinaryOem32Data:\r
+ {\r
+ Legacy16Table->Oem32Segment = Regs.X.DS;\r
+ Legacy16Table->Oem32Offset = Regs.X.BX;\r
+ DEBUG ((EFI_D_INFO, "Oem32 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem32Segment, (UINTN)Legacy16Table->Oem32Offset));\r
+ break;\r
+ }\r
+\r
+ case EfiGetPlatformBinaryOem16Data:\r
+ {\r
+ //\r
+ // Legacy16Table->Oem16Segment = Regs.X.DS;\r
+ // Legacy16Table->Oem16Offset = Regs.X.BX;\r
+ DEBUG ((EFI_D_INFO, "Oem16 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem16Segment, (UINTN)Legacy16Table->Oem16Offset));\r
+ break;\r
+ }\r
+\r
+ default:\r
+ {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Phase 3 Copy table to final location\r
+ //\r
+ TablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
+\r
+ CopyMem (\r
+ (VOID *) (UINTN)TablePtr,\r
+ Table,\r
+ TableSize\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Assign drive number to legacy HDD drives prior to booting an EFI\r
+ aware OS so the OS can access drives without an EFI driver.\r
+ Note: BBS compliant drives ARE NOT available until this call by\r
+ either shell or EFI.\r
+\r
+ @param This Protocol instance pointer.\r
+\r
+ @retval EFI_SUCCESS Drive numbers assigned\r
+\r
+**/\r
+EFI_STATUS\r
+GenericLegacyBoot (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
+ EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;\r
+ UINTN CopySize;\r
+ VOID *AcpiPtr;\r
+ HDD_INFO *HddInfo;\r
+ HDD_INFO *LocalHddInfo;\r
+ UINTN Index;\r
+ EFI_COMPATIBILITY16_TABLE *Legacy16Table;\r
+ UINT32 *BdaPtr;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ BBS_TABLE *LocalBbsTable;\r
+ UINT32 *BaseVectorMaster;\r
+ EFI_TIME BootTime;\r
+ UINT32 LocalTime;\r
+ EFI_HANDLE IdeController;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ VOID *SmbiosTable;\r
+ VOID *AcpiTable;\r
+ UINTN ShadowAddress;\r
+ UINT32 Granularity;\r
+ EFI_TIMER_ARCH_PROTOCOL *Timer;\r
+ UINT64 TimerPeriod;\r
+\r
+ LocalHddInfo = NULL;\r
+ HddCount = 0;\r
+ BbsCount = 0;\r
+ LocalBbsTable = NULL;\r
+ TimerPeriod = 0;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ DEBUG_CODE (\r
+ DEBUG ((EFI_D_ERROR, "Start of legacy boot\n"));\r
+ );\r
+\r
+ Legacy16Table = Private->Legacy16Table;\r
+ EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
+ HddInfo = &EfiToLegacy16BootTable->HddInfo[0];\r
+\r
+ LegacyBiosPlatform = Private->LegacyBiosPlatform;\r
+\r
+ EfiToLegacy16BootTable->MajorVersion = EFI_TO_LEGACY_MAJOR_VERSION;\r
+ EfiToLegacy16BootTable->MinorVersion = EFI_TO_LEGACY_MINOR_VERSION;\r
+\r
+ //\r
+ // Before starting the Legacy boot check the system ticker.\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiTimerArchProtocolGuid, \r
+ NULL,\r
+ (VOID **) &Timer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = Timer->GetTimerPeriod (\r
+ Timer,\r
+ &TimerPeriod\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (TimerPeriod != DEFAULT_LAGACY_TIMER_TICK_DURATION) {\r
+ Status = Timer->SetTimerPeriod (\r
+ Timer, \r
+ DEFAULT_LAGACY_TIMER_TICK_DURATION\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // If booting to a legacy OS then force HDD drives to the appropriate\r
+ // boot mode by calling GetIdeHandle.\r
+ // A reconnect -r can force all HDDs back to native mode.\r
+ //\r
+ IdeController = NULL;\r
+ if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
+ Status = LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformIdeHandle,\r
+ 0,\r
+ &HandleBuffer,\r
+ &HandleCount,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ IdeController = HandleBuffer[0];\r
+ } \r
+ }\r
+ //\r
+ // Unlock the Legacy BIOS region\r
+ //\r
+ Private->LegacyRegion->UnLock (\r
+ Private->LegacyRegion,\r
+ 0xE0000,\r
+ 0x20000,\r
+ &Granularity\r
+ );\r
+\r
+ //\r
+ // Reconstruct the Legacy16 boot memory map\r
+ //\r
+ LegacyBiosBuildE820 (Private, &CopySize);\r
+ if (CopySize > Private->Legacy16Table->E820Length) {\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16GetTableAddress;\r
+ Regs.X.CX = (UINT16) CopySize;\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Private->Legacy16Table->Compatibility16CallSegment,\r
+ Private->Legacy16Table->Compatibility16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ Private->Legacy16Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
+ Private->Legacy16Table->E820Length = (UINT32) CopySize;\r
+ if (Regs.X.AX != 0) {\r
+ DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n"));\r
+ } else {\r
+ CopyMem (\r
+ (VOID *)(UINTN) Private->Legacy16Table->E820Pointer,\r
+ Private->E820Table,\r
+ CopySize\r
+ );\r
+ }\r
+ } else {\r
+ CopyMem (\r
+ (VOID *)(UINTN) Private->Legacy16Table->E820Pointer,\r
+ Private->E820Table,\r
+ CopySize\r
+ );\r
+ Private->Legacy16Table->E820Length = (UINT32) CopySize;\r
+ }\r
+ //\r
+ // Get SMBIOS and ACPI table pointers\r
+ //\r
+ SmbiosTable = NULL;\r
+ EfiGetSystemConfigurationTable (\r
+ &gEfiSmbiosTableGuid,\r
+ &SmbiosTable\r
+ );\r
+ //\r
+ // We do not ASSERT if SmbiosTable not found. It is possbile that a platform does not produce SmbiosTable.\r
+ //\r
+ if (SmbiosTable == NULL) {\r
+ DEBUG ((EFI_D_INFO, "Smbios table is not found!\n"));\r
+ }\r
+ EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)SmbiosTable;\r
+\r
+ AcpiTable = NULL;\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiAcpi20TableGuid,\r
+ &AcpiTable\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiAcpi10TableGuid,\r
+ &AcpiTable\r
+ );\r
+ }\r
+ //\r
+ // We do not ASSERT if AcpiTable not found. It is possbile that a platform does not produce AcpiTable.\r
+ //\r
+ if (AcpiTable == NULL) {\r
+ DEBUG ((EFI_D_INFO, "ACPI table is not found!\n"));\r
+ }\r
+ EfiToLegacy16BootTable->AcpiTable = (UINT32)(UINTN)AcpiTable;\r
+\r
+ //\r
+ // Get RSD Ptr table rev at offset 15 decimal\r
+ // Rev = 0 Length is 20 decimal\r
+ // Rev != 0 Length is UINT32 at offset 20 decimal\r
+ //\r
+ if (AcpiTable != NULL) {\r
+\r
+ AcpiPtr = AcpiTable;\r
+ if (*((UINT8 *) AcpiPtr + 15) == 0) {\r
+ CopySize = 20;\r
+ } else {\r
+ AcpiPtr = ((UINT8 *) AcpiPtr + 20);\r
+ CopySize = (*(UINT32 *) AcpiPtr);\r
+ }\r
+\r
+ CopyMem (\r
+ (VOID *)(UINTN) Private->Legacy16Table->AcpiRsdPtrPointer,\r
+ AcpiTable,\r
+ CopySize\r
+ );\r
+ }\r
+ //\r
+ // Make sure all PCI Interrupt Line register are programmed to match 8259\r
+ //\r
+ PciProgramAllInterruptLineRegisters (Private);\r
+\r
+ //\r
+ // Unlock the Legacy BIOS region as PciProgramAllInterruptLineRegisters\r
+ // can lock it.\r
+ //\r
+ Private->LegacyRegion->UnLock (\r
+ Private->LegacyRegion,\r
+ Private->BiosStart,\r
+ Private->LegacyBiosImageSize,\r
+ &Granularity\r
+ );\r
+\r
+ //\r
+ // Configure Legacy Device Magic\r
+ //\r
+ // Only do this code if booting legacy OS\r
+ //\r
+ if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
+ UpdateSioData (Private);\r
+ }\r
+ //\r
+ // Setup BDA and EBDA standard areas before Legacy Boot\r
+ //\r
+ LegacyBiosCompleteBdaBeforeBoot (Private);\r
+ LegacyBiosCompleteStandardCmosBeforeBoot (Private);\r
+\r
+ //\r
+ // We must build IDE data, if it hasn't been done, before PciShadowRoms\r
+ // to insure EFI drivers are connected.\r
+ //\r
+ LegacyBiosBuildIdeData (Private, &HddInfo, 1);\r
+ UpdateAllIdentifyDriveData (Private);\r
+\r
+ //\r
+ // Clear IO BAR, if IDE controller in legacy mode.\r
+ //\r
+ InitLegacyIdeController (IdeController);\r
+\r
+ //\r
+ // Generate number of ticks since midnight for BDA. DOS requires this\r
+ // for its time. We have to make assumptions as to how long following\r
+ // code takes since after PciShadowRoms PciIo is gone. Place result in\r
+ // 40:6C-6F\r
+ //\r
+ // Adjust value by 1 second.\r
+ //\r
+ gRT->GetTime (&BootTime, NULL);\r
+ LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second;\r
+ LocalTime += 1;\r
+\r
+ //\r
+ // Multiply result by 18.2 for number of ticks since midnight.\r
+ // Use 182/10 to avoid floating point math.\r
+ //\r
+ LocalTime = (LocalTime * 182) / 10;\r
+ BdaPtr = (UINT32 *) (UINTN)0x46C;\r
+ *BdaPtr = LocalTime;\r
+\r
+ //\r
+ // Shadow PCI ROMs. We must do this near the end since this will kick\r
+ // of Native EFI drivers that may be needed to collect info for Legacy16\r
+ //\r
+ // WARNING: PciIo is gone after this call.\r
+ //\r
+ PciShadowRoms (Private);\r
+\r
+ //\r
+ // Shadow PXE base code, BIS etc.\r
+ //\r
+ Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity);\r
+ ShadowAddress = Private->OptionRom;\r
+ Private->LegacyBiosPlatform->PlatformHooks (\r
+ Private->LegacyBiosPlatform,\r
+ EfiPlatformHookShadowServiceRoms,\r
+ 0,\r
+ 0,\r
+ &ShadowAddress,\r
+ Legacy16Table,\r
+ NULL\r
+ );\r
+ Private->OptionRom = (UINT32)ShadowAddress;\r
+ //\r
+ // Register Legacy SMI Handler\r
+ //\r
+ LegacyBiosPlatform->SmmInit (\r
+ LegacyBiosPlatform,\r
+ EfiToLegacy16BootTable\r
+ );\r
+\r
+ //\r
+ // Let platform code know the boot options\r
+ //\r
+ LegacyBiosGetBbsInfo (\r
+ This,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+\r
+ PrintBbsTable (LocalBbsTable);\r
+ PrintHddInfo (LocalHddInfo);\r
+\r
+ //\r
+ // If drive wasn't spun up then BuildIdeData may have found new drives.\r
+ // Need to update BBS boot priority.\r
+ //\r
+ for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {\r
+ if ((LocalHddInfo[Index].IdentifyDrive[0].Raw[0] != 0) &&\r
+ (LocalBbsTable[2 * Index + 1].BootPriority == BBS_IGNORE_ENTRY)\r
+ ) {\r
+ LocalBbsTable[2 * Index + 1].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+ }\r
+\r
+ if ((LocalHddInfo[Index].IdentifyDrive[1].Raw[0] != 0) &&\r
+ (LocalBbsTable[2 * Index + 2].BootPriority == BBS_IGNORE_ENTRY)\r
+ ) {\r
+ LocalBbsTable[2 * Index + 2].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+ }\r
+ }\r
+\r
+ Private->LegacyRegion->UnLock (\r
+ Private->LegacyRegion,\r
+ 0xc0000,\r
+ 0x40000,\r
+ &Granularity\r
+ );\r
+\r
+ LegacyBiosPlatform->PrepareToBoot (\r
+ LegacyBiosPlatform,\r
+ mBbsDevicePathPtr,\r
+ mBbsTable,\r
+ mLoadOptionsSize,\r
+ mLoadOptions,\r
+ (VOID *) &Private->IntThunk->EfiToLegacy16BootTable\r
+ );\r
+\r
+ //\r
+ // If no boot device return to BDS\r
+ //\r
+ if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
+ for (Index = 0; Index < BbsCount; Index++){\r
+ if ((LocalBbsTable[Index].BootPriority != BBS_DO_NOT_BOOT_FROM) &&\r
+ (LocalBbsTable[Index].BootPriority != BBS_UNPRIORITIZED_ENTRY) &&\r
+ (LocalBbsTable[Index].BootPriority != BBS_IGNORE_ENTRY)) {\r
+ break;\r
+ }\r
+ }\r
+ if (Index == BbsCount) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+ //\r
+ // Let the Legacy16 code know the device path type for legacy boot\r
+ //\r
+ EfiToLegacy16BootTable->DevicePathType = mBbsDevicePathPtr->DeviceType;\r
+\r
+ //\r
+ // Copy MP table, if it exists.\r
+ //\r
+ LegacyGetDataOrTable (This, EfiGetPlatformBinaryMpTable);\r
+\r
+ if (!Private->LegacyBootEntered) {\r
+ //\r
+ // Copy OEM INT Data, if it exists. Note: This code treats any data\r
+ // as a bag of bits and knows nothing of the contents nor cares.\r
+ // Contents are IBV specific.\r
+ //\r
+ LegacyGetDataOrTable (This, EfiGetPlatformBinaryOemIntData);\r
+\r
+ //\r
+ // Copy OEM16 Data, if it exists.Note: This code treats any data\r
+ // as a bag of bits and knows nothing of the contents nor cares.\r
+ // Contents are IBV specific.\r
+ //\r
+ LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem16Data);\r
+\r
+ //\r
+ // Copy OEM32 Data, if it exists.Note: This code treats any data\r
+ // as a bag of bits and knows nothing of the contents nor cares.\r
+ // Contents are IBV specific.\r
+ //\r
+ LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem32Data);\r
+ }\r
+\r
+ //\r
+ // Call into Legacy16 code to prepare for INT 19h\r
+ //\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16PrepareToBoot;\r
+\r
+ //\r
+ // Pass in handoff data\r
+ //\r
+ Regs.X.ES = EFI_SEGMENT ((UINTN)EfiToLegacy16BootTable);\r
+ Regs.X.BX = EFI_OFFSET ((UINTN)EfiToLegacy16BootTable);\r
+\r
+ Private->LegacyBios.FarCall86 (\r
+ This,\r
+ Private->Legacy16CallSegment,\r
+ Private->Legacy16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ if (Regs.X.AX != 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Lock the Legacy BIOS region\r
+ //\r
+ Private->LegacyRegion->Lock (\r
+ Private->LegacyRegion,\r
+ 0xc0000,\r
+ 0x40000,\r
+ &Granularity\r
+ );\r
+ //\r
+ // Lock attributes of the Legacy Region if chipset supports\r
+ //\r
+ Private->LegacyRegion->BootLock (\r
+ Private->LegacyRegion,\r
+ 0xc0000,\r
+ 0x40000,\r
+ &Granularity\r
+ );\r
+\r
+ //\r
+ // Call into Legacy16 code to do the INT 19h\r
+ //\r
+ EnableAllControllers (Private);\r
+ if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
+ //\r
+ // Signal all the events that are waiting on EVT_SIGNAL_LEGACY_BOOT\r
+ //\r
+ EfiSignalEventLegacyBoot ();\r
+ DEBUG ((EFI_D_INFO, "Legacy INT19 Boot...\n"));\r
+ //\r
+ // Raise TPL to high level to disable CPU interrupts\r
+ //\r
+ gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ //\r
+ // Put the 8259 into its legacy mode by reprogramming the vector bases\r
+ //\r
+ Private->Legacy8259->SetVectorBase (Private->Legacy8259, LEGACY_MODE_BASE_VECTOR_MASTER, LEGACY_MODE_BASE_VECTOR_SLAVE);\r
+ //\r
+ // PC History\r
+ // The original PC used INT8-F for master PIC. Since these mapped over\r
+ // processor exceptions TIANO moved the master PIC to INT68-6F.\r
+ // We need to set these back to the Legacy16 unexpected interrupt(saved\r
+ // in LegacyBios.c) since some OS see that these have values different from\r
+ // what is expected and invoke them. Since the legacy OS corrupts EFI\r
+ // memory, there is no handler for these interrupts and OS blows up.\r
+ //\r
+ // We need to save the TIANO values for the rare case that the Legacy16\r
+ // code cannot boot but knows memory hasn't been destroyed.\r
+ //\r
+ // To compound the problem, video takes over one of these INTS and must be\r
+ // be left.\r
+ // @bug - determine if video hooks INT(in which case we must find new\r
+ // set of TIANO vectors) or takes it over.\r
+ //\r
+ //\r
+ BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);\r
+ for (Index = 0; Index < 8; Index++) {\r
+ Private->ThunkSavedInt[Index] = BaseVectorMaster[Index];\r
+ if (Private->ThunkSeg == (UINT16) (BaseVectorMaster[Index] >> 16)) {\r
+ BaseVectorMaster[Index] = (UINT32) (Private->BiosUnexpectedInt);\r
+ }\r
+ }\r
+\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16Boot;\r
+\r
+ Private->LegacyBios.FarCall86 (\r
+ This,\r
+ Private->Legacy16CallSegment,\r
+ Private->Legacy16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);\r
+ for (Index = 0; Index < 8; Index++) {\r
+ BaseVectorMaster[Index] = Private->ThunkSavedInt[Index];\r
+ }\r
+ }\r
+ Private->LegacyBootEntered = TRUE;\r
+ if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
+ //\r
+ // Should never return unless never passed control to 0:7c00(first stage\r
+ // OS loader) and only then if no bootable device found.\r
+ //\r
+ return EFI_DEVICE_ERROR;\r
+ } else {\r
+ //\r
+ // If boot to EFI then expect to return to caller\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Assign drive number to legacy HDD drives prior to booting an EFI\r
+ aware OS so the OS can access drives without an EFI driver.\r
+ Note: BBS compliant drives ARE NOT available until this call by\r
+ either shell or EFI.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BbsCount Number of BBS_TABLE structures\r
+ @param BbsTable List BBS entries\r
+\r
+ @retval EFI_SUCCESS Drive numbers assigned\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosPrepareToBootEfi (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ OUT UINT16 *BbsCount,\r
+ OUT BBS_TABLE **BbsTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
+ mBootMode = BOOT_EFI_OS;\r
+ mBbsDevicePathPtr = NULL;\r
+ Status = GenericLegacyBoot (This);\r
+ *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;\r
+ *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));\r
+ return Status;\r
+}\r
+\r
+/**\r
+ To boot from an unconventional device like parties and/or execute HDD diagnostics.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Attributes How to interpret the other input parameters\r
+ @param BbsEntry The 0-based index into the BbsTable for the parent\r
+ device.\r
+ @param BeerData Pointer to the 128 bytes of ram BEER data.\r
+ @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. The\r
+ caller must provide a pointer to the specific Service\r
+ Area and not the start all Service Areas.\r
+\r
+ @retval EFI_INVALID_PARAMETER if error. Does NOT return if no error.\r
+\r
+***/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosBootUnconventionalDevice (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UDC_ATTRIBUTES Attributes,\r
+ IN UINTN BbsEntry,\r
+ IN VOID *BeerData,\r
+ IN VOID *ServiceAreaData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ UD_TABLE *UcdTable;\r
+ UINTN Index;\r
+ UINT16 BootPriority;\r
+ BBS_TABLE *BbsTable;\r
+\r
+ BootPriority = 0;\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ mBootMode = BOOT_UNCONVENTIONAL_DEVICE;\r
+ mBbsDevicePathPtr = &mBbsDevicePathNode;\r
+ mAttributes = Attributes;\r
+ mBbsEntry = BbsEntry;\r
+ mBeerData = BeerData, mServiceAreaData = ServiceAreaData;\r
+\r
+ EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
+\r
+ //\r
+ // Do input parameter checking\r
+ //\r
+ if ((Attributes.DirectoryServiceValidity == 0) &&\r
+ (Attributes.RabcaUsedFlag == 0) &&\r
+ (Attributes.ExecuteHddDiagnosticsFlag == 0)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (((Attributes.DirectoryServiceValidity != 0) && (ServiceAreaData == NULL)) ||\r
+ (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag) != 0) && (BeerData == NULL))\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ UcdTable = (UD_TABLE *) AllocatePool (\r
+ sizeof (UD_TABLE)\r
+ );\r
+ if (NULL == UcdTable) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ EfiToLegacy16BootTable->UnconventionalDeviceTable = (UINT32)(UINTN)UcdTable;\r
+ UcdTable->Attributes = Attributes;\r
+ UcdTable->BbsTableEntryNumberForParentDevice = (UINT8) BbsEntry;\r
+ //\r
+ // Force all existing BBS entries to DoNotBoot. This allows 16-bit CSM\r
+ // to assign drive numbers but bot boot from. Only newly created entries\r
+ // will be valid.\r
+ //\r
+ BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;\r
+ for (Index = 0; Index < EfiToLegacy16BootTable->NumberBbsEntries; Index++) {\r
+ BbsTable[Index].BootPriority = BBS_DO_NOT_BOOT_FROM;\r
+ }\r
+ //\r
+ // If parent is onboard IDE then assign controller & device number\r
+ // else they are 0.\r
+ //\r
+ if (BbsEntry < MAX_IDE_CONTROLLER * 2) {\r
+ UcdTable->DeviceNumber = (UINT8) ((BbsEntry - 1) % 2);\r
+ }\r
+\r
+ if (BeerData != NULL) {\r
+ CopyMem (\r
+ (VOID *) UcdTable->BeerData,\r
+ BeerData,\r
+ (UINTN) 128\r
+ );\r
+ }\r
+\r
+ if (ServiceAreaData != NULL) {\r
+ CopyMem (\r
+ (VOID *) UcdTable->ServiceAreaData,\r
+ ServiceAreaData,\r
+ (UINTN) 64\r
+ );\r
+ }\r
+ //\r
+ // For each new entry do the following:\r
+ // 1. Increment current number of BBS entries\r
+ // 2. Copy parent entry to new entry.\r
+ // 3. Zero out BootHandler Offset & segment\r
+ // 4. Set appropriate device type. BEV(0x80) for HDD diagnostics\r
+ // and Floppy(0x01) for PARTIES boot.\r
+ // 5. Assign new priority.\r
+ //\r
+ if ((Attributes.ExecuteHddDiagnosticsFlag) != 0) {\r
+ EfiToLegacy16BootTable->NumberBbsEntries += 1;\r
+\r
+ CopyMem (\r
+ (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority,\r
+ (VOID *) &BbsTable[BbsEntry].BootPriority,\r
+ sizeof (BBS_TABLE)\r
+ );\r
+\r
+ BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = 0;\r
+ BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0;\r
+ BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = 0x80;\r
+\r
+ UcdTable->BbsTableEntryNumberForHddDiag = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1);\r
+\r
+ BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority;\r
+ BootPriority += 1;\r
+\r
+ //\r
+ // Set device type as BBS_TYPE_DEV for PARTIES diagnostic\r
+ //\r
+ mBbsDevicePathNode.DeviceType = BBS_TYPE_BEV;\r
+ }\r
+\r
+ if (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag)) != 0) {\r
+ EfiToLegacy16BootTable->NumberBbsEntries += 1;\r
+ CopyMem (\r
+ (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority,\r
+ (VOID *) &BbsTable[BbsEntry].BootPriority,\r
+ sizeof (BBS_TABLE)\r
+ );\r
+\r
+ BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = 0;\r
+ BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0;\r
+ BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = 0x01;\r
+ UcdTable->BbsTableEntryNumberForBoot = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1);\r
+ BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority;\r
+\r
+ //\r
+ // Set device type as BBS_TYPE_FLOPPY for PARTIES boot as floppy\r
+ //\r
+ mBbsDevicePathNode.DeviceType = BBS_TYPE_FLOPPY;\r
+ }\r
+ //\r
+ // Build the BBS Device Path for this boot selection\r
+ //\r
+ mBbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;\r
+ mBbsDevicePathNode.Header.SubType = BBS_BBS_DP;\r
+ SetDevicePathNodeLength (&mBbsDevicePathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
+ mBbsDevicePathNode.StatusFlag = 0;\r
+ mBbsDevicePathNode.String[0] = 0;\r
+\r
+ Status = GenericLegacyBoot (This);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Attempt to legacy boot the BootOption. If the EFI contexted has been\r
+ compromised this function will not return.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BbsDevicePath EFI Device Path from BootXXXX variable.\r
+ @param LoadOptionsSize Size of LoadOption in size.\r
+ @param LoadOptions LoadOption from BootXXXX variable\r
+\r
+ @retval EFI_SUCCESS Removable media not present\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosLegacyBoot (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN BBS_BBS_DEVICE_PATH *BbsDevicePath,\r
+ IN UINT32 LoadOptionsSize,\r
+ IN VOID *LoadOptions\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ mBbsDevicePathPtr = BbsDevicePath;\r
+ mLoadOptionsSize = LoadOptionsSize;\r
+ mLoadOptions = LoadOptions;\r
+ mBootMode = BOOT_LEGACY_OS;\r
+ Status = GenericLegacyBoot (This);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Convert EFI Memory Type to E820 Memory Type.\r
+\r
+ @param Type EFI Memory Type\r
+\r
+ @return ACPI Memory Type for EFI Memory Type\r
+\r
+**/\r
+EFI_ACPI_MEMORY_TYPE\r
+EfiMemoryTypeToE820Type (\r
+ IN UINT32 Type\r
+ )\r
+{\r
+ switch (Type) {\r
+ case EfiLoaderCode:\r
+ case EfiLoaderData:\r
+ case EfiBootServicesCode:\r
+ case EfiBootServicesData:\r
+ case EfiConventionalMemory:\r
+ case EfiRuntimeServicesCode:\r
+ case EfiRuntimeServicesData:\r
+ return EfiAcpiAddressRangeMemory;\r
+\r
+ case EfiACPIReclaimMemory:\r
+ return EfiAcpiAddressRangeACPI;\r
+\r
+ case EfiACPIMemoryNVS:\r
+ return EfiAcpiAddressRangeNVS;\r
+\r
+ //\r
+ // All other types map to reserved.\r
+ // Adding the code just waists FLASH space.\r
+ //\r
+ // case EfiReservedMemoryType:\r
+ // case EfiUnusableMemory:\r
+ // case EfiMemoryMappedIO:\r
+ // case EfiMemoryMappedIOPortSpace:\r
+ // case EfiPalCode:\r
+ //\r
+ default:\r
+ return EfiAcpiAddressRangeReserved;\r
+ }\r
+}\r
+\r
+/**\r
+ Build the E820 table.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param Size Size of E820 Table\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildE820 (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ OUT UINTN *Size\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_E820_ENTRY64 *E820Table;\r
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMap;\r
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd;\r
+ EFI_MEMORY_DESCRIPTOR *EfiEntry;\r
+ EFI_MEMORY_DESCRIPTOR *NextEfiEntry;\r
+ EFI_MEMORY_DESCRIPTOR TempEfiEntry;\r
+ UINTN EfiMemoryMapSize;\r
+ UINTN EfiMapKey;\r
+ UINTN EfiDescriptorSize;\r
+ UINT32 EfiDescriptorVersion;\r
+ UINTN Index;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
+ UINTN TempIndex;\r
+ UINTN IndexSort;\r
+ UINTN TempNextIndex;\r
+ EFI_E820_ENTRY64 TempE820;\r
+ EFI_ACPI_MEMORY_TYPE TempType;\r
+ BOOLEAN ChangedFlag;\r
+ UINTN Above1MIndex;\r
+ UINT64 MemoryBlockLength;\r
+\r
+ E820Table = (EFI_E820_ENTRY64 *) Private->E820Table;\r
+\r
+ //\r
+ // Get the EFI memory map.\r
+ //\r
+ EfiMemoryMapSize = 0;\r
+ EfiMemoryMap = NULL;\r
+ Status = gBS->GetMemoryMap (\r
+ &EfiMemoryMapSize,\r
+ EfiMemoryMap,\r
+ &EfiMapKey,\r
+ &EfiDescriptorSize,\r
+ &EfiDescriptorVersion\r
+ );\r
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+\r
+ do {\r
+ //\r
+ // Use size returned back plus 1 descriptor for the AllocatePool.\r
+ // We don't just multiply by 2 since the "for" loop below terminates on\r
+ // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize\r
+ // we process bogus entries and create bogus E820 entries.\r
+ //\r
+ EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapSize);\r
+ ASSERT (EfiMemoryMap != NULL);\r
+ Status = gBS->GetMemoryMap (\r
+ &EfiMemoryMapSize,\r
+ EfiMemoryMap,\r
+ &EfiMapKey,\r
+ &EfiDescriptorSize,\r
+ &EfiDescriptorVersion\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (EfiMemoryMap);\r
+ }\r
+ } while (Status == EFI_BUFFER_TOO_SMALL);\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Punch in the E820 table for memory less than 1 MB.\r
+ // Assume ZeroMem () has been done on data structure.\r
+ //\r
+ //\r
+ // First entry is 0 to (640k - EBDA)\r
+ //\r
+ E820Table[0].BaseAddr = 0;\r
+ E820Table[0].Length = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4);\r
+ E820Table[0].Type = EfiAcpiAddressRangeMemory;\r
+\r
+ //\r
+ // Second entry is (640k - EBDA) to 640k\r
+ //\r
+ E820Table[1].BaseAddr = E820Table[0].Length;\r
+ E820Table[1].Length = (UINT64) ((640 * 1024) - E820Table[0].Length);\r
+ E820Table[1].Type = EfiAcpiAddressRangeReserved;\r
+\r
+ //\r
+ // Third Entry is legacy BIOS\r
+ // DO NOT CLAIM region from 0xA0000-0xDFFFF. OS can use free areas\r
+ // to page in memory under 1MB.\r
+ // Omit region from 0xE0000 to start of BIOS, if any. This can be\r
+ // used for a multiple reasons including OPROMS.\r
+ //\r
+\r
+ //\r
+ // The CSM binary image size is not the actually size that CSM binary used,\r
+ // to avoid memory corrupt, we declare the 0E0000 - 0FFFFF is used by CSM binary.\r
+ //\r
+ E820Table[2].BaseAddr = 0xE0000;\r
+ E820Table[2].Length = 0x20000;\r
+ E820Table[2].Type = EfiAcpiAddressRangeReserved;\r
+\r
+ Above1MIndex = 2;\r
+\r
+ //\r
+ // Process the EFI map to produce E820 map;\r
+ //\r
+\r
+ //\r
+ // Sort memory map from low to high\r
+ //\r
+ EfiEntry = EfiMemoryMap;\r
+ NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);\r
+ EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);\r
+ while (EfiEntry < EfiMemoryMapEnd) {\r
+ while (NextEfiEntry < EfiMemoryMapEnd) {\r
+ if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {\r
+ CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));\r
+ CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));\r
+ CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));\r
+ }\r
+\r
+ NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptorSize);\r
+ }\r
+\r
+ EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);\r
+ NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);\r
+ }\r
+\r
+ EfiEntry = EfiMemoryMap;\r
+ EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);\r
+ for (Index = Above1MIndex; (EfiEntry < EfiMemoryMapEnd) && (Index < EFI_MAX_E820_ENTRY - 1); ) {\r
+ MemoryBlockLength = (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12));\r
+ if ((EfiEntry->PhysicalStart + MemoryBlockLength) < 0x100000) {\r
+ //\r
+ // Skip the memory block is under 1MB\r
+ //\r
+ } else {\r
+ if (EfiEntry->PhysicalStart < 0x100000) {\r
+ //\r
+ // When the memory block spans below 1MB, ensure the memory block start address is at least 1MB\r
+ //\r
+ MemoryBlockLength -= 0x100000 - EfiEntry->PhysicalStart;\r
+ EfiEntry->PhysicalStart = 0x100000;\r
+ }\r
+\r
+ //\r
+ // Convert memory type to E820 type\r
+ //\r
+ TempType = EfiMemoryTypeToE820Type (EfiEntry->Type);\r
+\r
+ if ((E820Table[Index].Type == TempType) && (EfiEntry->PhysicalStart == (E820Table[Index].BaseAddr + E820Table[Index].Length))) {\r
+ //\r
+ // Grow an existing entry\r
+ //\r
+ E820Table[Index].Length += MemoryBlockLength;\r
+ } else {\r
+ //\r
+ // Make a new entry\r
+ //\r
+ ++Index;\r
+ E820Table[Index].BaseAddr = EfiEntry->PhysicalStart;\r
+ E820Table[Index].Length = MemoryBlockLength;\r
+ E820Table[Index].Type = TempType;\r
+ }\r
+ }\r
+ EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);\r
+ }\r
+\r
+ FreePool (EfiMemoryMap);\r
+\r
+ //\r
+ // Process the reserved memory map to produce E820 map ;\r
+ //\r
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ if (Hob.Raw != NULL && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ ResourceHob = Hob.ResourceDescriptor;\r
+ if (((ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_MAPPED_IO) ||\r
+ (ResourceHob->ResourceType == EFI_RESOURCE_FIRMWARE_DEVICE) ||\r
+ (ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) ) &&\r
+ (ResourceHob->PhysicalStart > 0x100000) &&\r
+ (Index < EFI_MAX_E820_ENTRY - 1)) {\r
+ ++Index;\r
+ E820Table[Index].BaseAddr = ResourceHob->PhysicalStart;\r
+ E820Table[Index].Length = ResourceHob->ResourceLength;\r
+ E820Table[Index].Type = EfiAcpiAddressRangeReserved;\r
+ }\r
+ }\r
+ }\r
+\r
+ Index ++;\r
+ Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index;\r
+ Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index;\r
+ Private->NumberE820Entries = (UINT32)Index;\r
+ *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64));\r
+\r
+ //\r
+ // Sort E820Table from low to high\r
+ //\r
+ for (TempIndex = 0; TempIndex < Index; TempIndex++) {\r
+ ChangedFlag = FALSE;\r
+ for (TempNextIndex = 1; TempNextIndex < Index - TempIndex; TempNextIndex++) {\r
+ if (E820Table[TempNextIndex - 1].BaseAddr > E820Table[TempNextIndex].BaseAddr) {\r
+ ChangedFlag = TRUE;\r
+ TempE820.BaseAddr = E820Table[TempNextIndex - 1].BaseAddr;\r
+ TempE820.Length = E820Table[TempNextIndex - 1].Length;\r
+ TempE820.Type = E820Table[TempNextIndex - 1].Type;\r
+\r
+ E820Table[TempNextIndex - 1].BaseAddr = E820Table[TempNextIndex].BaseAddr;\r
+ E820Table[TempNextIndex - 1].Length = E820Table[TempNextIndex].Length;\r
+ E820Table[TempNextIndex - 1].Type = E820Table[TempNextIndex].Type;\r
+\r
+ E820Table[TempNextIndex].BaseAddr = TempE820.BaseAddr;\r
+ E820Table[TempNextIndex].Length = TempE820.Length;\r
+ E820Table[TempNextIndex].Type = TempE820.Type;\r
+ }\r
+ }\r
+\r
+ if (!ChangedFlag) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Remove the overlap range\r
+ //\r
+ for (TempIndex = 1; TempIndex < Index; TempIndex++) {\r
+ if (E820Table[TempIndex - 1].BaseAddr <= E820Table[TempIndex].BaseAddr &&\r
+ ((E820Table[TempIndex - 1].BaseAddr + E820Table[TempIndex - 1].Length) >=\r
+ (E820Table[TempIndex].BaseAddr +E820Table[TempIndex].Length))) {\r
+ //\r
+ //Overlap range is found\r
+ //\r
+ ASSERT (E820Table[TempIndex - 1].Type == E820Table[TempIndex].Type);\r
+\r
+ if (TempIndex == Index - 1) {\r
+ E820Table[TempIndex].BaseAddr = 0;\r
+ E820Table[TempIndex].Length = 0;\r
+ E820Table[TempIndex].Type = (EFI_ACPI_MEMORY_TYPE) 0;\r
+ Index--;\r
+ break;\r
+ } else {\r
+ for (IndexSort = TempIndex; IndexSort < Index - 1; IndexSort ++) {\r
+ E820Table[IndexSort].BaseAddr = E820Table[IndexSort + 1].BaseAddr;\r
+ E820Table[IndexSort].Length = E820Table[IndexSort + 1].Length;\r
+ E820Table[IndexSort].Type = E820Table[IndexSort + 1].Type;\r
+ }\r
+ Index--;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+\r
+ Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index;\r
+ Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index;\r
+ Private->NumberE820Entries = (UINT32)Index;\r
+ *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64));\r
+\r
+ //\r
+ // Determine OS usable memory above 1Mb\r
+ //\r
+ Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb = 0x0000;\r
+ for (TempIndex = Above1MIndex; TempIndex < Index; TempIndex++) {\r
+ if (E820Table[TempIndex].BaseAddr >= 0x100000 && E820Table[TempIndex].BaseAddr < 0x100000000ULL) { // not include above 4G memory\r
+ //\r
+ // ACPIReclaimMemory is also usable memory for ACPI OS, after OS dumps all ACPI tables.\r
+ //\r
+ if ((E820Table[TempIndex].Type == EfiAcpiAddressRangeMemory) || (E820Table[TempIndex].Type == EfiAcpiAddressRangeACPI)) {\r
+ Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb += (UINT32) (E820Table[TempIndex].Length);\r
+ } else {\r
+ break; // break at first not normal memory, because SMM may use reserved memory.\r
+ }\r
+ }\r
+ }\r
+\r
+ Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb = Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb;\r
+\r
+ //\r
+ // Print DEBUG information\r
+ //\r
+ for (TempIndex = 0; TempIndex < Index; TempIndex++) {\r
+ DEBUG((EFI_D_INFO, "E820[%2d]: 0x%16lx ---- 0x%16lx, Type = 0x%x \n",\r
+ TempIndex,\r
+ E820Table[TempIndex].BaseAddr,\r
+ (E820Table[TempIndex].BaseAddr + E820Table[TempIndex].Length),\r
+ E820Table[TempIndex].Type\r
+ ));\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Fill in the standard BDA and EBDA stuff prior to legacy Boot\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosCompleteBdaBeforeBoot (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ BDA_STRUC *Bda;\r
+ UINT16 MachineConfig;\r
+ DEVICE_PRODUCER_DATA_HEADER *SioPtr;\r
+\r
+ Bda = (BDA_STRUC *) ((UINTN) 0x400);\r
+ MachineConfig = 0;\r
+\r
+ SioPtr = &(Private->IntThunk->EfiToLegacy16BootTable.SioData);\r
+ Bda->Com1 = SioPtr->Serial[0].Address;\r
+ Bda->Com2 = SioPtr->Serial[1].Address;\r
+ Bda->Com3 = SioPtr->Serial[2].Address;\r
+ Bda->Com4 = SioPtr->Serial[3].Address;\r
+\r
+ if (SioPtr->Serial[0].Address != 0x00) {\r
+ MachineConfig += 0x200;\r
+ }\r
+\r
+ if (SioPtr->Serial[1].Address != 0x00) {\r
+ MachineConfig += 0x200;\r
+ }\r
+\r
+ if (SioPtr->Serial[2].Address != 0x00) {\r
+ MachineConfig += 0x200;\r
+ }\r
+\r
+ if (SioPtr->Serial[3].Address != 0x00) {\r
+ MachineConfig += 0x200;\r
+ }\r
+\r
+ Bda->Lpt1 = SioPtr->Parallel[0].Address;\r
+ Bda->Lpt2 = SioPtr->Parallel[1].Address;\r
+ Bda->Lpt3 = SioPtr->Parallel[2].Address;\r
+\r
+ if (SioPtr->Parallel[0].Address != 0x00) {\r
+ MachineConfig += 0x4000;\r
+ }\r
+\r
+ if (SioPtr->Parallel[1].Address != 0x00) {\r
+ MachineConfig += 0x4000;\r
+ }\r
+\r
+ if (SioPtr->Parallel[2].Address != 0x00) {\r
+ MachineConfig += 0x4000;\r
+ }\r
+\r
+ Bda->NumberOfDrives = (UINT8) (Bda->NumberOfDrives + Private->IdeDriveCount);\r
+ if (SioPtr->Floppy.NumberOfFloppy != 0x00) {\r
+ MachineConfig = (UINT16) (MachineConfig + 0x01 + (SioPtr->Floppy.NumberOfFloppy - 1) * 0x40);\r
+ Bda->FloppyXRate = 0x07;\r
+ }\r
+\r
+ Bda->Lpt1_2Timeout = 0x1414;\r
+ Bda->Lpt3_4Timeout = 0x1414;\r
+ Bda->Com1_2Timeout = 0x0101;\r
+ Bda->Com3_4Timeout = 0x0101;\r
+\r
+ //\r
+ // Force VGA and Coprocessor, indicate 101/102 keyboard\r
+ //\r
+ MachineConfig = (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr->MousePresent * 0x04));\r
+ Bda->MachineConfig = MachineConfig;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Fill in the standard BDA for Keyboard LEDs\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Leds Current LED status\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosUpdateKeyboardLedStatus (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT8 Leds\r
+ )\r
+{\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ BDA_STRUC *Bda;\r
+ UINT8 LocalLeds;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+\r
+ Bda = (BDA_STRUC *) ((UINTN) 0x400);\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ LocalLeds = Leds;\r
+ Bda->LedStatus = (UINT8) ((Bda->LedStatus &~0x07) | LocalLeds);\r
+ LocalLeds = (UINT8) (LocalLeds << 4);\r
+ Bda->ShiftStatus = (UINT8) ((Bda->ShiftStatus &~0x70) | LocalLeds);\r
+ LocalLeds = (UINT8) (Leds & 0x20);\r
+ Bda->KeyboardStatus = (UINT8) ((Bda->KeyboardStatus &~0x20) | LocalLeds);\r
+ //\r
+ // Call into Legacy16 code to allow it to do any processing\r
+ //\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+ Regs.X.AX = Legacy16SetKeyboardLeds;\r
+ Regs.H.CL = Leds;\r
+\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Private->Legacy16Table->Compatibility16CallSegment,\r
+ Private->Legacy16Table->Compatibility16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Fill in the standard CMOS stuff prior to legacy Boot\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosCompleteStandardCmosBeforeBoot (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ UINT8 Bda;\r
+ UINT8 Floppy;\r
+ UINT32 Size;\r
+\r
+ //\r
+ // Update CMOS locations\r
+ // 10 floppy\r
+ // 12,19,1A - ignore as OS don't use them and there is no standard due\r
+ // to large capacity drives\r
+ // CMOS 14 = BDA 40:10 plus bit 3(display enabled)\r
+ //\r
+ Bda = (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3);\r
+\r
+ //\r
+ // Force display enabled\r
+ //\r
+ Floppy = 0x00;\r
+ if ((Bda & BIT0) != 0) {\r
+ Floppy = BIT6;\r
+ }\r
+\r
+ //\r
+ // Check if 2.88MB floppy set\r
+ //\r
+ if ((Bda & (BIT7 | BIT6)) != 0) {\r
+ Floppy = (UINT8)(Floppy | BIT1);\r
+ }\r
+\r
+ LegacyWriteStandardCmos (CMOS_10, Floppy);\r
+ LegacyWriteStandardCmos (CMOS_14, Bda);\r
+\r
+ //\r
+ // Force Status Register A to set rate selection bits and divider\r
+ //\r
+ LegacyWriteStandardCmos (CMOS_0A, 0x26);\r
+\r
+ //\r
+ // redo memory size since it can change\r
+ //\r
+ Size = 15 * SIZE_1MB;\r
+ if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) {\r
+ Size = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10;\r
+ }\r
+\r
+ LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF));\r
+ LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF));\r
+ LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8));\r
+ LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8));\r
+\r
+ LegacyCalculateWriteStandardCmosChecksum ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Relocate this image under 4G memory for IPF.\r
+\r
+ @param ImageHandle Handle of driver image.\r
+ @param SystemTable Pointer to system table.\r
+\r
+ @retval EFI_SUCCESS Image successfully relocated.\r
+ @retval EFI_ABORTED Failed to relocate image.\r
+\r
+**/\r
+EFI_STATUS\r
+RelocateImageUnder4GIfNeeded (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ This code fills in standard CMOS values and updates the standard CMOS\r
+ checksum. The Legacy16 code or LegacyBiosPlatform.c is responsible for\r
+ non-standard CMOS locations and non-standard checksums.\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+\r
+/**\r
+ Read CMOS register through index/data port.\r
+\r
+ @param[in] Index The index of the CMOS register to read.\r
+\r
+ @return The data value from the CMOS register specified by Index.\r
+\r
+**/\r
+UINT8\r
+LegacyReadStandardCmos (\r
+ IN UINT8 Index\r
+ )\r
+{\r
+ IoWrite8 (PORT_70, Index);\r
+ return IoRead8 (PORT_71);\r
+}\r
+\r
+/**\r
+ Write CMOS register through index/data port.\r
+\r
+ @param[in] Index The index of the CMOS register to write.\r
+ @param[in] Value The value of CMOS register to write.\r
+\r
+ @return The value written to the CMOS register specified by Index.\r
+\r
+**/\r
+UINT8\r
+LegacyWriteStandardCmos (\r
+ IN UINT8 Index,\r
+ IN UINT8 Value\r
+ )\r
+{\r
+ IoWrite8 (PORT_70, Index);\r
+ return IoWrite8 (PORT_71, Value);\r
+}\r
+\r
+/**\r
+ Calculate the new standard CMOS checksum and write it.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS Calculate 16-bit checksum successfully\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyCalculateWriteStandardCmosChecksum (\r
+ VOID\r
+ )\r
+{\r
+ UINT8 Register;\r
+ UINT16 Checksum;\r
+\r
+ for (Checksum = 0, Register = 0x10; Register < 0x2e; Register++) {\r
+ Checksum = (UINT16)(Checksum + LegacyReadStandardCmos (Register));\r
+ }\r
+ LegacyWriteStandardCmos (CMOS_2E, (UINT8)(Checksum >> 8));\r
+ LegacyWriteStandardCmos (CMOS_2F, (UINT8)(Checksum & 0xff));\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Fill in the standard CMOS stuff before Legacy16 load\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosInitCmos (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ UINT32 Size;\r
+\r
+ //\r
+ // Clear all errors except RTC lost power\r
+ //\r
+ LegacyWriteStandardCmos (CMOS_0E, (UINT8)(LegacyReadStandardCmos (CMOS_0E) & BIT7));\r
+\r
+ //\r
+ // Update CMOS locations 15,16,17,18,30,31 and 32\r
+ // CMOS 16,15 = 640Kb = 0x280\r
+ // CMOS 18,17 = 31,30 = 15Mb max in 1Kb increments =0x3C00 max\r
+ // CMOS 32 = 0x20\r
+ //\r
+ LegacyWriteStandardCmos (CMOS_15, 0x80);\r
+ LegacyWriteStandardCmos (CMOS_16, 0x02);\r
+\r
+ Size = 15 * SIZE_1MB;\r
+ if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) {\r
+ Size = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10;\r
+ }\r
+\r
+ LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF));\r
+ LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF));\r
+ LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8));\r
+ LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8));\r
+\r
+ LegacyCalculateWriteStandardCmosChecksum ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ Collect IDE information from Native EFI Driver\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+\r
+BOOLEAN mIdeDataBuiltFlag = FALSE;\r
+\r
+/**\r
+ Collect IDE Inquiry data from the IDE disks\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param HddInfo Hdd Information\r
+ @param Flag Reconnect IdeController or not\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildIdeData (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN HDD_INFO **HddInfo,\r
+ IN UINT16 Flag\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE IdeController;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ EFI_DISK_INFO_PROTOCOL *DiskInfo;\r
+ UINT32 IdeChannel;\r
+ UINT32 IdeDevice;\r
+ UINT32 Size;\r
+ UINT8 *InquiryData;\r
+ UINT32 InquiryDataSize;\r
+ HDD_INFO *LocalHddInfo;\r
+ UINT32 PciIndex;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode;\r
+ PCI_DEVICE_PATH *PciDevicePath;\r
+\r
+ //\r
+ // Only build data once\r
+ // We have a problem with GetBbsInfo in that it can be invoked two\r
+ // places. Once in BDS, when all EFI drivers are connected and once in\r
+ // LegacyBoot after all EFI drivers are disconnected causing this routine\r
+ // to hang. In LegacyBoot this function is also called before EFI drivers\r
+ // are disconnected.\r
+ // Cases covered\r
+ // GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored.\r
+ // GetBbsInfo not invoked in BDS. First invocation of this function\r
+ // proceeds normally and second via GetBbsInfo ignored.\r
+ //\r
+ PciDevicePath = NULL;\r
+ LocalHddInfo = *HddInfo;\r
+ Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformIdeHandle,\r
+ 0,\r
+ &HandleBuffer,\r
+ &HandleCount,\r
+ (VOID *) &LocalHddInfo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ IdeController = HandleBuffer[0]; \r
+ //\r
+ // Force IDE drive spin up!\r
+ //\r
+ if (Flag != 0) {\r
+ gBS->DisconnectController (\r
+ IdeController,\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ gBS->ConnectController (IdeController, NULL, NULL, FALSE);\r
+\r
+ //\r
+ // Do GetIdeHandle twice since disconnect/reconnect will switch to native mode\r
+ // And GetIdeHandle will switch to Legacy mode, if required.\r
+ //\r
+ Private->LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformIdeHandle,\r
+ 0,\r
+ &HandleBuffer,\r
+ &HandleCount,\r
+ (VOID *) &LocalHddInfo\r
+ );\r
+ }\r
+\r
+ mIdeDataBuiltFlag = TRUE;\r
+\r
+ //\r
+ // Get Identity command from all drives\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiDiskInfoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ Private->IdeDriveCount = (UINT8) HandleCount;\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiDiskInfoProtocolGuid,\r
+ (VOID **) &DiskInfo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {\r
+ //\r
+ // Locate which PCI device\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID *) &DevicePath\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DevicePathNode = DevicePath;\r
+ while (!IsDevicePathEnd (DevicePathNode)) {\r
+ TempDevicePathNode = NextDevicePathNode (DevicePathNode);\r
+ if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) &&\r
+ ( DevicePathSubType (DevicePathNode) == HW_PCI_DP) &&\r
+ ( DevicePathType(TempDevicePathNode) == MESSAGING_DEVICE_PATH) &&\r
+ ( DevicePathSubType(TempDevicePathNode) == MSG_ATAPI_DP) ) {\r
+ PciDevicePath = (PCI_DEVICE_PATH *) DevicePathNode;\r
+ break;\r
+ }\r
+ DevicePathNode = NextDevicePathNode (DevicePathNode);\r
+ }\r
+\r
+ if (PciDevicePath == NULL) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Find start of PCI device in HddInfo. The assumption of the data\r
+ // structure is 2 controllers(channels) per PCI device and each\r
+ // controller can have 2 drives(devices).\r
+ // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master\r
+ // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave\r
+ // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master\r
+ // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave\r
+ // @bug eventually need to pass in max number of entries\r
+ // for end of for loop\r
+ //\r
+ for (PciIndex = 0; PciIndex < 8; PciIndex++) {\r
+ if ((PciDevicePath->Device == LocalHddInfo[PciIndex].Device) &&\r
+ (PciDevicePath->Function == LocalHddInfo[PciIndex].Function)\r
+ ) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (PciIndex == 8) {\r
+ continue;\r
+ }\r
+\r
+ Status = DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice);\r
+ if (!EFI_ERROR (Status)) {\r
+ Size = sizeof (ATAPI_IDENTIFY);\r
+ DiskInfo->Identify (\r
+ DiskInfo,\r
+ &LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[IdeDevice],\r
+ &Size\r
+ );\r
+ if (IdeChannel == 0) {\r
+ LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_PRIMARY;\r
+ } else if (IdeChannel == 1) {\r
+ LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SECONDARY;\r
+ }\r
+\r
+ InquiryData = NULL;\r
+ InquiryDataSize = 0;\r
+ Status = DiskInfo->Inquiry (\r
+ DiskInfo,\r
+ NULL,\r
+ &InquiryDataSize\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ InquiryData = (UINT8 *) AllocatePool (\r
+ InquiryDataSize\r
+ );\r
+ if (InquiryData != NULL) {\r
+ Status = DiskInfo->Inquiry (\r
+ DiskInfo,\r
+ InquiryData,\r
+ &InquiryDataSize\r
+ );\r
+ }\r
+ } else {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // If ATAPI device then Inquiry will pass and ATA fail.\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ ASSERT (InquiryData != NULL);\r
+ //\r
+ // If IdeDevice = 0 then set master bit, else slave bit\r
+ //\r
+ if (IdeDevice == 0) {\r
+ if ((InquiryData[0] & 0x1f) == 0x05) {\r
+ LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_CDROM;\r
+ } else if ((InquiryData[0] & 0x1f) == 0x00) {\r
+ LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_ZIPDISK;\r
+ }\r
+ } else {\r
+ if ((InquiryData[0] & 0x1f) == 0x05) {\r
+ LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_CDROM;\r
+ } else if ((InquiryData[0] & 0x1f) == 0x00) {\r
+ LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_ZIPDISK;\r
+ }\r
+ }\r
+ FreePool (InquiryData);\r
+ } else {\r
+ if (IdeDevice == 0) {\r
+ LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_IDE;\r
+ } else {\r
+ LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_IDE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ If the IDE channel is in compatibility (legacy) mode, remove all\r
+ PCI I/O BAR addresses from the controller.\r
+\r
+ @param IdeController The handle of target IDE controller\r
+\r
+\r
+**/\r
+VOID\r
+InitLegacyIdeController (\r
+ IN EFI_HANDLE IdeController\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 Pi;\r
+ UINT32 IOBarClear;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // If the IDE channel is in compatibility (legacy) mode, remove all\r
+ // PCI I/O BAR addresses from the controller. Some software gets\r
+ // confused if an IDE controller is in compatibility (legacy) mode\r
+ // and has PCI I/O resources allocated\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ IdeController,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ IOBarClear = 0x00;\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 1, &Pi);\r
+ if ((Pi & 0x01) == 0) {\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear);\r
+ }\r
+ if ((Pi & 0x04) == 0) {\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear);\r
+ }\r
+ }\r
+\r
+ return ;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+#include <IndustryStandard/Pci30.h>\r
+\r
+#define PCI_START_ADDRESS(x) (((x) + 0x7ff) & ~0x7ff)\r
+\r
+#define MAX_BRIDGE_INDEX 0x20\r
+typedef struct {\r
+ UINTN PciSegment;\r
+ UINTN PciBus;\r
+ UINTN PciDevice;\r
+ UINTN PciFunction;\r
+ UINT8 PrimaryBus;\r
+ UINT8 SecondaryBus;\r
+ UINT8 SubordinateBus;\r
+} BRIDGE_TABLE;\r
+\r
+#define ROM_MAX_ENTRIES 24\r
+BRIDGE_TABLE Bridges[MAX_BRIDGE_INDEX];\r
+UINTN SortedBridgeIndex[MAX_BRIDGE_INDEX];\r
+UINTN NumberOfBridges;\r
+LEGACY_PNP_EXPANSION_HEADER *mBasePnpPtr;\r
+UINT16 mBbsRomSegment;\r
+UINTN mHandleCount;\r
+EFI_HANDLE mVgaHandle;\r
+BOOLEAN mIgnoreBbsUpdateFlag;\r
+BOOLEAN mVgaInstallationInProgress = FALSE;\r
+UINT32 mRomCount = 0x00;\r
+ROM_INSTANCE_ENTRY mRomEntry[ROM_MAX_ENTRIES];\r
+\r
+\r
+/**\r
+ Query shadowed legacy ROM parameters registered by RomShadow() previously.\r
+\r
+ @param PciHandle PCI device whos ROM has been shadowed\r
+ @param DiskStart DiskStart value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom\r
+ @param DiskEnd DiskEnd value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom\r
+ @param RomShadowAddress Address where ROM was shadowed\r
+ @param ShadowedSize Runtime size of ROM\r
+\r
+ @retval EFI_SUCCESS Query Logging successful.\r
+ @retval EFI_NOT_FOUND No logged data found about PciHandle.\r
+\r
+**/\r
+EFI_STATUS\r
+GetShadowedRomParameters (\r
+ IN EFI_HANDLE PciHandle,\r
+ OUT UINT8 *DiskStart, OPTIONAL\r
+ OUT UINT8 *DiskEnd, OPTIONAL\r
+ OUT VOID **RomShadowAddress, OPTIONAL\r
+ OUT UINTN *ShadowedSize OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINTN Index;\r
+ UINTN PciSegment;\r
+ UINTN PciBus;\r
+ UINTN PciDevice;\r
+ UINTN PciFunction;\r
+\r
+ //\r
+ // Get the PCI I/O Protocol on PciHandle\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ PciHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the location of the PCI device\r
+ //\r
+ PciIo->GetLocation (\r
+ PciIo,\r
+ &PciSegment,\r
+ &PciBus,\r
+ &PciDevice,\r
+ &PciFunction\r
+ );\r
+\r
+ for(Index = 0; Index < mRomCount; Index++) {\r
+ if ((mRomEntry[Index].PciSegment == PciSegment) &&\r
+ (mRomEntry[Index].PciBus == PciBus) &&\r
+ (mRomEntry[Index].PciDevice == PciDevice) &&\r
+ (mRomEntry[Index].PciFunction == PciFunction)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index == mRomCount) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (DiskStart != NULL) {\r
+ *DiskStart = mRomEntry[Index].DiskStart;\r
+ }\r
+\r
+ if (DiskEnd != NULL) {\r
+ *DiskEnd = mRomEntry[Index].DiskEnd;\r
+ }\r
+\r
+ if (RomShadowAddress != NULL) {\r
+ *RomShadowAddress = (VOID *)(UINTN)mRomEntry[Index].ShadowAddress;\r
+ }\r
+\r
+ if (ShadowedSize != NULL) {\r
+ *ShadowedSize = mRomEntry[Index].ShadowedSize;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Every legacy ROM that is shadowed by the Legacy BIOS driver will be\r
+ registered into this API so that the policy code can know what has\r
+ happend\r
+\r
+ @param PciHandle PCI device whos ROM is being shadowed\r
+ @param ShadowAddress Address that ROM was shadowed\r
+ @param ShadowedSize Runtime size of ROM\r
+ @param DiskStart DiskStart value from\r
+ EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom\r
+ @param DiskEnd DiskEnd value from\r
+ EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom\r
+\r
+ @retval EFI_SUCCESS Logging successful.\r
+ @retval EFI_OUT_OF_RESOURCES No remaining room for registering another option\r
+ ROM.\r
+\r
+**/\r
+EFI_STATUS\r
+RomShadow (\r
+ IN EFI_HANDLE PciHandle,\r
+ IN UINT32 ShadowAddress,\r
+ IN UINT32 ShadowedSize, \r
+ IN UINT8 DiskStart,\r
+ IN UINT8 DiskEnd\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ //\r
+ // See if there is room to register another option ROM\r
+ //\r
+ if (mRomCount >= ROM_MAX_ENTRIES) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Get the PCI I/O Protocol on PciHandle\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ PciHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Get the location of the PCI device\r
+ //\r
+ PciIo->GetLocation (\r
+ PciIo,\r
+ &mRomEntry[mRomCount].PciSegment,\r
+ &mRomEntry[mRomCount].PciBus,\r
+ &mRomEntry[mRomCount].PciDevice,\r
+ &mRomEntry[mRomCount].PciFunction\r
+ );\r
+ mRomEntry[mRomCount].ShadowAddress = ShadowAddress;\r
+ mRomEntry[mRomCount].ShadowedSize = ShadowedSize;\r
+ mRomEntry[mRomCount].DiskStart = DiskStart;\r
+ mRomEntry[mRomCount].DiskEnd = DiskEnd;\r
+\r
+ mRomCount++;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Return EFI_SUCCESS if PciHandle has had a legacy BIOS ROM shadowed. This\r
+ information represents every call to RomShadow ()\r
+\r
+ @param PciHandle PCI device to get status for\r
+\r
+ @retval EFI_SUCCESS Legacy ROM loaded for this device\r
+ @retval EFI_NOT_FOUND No Legacy ROM loaded for this device\r
+\r
+**/\r
+EFI_STATUS\r
+IsLegacyRom (\r
+ IN EFI_HANDLE PciHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINTN Index;\r
+ UINTN Segment;\r
+ UINTN Bus;\r
+ UINTN Device;\r
+ UINTN Function;\r
+\r
+ //\r
+ // Get the PCI I/O Protocol on PciHandle\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ PciHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Get the location of the PCI device\r
+ //\r
+ PciIo->GetLocation (\r
+ PciIo,\r
+ &Segment,\r
+ &Bus,\r
+ &Device,\r
+ &Function\r
+ );\r
+\r
+ //\r
+ // See if the option ROM from PciHandle has been previously posted\r
+ //\r
+ for (Index = 0; Index < mRomCount; Index++) {\r
+ if (mRomEntry[Index].PciSegment == Segment &&\r
+ mRomEntry[Index].PciBus == Bus &&\r
+ mRomEntry[Index].PciDevice == Device &&\r
+ mRomEntry[Index].PciFunction == Function\r
+ ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Find the PC-AT ROM Image in the raw PCI Option ROM. Also return the \r
+ related information from the header.\r
+\r
+ @param Csm16Revision The PCI interface version of underlying CSM16\r
+ @param VendorId Vendor ID of the PCI device\r
+ @param DeviceId Device ID of the PCI device\r
+ @param Rom On input pointing to beginning of the raw PCI OpROM\r
+ On output pointing to the first legacy PCI OpROM\r
+ @param ImageSize On input is the size of Raw PCI Rom\r
+ On output is the size of the first legacy PCI ROM\r
+ @param MaxRuntimeImageLength The max runtime image length only valid if OpRomRevision >= 3\r
+ @param OpRomRevision Revision of the PCI Rom\r
+ @param ConfigUtilityCodeHeader Pointer to Configuration Utility Code Header\r
+\r
+ @retval EFI_SUCCESS Successfully find the legacy PCI ROM\r
+ @retval EFI_NOT_FOUND Failed to find the legacy PCI ROM\r
+\r
+**/\r
+EFI_STATUS\r
+GetPciLegacyRom (\r
+ IN UINT16 Csm16Revision,\r
+ IN UINT16 VendorId,\r
+ IN UINT16 DeviceId,\r
+ IN OUT VOID **Rom,\r
+ IN OUT UINTN *ImageSize,\r
+ OUT UINTN *MaxRuntimeImageLength, OPTIONAL\r
+ OUT UINT8 *OpRomRevision, OPTIONAL\r
+ OUT VOID **ConfigUtilityCodeHeader OPTIONAL\r
+ )\r
+{\r
+ BOOLEAN Match;\r
+ UINT16 *DeviceIdList;\r
+ EFI_PCI_ROM_HEADER RomHeader;\r
+ PCI_3_0_DATA_STRUCTURE *Pcir;\r
+ VOID *BackupImage;\r
+ VOID *BestImage;\r
+\r
+\r
+ if (*ImageSize < sizeof (EFI_PCI_ROM_HEADER)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ BestImage = NULL;\r
+ BackupImage = NULL;\r
+ RomHeader.Raw = *Rom;\r
+ while (RomHeader.Generic->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+ if (*ImageSize < \r
+ RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->PcirOffset + sizeof (PCI_DATA_STRUCTURE)\r
+ ) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);\r
+\r
+ if (Pcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
+ Match = FALSE;\r
+ if (Pcir->VendorId == VendorId) {\r
+ if (Pcir->DeviceId == DeviceId) {\r
+ Match = TRUE;\r
+ } else if ((Pcir->Revision >= 3) && (Pcir->DeviceListOffset != 0)) {\r
+ DeviceIdList = (UINT16 *)(((UINT8 *) Pcir) + Pcir->DeviceListOffset);\r
+ //\r
+ // Checking the device list\r
+ //\r
+ while (*DeviceIdList != 0) {\r
+ if (*DeviceIdList == DeviceId) {\r
+ Match = TRUE;\r
+ break;\r
+ }\r
+ DeviceIdList ++;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Match) {\r
+ if (Csm16Revision >= 0x0300) {\r
+ //\r
+ // Case 1: CSM16 3.0\r
+ //\r
+ if (Pcir->Revision >= 3) {\r
+ //\r
+ // case 1.1: meets OpRom 3.0\r
+ // Perfect!!!\r
+ //\r
+ BestImage = RomHeader.Raw;\r
+ break;\r
+ } else {\r
+ //\r
+ // case 1.2: meets OpRom 2.x\r
+ // Store it and try to find the OpRom 3.0\r
+ //\r
+ BackupImage = RomHeader.Raw;\r
+ }\r
+ } else {\r
+ //\r
+ // Case 2: CSM16 2.x\r
+ //\r
+ if (Pcir->Revision >= 3) {\r
+ //\r
+ // case 2.1: meets OpRom 3.0\r
+ // Store it and try to find the OpRom 2.x\r
+ //\r
+ BackupImage = RomHeader.Raw;\r
+ } else {\r
+ //\r
+ // case 2.2: meets OpRom 2.x\r
+ // Perfect!!!\r
+ //\r
+ BestImage = RomHeader.Raw;\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "GetPciLegacyRom - OpRom not match (%04x-%04x)\n", (UINTN)VendorId, (UINTN)DeviceId));\r
+ }\r
+ }\r
+ \r
+ if ((Pcir->Indicator & 0x80) == 0x80) {\r
+ break;\r
+ } else {\r
+ RomHeader.Raw += 512 * Pcir->ImageLength;\r
+ }\r
+ }\r
+\r
+ if (BestImage == NULL) {\r
+ if (BackupImage == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // The versions of CSM16 and OpRom don't match exactly\r
+ //\r
+ BestImage = BackupImage;\r
+ }\r
+ RomHeader.Raw = BestImage;\r
+ Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);\r
+ *Rom = BestImage;\r
+ *ImageSize = Pcir->ImageLength * 512;\r
+\r
+ if (MaxRuntimeImageLength != NULL) {\r
+ if (Pcir->Revision < 3) {\r
+ *MaxRuntimeImageLength = 0;\r
+ } else {\r
+ *MaxRuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;\r
+ }\r
+ }\r
+\r
+ if (OpRomRevision != NULL) {\r
+ // \r
+ // Optional return PCI Data Structure revision\r
+ //\r
+ if (Pcir->Length >= 0x1C) {\r
+ *OpRomRevision = Pcir->Revision;\r
+ } else {\r
+ *OpRomRevision = 0;\r
+ }\r
+ }\r
+\r
+ if (ConfigUtilityCodeHeader != NULL) {\r
+ //\r
+ // Optional return ConfigUtilityCodeHeaderOffset supported by the PC-AT ROM\r
+ //\r
+ if ((Pcir->Revision < 3) || (Pcir->ConfigUtilityCodeHeaderOffset == 0)) {\r
+ *ConfigUtilityCodeHeader = NULL;\r
+ } else {\r
+ *ConfigUtilityCodeHeader = RomHeader.Raw + Pcir->ConfigUtilityCodeHeaderOffset;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Build a table of bridge info for PIRQ translation.\r
+\r
+ @param RoutingTable RoutingTable obtained from Platform.\r
+ @param RoutingTableEntries Number of RoutingTable entries.\r
+\r
+ @retval EFI_SUCCESS New Subordinate bus.\r
+ @retval EFI_NOT_FOUND No more Subordinate busses.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateBridgeTable (\r
+ IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable,\r
+ IN UINTN RoutingTableEntries\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN BridgeIndex;\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE01 PciConfigHeader;\r
+ BRIDGE_TABLE SlotBridges[MAX_BRIDGE_INDEX];\r
+ UINTN SlotBridgeIndex;\r
+\r
+ BridgeIndex = 0x00;\r
+ SlotBridgeIndex = 0x00;\r
+\r
+ //\r
+ // Assumption is table is built from low bus to high bus numbers.\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (PciConfigHeader) / sizeof (UINT32),\r
+ &PciConfigHeader\r
+ );\r
+\r
+ if (IS_PCI_P2P (&PciConfigHeader) && (BridgeIndex < MAX_BRIDGE_INDEX)) {\r
+ PciIo->GetLocation (\r
+ PciIo,\r
+ &Bridges[BridgeIndex].PciSegment,\r
+ &Bridges[BridgeIndex].PciBus,\r
+ &Bridges[BridgeIndex].PciDevice,\r
+ &Bridges[BridgeIndex].PciFunction\r
+ );\r
+\r
+ Bridges[BridgeIndex].PrimaryBus = PciConfigHeader.Bridge.PrimaryBus;\r
+\r
+ Bridges[BridgeIndex].SecondaryBus = PciConfigHeader.Bridge.SecondaryBus;\r
+\r
+ Bridges[BridgeIndex].SubordinateBus = PciConfigHeader.Bridge.SubordinateBus;\r
+\r
+ for (Index1 = 0; Index1 < RoutingTableEntries; Index1++){\r
+ //\r
+ // Test whether we have found the Bridge in the slot, must be the one that directly interfaced to the board\r
+ // Once we find one, store it in the SlotBridges[]\r
+ //\r
+ if ((RoutingTable[Index1].Slot != 0) && (Bridges[BridgeIndex].PrimaryBus == RoutingTable[Index1].Bus)\r
+ && ((Bridges[BridgeIndex].PciDevice << 3) == RoutingTable[Index1].Device)) {\r
+ CopyMem (&SlotBridges[SlotBridgeIndex], &Bridges[BridgeIndex], sizeof (BRIDGE_TABLE));\r
+ SlotBridgeIndex++;\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ ++BridgeIndex;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Pack up Bridges by removing those useless ones\r
+ //\r
+ for (Index = 0; Index < BridgeIndex;){\r
+ for (Index1 = 0; Index1 < SlotBridgeIndex; Index1++) {\r
+ if (((Bridges[Index].PciBus == SlotBridges[Index1].PrimaryBus) && (Bridges[Index].PciDevice == SlotBridges[Index1].PciDevice)) ||\r
+ ((Bridges[Index].PciBus >= SlotBridges[Index1].SecondaryBus) && (Bridges[Index].PciBus <= SlotBridges[Index1].SubordinateBus))) {\r
+ //\r
+ // We have found one that meets our criteria\r
+ //\r
+ Index++;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // This one doesn't meet criteria, pack it\r
+ //\r
+ if (Index1 >= SlotBridgeIndex) {\r
+ for (Index1 = Index; BridgeIndex > 1 && Index1 < BridgeIndex - 1 ; Index1++) {\r
+ CopyMem (&Bridges[Index1], &Bridges[Index1 + 1], sizeof (BRIDGE_TABLE));\r
+ }\r
+\r
+ BridgeIndex--;\r
+ }\r
+ }\r
+\r
+ NumberOfBridges = BridgeIndex;\r
+\r
+ //\r
+ // Sort bridges low to high by Secondary bus followed by subordinate bus\r
+ //\r
+ if (NumberOfBridges > 1) {\r
+ Index = 0;\r
+ do {\r
+ SortedBridgeIndex[Index] = Index;\r
+ ++Index;\r
+ } while (Index < NumberOfBridges);\r
+\r
+ for (Index = 0; Index < NumberOfBridges - 1; Index++) {\r
+ for (Index1 = Index + 1; Index1 < NumberOfBridges; Index1++) {\r
+ if (Bridges[Index].SecondaryBus > Bridges[Index1].SecondaryBus) {\r
+ SortedBridgeIndex[Index] = Index1;\r
+ SortedBridgeIndex[Index1] = Index;\r
+ }\r
+\r
+ if ((Bridges[Index].SecondaryBus == Bridges[Index1].SecondaryBus) &&\r
+ (Bridges[Index].SubordinateBus > Bridges[Index1].SubordinateBus)\r
+ ) {\r
+ SortedBridgeIndex[Index] = Index1;\r
+ SortedBridgeIndex[Index1] = Index;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ FreePool (HandleBuffer);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Find base Bridge for device.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param PciBus Input = Bus of device.\r
+ @param PciDevice Input = Device.\r
+ @param RoutingTable The platform specific routing table\r
+ @param RoutingTableEntries Number of entries in table\r
+\r
+ @retval EFI_SUCCESS At base bus.\r
+ @retval EFI_NOT_FOUND Behind a bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+GetBaseBus (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN UINTN PciBus,\r
+ IN UINTN PciDevice,\r
+ IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable,\r
+ IN UINTN RoutingTableEntries\r
+ )\r
+{\r
+ UINTN Index;\r
+ for (Index = 0; Index < RoutingTableEntries; Index++) {\r
+ if ((RoutingTable[Index].Bus == PciBus) && (RoutingTable[Index].Device == (PciDevice << 3))) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Translate PIRQ through busses\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param PciBus Input = Bus of device. Output = Translated Bus\r
+ @param PciDevice Input = Device. Output = Translated Device\r
+ @param PciFunction Input = Function. Output = Translated Function\r
+ @param PirqIndex Input = Original PIRQ index. If single function\r
+ device then 0, otherwise 0-3.\r
+ Output = Translated Index\r
+\r
+ @retval EFI_SUCCESS Pirq successfully translated.\r
+ @retval EFI_NOT_FOUND The device is not behind any known bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+TranslateBusPirq (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN OUT UINTN *PciBus,\r
+ IN OUT UINTN *PciDevice,\r
+ IN OUT UINTN *PciFunction,\r
+ IN OUT UINT8 *PirqIndex\r
+ )\r
+{\r
+ /*\r
+ This routine traverses the PCI busses from base slot\r
+ and translates the PIRQ register to the appropriate one.\r
+\r
+ Example:\r
+\r
+ Bus 0, Device 1 is PCI-PCI bridge that all PCI slots reside on.\r
+ Primary bus# = 0\r
+ Secondary bus # = 1\r
+ Subordinate bus # is highest bus # behind this bus\r
+ Bus 1, Device 0 is Slot 0 and is not a bridge.\r
+ Bus 1, Device 1 is Slot 1 and is a bridge.\r
+ Slot PIRQ routing is A,B,C,D.\r
+ Primary bus # = 1\r
+ Secondary bus # = 2\r
+ Subordinate bus # = 5\r
+ Bus 2, Device 6 is a bridge. It has no bridges behind it.\r
+ Primary bus # = 2\r
+ Secondary bus # = 3\r
+ Subordinate bus # = 3\r
+ Bridge PIRQ routing is C,D,A,B\r
+ Bus 2, Device 7 is a bridge. It has 1 bridge behind it.\r
+ Primary bus # = 2\r
+ Secondary bus = 4 Device 6 takes bus 2.\r
+ Subordinate bus = 5.\r
+ Bridge PIRQ routing is D,A,B,C\r
+ Bus 4, Device 2 is a bridge. It has no bridges behind it.\r
+ Primary bus # = 4\r
+ Secondary bus # = 5\r
+ Subordinate bus = 5\r
+ Bridge PIRQ routing is B,C,D,A\r
+ Bus 5, Device 1 is to be programmed.\r
+ Device PIRQ routing is C,D,A,B\r
+\r
+\r
+Search busses starting from slot bus for final bus >= Secondary bus and\r
+final bus <= Suborninate bus. Assumption is bus entries increase in bus\r
+number.\r
+Starting PIRQ is A,B,C,D.\r
+Bus 2, Device 7 satisfies search criteria. Rotate (A,B,C,D) left by device\r
+ 7 modulo 4 giving (D,A,B,C).\r
+Bus 4, Device 2 satisfies search criteria. Rotate (D,A,B,C) left by 2 giving\r
+ (B,C,D,A).\r
+No other busses match criteria. Device to be programmed is Bus 5, Device 1.\r
+Rotate (B,C,D,A) by 1 giving C,D,A,B. Translated PIRQ is C.\r
+\r
+*/\r
+ UINTN LocalBus;\r
+ UINTN LocalDevice;\r
+ UINTN BaseBus;\r
+ UINTN BaseDevice;\r
+ UINTN BaseFunction;\r
+ UINT8 LocalPirqIndex;\r
+ BOOLEAN BaseIndexFlag;\r
+ UINTN BridgeIndex;\r
+ UINTN SBridgeIndex;\r
+ BaseIndexFlag = FALSE;\r
+ BridgeIndex = 0x00;\r
+\r
+ LocalPirqIndex = *PirqIndex;\r
+ LocalBus = *PciBus;\r
+ LocalDevice = *PciDevice;\r
+ BaseBus = *PciBus;\r
+ BaseDevice = *PciDevice;\r
+ BaseFunction = *PciFunction;\r
+\r
+ //\r
+ // LocalPirqIndex list PIRQs in rotated fashion\r
+ // = 0 A,B,C,D\r
+ // = 1 B,C,D,A\r
+ // = 2 C,D,A,B\r
+ // = 3 D,A,B,C\r
+ //\r
+\r
+ for (BridgeIndex = 0; BridgeIndex < NumberOfBridges; BridgeIndex++) {\r
+ SBridgeIndex = SortedBridgeIndex[BridgeIndex];\r
+ //\r
+ // Check if device behind this bridge\r
+ //\r
+ if ((LocalBus >= Bridges[SBridgeIndex].SecondaryBus) && (LocalBus <= Bridges[SBridgeIndex].SubordinateBus)) {\r
+ //\r
+ // If BaseIndexFlag = FALSE then have found base bridge, i.e\r
+ // bridge in slot. Save info for use by IRQ routing table.\r
+ //\r
+ if (!BaseIndexFlag) {\r
+ BaseBus = Bridges[SBridgeIndex].PciBus;\r
+ BaseDevice = Bridges[SBridgeIndex].PciDevice;\r
+ BaseFunction = Bridges[SBridgeIndex].PciFunction;\r
+ BaseIndexFlag = TRUE;\r
+ } else {\r
+ LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8)Bridges[SBridgeIndex].PciDevice)%4);\r
+ }\r
+\r
+ //\r
+ // Check if at device. If not get new PCI location & PIRQ\r
+ //\r
+ if (Bridges[SBridgeIndex].SecondaryBus == (UINT8) LocalBus) {\r
+ //\r
+ // Translate PIRQ\r
+ //\r
+ LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8) (LocalDevice)) % 4);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // In case we fail to find the Bridge just above us, this is some potential error and we want to warn the user\r
+ //\r
+ if(BridgeIndex >= NumberOfBridges){\r
+ DEBUG ((EFI_D_ERROR, "Cannot Find IRQ Routing for Bus %d, Device %d, Function %d\n", *PciBus, *PciDevice, *PciFunction));\r
+ }\r
+\r
+ *PirqIndex = LocalPirqIndex;\r
+ *PciBus = BaseBus;\r
+ *PciDevice = BaseDevice;\r
+ *PciFunction = BaseFunction;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Copy the $PIR table as required.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param RoutingTable Pointer to IRQ routing table\r
+ @param RoutingTableEntries IRQ routing table entries\r
+ @param PirqTable Pointer to $PIR table\r
+ @param PirqTableSize Length of table\r
+\r
+**/\r
+VOID\r
+CopyPirqTable (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable,\r
+ IN UINTN RoutingTableEntries,\r
+ IN EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable,\r
+ IN UINTN PirqTableSize\r
+ )\r
+{\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT32 Granularity;\r
+\r
+ //\r
+ // Copy $PIR table, if it exists.\r
+ //\r
+ if (PirqTable != NULL) {\r
+ Private->LegacyRegion->UnLock (\r
+ Private->LegacyRegion,\r
+ 0xE0000,\r
+ 0x20000,\r
+ &Granularity\r
+ );\r
+\r
+ Private->InternalIrqRoutingTable = RoutingTable;\r
+ Private->NumberIrqRoutingEntries = (UINT16) (RoutingTableEntries);\r
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
+\r
+ Regs.X.AX = Legacy16GetTableAddress;\r
+ Regs.X.CX = (UINT16) PirqTableSize;\r
+ //\r
+ // Allocate at F segment according to PCI IRQ Routing Table Specification\r
+ //\r
+ Regs.X.BX = (UINT16) 0x1;\r
+ //\r
+ // 16-byte boundary alignment requirement according to \r
+ // PCI IRQ Routing Table Specification\r
+ //\r
+ Regs.X.DX = 0x10;\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Private->Legacy16CallSegment,\r
+ Private->Legacy16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ Private->Legacy16Table->IrqRoutingTablePointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
+ if (Regs.X.AX != 0) {\r
+ DEBUG ((EFI_D_ERROR, "PIRQ table length insufficient - %x\n", PirqTableSize));\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "PIRQ table in legacy region - %x\n", Private->Legacy16Table->IrqRoutingTablePointer)); \r
+ Private->Legacy16Table->IrqRoutingTableLength = (UINT32)PirqTableSize;\r
+ CopyMem (\r
+ (VOID *) (UINTN)Private->Legacy16Table->IrqRoutingTablePointer,\r
+ PirqTable,\r
+ PirqTableSize\r
+ );\r
+ }\r
+\r
+ Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);\r
+ Private->LegacyRegion->Lock (\r
+ Private->LegacyRegion,\r
+ 0xE0000,\r
+ 0x20000,\r
+ &Granularity\r
+ );\r
+ }\r
+\r
+ Private->PciInterruptLine = TRUE;\r
+ mHandleCount = 0;\r
+}\r
+\r
+/**\r
+ Dump EFI_LEGACY_INSTALL_PCI_HANDLER structure information.\r
+\r
+ @param PciHandle The pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure\r
+\r
+**/\r
+VOID\r
+DumpPciHandle (\r
+ IN EFI_LEGACY_INSTALL_PCI_HANDLER *PciHandle\r
+ )\r
+{\r
+ DEBUG ((EFI_D_INFO, "PciBus - %02x\n", (UINTN)PciHandle->PciBus));\r
+ DEBUG ((EFI_D_INFO, "PciDeviceFun - %02x\n", (UINTN)PciHandle->PciDeviceFun));\r
+ DEBUG ((EFI_D_INFO, "PciSegment - %02x\n", (UINTN)PciHandle->PciSegment));\r
+ DEBUG ((EFI_D_INFO, "PciClass - %02x\n", (UINTN)PciHandle->PciClass));\r
+ DEBUG ((EFI_D_INFO, "PciSubclass - %02x\n", (UINTN)PciHandle->PciSubclass));\r
+ DEBUG ((EFI_D_INFO, "PciInterface - %02x\n", (UINTN)PciHandle->PciInterface));\r
+\r
+ DEBUG ((EFI_D_INFO, "PrimaryIrq - %02x\n", (UINTN)PciHandle->PrimaryIrq));\r
+ DEBUG ((EFI_D_INFO, "PrimaryReserved - %02x\n", (UINTN)PciHandle->PrimaryReserved));\r
+ DEBUG ((EFI_D_INFO, "PrimaryControl - %04x\n", (UINTN)PciHandle->PrimaryControl));\r
+ DEBUG ((EFI_D_INFO, "PrimaryBase - %04x\n", (UINTN)PciHandle->PrimaryBase));\r
+ DEBUG ((EFI_D_INFO, "PrimaryBusMaster - %04x\n", (UINTN)PciHandle->PrimaryBusMaster));\r
+\r
+ DEBUG ((EFI_D_INFO, "SecondaryIrq - %02x\n", (UINTN)PciHandle->SecondaryIrq));\r
+ DEBUG ((EFI_D_INFO, "SecondaryReserved - %02x\n", (UINTN)PciHandle->SecondaryReserved));\r
+ DEBUG ((EFI_D_INFO, "SecondaryControl - %04x\n", (UINTN)PciHandle->SecondaryControl));\r
+ DEBUG ((EFI_D_INFO, "SecondaryBase - %04x\n", (UINTN)PciHandle->SecondaryBase));\r
+ DEBUG ((EFI_D_INFO, "SecondaryBusMaster - %04x\n", (UINTN)PciHandle->SecondaryBusMaster));\r
+ return;\r
+}\r
+\r
+/**\r
+ Copy the $PIR table as required.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+ @param PciIo Pointer to PCI_IO protocol\r
+ @param PciIrq Pci IRQ number\r
+ @param PciConfigHeader Type00 Pci configuration header\r
+\r
+**/\r
+VOID\r
+InstallLegacyIrqHandler (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT8 PciIrq,\r
+ IN PCI_TYPE00 *PciConfigHeader\r
+ )\r
+{\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT16 LegMask;\r
+ UINTN PciSegment;\r
+ UINTN PciBus;\r
+ UINTN PciDevice;\r
+ UINTN PciFunction;\r
+ EFI_LEGACY_8259_PROTOCOL *Legacy8259;\r
+ UINT16 PrimaryMaster;\r
+ UINT16 SecondaryMaster;\r
+ UINTN TempData;\r
+ UINTN RegisterAddress;\r
+ UINT32 Granularity;\r
+\r
+ PrimaryMaster = 0;\r
+ SecondaryMaster = 0;\r
+ Legacy8259 = Private->Legacy8259;\r
+ //\r
+ // Disable interrupt in PIC, in case shared, to prevent an\r
+ // interrupt from occuring.\r
+ //\r
+ Legacy8259->GetMask (\r
+ Legacy8259,\r
+ &LegMask,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ LegMask = (UINT16) (LegMask | (UINT16) (1 << PciIrq));\r
+\r
+ Legacy8259->SetMask (\r
+ Legacy8259,\r
+ &LegMask,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ PciIo->GetLocation (\r
+ PciIo,\r
+ &PciSegment,\r
+ &PciBus,\r
+ &PciDevice,\r
+ &PciFunction\r
+ );\r
+ Private->IntThunk->PciHandler.PciBus = (UINT8) PciBus;\r
+ Private->IntThunk->PciHandler.PciDeviceFun = (UINT8) ((PciDevice << 3) + PciFunction);\r
+ Private->IntThunk->PciHandler.PciSegment = (UINT8) PciSegment;\r
+ Private->IntThunk->PciHandler.PciClass = PciConfigHeader->Hdr.ClassCode[2];\r
+ Private->IntThunk->PciHandler.PciSubclass = PciConfigHeader->Hdr.ClassCode[1];\r
+ Private->IntThunk->PciHandler.PciInterface = PciConfigHeader->Hdr.ClassCode[0];\r
+\r
+ //\r
+ // Use native mode base address registers in two cases:\r
+ // 1. Programming Interface (PI) register indicates Primary Controller is\r
+ // in native mode OR\r
+ // 2. PCI device Sub Class Code is not IDE\r
+ //\r
+ Private->IntThunk->PciHandler.PrimaryBusMaster = (UINT16)(PciConfigHeader->Device.Bar[4] & 0xfffc);\r
+ if (((PciConfigHeader->Hdr.ClassCode[0] & 0x01) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) {\r
+ Private->IntThunk->PciHandler.PrimaryIrq = PciIrq;\r
+ Private->IntThunk->PciHandler.PrimaryBase = (UINT16) (PciConfigHeader->Device.Bar[0] & 0xfffc);\r
+ Private->IntThunk->PciHandler.PrimaryControl = (UINT16) ((PciConfigHeader->Device.Bar[1] & 0xfffc) + 2);\r
+ } else {\r
+ Private->IntThunk->PciHandler.PrimaryIrq = 14;\r
+ Private->IntThunk->PciHandler.PrimaryBase = 0x1f0;\r
+ Private->IntThunk->PciHandler.PrimaryControl = 0x3f6;\r
+ }\r
+ //\r
+ // Secondary controller data\r
+ //\r
+ if (Private->IntThunk->PciHandler.PrimaryBusMaster != 0) {\r
+ Private->IntThunk->PciHandler.SecondaryBusMaster = (UINT16) ((PciConfigHeader->Device.Bar[4] & 0xfffc) + 8);\r
+ PrimaryMaster = (UINT16) (Private->IntThunk->PciHandler.PrimaryBusMaster + 2);\r
+ SecondaryMaster = (UINT16) (Private->IntThunk->PciHandler.SecondaryBusMaster + 2);\r
+\r
+ //\r
+ // Clear pending interrupts in Bus Master registers\r
+ //\r
+ IoWrite16 (PrimaryMaster, 0x04);\r
+ IoWrite16 (SecondaryMaster, 0x04);\r
+\r
+ }\r
+\r
+ //\r
+ // Use native mode base address registers in two cases:\r
+ // 1. Programming Interface (PI) register indicates Secondary Controller is\r
+ // in native mode OR\r
+ // 2. PCI device Sub Class Code is not IDE\r
+ //\r
+ if (((PciConfigHeader->Hdr.ClassCode[0] & 0x04) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) {\r
+ Private->IntThunk->PciHandler.SecondaryIrq = PciIrq;\r
+ Private->IntThunk->PciHandler.SecondaryBase = (UINT16) (PciConfigHeader->Device.Bar[2] & 0xfffc);\r
+ Private->IntThunk->PciHandler.SecondaryControl = (UINT16) ((PciConfigHeader->Device.Bar[3] & 0xfffc) + 2);\r
+ } else {\r
+\r
+ Private->IntThunk->PciHandler.SecondaryIrq = 15;\r
+ Private->IntThunk->PciHandler.SecondaryBase = 0x170;\r
+ Private->IntThunk->PciHandler.SecondaryControl = 0x376;\r
+ }\r
+\r
+ //\r
+ // Clear pending interrupts in IDE Command Block Status reg before we\r
+ // Thunk to CSM16 below. Don't want a pending Interrupt before we\r
+ // install the handlers as wierd corruption would occur and hang system.\r
+ //\r
+ //\r
+ // Read IDE CMD blk status reg to clear out any pending interrupts.\r
+ // Do here for Primary and Secondary IDE channels\r
+ //\r
+ RegisterAddress = (UINT16)Private->IntThunk->PciHandler.PrimaryBase + 0x07;\r
+ IoRead8 (RegisterAddress);\r
+ RegisterAddress = (UINT16)Private->IntThunk->PciHandler.SecondaryBase + 0x07;\r
+ IoRead8 (RegisterAddress);\r
+\r
+ Private->IntThunk->PciHandler.PrimaryReserved = 0;\r
+ Private->IntThunk->PciHandler.SecondaryReserved = 0;\r
+ Private->LegacyRegion->UnLock (\r
+ Private->LegacyRegion,\r
+ 0xE0000,\r
+ 0x20000,\r
+ &Granularity\r
+ );\r
+\r
+ Regs.X.AX = Legacy16InstallPciHandler;\r
+ TempData = (UINTN) &Private->IntThunk->PciHandler;\r
+ Regs.X.ES = EFI_SEGMENT ((UINT32) TempData);\r
+ Regs.X.BX = EFI_OFFSET ((UINT32) TempData);\r
+\r
+ DumpPciHandle (&Private->IntThunk->PciHandler);\r
+\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Private->Legacy16CallSegment,\r
+ Private->Legacy16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+\r
+ Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);\r
+ Private->LegacyRegion->Lock (\r
+ Private->LegacyRegion,\r
+ 0xE0000,\r
+ 0x20000,\r
+ &Granularity\r
+ );\r
+\r
+}\r
+\r
+\r
+/**\r
+ Program the interrupt routing register in all the PCI devices. On a PC AT system\r
+ this register contains the 8259 IRQ vector that matches it's PCI interrupt.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_ALREADY_STARTED All PCI devices have been processed.\r
+\r
+**/\r
+EFI_STATUS\r
+PciProgramAllInterruptLineRegisters (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_LEGACY_8259_PROTOCOL *Legacy8259;\r
+ EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;\r
+ EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;\r
+ UINT8 InterruptPin;\r
+ UINTN Index;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN MassStorageHandleCount;\r
+ EFI_HANDLE *MassStorageHandleBuffer;\r
+ UINTN MassStorageHandleIndex;\r
+ UINT8 PciIrq;\r
+ UINT16 Command;\r
+ UINTN PciSegment;\r
+ UINTN PciBus;\r
+ UINTN PciDevice;\r
+ UINTN PciFunction;\r
+ EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable;\r
+ UINTN RoutingTableEntries;\r
+ UINT16 LegMask;\r
+ UINT16 LegEdgeLevel;\r
+ PCI_TYPE00 PciConfigHeader;\r
+ EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable;\r
+ UINTN PirqTableSize;\r
+ UINTN Flags;\r
+ HDD_INFO *HddInfo;\r
+ UINT64 Supports;\r
+\r
+ //\r
+ // Note - This routine use to return immediately if Private->PciInterruptLine\r
+ // was true. Routine changed since resets etc can cause not all\r
+ // PciIo protocols to be registered the first time through.\r
+ // New algorithm is to do the copy $PIR table on first pass and save\r
+ // HandleCount on first pass. If subsequent passes LocateHandleBuffer gives\r
+ // a larger handle count then proceed with body of function else return\r
+ // EFI_ALREADY_STARTED. In addition check if PCI device InterruptLine != 0.\r
+ // If zero then function unprogrammed else skip function.\r
+ //\r
+ Legacy8259 = Private->Legacy8259;\r
+ LegacyInterrupt = Private->LegacyInterrupt;\r
+ LegacyBiosPlatform = Private->LegacyBiosPlatform;\r
+\r
+ LegacyBiosPlatform->GetRoutingTable (\r
+ Private->LegacyBiosPlatform,\r
+ (VOID *) &RoutingTable,\r
+ &RoutingTableEntries,\r
+ (VOID *) &PirqTable,\r
+ &PirqTableSize,\r
+ NULL,\r
+ NULL\r
+ );\r
+ CreateBridgeTable (RoutingTable, RoutingTableEntries);\r
+\r
+ if (!Private->PciInterruptLine) {\r
+ CopyPirqTable (\r
+ Private,\r
+ RoutingTable,\r
+ RoutingTableEntries,\r
+ PirqTable,\r
+ PirqTableSize\r
+ );\r
+ }\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ if (HandleCount == mHandleCount) {\r
+ FreePool (HandleBuffer);\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ if (mHandleCount == 0x00) {\r
+ mHandleCount = HandleCount;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ //\r
+ // If VGA then only do VGA to allow drives fore time to spin up\r
+ // otherwise assign PCI IRQs to all potential devices.\r
+ //\r
+ if ((mVgaInstallationInProgress) && (HandleBuffer[Index] != mVgaHandle)) {\r
+ continue;\r
+ } else {\r
+ //\r
+ // Force code to go through all handles next time called if video.\r
+ // This will catch case where HandleCount doesn't change but want\r
+ // to get drive info etc.\r
+ //\r
+ mHandleCount = 0x00;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Test whether the device can be enabled or not.\r
+ // If it can't be enabled, then just skip it to avoid further operation.\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (PciConfigHeader) / sizeof (UINT32),\r
+ &PciConfigHeader\r
+ );\r
+ Command = PciConfigHeader.Hdr.Command;\r
+\r
+ //\r
+ // Note PciIo->Attributes does not program the PCI command register\r
+ //\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ Supports,\r
+ NULL\r
+ );\r
+ }\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x04, 1, &Command);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ InterruptPin = PciConfigHeader.Device.InterruptPin;\r
+\r
+ if ((InterruptPin != 0) && (PciConfigHeader.Device.InterruptLine == PCI_INT_LINE_UNKNOWN)) {\r
+ PciIo->GetLocation (\r
+ PciIo,\r
+ &PciSegment,\r
+ &PciBus,\r
+ &PciDevice,\r
+ &PciFunction\r
+ );\r
+ //\r
+ // Translate PIRQ index back thru busses to slot bus with InterruptPin\r
+ // zero based\r
+ //\r
+ InterruptPin -= 1;\r
+\r
+ Status = GetBaseBus (\r
+ Private,\r
+ PciBus,\r
+ PciDevice,\r
+ RoutingTable,\r
+ RoutingTableEntries\r
+ );\r
+\r
+ if (Status == EFI_NOT_FOUND) {\r
+ TranslateBusPirq (\r
+ Private,\r
+ &PciBus,\r
+ &PciDevice,\r
+ &PciFunction,\r
+ &InterruptPin\r
+ );\r
+ }\r
+ //\r
+ // Translate InterruptPin(0-3) into PIRQ\r
+ //\r
+ Status = LegacyBiosPlatform->TranslatePirq (\r
+ LegacyBiosPlatform,\r
+ PciBus,\r
+ (PciDevice << 3),\r
+ PciFunction,\r
+ &InterruptPin,\r
+ &PciIrq\r
+ );\r
+ //\r
+ // TranslatePirq() should never fail or we are in trouble\r
+ // If it does return failure status, check your PIRQ routing table to see if some item is missing or incorrect\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Translate Pirq Failed - Status = %r\n ", Status));\r
+ continue;\r
+ }\r
+\r
+ LegacyInterrupt->WritePirq (\r
+ LegacyInterrupt,\r
+ InterruptPin,\r
+ PciIrq\r
+ );\r
+\r
+ //\r
+ // Check if device has an OPROM associated with it.\r
+ // If not invoke special 16-bit function, to allow 16-bit\r
+ // code to install an interrupt handler.\r
+ //\r
+ Status = LegacyBiosCheckPciRom (\r
+ &Private->LegacyBios,\r
+ HandleBuffer[Index],\r
+ NULL,\r
+ NULL,\r
+ &Flags\r
+ );\r
+ if ((EFI_ERROR (Status)) && (PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE)) {\r
+ //\r
+ // Device has no OPROM associated with it and is a mass storage\r
+ // device. It needs to have an PCI IRQ handler installed. To\r
+ // correctly install the handler we need to insure device is\r
+ // connected. The device may just have register itself but not\r
+ // been connected. Re-read PCI config space after as it can\r
+ // change\r
+ //\r
+ //\r
+ // Get IDE Handle. If matches handle then skip ConnectController\r
+ // since ConnectController may force native mode and we don't\r
+ // want that for primary IDE controller\r
+ //\r
+ MassStorageHandleCount = 0;\r
+ MassStorageHandleBuffer = NULL;\r
+ LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformIdeHandle,\r
+ 0,\r
+ &MassStorageHandleBuffer,\r
+ &MassStorageHandleCount,\r
+ NULL\r
+ );\r
+\r
+ HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];\r
+\r
+ LegacyBiosBuildIdeData (Private, &HddInfo, 0);\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (PciConfigHeader) / sizeof (UINT32),\r
+ &PciConfigHeader\r
+ );\r
+\r
+ for (MassStorageHandleIndex = 0; MassStorageHandleIndex < MassStorageHandleCount; MassStorageHandleIndex++) {\r
+ if (MassStorageHandleBuffer[MassStorageHandleIndex] == HandleBuffer[Index]) {\r
+ //\r
+ // InstallLegacyIrqHandler according to Platform requirement\r
+ //\r
+ InstallLegacyIrqHandler (\r
+ Private,\r
+ PciIo,\r
+ PciIrq,\r
+ &PciConfigHeader\r
+ );\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Write InterruptPin and enable 8259.\r
+ //\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ 0x3c,\r
+ 1,\r
+ &PciIrq\r
+ );\r
+ Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask = (UINT16) (Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask | (UINT16) (1 << PciIrq));\r
+\r
+ Legacy8259->GetMask (\r
+ Legacy8259,\r
+ &LegMask,\r
+ &LegEdgeLevel,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ LegMask = (UINT16) (LegMask & (UINT16)~(1 << PciIrq));\r
+ LegEdgeLevel = (UINT16) (LegEdgeLevel | (UINT16) (1 << PciIrq));\r
+ Legacy8259->SetMask (\r
+ Legacy8259,\r
+ &LegMask,\r
+ &LegEdgeLevel,\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
+ }\r
+ FreePool (HandleBuffer);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Find & verify PnP Expansion header in ROM image\r
+\r
+ @param Private Protocol instance pointer.\r
+ @param FirstHeader 1 = Find first header, 0 = Find successive headers\r
+ @param PnpPtr Input Rom start if FirstHeader =1, Current Header\r
+ otherwise Output Next header, if it exists\r
+\r
+ @retval EFI_SUCCESS Next Header found at BasePnpPtr\r
+ @retval EFI_NOT_FOUND No more headers\r
+\r
+**/\r
+EFI_STATUS\r
+FindNextPnpExpansionHeader (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN BOOLEAN FirstHeader,\r
+ IN OUT LEGACY_PNP_EXPANSION_HEADER **PnpPtr\r
+\r
+ )\r
+{\r
+ UINTN TempData;\r
+ LEGACY_PNP_EXPANSION_HEADER *LocalPnpPtr;\r
+ LocalPnpPtr = *PnpPtr;\r
+ if (FirstHeader == FIRST_INSTANCE) {\r
+ mBasePnpPtr = LocalPnpPtr;\r
+ mBbsRomSegment = (UINT16) ((UINTN) mBasePnpPtr >> 4);\r
+ //\r
+ // Offset 0x1a gives offset to PnP expansion header for the first\r
+ // instance, there after the structure gives the offset to the next\r
+ // structure\r
+ //\r
+ LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) ((UINT8 *) LocalPnpPtr + 0x1a);\r
+ TempData = (*((UINT16 *) LocalPnpPtr));\r
+ } else {\r
+ TempData = (UINT16) LocalPnpPtr->NextHeader;\r
+ }\r
+\r
+ LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) (((UINT8 *) mBasePnpPtr + TempData));\r
+\r
+ //\r
+ // Search for PnP table in Shadowed ROM\r
+ //\r
+ *PnpPtr = LocalPnpPtr;\r
+ if (*(UINT32 *) LocalPnpPtr == SIGNATURE_32 ('$', 'P', 'n', 'P')) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Update list of Bev or BCV table entries.\r
+\r
+ @param Private Protocol instance pointer.\r
+ @param RomStart Table of ROM start address in RAM/ROM. PciIo _\r
+ Handle to PCI IO for this device\r
+ @param PciIo Instance of PCI I/O Protocol\r
+\r
+ @retval EFI_SUCCESS Always should succeed.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateBevBcvTable (\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN EFI_LEGACY_EXPANSION_ROM_HEADER *RomStart,\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo\r
+ )\r
+{\r
+ VOID *RomEnd;\r
+ BBS_TABLE *BbsTable;\r
+ UINTN BbsIndex;\r
+ EFI_LEGACY_EXPANSION_ROM_HEADER *PciPtr;\r
+ LEGACY_PNP_EXPANSION_HEADER *PnpPtr;\r
+ BOOLEAN Instance;\r
+ EFI_STATUS Status;\r
+ UINTN Segment;\r
+ UINTN Bus;\r
+ UINTN Device;\r
+ UINTN Function;\r
+ UINT8 Class;\r
+ UINT16 DeviceType;\r
+ Segment = 0;\r
+ Bus = 0;\r
+ Device = 0;\r
+ Function = 0;\r
+ Class = 0;\r
+ DeviceType = BBS_UNKNOWN;\r
+\r
+ //\r
+ // Skip floppy and 2*onboard IDE controller entries(Master/Slave per\r
+ // controller).\r
+ //\r
+ BbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;\r
+\r
+ BbsTable = (BBS_TABLE*)(UINTN) Private->IntThunk->EfiToLegacy16BootTable.BbsTable;\r
+ PnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) RomStart;\r
+ PciPtr = (EFI_LEGACY_EXPANSION_ROM_HEADER *) RomStart;\r
+\r
+ RomEnd = (VOID *) (PciPtr->Size512 * 512 + (UINTN) PciPtr);\r
+ Instance = FIRST_INSTANCE;\r
+ //\r
+ // OPROMs like PXE may not be tied to a piece of hardware and thus\r
+ // don't have a PciIo associated with them\r
+ //\r
+ if (PciIo != NULL) {\r
+ PciIo->GetLocation (\r
+ PciIo,\r
+ &Segment,\r
+ &Bus,\r
+ &Device,\r
+ &Function\r
+ );\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ 0x0b,\r
+ 1,\r
+ &Class\r
+ );\r
+\r
+ if (Class == PCI_CLASS_MASS_STORAGE) {\r
+ DeviceType = BBS_HARDDISK;\r
+ } else {\r
+ if (Class == PCI_CLASS_NETWORK) {\r
+ DeviceType = BBS_EMBED_NETWORK;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (PciPtr >= (EFI_LEGACY_EXPANSION_ROM_HEADER *) ((UINTN) 0xc8000)) {\r
+ while (TRUE) {\r
+ Status = FindNextPnpExpansionHeader (Private, Instance, &PnpPtr);\r
+ Instance = NOT_FIRST_INSTANCE;\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ //\r
+ // There can be additional $PnP headers within the OPROM.\r
+ // Example: SCSI can have one per drive.\r
+ //\r
+ BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+ BbsTable[BbsIndex].DeviceType = DeviceType;\r
+ BbsTable[BbsIndex].Bus = (UINT32) Bus;\r
+ BbsTable[BbsIndex].Device = (UINT32) Device;\r
+ BbsTable[BbsIndex].Function = (UINT32) Function;\r
+ BbsTable[BbsIndex].StatusFlags.OldPosition = 0;\r
+ BbsTable[BbsIndex].StatusFlags.Reserved1 = 0;\r
+ BbsTable[BbsIndex].StatusFlags.Enabled = 0;\r
+ BbsTable[BbsIndex].StatusFlags.Failed = 0;\r
+ BbsTable[BbsIndex].StatusFlags.MediaPresent = 0;\r
+ BbsTable[BbsIndex].StatusFlags.Reserved2 = 0;\r
+ BbsTable[BbsIndex].Class = PnpPtr->Class;\r
+ BbsTable[BbsIndex].SubClass = PnpPtr->SubClass;\r
+ BbsTable[BbsIndex].DescStringOffset = PnpPtr->ProductNamePointer;\r
+ BbsTable[BbsIndex].DescStringSegment = mBbsRomSegment;\r
+ BbsTable[BbsIndex].MfgStringOffset = PnpPtr->MfgPointer;\r
+ BbsTable[BbsIndex].MfgStringSegment = mBbsRomSegment;\r
+ BbsTable[BbsIndex].BootHandlerSegment = mBbsRomSegment;\r
+\r
+ //\r
+ // Have seen case where PXE base code have PnP expansion ROM\r
+ // header but no Bcv or Bev vectors.\r
+ //\r
+ if (PnpPtr->Bcv != 0) {\r
+ BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bcv;\r
+ ++BbsIndex;\r
+ }\r
+\r
+ if (PnpPtr->Bev != 0) {\r
+ BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bev;\r
+ BbsTable[BbsIndex].DeviceType = BBS_BEV_DEVICE;\r
+ ++BbsIndex;\r
+ }\r
+\r
+ if ((PnpPtr == (LEGACY_PNP_EXPANSION_HEADER *) PciPtr) || (PnpPtr > (LEGACY_PNP_EXPANSION_HEADER *) RomEnd)) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ BbsTable[BbsIndex].BootPriority = BBS_IGNORE_ENTRY;\r
+ Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT32) BbsIndex;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol\r
+ to chose the order. Skip any devices that have already have legacy\r
+ BIOS run.\r
+\r
+ @param Private Protocol instance pointer.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_UNSUPPORTED Cannot get VGA device handle.\r
+\r
+**/\r
+EFI_STATUS\r
+PciShadowRoms (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE00 Pci;\r
+ UINTN Index;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ EFI_HANDLE VgaHandle;\r
+ EFI_HANDLE FirstHandle;\r
+ VOID **RomStart;\r
+ UINTN Flags;\r
+ PCI_TYPE00 PciConfigHeader;\r
+ UINT16 *Command;\r
+ UINT64 Supports;\r
+\r
+ //\r
+ // Make the VGA device first\r
+ //\r
+ Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformVgaHandle,\r
+ 0,\r
+ &HandleBuffer,\r
+ &HandleCount,\r
+ NULL\r
+ ); \r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ VgaHandle = HandleBuffer[0];\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Place the VGA handle as first.\r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ if (HandleBuffer[Index] == VgaHandle) {\r
+ FirstHandle = HandleBuffer[0];\r
+ HandleBuffer[0] = HandleBuffer[Index];\r
+ HandleBuffer[Index] = FirstHandle;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Allocate memory to save Command WORD from each device. We do this\r
+ // to restore devices to same state as EFI after switching to legacy.\r
+ //\r
+ Command = (UINT16 *) AllocatePool (\r
+ sizeof (UINT16) * (HandleCount + 1)\r
+ );\r
+ if (NULL == Command) {\r
+ FreePool (HandleBuffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Disconnect all EFI devices first. This covers cases where alegacy BIOS\r
+ // may control multiple PCI devices.\r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Save command register for "connect" loop\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (PciConfigHeader) / sizeof (UINT32),\r
+ &PciConfigHeader\r
+ );\r
+ Command[Index] = PciConfigHeader.Hdr.Command;\r
+ //\r
+ // Skip any device that already has a legacy ROM run\r
+ //\r
+ Status = IsLegacyRom (HandleBuffer[Index]);\r
+ if (!EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ //\r
+ // Stop EFI Drivers with oprom.\r
+ //\r
+ gBS->DisconnectController (\r
+ HandleBuffer[Index],\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
+ //\r
+ // For every device that has not had a legacy ROM started. Start a legacy ROM.\r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Here make sure if one VGA have been shadowed,\r
+ // then wil not shadowed another one.\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (Pci) / sizeof (UINT32),\r
+ &Pci\r
+ );\r
+ \r
+ //\r
+ // Only one Video OPROM can be given control in BIOS phase. If there are multiple Video devices, \r
+ // one will work in legacy mode (OPROM will be given control) and \r
+ // other Video devices will work in native mode (OS driver will handle these devices).\r
+ // \r
+ if (IS_PCI_DISPLAY (&Pci) && Index != 0) { \r
+ continue;\r
+ }\r
+ //\r
+ // Skip any device that already has a legacy ROM run\r
+ //\r
+ Status = IsLegacyRom (HandleBuffer[Index]);\r
+ if (!EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ //\r
+ // Install legacy ROM\r
+ //\r
+ Status = LegacyBiosInstallPciRom (\r
+ &Private->LegacyBios,\r
+ HandleBuffer[Index],\r
+ NULL,\r
+ &Flags,\r
+ NULL,\r
+ NULL,\r
+ (VOID **) &RomStart,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ if (!((Status == EFI_UNSUPPORTED) && (Flags == NO_ROM))) {\r
+ continue;\r
+ }\r
+ }\r
+ //\r
+ // Restore Command register so legacy has same devices enabled or disabled\r
+ // as EFI.\r
+ // If Flags = NO_ROM use command register as is. This covers the\r
+ // following cases:\r
+ // Device has no ROMs associated with it.\r
+ // Device has ROM associated with it but was already\r
+ // installed.\r
+ // = ROM_FOUND but not VALID_LEGACY_ROM, disable it.\r
+ // = ROM_FOUND and VALID_LEGACY_ROM, enable it.\r
+ //\r
+ if ((Flags & ROM_FOUND) == ROM_FOUND) {\r
+ if ((Flags & VALID_LEGACY_ROM) == 0) {\r
+ Command[Index] = 0;\r
+ } else {\r
+ //\r
+ // For several VGAs, only one of them can be enabled.\r
+ //\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ Supports,\r
+ NULL\r
+ );\r
+ }\r
+ if (!EFI_ERROR (Status)) {\r
+ Command[Index] = 0x1f;\r
+ }\r
+ }\r
+ }\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x04,\r
+ 1,\r
+ &Command[Index]\r
+ );\r
+ }\r
+\r
+ FreePool (Command);\r
+ FreePool (HandleBuffer);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Test to see if a legacy PCI ROM exists for this device. Optionally return\r
+ the Legacy ROM instance for this PCI device.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will\r
+ be loaded\r
+ @param RomImage Return the legacy PCI ROM for this device\r
+ @param RomSize Size of ROM Image\r
+ @param Flags Indicates if ROM found and if PC-AT.\r
+\r
+ @retval EFI_SUCCESS Legacy Option ROM availible for this device\r
+ @retval EFI_UNSUPPORTED Legacy Option ROM not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosCheckPciRom (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN EFI_HANDLE PciHandle,\r
+ OUT VOID **RomImage, OPTIONAL\r
+ OUT UINTN *RomSize, OPTIONAL\r
+ OUT UINTN *Flags\r
+ )\r
+{\r
+ return LegacyBiosCheckPciRomEx (\r
+ This,\r
+ PciHandle,\r
+ RomImage,\r
+ RomSize,\r
+ NULL,\r
+ Flags,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+}\r
+\r
+/**\r
+\r
+ Routine Description:\r
+ Test to see if a legacy PCI ROM exists for this device. Optionally return\r
+ the Legacy ROM instance for this PCI device.\r
+\r
+ @param[in] This Protocol instance pointer.\r
+ @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded\r
+ @param[out] RomImage Return the legacy PCI ROM for this device\r
+ @param[out] RomSize Size of ROM Image\r
+ @param[out] RuntimeImageLength Runtime size of ROM Image\r
+ @param[out] Flags Indicates if ROM found and if PC-AT.\r
+ @param[out] OpromRevision Revision of the PCI Rom\r
+ @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header\r
+\r
+ @return EFI_SUCCESS Legacy Option ROM availible for this device\r
+ @return EFI_ALREADY_STARTED This device is already managed by its Oprom\r
+ @return EFI_UNSUPPORTED Legacy Option ROM not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosCheckPciRomEx (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN EFI_HANDLE PciHandle,\r
+ OUT VOID **RomImage, OPTIONAL\r
+ OUT UINTN *RomSize, OPTIONAL\r
+ OUT UINTN *RuntimeImageLength, OPTIONAL\r
+ OUT UINTN *Flags, OPTIONAL\r
+ OUT UINT8 *OpromRevision, OPTIONAL\r
+ OUT VOID **ConfigUtilityCodeHeader OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINTN LocalRomSize;\r
+ VOID *LocalRomImage;\r
+ PCI_TYPE00 PciConfigHeader;\r
+ VOID *LocalConfigUtilityCodeHeader;\r
+\r
+ *Flags = NO_ROM;\r
+ Status = gBS->HandleProtocol (\r
+ PciHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // See if the option ROM for PciHandle has already been executed\r
+ //\r
+ Status = IsLegacyRom (PciHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ *Flags |= (ROM_FOUND | VALID_LEGACY_ROM);\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Check for PCI ROM Bar\r
+ //\r
+ LocalRomSize = (UINTN) PciIo->RomSize;\r
+ LocalRomImage = PciIo->RomImage;\r
+ if (LocalRomSize != 0) {\r
+ *Flags |= ROM_FOUND;\r
+ }\r
+\r
+ //\r
+ // PCI specification states you should check VendorId and Device Id.\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (PciConfigHeader) / sizeof (UINT32),\r
+ &PciConfigHeader\r
+ );\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ Status = GetPciLegacyRom (\r
+ Private->Csm16PciInterfaceVersion,\r
+ PciConfigHeader.Hdr.VendorId,\r
+ PciConfigHeader.Hdr.DeviceId,\r
+ &LocalRomImage,\r
+ &LocalRomSize,\r
+ RuntimeImageLength,\r
+ OpromRevision,\r
+ &LocalConfigUtilityCodeHeader\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *Flags |= VALID_LEGACY_ROM;\r
+\r
+ //\r
+ // See if Configuration Utility Code Header valid\r
+ //\r
+ if (LocalConfigUtilityCodeHeader != NULL) {\r
+ *Flags |= ROM_WITH_CONFIG;\r
+ }\r
+\r
+ if (ConfigUtilityCodeHeader != NULL) {\r
+ *ConfigUtilityCodeHeader = LocalConfigUtilityCodeHeader;\r
+ }\r
+\r
+ if (RomImage != NULL) {\r
+ *RomImage = LocalRomImage;\r
+ }\r
+\r
+ if (RomSize != NULL) {\r
+ *RomSize = LocalRomSize;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Load a legacy PC-AT OPROM on the PciHandle device. Return information\r
+ about how many disks were added by the OPROM and the shadow address and\r
+ size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C:\r
+\r
+ @retval EFI_SUCCESS Legacy ROM loaded for this device\r
+ @retval EFI_NOT_FOUND No PS2 Keyboard found\r
+\r
+**/\r
+EFI_STATUS\r
+EnablePs2Keyboard (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+ EFI_ISA_IO_PROTOCOL *IsaIo;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Get SimpleTextIn and find PS2 controller\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ //\r
+ // Open the IO Abstraction(s) needed to perform the supported test\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiIsaIoProtocolGuid,\r
+ (VOID **) &IsaIo,\r
+ NULL,\r
+ HandleBuffer[Index],\r
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Use the ISA I/O Protocol to see if Controller is the Keyboard\r
+ // controller\r
+ //\r
+ if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiIsaIoProtocolGuid,\r
+ NULL,\r
+ HandleBuffer[Index]\r
+ );\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);\r
+ }\r
+ }\r
+ FreePool (HandleBuffer);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Load a legacy PC-AT OpROM for VGA controller.\r
+\r
+ @param Private Driver private data.\r
+\r
+ @retval EFI_SUCCESS Legacy ROM successfully installed for this device.\r
+ @retval EFI_DEVICE_ERROR No VGA device handle found, or native EFI video\r
+ driver cannot be successfully disconnected, or VGA\r
+ thunk driver cannot be successfully connected.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosInstallVgaRom (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE VgaHandle;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ EFI_HANDLE *ConnectHandleBuffer;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE00 PciConfigHeader;\r
+ UINT64 Supports;\r
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
+ UINTN EntryCount;\r
+ UINTN Index;\r
+ VOID *Interface;\r
+\r
+ //\r
+ // EfiLegacyBiosGuild attached to a device implies that there is a legacy\r
+ // BIOS associated with that device.\r
+ //\r
+ // There are 3 cases to consider.\r
+ // Case 1: No EFI driver is controlling the video.\r
+ // Action: Return EFI_SUCCESS from DisconnectController, search\r
+ // video thunk driver, and connect it.\r
+ // Case 2: EFI driver is controlling the video and EfiLegacyBiosGuid is\r
+ // not on the image handle.\r
+ // Action: Disconnect EFI driver.\r
+ // ConnectController for video thunk\r
+ // Case 3: EFI driver is controlling the video and EfiLegacyBiosGuid is\r
+ // on the image handle.\r
+ // Action: Do nothing and set Private->VgaInstalled = TRUE.\r
+ // Then this routine is not called any more.\r
+ //\r
+ //\r
+ // Get the VGA device.\r
+ //\r
+ Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformVgaHandle,\r
+ 0,\r
+ &HandleBuffer,\r
+ &HandleCount,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ VgaHandle = HandleBuffer[0];\r
+\r
+ //\r
+ // Check whether video thunk driver already starts.\r
+ //\r
+ Status = gBS->OpenProtocolInformation (\r
+ VgaHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ &OpenInfoBuffer,\r
+ &EntryCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ for (Index = 0; Index < EntryCount; Index++) {\r
+ if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
+ Status = gBS->HandleProtocol (\r
+ OpenInfoBuffer[Index].AgentHandle,\r
+ &gEfiLegacyBiosGuid,\r
+ (VOID **) &Interface\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // This should be video thunk driver which is managing video device\r
+ // So it need not start again\r
+ //\r
+ DEBUG ((EFI_D_INFO, "Video thunk driver already start! Return!\n"));\r
+ Private->VgaInstalled = TRUE;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Kick off the native EFI driver\r
+ //\r
+ Status = gBS->DisconnectController (\r
+ VgaHandle,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status != EFI_NOT_FOUND) {\r
+ return EFI_DEVICE_ERROR;\r
+ } else {\r
+ return Status;\r
+ }\r
+ }\r
+ //\r
+ // Find all the Thunk Driver\r
+ //\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiLegacyBiosGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ ConnectHandleBuffer = (EFI_HANDLE *) AllocatePool (sizeof (EFI_HANDLE) * (HandleCount + 1));\r
+ ASSERT (ConnectHandleBuffer != NULL);\r
+\r
+ CopyMem (\r
+ ConnectHandleBuffer,\r
+ HandleBuffer,\r
+ sizeof (EFI_HANDLE) * HandleCount\r
+ );\r
+ ConnectHandleBuffer[HandleCount] = NULL;\r
+\r
+ FreePool (HandleBuffer);\r
+\r
+ //\r
+ // Enable the device and make sure VGA cycles are being forwarded to this VGA device\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ VgaHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (PciConfigHeader) / sizeof (UINT32),\r
+ &PciConfigHeader\r
+ );\r
+\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Supports &= EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \\r
+ EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ Supports,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (Status == EFI_SUCCESS) {\r
+ Private->VgaInstalled = TRUE;\r
+\r
+ //\r
+ // Attach the VGA thunk driver.\r
+ // Assume the video is installed. This prevents potential of infinite recursion.\r
+ //\r
+ Status = gBS->ConnectController (\r
+ VgaHandle,\r
+ ConnectHandleBuffer,\r
+ NULL,\r
+ TRUE\r
+ );\r
+ }\r
+\r
+ FreePool (ConnectHandleBuffer);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+\r
+ Private->VgaInstalled = FALSE;\r
+\r
+ //\r
+ // Reconnect the EFI VGA driver.\r
+ //\r
+ gBS->ConnectController (VgaHandle, NULL, NULL, TRUE);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Load a legacy PC-AT OpROM.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Private Driver's private data.\r
+ @param PciHandle The EFI handle for the PCI device. It could be\r
+ NULL if the OpROM image is not associated with\r
+ any device.\r
+ @param OpromRevision The revision of PCI PC-AT ROM image.\r
+ @param RomImage Pointer to PCI PC-AT ROM image header. It must not\r
+ be NULL.\r
+ @param ImageSize Size of the PCI PC-AT ROM image.\r
+ @param RuntimeImageLength On input is the max runtime image length indicated by the PCIR structure\r
+ On output is the actual runtime image length\r
+ @param DiskStart Disk number of first device hooked by the ROM. If\r
+ DiskStart is the same as DiskEnd no disked were\r
+ hooked.\r
+ @param DiskEnd Disk number of the last device hooked by the ROM.\r
+ @param RomShadowAddress Shadow address of PC-AT ROM\r
+\r
+ @retval EFI_SUCCESS Legacy ROM loaded for this device\r
+ @retval EFI_OUT_OF_RESOURCES No more space for this ROM\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosInstallRom (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN LEGACY_BIOS_INSTANCE *Private,\r
+ IN EFI_HANDLE PciHandle,\r
+ IN UINT8 OpromRevision,\r
+ IN VOID *RomImage,\r
+ IN UINTN ImageSize,\r
+ IN OUT UINTN *RuntimeImageLength,\r
+ OUT UINT8 *DiskStart, OPTIONAL\r
+ OUT UINT8 *DiskEnd, OPTIONAL\r
+ OUT VOID **RomShadowAddress OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS PciEnableStatus;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 LocalDiskStart;\r
+ UINT8 LocalDiskEnd;\r
+ UINTN Segment;\r
+ UINTN Bus;\r
+ UINTN Device;\r
+ UINTN Function;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT8 VideoMode;\r
+ EFI_TIME BootTime;\r
+ UINT32 *BdaPtr;\r
+ UINT32 LocalTime;\r
+ UINT32 StartBbsIndex;\r
+ UINT32 EndBbsIndex;\r
+ UINTN TempData;\r
+ UINTN InitAddress;\r
+ UINTN RuntimeAddress;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ UINT32 Granularity;\r
+\r
+ PciIo = NULL;\r
+ LocalDiskStart = 0;\r
+ LocalDiskEnd = 0;\r
+ Segment = 0;\r
+ Bus = 0;\r
+ Device = 0;\r
+ Function = 0;\r
+ VideoMode = 0;\r
+ PhysicalAddress = 0;\r
+\r
+ PciProgramAllInterruptLineRegisters (Private);\r
+\r
+ if ((OpromRevision >= 3) && (Private->Csm16PciInterfaceVersion >= 0x0300)) {\r
+ //\r
+ // CSM16 3.0 meets PCI 3.0 OpROM\r
+ // first test if there is enough space for its INIT code\r
+ //\r
+ PhysicalAddress = CONVENTIONAL_MEMORY_TOP;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiBootServicesCode,\r
+ EFI_SIZE_TO_PAGES (ImageSize),\r
+ &PhysicalAddress\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ InitAddress = (UINTN) PhysicalAddress;\r
+ //\r
+ // then test if there is enough space for its RT code\r
+ //\r
+ RuntimeAddress = Private->OptionRom;\r
+ if (RuntimeAddress + *RuntimeImageLength > mEndOpromShadowAddress) {\r
+ DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\r
+ gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ // CSM16 3.0 meets PCI 2.x OpROM\r
+ // CSM16 2.x meets PCI 2.x/3.0 OpROM\r
+ // test if there is enough space for its INIT code\r
+ //\r
+ InitAddress = PCI_START_ADDRESS (Private->OptionRom);\r
+ if (InitAddress + ImageSize > mEndOpromShadowAddress) {\r
+ DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ RuntimeAddress = InitAddress;\r
+ }\r
+\r
+ Private->LegacyRegion->UnLock (\r
+ Private->LegacyRegion,\r
+ 0xE0000,\r
+ 0x20000,\r
+ &Granularity\r
+ );\r
+\r
+ Private->LegacyRegion->UnLock (\r
+ Private->LegacyRegion,\r
+ (UINT32) RuntimeAddress,\r
+ (UINT32) ImageSize,\r
+ &Granularity\r
+ );\r
+ \r
+ DEBUG ((EFI_D_INFO, " Shadowing OpROM init/runtime/isize = %x/%x/%x\n", InitAddress, RuntimeAddress, ImageSize));\r
+\r
+ CopyMem ((VOID *) InitAddress, RomImage, ImageSize);\r
+\r
+ //\r
+ // Read the highest disk number "installed: and assume a new disk will\r
+ // show up on the first drive past the current value.\r
+ // There are several considerations here:\r
+ // 1. Non-BBS compliant drives will change 40:75 but 16-bit CSM will undo\r
+ // the change until boot selection time frame.\r
+ // 2. BBS compliants drives will not change 40:75 until boot time.\r
+ // 3. Onboard IDE controllers will change 40:75\r
+ //\r
+ LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);\r
+ if ((Private->Disk4075 + 0x80) < LocalDiskStart) {\r
+ //\r
+ // Update table since onboard IDE drives found\r
+ //\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = 0xff;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = 0xff;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = 0xff;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = 0xff;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = (UINT8) (Private->Disk4075 + 0x80);\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = LocalDiskStart;\r
+ Private->LegacyEfiHddTableIndex ++;\r
+ Private->Disk4075 = (UINT8) (LocalDiskStart & 0x7f);\r
+ Private->DiskEnd = LocalDiskStart;\r
+ }\r
+\r
+ if (PciHandle != mVgaHandle) {\r
+\r
+ EnablePs2Keyboard ();\r
+\r
+ //\r
+ // Store current mode settings since PrepareToScanRom may change mode.\r
+ //\r
+ VideoMode = *(UINT8 *) ((UINTN) 0x449);\r
+ }\r
+ //\r
+ // Notify the platform that we are about to scan the ROM\r
+ //\r
+ Status = Private->LegacyBiosPlatform->PlatformHooks (\r
+ Private->LegacyBiosPlatform,\r
+ EfiPlatformHookPrepareToScanRom,\r
+ 0,\r
+ PciHandle,\r
+ &InitAddress,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // If Status returned is EFI_UNSUPPORTED then abort due to platform\r
+ // policy.\r
+ //\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Report corresponding status code\r
+ //\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_CSM_LEGACY_ROM_INIT)\r
+ );\r
+\r
+ //\r
+ // Generate number of ticks since midnight for BDA. Some OPROMs require\r
+ // this. Place result in 40:6C-6F\r
+ //\r
+ gRT->GetTime (&BootTime, NULL);\r
+ LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second;\r
+ \r
+ //\r
+ // Multiply result by 18.2 for number of ticks since midnight.\r
+ // Use 182/10 to avoid floating point math.\r
+ //\r
+ LocalTime = (LocalTime * 182) / 10;\r
+ BdaPtr = (UINT32 *) ((UINTN) 0x46C);\r
+ *BdaPtr = LocalTime;\r
+ \r
+ //\r
+ // Pass in handoff data\r
+ //\r
+ PciEnableStatus = EFI_UNSUPPORTED;\r
+ ZeroMem (&Regs, sizeof (Regs));\r
+ if (PciHandle != NULL) {\r
+ \r
+ Status = gBS->HandleProtocol (\r
+ PciHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ //\r
+ // Enable command register.\r
+ //\r
+ PciEnableStatus = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ EFI_PCI_DEVICE_ENABLE,\r
+ NULL\r
+ );\r
+ \r
+ PciIo->GetLocation (\r
+ PciIo,\r
+ &Segment,\r
+ &Bus,\r
+ &Device,\r
+ &Function\r
+ );\r
+ DEBUG ((EFI_D_INFO, "Shadowing OpROM on the PCI device %x/%x/%x\n", Bus, Device, Function));\r
+ }\r
+ \r
+ mIgnoreBbsUpdateFlag = FALSE;\r
+ Regs.X.AX = Legacy16DispatchOprom;\r
+ \r
+ //\r
+ // Generate DispatchOpRomTable data\r
+ //\r
+ Private->IntThunk->DispatchOpromTable.PnPInstallationCheckSegment = Private->Legacy16Table->PnPInstallationCheckSegment;\r
+ Private->IntThunk->DispatchOpromTable.PnPInstallationCheckOffset = Private->Legacy16Table->PnPInstallationCheckOffset;\r
+ Private->IntThunk->DispatchOpromTable.OpromSegment = (UINT16) (InitAddress >> 4);\r
+ Private->IntThunk->DispatchOpromTable.PciBus = (UINT8) Bus;\r
+ Private->IntThunk->DispatchOpromTable.PciDeviceFunction = (UINT8) ((Device << 3) | Function);\r
+ Private->IntThunk->DispatchOpromTable.NumberBbsEntries = (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;\r
+ Private->IntThunk->DispatchOpromTable.BbsTablePointer = (UINT32) (UINTN) Private->BbsTablePtr;\r
+ Private->IntThunk->DispatchOpromTable.RuntimeSegment = (UINT16)((OpromRevision < 3) ? 0xffff : (RuntimeAddress >> 4));\r
+ TempData = (UINTN) &Private->IntThunk->DispatchOpromTable;\r
+ Regs.X.ES = EFI_SEGMENT ((UINT32) TempData);\r
+ Regs.X.BX = EFI_OFFSET ((UINT32) TempData);\r
+ //\r
+ // Skip dispatching ROM for those PCI devices that can not be enabled by PciIo->Attributes\r
+ // Otherwise, it may cause the system to hang in some cases\r
+ //\r
+ if (!EFI_ERROR (PciEnableStatus)) {\r
+ DEBUG ((EFI_D_INFO, " Legacy16DispatchOprom - %02x/%02x/%02x\n", Bus, Device, Function));\r
+ Private->LegacyBios.FarCall86 (\r
+ &Private->LegacyBios,\r
+ Private->Legacy16CallSegment,\r
+ Private->Legacy16CallOffset,\r
+ &Regs,\r
+ NULL,\r
+ 0\r
+ );\r
+ } else {\r
+ Regs.X.BX = 0;\r
+ }\r
+ \r
+ if (Private->IntThunk->DispatchOpromTable.NumberBbsEntries != (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries) {\r
+ Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT8) Private->IntThunk->DispatchOpromTable.NumberBbsEntries;\r
+ mIgnoreBbsUpdateFlag = TRUE;\r
+ }\r
+ //\r
+ // Check if non-BBS compliant drives found\r
+ //\r
+ if (Regs.X.BX != 0) {\r
+ LocalDiskEnd = (UINT8) (LocalDiskStart + Regs.H.BL);\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = (UINT8) Segment;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = (UINT8) Bus;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = (UINT8) Device;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = (UINT8) Function;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = Private->DiskEnd;\r
+ Private->DiskEnd = LocalDiskEnd;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd;\r
+ Private->LegacyEfiHddTableIndex += 1;\r
+ }\r
+ //\r
+ // Skip video mode set, if installing VGA\r
+ //\r
+ if (PciHandle != mVgaHandle) {\r
+ //\r
+ // Set mode settings since PrepareToScanRom may change mode\r
+ //\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.AL = VideoMode;\r
+ Private->LegacyBios.Int86 (&Private->LegacyBios, 0x10, &Regs);\r
+ }\r
+ //\r
+ // Regs.X.AX from the adapter initializion is ignored since some adapters\r
+ // do not follow the standard of setting AX = 0 on success.\r
+ //\r
+ //\r
+ // The ROM could have updated it's size so we need to read again.\r
+ //\r
+ *RuntimeImageLength = ((EFI_LEGACY_EXPANSION_ROM_HEADER *) (RuntimeAddress))->Size512 * 512;\r
+ DEBUG ((EFI_D_INFO, " fsize = %x\n", *RuntimeImageLength));\r
+\r
+ //\r
+ // If OpROM runs in 2.0 mode\r
+ //\r
+ if (PhysicalAddress == 0) {\r
+ if (*RuntimeImageLength < ImageSize) {\r
+ //\r
+ // Make area from end of shadowed rom to end of original rom all ffs\r
+ //\r
+ gBS->SetMem ((VOID *) (InitAddress + *RuntimeImageLength), ImageSize - *RuntimeImageLength, 0xff);\r
+ }\r
+ }\r
+\r
+ LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);\r
+ \r
+ //\r
+ // Allow platform to perform any required actions after the\r
+ // OPROM has been initialized.\r
+ //\r
+ Status = Private->LegacyBiosPlatform->PlatformHooks (\r
+ Private->LegacyBiosPlatform,\r
+ EfiPlatformHookAfterRomInit,\r
+ 0,\r
+ PciHandle,\r
+ &RuntimeAddress,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (PciHandle != NULL) {\r
+ //\r
+ // If no PCI Handle then no header or Bevs.\r
+ //\r
+ if ((*RuntimeImageLength != 0) && (!mIgnoreBbsUpdateFlag)) {\r
+ StartBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;\r
+ TempData = RuntimeAddress;\r
+ UpdateBevBcvTable (\r
+ Private,\r
+ (EFI_LEGACY_EXPANSION_ROM_HEADER *) TempData,\r
+ PciIo\r
+ );\r
+ EndBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;\r
+ LocalDiskEnd = (UINT8) (LocalDiskStart + (UINT8) (EndBbsIndex - StartBbsIndex));\r
+ if (LocalDiskEnd != LocalDiskStart) {\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = (UINT8) Segment;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = (UINT8) Bus;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = (UINT8) Device;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = (UINT8) Function;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = Private->DiskEnd;\r
+ Private->DiskEnd = LocalDiskEnd;\r
+ Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd;\r
+ Private->LegacyEfiHddTableIndex += 1;\r
+ }\r
+ }\r
+ //\r
+ // Mark PCI device as having a legacy BIOS ROM loaded.\r
+ //\r
+ RomShadow (\r
+ PciHandle,\r
+ (UINT32) RuntimeAddress,\r
+ (UINT32) *RuntimeImageLength,\r
+ LocalDiskStart,\r
+ LocalDiskEnd\r
+ );\r
+ }\r
+\r
+ //\r
+ // Stuff caller's OPTIONAL return parameters.\r
+ //\r
+ if (RomShadowAddress != NULL) {\r
+ *RomShadowAddress = (VOID *) RuntimeAddress;\r
+ }\r
+\r
+ if (DiskStart != NULL) {\r
+ *DiskStart = LocalDiskStart;\r
+ }\r
+\r
+ if (DiskEnd != NULL) {\r
+ *DiskEnd = LocalDiskEnd;\r
+ }\r
+\r
+ Private->OptionRom = (UINT32) (RuntimeAddress + *RuntimeImageLength);\r
+\r
+ Status = EFI_SUCCESS;\r
+ \r
+Done:\r
+ if (PhysicalAddress != 0) {\r
+ //\r
+ // Free pages when OpROM is 3.0\r
+ //\r
+ gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize));\r
+ }\r
+\r
+ //\r
+ // Insure all shadowed areas are locked\r
+ //\r
+ Private->LegacyRegion->Lock (\r
+ Private->LegacyRegion,\r
+ 0xC0000,\r
+ 0x40000,\r
+ &Granularity\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Load a legacy PC-AT OPROM on the PciHandle device. Return information\r
+ about how many disks were added by the OPROM and the shadow address and\r
+ size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C:\r
+\r
+ @param This Protocol instance pointer.\r
+ @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will\r
+ be loaded. This value is NULL if RomImage is\r
+ non-NULL. This is the normal case.\r
+ @param RomImage A PCI PC-AT ROM image. This argument is non-NULL\r
+ if there is no hardware associated with the ROM\r
+ and thus no PciHandle, otherwise is must be NULL.\r
+ Example is PXE base code.\r
+ @param Flags Indicates if ROM found and if PC-AT.\r
+ @param DiskStart Disk number of first device hooked by the ROM. If\r
+ DiskStart is the same as DiskEnd no disked were\r
+ hooked.\r
+ @param DiskEnd Disk number of the last device hooked by the ROM.\r
+ @param RomShadowAddress Shadow address of PC-AT ROM\r
+ @param RomShadowedSize Size of RomShadowAddress in bytes\r
+\r
+ @retval EFI_SUCCESS Legacy ROM loaded for this device\r
+ @retval EFI_INVALID_PARAMETER PciHandle not found\r
+ @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no onboard\r
+ ROM\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBiosInstallPciRom (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL * This,\r
+ IN EFI_HANDLE PciHandle,\r
+ IN VOID **RomImage,\r
+ OUT UINTN *Flags,\r
+ OUT UINT8 *DiskStart, OPTIONAL\r
+ OUT UINT8 *DiskEnd, OPTIONAL\r
+ OUT VOID **RomShadowAddress, OPTIONAL\r
+ OUT UINT32 *RomShadowedSize OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ VOID *LocalRomImage;\r
+ UINTN ImageSize;\r
+ UINTN RuntimeImageLength;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE01 PciConfigHeader;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN PciSegment;\r
+ UINTN PciBus;\r
+ UINTN PciDevice;\r
+ UINTN PciFunction;\r
+ UINTN LastBus;\r
+ UINTN Index;\r
+ UINT8 OpromRevision;\r
+ UINT32 Granularity;\r
+ PCI_3_0_DATA_STRUCTURE *Pcir;\r
+\r
+ OpromRevision = 0;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+ if (Private->Legacy16Table->LastPciBus == 0) {\r
+ //\r
+ // Get last bus number if not already found\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ LastBus = 0;\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ Status = PciIo->GetLocation (\r
+ PciIo,\r
+ &PciSegment,\r
+ &PciBus,\r
+ &PciDevice,\r
+ &PciFunction\r
+ );\r
+ if (PciBus > LastBus) {\r
+ LastBus = PciBus;\r
+ }\r
+ }\r
+\r
+ Private->LegacyRegion->UnLock (\r
+ Private->LegacyRegion,\r
+ 0xE0000,\r
+ 0x20000,\r
+ &Granularity\r
+ );\r
+ Private->Legacy16Table->LastPciBus = (UINT8) LastBus;\r
+ Private->LegacyRegion->Lock (\r
+ Private->LegacyRegion,\r
+ 0xE0000,\r
+ 0x20000,\r
+ &Granularity\r
+ );\r
+ }\r
+\r
+ *Flags = 0;\r
+ if ((PciHandle != NULL) && (RomImage == NULL)) {\r
+ //\r
+ // If PciHandle has OpRom to Execute \r
+ // and OpRom are all associated with Hardware\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ PciHandle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (PciConfigHeader) / sizeof (UINT32),\r
+ &PciConfigHeader\r
+ );\r
+\r
+ //\r
+ // if video installed & OPROM is video return\r
+ //\r
+ if (\r
+ (\r
+ ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_OLD) &&\r
+ (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA))\r
+ ||\r
+ ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY) &&\r
+ (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA))\r
+ )\r
+ &&\r
+ (!Private->VgaInstalled)\r
+ ) {\r
+ mVgaInstallationInProgress = TRUE;\r
+\r
+ //\r
+ // return EFI_UNSUPPORTED;\r
+ //\r
+ }\r
+ }\r
+ //\r
+ // To run any legacy image, the VGA needs to be installed first.\r
+ // if installing the video, then don't need the thunk as already installed.\r
+ //\r
+ Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformVgaHandle,\r
+ 0,\r
+ &HandleBuffer,\r
+ &HandleCount,\r
+ NULL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ mVgaHandle = HandleBuffer[0];\r
+ if ((!Private->VgaInstalled) && (PciHandle != mVgaHandle)) {\r
+ //\r
+ // A return status of EFI_NOT_FOUND is considered valid (No EFI\r
+ // driver is controlling video.\r
+ //\r
+ mVgaInstallationInProgress = TRUE;\r
+ Status = LegacyBiosInstallVgaRom (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status != EFI_NOT_FOUND) {\r
+ mVgaInstallationInProgress = FALSE;\r
+ return Status;\r
+ }\r
+ } else {\r
+ mVgaInstallationInProgress = FALSE;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // See if the option ROM for PciHandle has already been executed\r
+ //\r
+ Status = IsLegacyRom (PciHandle);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ mVgaInstallationInProgress = FALSE;\r
+ GetShadowedRomParameters (\r
+ PciHandle,\r
+ DiskStart,\r
+ DiskEnd,\r
+ RomShadowAddress,\r
+ (UINTN *) RomShadowedSize\r
+ );\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = LegacyBiosCheckPciRomEx (\r
+ &Private->LegacyBios,\r
+ PciHandle,\r
+ &LocalRomImage,\r
+ &ImageSize,\r
+ &RuntimeImageLength,\r
+ Flags,\r
+ &OpromRevision,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // There is no PCI ROM in the ROM BAR or no onboard ROM\r
+ //\r
+ mVgaInstallationInProgress = FALSE;\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ if (*RomImage == NULL) {\r
+ //\r
+ // If PciHandle is NULL, and no OpRom is to be associated\r
+ //\r
+ mVgaInstallationInProgress = FALSE;\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ LocalRomImage = *RomImage;\r
+ Pcir = (PCI_3_0_DATA_STRUCTURE *)\r
+ ((UINT8 *) LocalRomImage + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset);\r
+ ImageSize = Pcir->ImageLength * 512;\r
+ if (Pcir->Length >= 0x1C) {\r
+ OpromRevision = Pcir->Revision;\r
+ } else {\r
+ OpromRevision = 0;\r
+ }\r
+ if (Pcir->Revision < 3) {\r
+ RuntimeImageLength = 0;\r
+ } else {\r
+ RuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;\r
+ }\r
+ }\r
+ //\r
+ // Shadow and initialize the OpROM.\r
+ //\r
+ ASSERT (Private->TraceIndex < 0x200);\r
+ Private->Trace[Private->TraceIndex] = LEGACY_PCI_TRACE_000;\r
+ Private->TraceIndex ++;\r
+ Private->TraceIndex = (UINT16) (Private->TraceIndex % 0x200);\r
+ Status = LegacyBiosInstallRom (\r
+ This,\r
+ Private,\r
+ PciHandle,\r
+ OpromRevision,\r
+ LocalRomImage,\r
+ ImageSize,\r
+ &RuntimeImageLength,\r
+ DiskStart,\r
+ DiskEnd,\r
+ RomShadowAddress\r
+ );\r
+ if (RomShadowedSize != NULL) {\r
+ *RomShadowedSize = (UINT32) RuntimeImageLength;\r
+ }\r
+\r
+ mVgaInstallationInProgress = FALSE;\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Collect Sio information from Native EFI Drivers.\r
+ Sio is floppy, parallel, serial, ... hardware\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+\r
+\r
+/**\r
+ Collect EFI Info about legacy devices.\r
+\r
+ @param Private Legacy BIOS Instance data\r
+\r
+ @retval EFI_SUCCESS It should always work.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosBuildSioData (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_PRODUCER_DATA_HEADER *SioPtr;\r
+ DEVICE_PRODUCER_SERIAL *Sio1Ptr;\r
+ DEVICE_PRODUCER_PARALLEL *Sio2Ptr;\r
+ DEVICE_PRODUCER_FLOPPY *Sio3Ptr;\r
+ EFI_HANDLE IsaBusController;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ UINTN ResourceIndex;\r
+ UINTN ChildIndex;\r
+ EFI_ISA_IO_PROTOCOL *IsaIo;\r
+ EFI_ISA_ACPI_RESOURCE_LIST *ResourceList;\r
+ EFI_ISA_ACPI_RESOURCE *IoResource;\r
+ EFI_ISA_ACPI_RESOURCE *DmaResource;\r
+ EFI_ISA_ACPI_RESOURCE *InterruptResource;\r
+ UINTN EntryCount;\r
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ //\r
+ // Get the pointer to the SIO data structure\r
+ //\r
+ SioPtr = &Private->IntThunk->EfiToLegacy16BootTable.SioData;\r
+\r
+ //\r
+ // Zero the data in the SIO data structure\r
+ //\r
+ gBS->SetMem (SioPtr, sizeof (DEVICE_PRODUCER_DATA_HEADER), 0);\r
+\r
+ //\r
+ // Find the ISA Bus Controller used for legacy\r
+ //\r
+ Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
+ Private->LegacyBiosPlatform,\r
+ EfiGetPlatformIsaBusHandle,\r
+ 0,\r
+ &HandleBuffer,\r
+ &HandleCount,\r
+ NULL\r
+ );\r
+ IsaBusController = HandleBuffer[0];\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Force ISA Bus Controller to produce all ISA devices\r
+ //\r
+ gBS->ConnectController (IsaBusController, NULL, NULL, TRUE);\r
+ }\r
+ //\r
+ // Get the list of ISA controllers in the system\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiIsaIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Collect legacy information from each of the ISA controllers in the system\r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+\r
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ ResourceList = IsaIo->ResourceList;\r
+\r
+ if (ResourceList == NULL) {\r
+ continue;\r
+ }\r
+ //\r
+ // Collect the resource types neededto fill in the SIO data structure\r
+ //\r
+ IoResource = NULL;\r
+ DmaResource = NULL;\r
+ InterruptResource = NULL;\r
+ for (ResourceIndex = 0;\r
+ ResourceList->ResourceItem[ResourceIndex].Type != EfiIsaAcpiResourceEndOfList;\r
+ ResourceIndex++\r
+ ) {\r
+ switch (ResourceList->ResourceItem[ResourceIndex].Type) {\r
+ case EfiIsaAcpiResourceIo:\r
+ IoResource = &ResourceList->ResourceItem[ResourceIndex];\r
+ break;\r
+\r
+ case EfiIsaAcpiResourceMemory:\r
+ break;\r
+\r
+ case EfiIsaAcpiResourceDma:\r
+ DmaResource = &ResourceList->ResourceItem[ResourceIndex];\r
+ break;\r
+\r
+ case EfiIsaAcpiResourceInterrupt:\r
+ InterruptResource = &ResourceList->ResourceItem[ResourceIndex];\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // See if this is an ISA serial port\r
+ //\r
+ // Ignore DMA resource since it is always returned NULL\r
+ //\r
+ if (ResourceList->Device.HID == EISA_PNP_ID (0x500) || ResourceList->Device.HID == EISA_PNP_ID (0x501)) {\r
+\r
+ if (ResourceList->Device.UID <= 3 &&\r
+ IoResource != NULL &&\r
+ InterruptResource != NULL\r
+ ) {\r
+ //\r
+ // Get the handle of the child device that has opened the ISA I/O Protocol\r
+ //\r
+ Status = gBS->OpenProtocolInformation (\r
+ HandleBuffer[Index],\r
+ &gEfiIsaIoProtocolGuid,\r
+ &OpenInfoBuffer,\r
+ &EntryCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ //\r
+ // We want resource for legacy even if no 32-bit driver installed\r
+ //\r
+ for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) {\r
+ Sio1Ptr = &SioPtr->Serial[ResourceList->Device.UID];\r
+ Sio1Ptr->Address = (UINT16) IoResource->StartRange;\r
+ Sio1Ptr->Irq = (UINT8) InterruptResource->StartRange;\r
+ Sio1Ptr->Mode = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF;\r
+ }\r
+\r
+ FreePool (OpenInfoBuffer);\r
+ }\r
+ }\r
+ //\r
+ // See if this is an ISA parallel port\r
+ //\r
+ // Ignore DMA resource since it is always returned NULL, port\r
+ // only used in output mode.\r
+ //\r
+ if (ResourceList->Device.HID == EISA_PNP_ID (0x400) || ResourceList->Device.HID == EISA_PNP_ID (0x401)) {\r
+ if (ResourceList->Device.UID <= 2 &&\r
+ IoResource != NULL &&\r
+ InterruptResource != NULL &&\r
+ DmaResource != NULL\r
+ ) {\r
+ Sio2Ptr = &SioPtr->Parallel[ResourceList->Device.UID];\r
+ Sio2Ptr->Address = (UINT16) IoResource->StartRange;\r
+ Sio2Ptr->Irq = (UINT8) InterruptResource->StartRange;\r
+ Sio2Ptr->Dma = (UINT8) DmaResource->StartRange;\r
+ Sio2Ptr->Mode = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY;\r
+ }\r
+ }\r
+ //\r
+ // See if this is an ISA floppy controller\r
+ //\r
+ if (ResourceList->Device.HID == EISA_PNP_ID (0x604)) {\r
+ if (IoResource != NULL && InterruptResource != NULL && DmaResource != NULL) {\r
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+ if (!EFI_ERROR (Status)) {\r
+ Sio3Ptr = &SioPtr->Floppy;\r
+ Sio3Ptr->Address = (UINT16) IoResource->StartRange;\r
+ Sio3Ptr->Irq = (UINT8) InterruptResource->StartRange;\r
+ Sio3Ptr->Dma = (UINT8) DmaResource->StartRange;\r
+ Sio3Ptr->NumberOfFloppy++;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // See if this is a mouse\r
+ // Always set mouse found so USB hot plug will work\r
+ //\r
+ // Ignore lower byte of HID. Pnp0fxx is any type of mouse.\r
+ //\r
+ // Hid = ResourceList->Device.HID & 0xff00ffff;\r
+ // PnpId = EISA_PNP_ID(0x0f00);\r
+ // if (Hid == PnpId) {\r
+ // if (ResourceList->Device.UID == 1) {\r
+ // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);\r
+ // if (!EFI_ERROR (Status)) {\r
+ //\r
+ SioPtr->MousePresent = 0x01;\r
+ //\r
+ // }\r
+ // }\r
+ // }\r
+ //\r
+ }\r
+\r
+ FreePool (HandleBuffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ Call into 16-bit BIOS code, Use AsmThunk16 function of BaseLib.\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LegacyBiosInterface.h"\r
+\r
+THUNK_CONTEXT mThunkContext;\r
+\r
+/**\r
+ Thunk to 16-bit real mode and execute a software interrupt with a vector\r
+ of BiosInt. Regs will contain the 16-bit register context on entry and\r
+ exit.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param BiosInt Processor interrupt vector to invoke\r
+ @param Regs Register contexted passed into (and returned) from thunk to\r
+ 16-bit mode\r
+\r
+ @retval FALSE Thunk completed, and there were no BIOS errors in the target code.\r
+ See Regs for status.\r
+ @retval TRUE There was a BIOS erro in the target code.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosInt86 (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT8 BiosInt,\r
+ IN EFI_IA32_REGISTER_SET *Regs\r
+ )\r
+{\r
+ Regs->X.Flags.Reserved1 = 1;\r
+ Regs->X.Flags.Reserved2 = 0;\r
+ Regs->X.Flags.Reserved3 = 0;\r
+ Regs->X.Flags.Reserved4 = 0;\r
+ Regs->X.Flags.IOPL = 3;\r
+ Regs->X.Flags.NT = 0;\r
+ Regs->X.Flags.IF = 0;\r
+ Regs->X.Flags.TF = 0;\r
+ Regs->X.Flags.CF = 0;\r
+\r
+ return InternalLegacyBiosFarCall (\r
+ This,\r
+ (UINT16) (((UINT32 *)NULL)[BiosInt] >> 16),\r
+ (UINT16) ((UINT32 *)NULL)[BiosInt],\r
+ Regs,\r
+ &Regs->X.Flags,\r
+ sizeof (Regs->X.Flags)\r
+ );\r
+}\r
+\r
+/**\r
+ Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the\r
+ 16-bit register context on entry and exit. Arguments can be passed on\r
+ the Stack argument\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Segment Segemnt of 16-bit mode call\r
+ @param Offset Offset of 16-bit mdoe call\r
+ @param Regs Register contexted passed into (and returned) from\r
+ thunk to 16-bit mode\r
+ @param Stack Caller allocated stack used to pass arguments\r
+ @param StackSize Size of Stack in bytes\r
+\r
+ @retval FALSE Thunk completed, and there were no BIOS errors in\r
+ the target code. See Regs for status.\r
+ @retval TRUE There was a BIOS erro in the target code.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LegacyBiosFarCall86 (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT16 Segment,\r
+ IN UINT16 Offset,\r
+ IN EFI_IA32_REGISTER_SET *Regs,\r
+ IN VOID *Stack,\r
+ IN UINTN StackSize\r
+ )\r
+{\r
+ Regs->X.Flags.Reserved1 = 1;\r
+ Regs->X.Flags.Reserved2 = 0;\r
+ Regs->X.Flags.Reserved3 = 0;\r
+ Regs->X.Flags.Reserved4 = 0;\r
+ Regs->X.Flags.IOPL = 3;\r
+ Regs->X.Flags.NT = 0;\r
+ Regs->X.Flags.IF = 1;\r
+ Regs->X.Flags.TF = 0;\r
+ Regs->X.Flags.CF = 0;\r
+\r
+ return InternalLegacyBiosFarCall (This, Segment, Offset, Regs, Stack, StackSize);\r
+}\r
+\r
+/**\r
+ Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the\r
+ 16-bit register context on entry and exit. Arguments can be passed on\r
+ the Stack argument\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Segment Segemnt of 16-bit mode call\r
+ @param Offset Offset of 16-bit mdoe call\r
+ @param Regs Register contexted passed into (and returned) from thunk to\r
+ 16-bit mode\r
+ @param Stack Caller allocated stack used to pass arguments\r
+ @param StackSize Size of Stack in bytes\r
+\r
+ @retval FALSE Thunk completed, and there were no BIOS errors in the target code.\r
+ See Regs for status.\r
+ @retval TRUE There was a BIOS erro in the target code.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalLegacyBiosFarCall (\r
+ IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
+ IN UINT16 Segment,\r
+ IN UINT16 Offset,\r
+ IN EFI_IA32_REGISTER_SET *Regs,\r
+ IN VOID *Stack,\r
+ IN UINTN StackSize\r
+ )\r
+{\r
+ UINTN Status;\r
+ LEGACY_BIOS_INSTANCE *Private;\r
+ UINT16 *Stack16;\r
+ EFI_TPL OriginalTpl;\r
+ IA32_REGISTER_SET ThunkRegSet;\r
+ BOOLEAN InterruptState;\r
+\r
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
+\r
+ ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));\r
+ ThunkRegSet.X.DI = Regs->X.DI;\r
+ ThunkRegSet.X.SI = Regs->X.SI;\r
+ ThunkRegSet.X.BP = Regs->X.BP;\r
+ ThunkRegSet.X.BX = Regs->X.BX;\r
+ ThunkRegSet.X.DX = Regs->X.DX;\r
+ //\r
+ // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, AX = B10Dh is\r
+ // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to write.\r
+ //\r
+ ThunkRegSet.E.ECX = Regs->E.ECX;\r
+ ThunkRegSet.X.AX = Regs->X.AX;\r
+ ThunkRegSet.E.DS = Regs->X.DS;\r
+ ThunkRegSet.E.ES = Regs->X.ES;\r
+\r
+ CopyMem (&(ThunkRegSet.E.EFLAGS.UintN), &(Regs->X.Flags), sizeof (Regs->X.Flags));\r
+\r
+ //\r
+ // Clear the error flag; thunk code may set it. Stack16 should be the high address\r
+ // Make Statk16 address the low 16 bit must be not zero.\r
+ //\r
+ Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16));\r
+\r
+ //\r
+ // Save and disable interrutp of debug timer\r
+ //\r
+ InterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
+\r
+ //\r
+ // The call to Legacy16 is a critical section to EFI\r
+ //\r
+ OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ if (Stack != NULL && StackSize != 0) {\r
+ //\r
+ // Copy Stack to low memory stack\r
+ //\r
+ Stack16 -= StackSize / sizeof (UINT16);\r
+ CopyMem (Stack16, Stack, StackSize);\r
+ }\r
+\r
+ ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12);\r
+ ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16;\r
+ ThunkRegSet.E.CS = Segment;\r
+ ThunkRegSet.E.Eip = Offset;\r
+\r
+ mThunkContext.RealModeState = &ThunkRegSet;\r
+\r
+ //\r
+ // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.\r
+ //\r
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ AsmThunk16 (&mThunkContext);\r
+\r
+ //\r
+ // OPROM may allocate EBDA range by itself and change EBDA base and EBDA size.\r
+ // Get the current EBDA base address, and compared with pre-allocate minimum\r
+ // EBDA base address, if the current EBDA base address is smaller, it indicates\r
+ // PcdEbdaReservedMemorySize should be adjusted to larger for more OPROMs.\r
+ //\r
+ DEBUG_CODE (\r
+ {\r
+ UINTN EbdaBaseAddress;\r
+ UINTN ReservedEbdaBaseAddress;\r
+\r
+ EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4;\r
+ ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize);\r
+ ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress);\r
+ }\r
+ );\r
+\r
+ if (Stack != NULL && StackSize != 0) {\r
+ //\r
+ // Copy low memory stack to Stack\r
+ //\r
+ CopyMem (Stack, Stack16, StackSize);\r
+ }\r
+\r
+ //\r
+ // Restore protected mode interrupt state\r
+ //\r
+ Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ mThunkContext.RealModeState = NULL;\r
+\r
+ //\r
+ // End critical section\r
+ //\r
+ gBS->RestoreTPL (OriginalTpl);\r
+\r
+ //\r
+ // Restore interrutp of debug timer\r
+ //\r
+ SaveAndSetDebugTimerInterrupt (InterruptState);\r
+\r
+ Regs->E.EDI = ThunkRegSet.E.EDI;\r
+ Regs->E.ESI = ThunkRegSet.E.ESI;\r
+ Regs->E.EBP = ThunkRegSet.E.EBP;\r
+ Regs->E.EBX = ThunkRegSet.E.EBX;\r
+ Regs->E.EDX = ThunkRegSet.E.EDX;\r
+ Regs->E.ECX = ThunkRegSet.E.ECX;\r
+ Regs->E.EAX = ThunkRegSet.E.EAX;\r
+ Regs->X.SS = ThunkRegSet.E.SS;\r
+ Regs->X.CS = ThunkRegSet.E.CS;\r
+ Regs->X.DS = ThunkRegSet.E.DS;\r
+ Regs->X.ES = ThunkRegSet.E.ES;\r
+\r
+ CopyMem (&(Regs->X.Flags), &(ThunkRegSet.E.EFLAGS.UintN), sizeof (Regs->X.Flags));\r
+\r
+ return (BOOLEAN) (Regs->X.Flags.CF == 1);\r
+}\r
+\r
+/**\r
+ Allocate memory < 1 MB and copy the thunker code into low memory. Se up\r
+ all the descriptors.\r
+\r
+ @param Private Private context for Legacy BIOS\r
+\r
+ @retval EFI_SUCCESS Should only pass.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBiosInitializeThunk (\r
+ IN LEGACY_BIOS_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_PHYSICAL_ADDRESS MemoryAddress;\r
+\r
+ MemoryAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->IntThunk;\r
+\r
+ mThunkContext.RealModeBuffer = (VOID *) (UINTN) (MemoryAddress + ((sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE);\r
+ mThunkContext.RealModeBufferSize = EFI_PAGE_SIZE;\r
+ mThunkContext.ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE | THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15;\r
+\r
+ AsmPrepareThunk16 (&mThunkContext);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+## @file
+# Interrupt Redirection Template
+#
+# Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions
+# of the BSD License which accompanies this distribution. The
+# full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+#text SEGMENT
+
+
+#----------------------------------------------------------------------------
+# Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F
+#
+# Input: None
+#
+# Output: None
+#
+# Prototype: VOID
+# InterruptRedirectionTemplate (
+# VOID
+# );
+#
+# Saves: None
+#
+# Modified: None
+#
+# Description: Contains the code that is copied into low memory (below 640K).
+# This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.
+# This template must be copied into low memory, and the IDT entries
+# 0x68-0x6F must be point to the low memory copy of this code. Each
+# entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily
+# computed.
+#
+#----------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(InterruptRedirectionTemplate)
+ASM_PFX(InterruptRedirectionTemplate):
+ int $0x08
+ .byte 0x0cf # IRET
+ nop
+ int $0x09
+ .byte 0x0cf # IRET
+ nop
+ int $0x0a
+ .byte 0x0cf # IRET
+ nop
+ int $0x0b
+ .byte 0x0cf # IRET
+ nop
+ int $0x0c
+ .byte 0x0cf # IRET
+ nop
+ int $0x0d
+ .byte 0x0cf # IRET
+ nop
+ int $0x0e
+ .byte 0x0cf # IRET
+ nop
+ int $0x0f
+ .byte 0x0cf # IRET
+ nop
+
+#END
--- /dev/null
+;; @file\r
+; Interrupt Redirection Template\r
+;\r
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
+;\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions\r
+; of the BSD License which accompanies this distribution. The\r
+; full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+;;\r
+\r
+text SEGMENT\r
+\r
+;----------------------------------------------------------------------------\r
+; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x6F \r
+;\r
+; Input: None\r
+;\r
+; Output: None\r
+;\r
+; Prototype: VOID\r
+; InterruptRedirectionTemplate ( \r
+; VOID\r
+; );\r
+;\r
+; Saves: None\r
+;\r
+; Modified: None\r
+;\r
+; Description: Contains the code that is copied into low memory (below 640K).\r
+; This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f.\r
+; This template must be copied into low memory, and the IDT entries\r
+; 0x68-0x6F must be point to the low memory copy of this code. Each\r
+; entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily \r
+; computed.\r
+;\r
+;----------------------------------------------------------------------------\r
+\r
+InterruptRedirectionTemplate PROC\r
+ int 08h\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 09h\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0ah\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0bh\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0ch\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0dh\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0eh\r
+ DB 0cfh ; IRET\r
+ nop\r
+ int 0fh\r
+ DB 0cfh ; IRET\r
+ nop\r
+InterruptRedirectionTemplate ENDP\r
+\r
+END
\ No newline at end of file
--- /dev/null
+/** @file\r
+ Defines a Tag GUID used to mark a UEFI legacy BIOS thunk driver based\r
+ on legacy BIOS services and legacy option ROM. This Tag GUID must be installed on \r
+ the ImageHandle of any module that follows the EFI Driver Model and uses \r
+ the Int86() or FarCall() services of the Legacy Bios Protocol to produce\r
+ a standard UEFI I/O Protocol.\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LEGACY_BIOS_H_\r
+#define _LEGACY_BIOS_H_\r
+\r
+///\r
+/// The Global ID for the Legacy BIOS GUID that must be installed onto the ImageHandle \r
+/// of any module follows the EFI Driver Model and uses the Int86() or FarCall() \r
+/// services of the Legacy BIOS Protocol to produce a standard UEFI I/O Protocol.\r
+///\r
+#define EFI_LEGACY_BIOS_GUID \\r
+ { \\r
+ 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 } \\r
+ }\r
+\r
+extern EFI_GUID gEfiLegacyBiosGuid;\r
+\r
+#endif\r
## Include/Guid/AcpiVariable.h\r
gEfiAcpiVariableCompatiblityGuid = { 0xc020489e, 0x6db2, 0x4ef2, { 0x9a, 0xa5, 0xca, 0x6, 0xfc, 0x11, 0xd3, 0x6a }}\r
\r
+ ## Include/Guid/LegacyBios.h\r
+ gEfiLegacyBiosGuid = { 0x2E3044AC, 0x879F, 0x490F, { 0x97, 0x60, 0xBB, 0xDF, 0xAF, 0x69, 0x5F, 0x50 }}\r
+\r
[Protocols]\r
## Vga Mini port binding for a VGA controller\r
# Include/Protocol/VgaMiniPort.h\r
## This PCD specifies whether Serial device use half hand shake.\r
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE|BOOLEAN|0x00010043\r
\r
+ ## Indicates if CSM support is needed for ACPI S3 Save.\r
+ # If TRUE, CSM support is enclosed for ACPI S3 Save.\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformCsmSupport|TRUE|BOOLEAN|0x00010044\r
+\r
[PcdsFixedAtBuild]\r
## FFS filename to find the default BMP Logo file.\r
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile |{ 0x99, 0x8b, 0xB2, 0x7B, 0xBB, 0x61, 0xD5, 0x11, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }|VOID*|0x40000003\r
# This PCD should be set as HII type PCD by platform integrator mapped to variable L"HwErrRecSupport"\r
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|0|UINT16|0x40000002\r
\r
-\r
[PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule]\r
## I/O Base address of floppy device controller.\r
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFdcBaseAddress|0x3f0|UINT16|0x30000000\r
\r
+ ## If TRUE, BiosVideo will switch to 80x25 Text VGA Mode when exiting boot service.\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable|FALSE|BOOLEAN|0x30000001\r
+\r
+ ## If TRUE, BiosVideo will check for VESA BIOS Extension service support.\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable|TRUE|BOOLEAN|0x30000002\r
+\r
+ ## If TRUE, BiosVideo will check for VGA service support.\r
+ # NOTE: If both PcdBiosVideoCheckVbeEnable and PcdBiosVideoCheckVgaEnable are set to FALSE,\r
+ # that means Graphics Output protocol will not be installed, the VGA miniport protocol will be installed instead.\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable|TRUE|BOOLEAN|0x30000003\r
+\r
+ ## If TRUE, memory space for legacy region will be set as cacheable.\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion|TRUE|BOOLEAN|0x00000004\r
+\r
+ ## The PCD is used to specify memory size with bytes to reserve EBDA for OPROM.\r
+ ## The value should be a multiple of 4KB.\r
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize|0x8000|UINT32|0x30000005\r
+\r
0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.\r
\r
[LibraryClasses]\r
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf\r
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf\r
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf\r
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf \r
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf\r
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf\r
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf\r
PlatformBdsLib|IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf\r
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf\r
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf\r
IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/Ps2MouseAbsolutePointerDxe.inf\r
IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf\r
\r
+ IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf\r
+ IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf\r
+ IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf\r
+ IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf\r
+\r
IntelFrameworkModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf\r
IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf\r
IntelFrameworkModulePkg/Universal/DataHubStdErrDxe/DataHubStdErrDxe.inf\r
IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf\r
IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf\r
IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf\r
+\r
+[Components.IA32,Components.X64,Components.IPF]\r
+ IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf\r
\r
[Components.IA32]\r
IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf\r