summaryrefslogtreecommitdiff
path: root/IntelFrameworkModulePkg/Csm/BiosThunk
diff options
context:
space:
mode:
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-06-27 23:32:56 +0000
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-06-27 23:32:56 +0000
commitbcecde140a561c64e297225904afebebd62336ce (patch)
tree5f6333ccb04d851d151970e5dee6c9d8ac7ade71 /IntelFrameworkModulePkg/Csm/BiosThunk
parenta7a0f78bd6fa1fe4684bf6de2b3e5ed5d9b5bf1c (diff)
downloadedk2-platforms-bcecde140a561c64e297225904afebebd62336ce.tar.xz
IntelFrameworkModulePkg: Add Compatibility Support Module (CSM) drivers
Added these drivers: * LegacyBiosDxe * BlockIoDxe * KeyboardDxe * Snp16Dxe * VideoDxe Signed-off-by: jljusten Reviewed-by: mdkinney Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11905 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'IntelFrameworkModulePkg/Csm/BiosThunk')
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c782
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h439
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c1485
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf58
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c309
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h209
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c2365
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h744
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c183
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h153
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf68
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c3507
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h1655
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c309
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c956
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h613
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c1254
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf67
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c3164
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h532
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c313
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h451
-rw-r--r--IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf80
23 files changed, 19696 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c
new file mode 100644
index 0000000000..309cf1a9ed
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c
@@ -0,0 +1,782 @@
+/** @file
+ EFI glue for BIOS INT 13h block devices.
+
+ This file is coded to EDD 3.0 as defined by T13 D1386 Revision 4
+ Availible on http://www.t13.org/#Project drafts
+ Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r4.pdf
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosBlkIo.h"
+
+//
+// Global data declaration
+//
+//
+// EFI Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gBiosBlockIoDriverBinding = {
+ BiosBlockIoDriverBindingSupported,
+ BiosBlockIoDriverBindingStart,
+ BiosBlockIoDriverBindingStop,
+ 0x3,
+ NULL,
+ NULL
+};
+
+//
+// Semaphore to control access to global variables mActiveInstances and mBufferUnder1Mb
+//
+EFI_LOCK mGlobalDataLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_APPLICATION);
+
+//
+// Number of active instances of this protocol. This is used to allocate/free
+// the shared buffer. You must acquire the semaphore to modify.
+//
+UINTN mActiveInstances = 0;
+
+//
+// Pointer to the beginning of the buffer used for real mode thunk
+// You must acquire the semaphore to modify.
+//
+EFI_PHYSICAL_ADDRESS mBufferUnder1Mb = 0;
+
+//
+// Address packet is a buffer under 1 MB for all version EDD calls
+//
+EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb;
+
+//
+// This is a buffer for INT 13h func 48 information
+//
+BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb;
+
+//
+// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB
+// 0xFE00 bytes is the max transfer size supported.
+//
+VOID *mEdd11Buffer;
+
+EFI_GUID mUnknownDevGuid = UNKNOWN_DEVICE_GUID;
+
+/**
+ Driver entry point.
+
+ @param ImageHandle Handle of driver image.
+ @param SystemTable Pointer to system table.
+
+ @retval EFI_SUCCESS Entrypoint successfully executed.
+ @retval Others Fail to execute entrypoint.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install protocols
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gBiosBlockIoDriverBinding,
+ ImageHandle,
+ &gBiosBlockIoComponentName,
+ &gBiosBlockIoComponentName2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver
+ //
+ return gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiLegacyBiosGuid,
+ NULL,
+ NULL
+ );
+}
+
+/**
+ Check whether the driver supports this device.
+
+ @param This The Udriver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval other This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ PCI_TYPE00 Pci;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // See if this is a PCI VGA Controller by looking at the Command register and
+ // Class Code Register
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (Pci.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE ||
+ (Pci.Hdr.ClassCode[2] == PCI_BASE_CLASS_INTELLIGENT && Pci.Hdr.ClassCode[1] == PCI_SUB_CLASS_INTELLIGENT)
+ ) {
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+/**
+ Starts the device with this driver.
+
+ @param This The driver binding instance.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS The controller is controlled by the driver.
+ @retval Other This controller cannot be started.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 DiskStart;
+ UINT8 DiskEnd;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate;
+ EFI_DEVICE_PATH_PROTOCOL *PciDevPath;
+ UINTN Index;
+ UINTN Flags;
+ UINTN TmpAddress;
+ BOOLEAN DeviceEnable;
+
+ //
+ // Initialize variables
+ //
+ PciIo = NULL;
+ PciDevPath = NULL;
+
+ DeviceEnable = FALSE;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Open the IO Abstraction(s) needed
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &PciDevPath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Enable the device and make sure VGA cycles are being forwarded to this VGA device
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ DeviceEnable = TRUE;
+
+ //
+ // Check to see if there is a legacy option ROM image associated with this PCI device
+ //
+ Status = LegacyBios->CheckPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ NULL,
+ &Flags
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Post the legacy option ROM if it is available.
+ //
+ Status = LegacyBios->InstallPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ &Flags,
+ &DiskStart,
+ &DiskEnd,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // All instances share a buffer under 1MB to put real mode thunk code in
+ // If it has not been allocated, then we allocate it.
+ //
+ if (mBufferUnder1Mb == 0) {
+ //
+ // Should only be here if there are no active instances
+ //
+ ASSERT (mActiveInstances == 0);
+
+ //
+ // Acquire the lock
+ //
+ EfiAcquireLock (&mGlobalDataLock);
+
+ //
+ // Allocate below 1MB
+ //
+ mBufferUnder1Mb = 0x00000000000FFFFF;
+ Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb);
+
+ //
+ // Release the lock
+ //
+ EfiReleaseLock (&mGlobalDataLock);
+
+ //
+ // Check memory allocation success
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // In checked builds we want to assert if the allocate failed.
+ //
+ ASSERT_EFI_ERROR (Status);
+ Status = EFI_OUT_OF_RESOURCES;
+ mBufferUnder1Mb = 0;
+ goto Error;
+ }
+
+ TmpAddress = (UINTN) mBufferUnder1Mb;
+ //
+ // Adjusting the value to be on proper boundary
+ //
+ mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress);
+
+ TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER;
+ //
+ // Adjusting the value to be on proper boundary
+ //
+ mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress);
+
+ TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE);
+ //
+ // Adjusting the value to be on proper boundary
+ //
+ mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress);
+ }
+ //
+ // Allocate the private device structure for each disk
+ //
+ for (Index = DiskStart; Index < DiskEnd; Index++) {
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (BIOS_BLOCK_IO_DEV),
+ (VOID **) &BiosBlockIoPrivate
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Zero the private device structure
+ //
+ ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV));
+
+ //
+ // Initialize the private device structure
+ //
+ BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE;
+ BiosBlockIoPrivate->ControllerHandle = Controller;
+ BiosBlockIoPrivate->LegacyBios = LegacyBios;
+ BiosBlockIoPrivate->PciIo = PciIo;
+
+ BiosBlockIoPrivate->Bios.Floppy = FALSE;
+ BiosBlockIoPrivate->Bios.Number = (UINT8) Index;
+ BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C');
+ BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE;
+
+ if (BiosInitBlockIo (BiosBlockIoPrivate)) {
+ SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath);
+
+ //
+ // Install the Block Io Protocol onto a new child handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &BiosBlockIoPrivate->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &BiosBlockIoPrivate->BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ BiosBlockIoPrivate->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (BiosBlockIoPrivate);
+ }
+ //
+ // Open For Child Device
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &BiosBlockIoPrivate->PciIo,
+ This->DriverBindingHandle,
+ BiosBlockIoPrivate->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ } else {
+ gBS->FreePool (BiosBlockIoPrivate);
+ }
+ }
+
+Error:
+ if (EFI_ERROR (Status)) {
+ if (PciIo != NULL) {
+ if (DeviceEnable) {
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (PciDevPath != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ if (mBufferUnder1Mb != 0 && mActiveInstances == 0) {
+ gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE);
+
+ //
+ // Clear the buffer back to 0
+ //
+ EfiAcquireLock (&mGlobalDataLock);
+ mBufferUnder1Mb = 0;
+ EfiReleaseLock (&mGlobalDataLock);
+ }
+ }
+ } else {
+ //
+ // Successfully installed, so increment the number of active instances
+ //
+ EfiAcquireLock (&mGlobalDataLock);
+ mActiveInstances++;
+ EfiReleaseLock (&mGlobalDataLock);
+ }
+
+ return Status;
+}
+
+/**
+ Stop the device handled by this driver.
+
+ @param This The driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval Others Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN AllChildrenStopped;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate;
+ UINTN Index;
+
+ //
+ // Decrement the number of active instances
+ //
+ if (mActiveInstances != 0) {
+ //
+ // Add a check since the stop function will be called 2 times for each handle
+ //
+ EfiAcquireLock (&mGlobalDataLock);
+ mActiveInstances--;
+ EfiReleaseLock (&mGlobalDataLock);
+ }
+
+ if ((mActiveInstances == 0) && (mBufferUnder1Mb != 0)) {
+ //
+ // Free our global buffer
+ //
+ Status = gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE);
+ ASSERT_EFI_ERROR (Status);
+
+ EfiAcquireLock (&mGlobalDataLock);
+ mBufferUnder1Mb = 0;
+ EfiReleaseLock (&mGlobalDataLock);
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BiosBlockIoPrivate = BIOS_BLOCK_IO_FROM_THIS (BlockIo);
+
+ //
+ // Release PCI I/O and Block IO Protocols on the clild handle.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ &BiosBlockIoPrivate->BlockIo,
+ &gEfiDevicePathProtocolGuid,
+ BiosBlockIoPrivate->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ //
+ // Shutdown the hardware
+ //
+ BiosBlockIoPrivate->PciIo->Attributes (
+ BiosBlockIoPrivate->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ gBS->FreePool (BiosBlockIoPrivate);
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Build device path for device.
+
+ @param BaseDevicePath Base device path.
+ @param Drive Legacy drive.
+ @param DevicePath Device path for output.
+
+**/
+VOID
+SetBiosInitBlockIoDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN BIOS_LEGACY_DRIVE *Drive,
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ EFI_STATUS Status;
+ UNKNOWN_DEVICE_VENDOR_DEVICE_PATH VendorNode;
+
+ Status = EFI_UNSUPPORTED;
+
+ //
+ // BugBug: Check for memory leaks!
+ //
+ if (Drive->EddVersion == EDD_VERSION_30) {
+ //
+ // EDD 3.0 case.
+ //
+ Status = BuildEdd30DevicePath (BaseDevicePath, Drive, DevicePath);
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // EDD 1.1 device case or it is unrecognized EDD 3.0 device
+ //
+ ZeroMem (&VendorNode, sizeof (VendorNode));
+ VendorNode.DevicePath.Header.Type = HARDWARE_DEVICE_PATH;
+ VendorNode.DevicePath.Header.SubType = HW_VENDOR_DP;
+ SetDevicePathNodeLength (&VendorNode.DevicePath.Header, sizeof (VendorNode));
+ CopyMem (&VendorNode.DevicePath.Guid, &mUnknownDevGuid, sizeof (EFI_GUID));
+ VendorNode.LegacyDriveLetter = Drive->Number;
+ *DevicePath = AppendDevicePathNode (BaseDevicePath, &VendorNode.DevicePath.Header);
+ }
+}
+
+/**
+ Build device path for EDD 3.0.
+
+ @param BaseDevicePath Base device path.
+ @param Drive Legacy drive.
+ @param DevicePath Device path for output.
+
+ @retval EFI_SUCCESS The device path is built successfully.
+ @retval EFI_UNSUPPORTED It is failed to built device path.
+
+**/
+EFI_STATUS
+BuildEdd30DevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN BIOS_LEGACY_DRIVE *Drive,
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ //
+ // AVL UINT64 Address;
+ // AVL EFI_HANDLE Handle;
+ //
+ EFI_DEV_PATH Node;
+ UINT32 Controller;
+
+ Controller = (UINT32) Drive->Parameters.InterfacePath.Pci.Controller;
+
+ ZeroMem (&Node, sizeof (Node));
+ if ((AsciiStrnCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) ||
+ (AsciiStrnCmp ("ATA", Drive->Parameters.InterfaceType, 3) == 0)
+ ) {
+ //
+ // ATA or ATAPI drive found
+ //
+ Node.Atapi.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.Atapi.Header.SubType = MSG_ATAPI_DP;
+ SetDevicePathNodeLength (&Node.Atapi.Header, sizeof (ATAPI_DEVICE_PATH));
+ Node.Atapi.SlaveMaster = Drive->Parameters.DevicePath.Atapi.Master;
+ Node.Atapi.Lun = Drive->Parameters.DevicePath.Atapi.Lun;
+ Node.Atapi.PrimarySecondary = (UINT8) Controller;
+ } else {
+ //
+ // Not an ATA/ATAPI drive
+ //
+ if (Controller != 0) {
+ ZeroMem (&Node, sizeof (Node));
+ Node.Controller.Header.Type = HARDWARE_DEVICE_PATH;
+ Node.Controller.Header.SubType = HW_CONTROLLER_DP;
+ SetDevicePathNodeLength (&Node.Controller.Header, sizeof (CONTROLLER_DEVICE_PATH));
+ Node.Controller.ControllerNumber = Controller;
+ *DevicePath = AppendDevicePathNode (*DevicePath, &Node.DevPath);
+ }
+
+ ZeroMem (&Node, sizeof (Node));
+
+ if (AsciiStrnCmp ("SCSI", Drive->Parameters.InterfaceType, 4) == 0) {
+ //
+ // SCSI drive
+ //
+ Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.Scsi.Header.SubType = MSG_SCSI_DP;
+ SetDevicePathNodeLength (&Node.Scsi.Header, sizeof (SCSI_DEVICE_PATH));
+
+ //
+ // Lun is miss aligned in both EDD and Device Path data structures.
+ // thus we do a byte copy, to prevent alignment traps on IA-64.
+ //
+ CopyMem (&Node.Scsi.Lun, &Drive->Parameters.DevicePath.Scsi.Lun, sizeof (UINT16));
+ Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.Pun;
+
+ } else if (AsciiStrnCmp ("USB", Drive->Parameters.InterfaceType, 3) == 0) {
+ //
+ // USB drive
+ //
+ Node.Usb.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.Usb.Header.SubType = MSG_USB_DP;
+ SetDevicePathNodeLength (&Node.Usb.Header, sizeof (USB_DEVICE_PATH));
+ Node.Usb.ParentPortNumber = (UINT8) Drive->Parameters.DevicePath.Usb.Reserved;
+
+ } else if (AsciiStrnCmp ("1394", Drive->Parameters.InterfaceType, 4) == 0) {
+ //
+ // 1394 drive
+ //
+ Node.F1394.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.F1394.Header.SubType = MSG_1394_DP;
+ SetDevicePathNodeLength (&Node.F1394.Header, sizeof (F1394_DEVICE_PATH));
+ Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid;
+
+ } else if (AsciiStrnCmp ("FIBRE", Drive->Parameters.InterfaceType, 5) == 0) {
+ //
+ // Fibre drive
+ //
+ Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH;
+ Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP;
+ SetDevicePathNodeLength (&Node.FibreChannel.Header, sizeof (FIBRECHANNEL_DEVICE_PATH));
+ Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn;
+ Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun;
+
+ } else {
+ DEBUG (
+ (
+ DEBUG_BLKIO, "It is unrecognized EDD 3.0 device, Drive Number = %x, InterfaceType = %s\n",
+ Drive->Number,
+ Drive->Parameters.InterfaceType
+ )
+ );
+ }
+ }
+
+ if (Node.DevPath.Type == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *DevicePath = AppendDevicePathNode (BaseDevicePath, &Node.DevPath);
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h
new file mode 100644
index 0000000000..de3c8d3518
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.h
@@ -0,0 +1,439 @@
+/** @file
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BIOS_BLOCK_IO_H_
+#define _BIOS_BLOCK_IO_H_
+
+#include <Uefi.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/DevicePath.h>
+#include <Guid/LegacyBios.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include "Edd.h"
+
+#define UNKNOWN_DEVICE_GUID \
+ { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} }
+
+typedef struct {
+ VENDOR_DEVICE_PATH DevicePath;
+ UINT8 LegacyDriveLetter;
+} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH;
+
+//
+// Global Variables
+//
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2;
+
+
+//
+// Define the I2O class code
+//
+#define PCI_BASE_CLASS_INTELLIGENT 0x0e
+#define PCI_SUB_CLASS_INTELLIGENT 0x00
+
+//
+// Number of pages needed for our buffer under 1MB
+//
+#define BLOCK_IO_BUFFER_PAGE_SIZE (((sizeof (EDD_DEVICE_ADDRESS_PACKET) + sizeof (BIOS_LEGACY_DRIVE) + MAX_EDD11_XFER) / EFI_PAGE_SIZE) + 1 \
+ )
+
+//
+// Driver Binding Protocol functions
+//
+
+/**
+ Check whether the driver supports this device.
+
+ @param This The Udriver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval other This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+
+/**
+ Starts the device with this driver.
+
+ @param This The driver binding instance.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS The controller is controlled by the driver.
+ @retval Other This controller cannot be started.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop the device handled by this driver.
+
+ @param This The driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval Others Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Other internal functions
+//
+
+/**
+ Build device path for EDD 3.0.
+
+ @param BaseDevicePath Base device path.
+ @param Drive Legacy drive.
+ @param DevicePath Device path for output.
+
+ @retval EFI_SUCCESS The device path is built successfully.
+ @retval EFI_UNSUPPORTED It is failed to built device path.
+
+**/
+EFI_STATUS
+BuildEdd30DevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN BIOS_LEGACY_DRIVE *Drive,
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+/**
+ Initialize block I/O device instance
+
+ @param Dev Instance of block I/O device instance
+
+ @retval TRUE Initialization succeeds.
+ @retval FALSE Initialization fails.
+
+**/
+BOOLEAN
+BiosInitBlockIo (
+ IN BIOS_BLOCK_IO_DEV *Dev
+ );
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd30BiosReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd30BiosWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Flush the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+/**
+ Reset the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd11BiosReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd11BiosWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosReadLegacyDrive (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosWriteLegacyDrive (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Gets parameters of block I/O device.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of device parameter retrieval.
+
+**/
+UINTN
+Int13GetDeviceParameters (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ );
+
+/**
+ Extension of INT13 call.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of this extension.
+
+**/
+UINTN
+Int13Extensions (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ );
+
+/**
+ Gets parameters of legacy drive.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of drive parameter retrieval.
+
+**/
+UINTN
+GetDriveParameters (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ );
+
+/**
+ Build device path for device.
+
+ @param BaseDevicePath Base device path.
+ @param Drive Legacy drive.
+ @param DevicePath Device path for output.
+
+**/
+VOID
+SetBiosInitBlockIoDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
+ IN BIOS_LEGACY_DRIVE *Drive,
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c
new file mode 100644
index 0000000000..c53490b0e3
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosInt13.c
@@ -0,0 +1,1485 @@
+/** @file
+ Routines that use BIOS to support INT 13 devices.
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosBlkIo.h"
+
+//
+// Module global variables
+//
+//
+// Address packet is a buffer under 1 MB for all version EDD calls
+//
+extern EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb;
+
+//
+// This is a buffer for INT 13h func 48 information
+//
+extern BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb;
+
+//
+// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB
+// 0xFE00 bytes is the max transfer size supported.
+//
+extern VOID *mEdd11Buffer;
+
+
+/**
+ Initialize block I/O device instance
+
+ @param Dev Instance of block I/O device instance
+
+ @retval TRUE Initialization succeeds.
+ @retval FALSE Initialization fails.
+
+**/
+BOOLEAN
+BiosInitBlockIo (
+ IN BIOS_BLOCK_IO_DEV *Dev
+ )
+{
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_BLOCK_IO_MEDIA *BlockMedia;
+ BIOS_LEGACY_DRIVE *Bios;
+
+ BlockIo = &Dev->BlockIo;
+ BlockIo->Media = &Dev->BlockMedia;
+ BlockMedia = BlockIo->Media;
+ Bios = &Dev->Bios;
+
+ if (Int13GetDeviceParameters (Dev, Bios) != 0) {
+ if (Int13Extensions (Dev, Bios) != 0) {
+ BlockMedia->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ BlockMedia->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+
+ if ((Bios->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) {
+ BlockMedia->RemovableMedia = TRUE;
+ }
+
+ } else {
+ //
+ // Legacy Interfaces
+ //
+ BlockMedia->BlockSize = 512;
+ BlockMedia->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
+ }
+
+ DEBUG ((DEBUG_INIT, "BlockSize = %d LastBlock = %d\n", BlockMedia->BlockSize, BlockMedia->LastBlock));
+
+ BlockMedia->LogicalPartition = FALSE;
+ BlockMedia->WriteCaching = FALSE;
+
+ //
+ // BugBug: Need to set this for removable media devices if they do not
+ // have media present
+ //
+ BlockMedia->ReadOnly = FALSE;
+ BlockMedia->MediaPresent = TRUE;
+
+ BlockIo->Reset = BiosBlockIoReset;
+ BlockIo->FlushBlocks = BiosBlockIoFlushBlocks;
+
+ if (!Bios->ExtendedInt13) {
+ //
+ // Legacy interfaces
+ //
+ BlockIo->ReadBlocks = BiosReadLegacyDrive;
+ BlockIo->WriteBlocks = BiosWriteLegacyDrive;
+ } else if ((Bios->EddVersion == EDD_VERSION_30) && (Bios->Extensions64Bit)) {
+ //
+ // EDD 3.0 Required for Device path, but extended reads are not required.
+ //
+ BlockIo->ReadBlocks = Edd30BiosReadBlocks;
+ BlockIo->WriteBlocks = Edd30BiosWriteBlocks;
+ } else {
+ //
+ // Assume EDD 1.1 - Read and Write functions.
+ // This could be EDD 3.0 without Extensions64Bit being set.
+ // If it's EDD 1.1 this will work, but the device path will not
+ // be correct. This will cause confusion to EFI OS installation.
+ //
+ BlockIo->ReadBlocks = Edd11BiosReadBlocks;
+ BlockIo->WriteBlocks = Edd11BiosWriteBlocks;
+ }
+
+ BlockMedia->LogicalPartition = FALSE;
+ BlockMedia->WriteCaching = FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Gets parameters of block I/O device.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of device parameter retrieval.
+
+**/
+UINTN
+Int13GetDeviceParameters (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ )
+{
+ UINTN CarryFlag;
+ UINT16 Cylinder;
+ EFI_IA32_REGISTER_SET Regs;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Regs.H.AH = 0x08;
+ Regs.H.DL = Drive->Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG ((DEBUG_INIT, "Int13GetDeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH));
+ if (CarryFlag != 0 || Regs.H.AH != 0x00) {
+ Drive->ErrorCode = Regs.H.AH;
+ return FALSE;
+ }
+
+ if (Drive->Floppy) {
+ if (Regs.H.BL == 0x10) {
+ Drive->AtapiFloppy = TRUE;
+ } else {
+ Drive->MaxHead = Regs.H.DH;
+ Drive->MaxSector = Regs.H.CL;
+ Drive->MaxCylinder = Regs.H.CH;
+ if (Drive->MaxSector == 0) {
+ //
+ // BugBug: You can not trust the Carry flag.
+ //
+ return FALSE;
+ }
+ }
+ } else {
+ Drive->MaxHead = (UINT8) (Regs.H.DH & 0x3f);
+ Cylinder = (UINT16) (((UINT16) Regs.H.DH & 0xc0) << 4);
+ Cylinder = (UINT16) (Cylinder | ((UINT16) Regs.H.CL & 0xc0) << 2);
+ Drive->MaxCylinder = (UINT16) (Cylinder + Regs.H.CH);
+ Drive->MaxSector = (UINT8) (Regs.H.CL & 0x3f);
+ }
+
+ return TRUE;
+}
+
+/**
+ Extension of INT13 call.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of this extension.
+
+**/
+UINTN
+Int13Extensions (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ )
+{
+ INTN CarryFlag;
+ EFI_IA32_REGISTER_SET Regs;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Regs.H.AH = 0x41;
+ Regs.X.BX = 0x55aa;
+ Regs.H.DL = Drive->Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG ((DEBUG_INIT, "Int13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX));
+ if (CarryFlag != 0 || Regs.X.BX != 0xaa55) {
+ Drive->ExtendedInt13 = FALSE;
+ Drive->DriveLockingAndEjecting = FALSE;
+ Drive->Edd = FALSE;
+ return FALSE;
+ }
+
+ Drive->EddVersion = Regs.H.AH;
+ Drive->ExtendedInt13 = (BOOLEAN) ((Regs.X.CX & 0x01) == 0x01);
+ Drive->DriveLockingAndEjecting = (BOOLEAN) ((Regs.X.CX & 0x02) == 0x02);
+ Drive->Edd = (BOOLEAN) ((Regs.X.CX & 0x04) == 0x04);
+ Drive->Extensions64Bit = (BOOLEAN) (Regs.X.CX & 0x08);
+
+ Drive->ParametersValid = (UINT8) GetDriveParameters (BiosBlockIoDev, Drive);
+ return TRUE;
+}
+
+/**
+ Gets parameters of legacy drive.
+
+ @param BiosBlockIoDev Instance of block I/O device.
+ @param Drive Legacy drive.
+
+ @return Result of drive parameter retrieval.
+
+**/
+UINTN
+GetDriveParameters (
+ IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev,
+ IN BIOS_LEGACY_DRIVE *Drive
+ )
+{
+ INTN CarryFlag;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN PointerMath;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Regs.H.AH = 0x48;
+ Regs.H.DL = Drive->Number;
+
+ //
+ // EDD Buffer must be passed in with max buffer size as first entry in the buffer
+ //
+ mLegacyDriverUnder1Mb->Parameters.StructureSize = (UINT16) sizeof (EDD_DRIVE_PARAMETERS);
+ Regs.X.DS = EFI_SEGMENT ((UINTN)(&mLegacyDriverUnder1Mb->Parameters));
+ Regs.X.SI = EFI_OFFSET ((UINTN)(&mLegacyDriverUnder1Mb->Parameters));
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 48 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH));
+ if (CarryFlag != 0 || Regs.H.AH != 0x00) {
+ Drive->ErrorCode = Regs.H.AH;
+ SetMem (&Drive->Parameters, sizeof (Drive->Parameters), 0xaf);
+ return FALSE;
+ }
+ //
+ // We only have one buffer < 1MB, so copy into our instance data
+ //
+ CopyMem (
+ &Drive->Parameters,
+ &mLegacyDriverUnder1Mb->Parameters,
+ sizeof (Drive->Parameters)
+ );
+
+ if (Drive->AtapiFloppy) {
+ //
+ // Sense Media Type
+ //
+ Regs.H.AH = 0x20;
+ Regs.H.DL = Drive->Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 20 DL=%02x : CF=%d AL=%02x\n", Drive->Number, CarryFlag, Regs.H.AL));
+ if (CarryFlag != 0) {
+ //
+ // Media not present or unknown media present
+ //
+ if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) {
+ Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1);
+ Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack;
+ ASSERT (Drive->MaxSector != 0);
+ Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1);
+ } else {
+ Drive->MaxHead = 0;
+ Drive->MaxSector = 1;
+ Drive->MaxCylinder = 0;
+ }
+
+ } else {
+ //
+ // Media Present
+ //
+ switch (Regs.H.AL) {
+ case 0x03:
+ //
+ // 720 KB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 9;
+ Drive->MaxCylinder = 79;
+ break;
+
+ case 0x04:
+ //
+ // 1.44MB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 18;
+ Drive->MaxCylinder = 79;
+ break;
+
+ case 0x06:
+ //
+ // 2.88MB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 36;
+ Drive->MaxCylinder = 79;
+ break;
+
+ case 0x0C:
+ //
+ // 360 KB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 9;
+ Drive->MaxCylinder = 39;
+ break;
+
+ case 0x0D:
+ //
+ // 1.2 MB
+ //
+ Drive->MaxHead = 1;
+ Drive->MaxSector = 15;
+ Drive->MaxCylinder = 79;
+ break;
+
+ case 0x0E:
+ //
+ // Toshiba 3 mode
+ //
+ case 0x0F:
+ //
+ // NEC 3 mode
+ //
+ case 0x10:
+ //
+ // Default Media
+ //
+ if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) {
+ Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1);
+ Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack;
+ ASSERT (Drive->MaxSector != 0);
+ Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1);
+ } else {
+ Drive->MaxHead = 0;
+ Drive->MaxSector = 1;
+ Drive->MaxCylinder = 0;
+ }
+ break;
+
+ default:
+ //
+ // Unknown media type.
+ //
+ Drive->MaxHead = 0;
+ Drive->MaxSector = 1;
+ Drive->MaxCylinder = 0;
+ break;
+ }
+ }
+
+ Drive->Parameters.PhysicalSectors = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1);
+ Drive->Parameters.BytesPerSector = 512;
+ }
+ //
+ // This data comes from the BIOS so it may not allways be valid
+ // since the BIOS may reuse this buffer for future accesses
+ //
+ PointerMath = EFI_SEGMENT (Drive->Parameters.Fdpt) << 4;
+ PointerMath += EFI_OFFSET (Drive->Parameters.Fdpt);
+ Drive->FdptPointer = (VOID *) PointerMath;
+
+ return TRUE;
+}
+//
+// Block IO Routines
+//
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd30BiosReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ //
+ // I exist only for readability
+ //
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Lba > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ AddressPacket = mEddBufferUnder1Mb;
+
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;
+
+ TransferBuffer = (UINT64)(UINTN) Buffer;
+ for (; BufferSize > 0;) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;
+ //
+ // Max transfer MaxTransferBlocks
+ //
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+ AddressPacket->SegOffset = 0xffffffff;
+ AddressPacket->Lba = (UINT64) Lba;
+ AddressPacket->TransferBuffer = TransferBuffer;
+
+ Regs.H.AH = 0x42;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ Regs.X.SI = EFI_OFFSET (AddressPacket);
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "Edd30BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,
+ CarryFlag, Regs.H.AH
+ )
+ );
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ BufferSize = BufferSize - TransferByteSize;
+ TransferBuffer += TransferByteSize;
+ Lba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd30BiosWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ //
+ // I exist only for readability
+ //
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Lba > Media->LastBlock) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ AddressPacket = mEddBufferUnder1Mb;
+
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;
+
+ TransferBuffer = (UINT64)(UINTN) Buffer;
+ for (; BufferSize > 0;) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;
+ //
+ // Max transfer MaxTransferBlocks
+ //
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+ AddressPacket->SegOffset = 0xffffffff;
+ AddressPacket->Lba = (UINT64) Lba;
+ AddressPacket->TransferBuffer = TransferBuffer;
+
+ Regs.H.AH = 0x43;
+ Regs.H.AL = 0x00;
+ //
+ // Write Verify Off
+ //
+ Regs.H.DL = (UINT8) (BiosBlockIoDev->Bios.Number);
+ Regs.X.SI = EFI_OFFSET (AddressPacket);
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "Edd30BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,
+ CarryFlag, Regs.H.AH
+ )
+ );
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ Media->ReadOnly = FALSE;
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ BufferSize = BufferSize - TransferByteSize;
+ TransferBuffer += TransferByteSize;
+ Lba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Flush the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN CarryFlag;
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Regs.H.AH = 0x00;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag,
+ Regs.H.AH
+ )
+ );
+ if (CarryFlag != 0) {
+ if (Regs.H.AL == BIOS_RESET_FAILED) {
+ Regs.H.AH = 0x00;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag,
+ Regs.H.AH
+ )
+ );
+ if (CarryFlag != 0) {
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+//
+//
+// These functions need to double buffer all data under 1MB!
+//
+//
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd11BiosReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ //
+ // I exist only for readability
+ //
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Lba > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ AddressPacket = mEddBufferUnder1Mb;
+
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;
+
+ TransferBuffer = (UINT64)(UINTN) mEdd11Buffer;
+ for (; BufferSize > 0;) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;
+ //
+ // Max transfer MaxTransferBlocks
+ //
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+ AddressPacket->SegOffset = EFI_SEGMENT (TransferBuffer) << 16;
+ AddressPacket->SegOffset |= EFI_OFFSET (TransferBuffer);
+ AddressPacket->Lba = (UINT64) Lba;
+
+ Regs.H.AH = 0x42;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ Regs.X.SI = EFI_OFFSET (AddressPacket);
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "Edd11BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n",
+ BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks
+ )
+ );
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ CopyMem (Buffer, (VOID *) (UINTN) TransferBuffer, TransferByteSize);
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);
+ Lba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+Edd11BiosWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ //
+ // I exist only for readability
+ //
+ EFI_IA32_REGISTER_SET Regs;
+ UINT64 TransferBuffer;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN MaxTransferBlocks;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Lba > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ AddressPacket = mEddBufferUnder1Mb;
+
+ MaxTransferBlocks = MAX_EDD11_XFER / BlockSize;
+
+ TransferBuffer = (UINT64)(UINTN) mEdd11Buffer;
+ for (; BufferSize > 0;) {
+ NumberOfBlocks = BufferSize / BlockSize;
+ NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks;
+ //
+ // Max transfer MaxTransferBlocks
+ //
+ AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET);
+ AddressPacket->Zero = 0;
+ AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks;
+ AddressPacket->Zero2 = 0;
+ AddressPacket->SegOffset = EFI_SEGMENT (TransferBuffer) << 16;
+ AddressPacket->SegOffset |= EFI_OFFSET (TransferBuffer);
+ AddressPacket->Lba = (UINT64) Lba;
+
+ Regs.H.AH = 0x43;
+ Regs.H.AL = 0x00;
+ //
+ // Write Verify disable
+ //
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+ Regs.X.SI = EFI_OFFSET (AddressPacket);
+ Regs.X.DS = EFI_SEGMENT (AddressPacket);
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ CopyMem ((VOID *) (UINTN) TransferBuffer, Buffer, TransferByteSize);
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "Edd11BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n",
+ BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks
+ )
+ );
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ Media->ReadOnly = FALSE;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);
+ Lba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosReadLegacyDrive (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN UpperCylinder;
+ UINTN Temp;
+ UINTN Cylinder;
+ UINTN Head;
+ UINTN Sector;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN ShortLba;
+ UINTN CheckLba;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN Retry;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Lba > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ ShortLba = (UINTN) Lba;
+
+ while (BufferSize != 0) {
+ //
+ // Compute I/O location in Sector, Head, Cylinder format
+ //
+ Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1;
+ Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector;
+ Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1);
+ Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1);
+
+ //
+ // Limit transfer to this Head & Cylinder
+ //
+ NumberOfBlocks = BufferSize / BlockSize;
+ Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1;
+ NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;
+
+ Retry = 3;
+ do {
+ //
+ // Perform the IO
+ //
+ Regs.H.AH = 2;
+ Regs.H.AL = (UINT8) NumberOfBlocks;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+
+ UpperCylinder = (Cylinder & 0x0f00) >> 2;
+
+ CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head;
+ CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1;
+
+ DEBUG (
+ (DEBUG_BLKIO,
+ "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n",
+ ShortLba,
+ CheckLba,
+ Sector,
+ BiosBlockIoDev->Bios.MaxSector,
+ Head,
+ BiosBlockIoDev->Bios.MaxHead,
+ Cylinder,
+ UpperCylinder)
+ );
+ ASSERT (CheckLba == ShortLba);
+
+ Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff));
+ Regs.H.DH = (UINT8) (Head & 0x3f);
+ Regs.H.CH = (UINT8) (Cylinder & 0xff);
+
+ Regs.X.BX = EFI_OFFSET (mEdd11Buffer);
+ Regs.X.ES = EFI_SEGMENT (mEdd11Buffer);
+
+ DEBUG (
+ (DEBUG_BLKIO,
+ "INT 13h: AX:(02%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n",
+ Regs.H.AL,
+ (UINT8) (Head & 0x3f),
+ Regs.H.DL,
+ (UINT8) (Cylinder & 0xff),
+ (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)),
+ EFI_OFFSET (mEdd11Buffer),
+ EFI_SEGMENT (mEdd11Buffer))
+ );
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "BiosReadLegacyDrive: INT 13 02 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,
+ CarryFlag, Regs.H.AH
+ )
+ );
+ Retry--;
+ } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED);
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ //
+ // If the size of the media changed we need to reset the disk geometry
+ //
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ //
+ // Legacy Interfaces
+ //
+ Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
+ Media->BlockSize = 512;
+ }
+
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ CopyMem (Buffer, mEdd11Buffer, TransferByteSize);
+
+ ShortLba = ShortLba + NumberOfBlocks;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosWriteLegacyDrive (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ BIOS_BLOCK_IO_DEV *BiosBlockIoDev;
+ EFI_IA32_REGISTER_SET Regs;
+ UINTN UpperCylinder;
+ UINTN Temp;
+ UINTN Cylinder;
+ UINTN Head;
+ UINTN Sector;
+ UINTN NumberOfBlocks;
+ UINTN TransferByteSize;
+ UINTN ShortLba;
+ UINTN CheckLba;
+ UINTN BlockSize;
+ BIOS_LEGACY_DRIVE *Bios;
+ UINTN CarryFlag;
+ UINTN Retry;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+
+ ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Lba > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This);
+ ShortLba = (UINTN) Lba;
+
+ while (BufferSize != 0) {
+ //
+ // Compute I/O location in Sector, Head, Cylinder format
+ //
+ Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1;
+ Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector;
+ Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1);
+ Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1);
+
+ //
+ // Limit transfer to this Head & Cylinder
+ //
+ NumberOfBlocks = BufferSize / BlockSize;
+ Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1;
+ NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks;
+
+ Retry = 3;
+ do {
+ //
+ // Perform the IO
+ //
+ Regs.H.AH = 3;
+ Regs.H.AL = (UINT8) NumberOfBlocks;
+ Regs.H.DL = BiosBlockIoDev->Bios.Number;
+
+ UpperCylinder = (Cylinder & 0x0f00) >> 2;
+
+ CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head;
+ CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1;
+
+ DEBUG (
+ (DEBUG_BLKIO,
+ "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n",
+ ShortLba,
+ CheckLba,
+ Sector,
+ BiosBlockIoDev->Bios.MaxSector,
+ Head,
+ BiosBlockIoDev->Bios.MaxHead,
+ Cylinder,
+ UpperCylinder)
+ );
+ ASSERT (CheckLba == ShortLba);
+
+ Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff));
+ Regs.H.DH = (UINT8) (Head & 0x3f);
+ Regs.H.CH = (UINT8) (Cylinder & 0xff);
+
+ Regs.X.BX = EFI_OFFSET (mEdd11Buffer);
+ Regs.X.ES = EFI_SEGMENT (mEdd11Buffer);
+
+ TransferByteSize = NumberOfBlocks * BlockSize;
+ CopyMem (mEdd11Buffer, Buffer, TransferByteSize);
+
+ DEBUG (
+ (DEBUG_BLKIO,
+ "INT 13h: AX:(03%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n",
+ Regs.H.AL,
+ (UINT8) (Head & 0x3f),
+ Regs.H.DL,
+ (UINT8) (Cylinder & 0xff),
+ (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)),
+ EFI_OFFSET (mEdd11Buffer),
+ EFI_SEGMENT (mEdd11Buffer))
+ );
+
+ CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs);
+ DEBUG (
+ (
+ DEBUG_BLKIO, "BiosWriteLegacyDrive: INT 13 03 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number,
+ CarryFlag, Regs.H.AH
+ )
+ );
+ Retry--;
+ } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED);
+
+ Media->MediaPresent = TRUE;
+ if (CarryFlag != 0) {
+ //
+ // Return Error Status
+ //
+ BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH;
+ if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) {
+ Media->MediaId++;
+ Bios = &BiosBlockIoDev->Bios;
+ if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) {
+ if (Int13Extensions (BiosBlockIoDev, Bios) != 0) {
+ Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1;
+ Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector;
+ } else {
+ //
+ // Legacy Interfaces
+ //
+ Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1;
+ Media->BlockSize = 512;
+ }
+ //
+ // If the size of the media changed we need to reset the disk geometry
+ //
+ Media->ReadOnly = FALSE;
+ gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
+ gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo);
+ return EFI_MEDIA_CHANGED;
+ }
+ } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) {
+ Media->ReadOnly = TRUE;
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (Media->RemovableMedia) {
+ Media->MediaPresent = FALSE;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ Media->ReadOnly = FALSE;
+ ShortLba = ShortLba + NumberOfBlocks;
+ BufferSize = BufferSize - TransferByteSize;
+ Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf
new file mode 100644
index 0000000000..3fcaa2723c
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BlockIoDxe.inf
@@ -0,0 +1,58 @@
+## @file
+# Component description file for BIOS Block IO module.
+#
+# Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions
+# of the BSD License which accompanies this distribution. The
+# full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BlockIoDxe
+ FILE_GUID = 4495E47E-42A9-4007-8c17-B6664F909D04
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BiosBlockIoDriverEntryPoint
+
+[Sources]
+ BiosBlkIo.h
+ Edd.h
+ BiosBlkIo.c
+ BiosInt13.c
+ ComponentName.c
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ UefiLib
+ DevicePathLib
+ MemoryAllocationLib
+
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiLegacyBiosProtocolGuid
+
+
+[Guids]
+ gEfiLegacyBiosGuid
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c
new file mode 100644
index 0000000000..88bca13d5f
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/ComponentName.c
@@ -0,0 +1,309 @@
+/** @file
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosBlkIo.h"
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosBlockIoComponentName = {
+ BiosBlockIoComponentNameGetDriverName,
+ BiosBlockIoComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosBlockIoComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosBlockIoComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosBlockIoComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosBlockIoDriverNameTable[] = {
+ {
+ "eng;en",
+ L"BIOS[INT13] Block Io Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mBiosBlockIoDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gBiosBlockIoComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosBlockIoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h
new file mode 100644
index 0000000000..be4d8302cf
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/Edd.h
@@ -0,0 +1,209 @@
+/** @file
+ Include file to suport EDD 3.0.
+ This file is coded to T13 D1386 Revision 3
+ Availible on http://www.t13.org/#Project drafts
+ Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r3.pdf
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EDD_H_
+#define _EDD_H_
+
+//
+// packing with no compiler padding, so that the fields
+// of the following architected structures can be
+// properly accessed from C code.
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 Controller;
+ UINT32 Reserved;
+} EDD_PCI;
+
+typedef struct {
+ UINT16 Base;
+ UINT16 Reserved;
+ UINT32 Reserved2;
+} EDD_LEGACY;
+
+typedef union {
+ EDD_PCI Pci;
+ EDD_LEGACY Legacy;
+} EDD_INTERFACE_PATH;
+
+typedef struct {
+ UINT8 Master;
+ UINT8 Reserved[15];
+} EDD_ATA;
+
+typedef struct {
+ UINT8 Master;
+ UINT8 Lun;
+ UINT8 Reserved[14];
+} EDD_ATAPI;
+
+typedef struct {
+ UINT16 Pun;
+ UINT64 Lun;
+ UINT8 Reserved[6];
+} EDD_SCSI;
+
+typedef struct {
+ UINT64 SerialNumber;
+ UINT64 Reserved;
+} EDD_USB;
+
+typedef struct {
+ UINT64 Guid;
+ UINT64 Reserved;
+} EDD_1394;
+
+typedef struct {
+ UINT64 Wwn;
+ UINT64 Lun;
+} EDD_FIBRE;
+
+typedef union {
+ EDD_ATA Ata;
+ EDD_ATAPI Atapi;
+ EDD_SCSI Scsi;
+ EDD_USB Usb;
+ EDD_1394 FireWire;
+ EDD_FIBRE FibreChannel;
+} EDD_DEVICE_PATH;
+
+typedef struct {
+ UINT16 StructureSize;
+ UINT16 Flags;
+ UINT32 MaxCylinders;
+ UINT32 MaxHeads;
+ UINT32 SectorsPerTrack;
+ UINT64 PhysicalSectors;
+ UINT16 BytesPerSector;
+ UINT32 Fdpt;
+ UINT16 Key;
+ UINT8 DevicePathLength;
+ UINT8 Reserved1;
+ UINT16 Reserved2;
+ CHAR8 HostBusType[4];
+ CHAR8 InterfaceType[8];
+ EDD_INTERFACE_PATH InterfacePath;
+ EDD_DEVICE_PATH DevicePath;
+ UINT8 Reserved3;
+ UINT8 Checksum;
+} EDD_DRIVE_PARAMETERS;
+
+//
+// EDD_DRIVE_PARAMETERS.Flags defines
+//
+#define EDD_GEOMETRY_VALID 0x02
+#define EDD_DEVICE_REMOVABLE 0x04
+#define EDD_WRITE_VERIFY_SUPPORTED 0x08
+#define EDD_DEVICE_CHANGE 0x10
+#define EDD_DEVICE_LOCKABLE 0x20
+
+//
+// BUGBUG: This bit does not follow the spec. It tends to be always set
+// to work properly with Win98.
+//
+#define EDD_DEVICE_GEOMETRY_MAX 0x40
+
+typedef struct {
+ UINT8 PacketSizeInBytes; // 0x18
+ UINT8 Zero;
+ UINT8 NumberOfBlocks; // Max 0x7f
+ UINT8 Zero2;
+ UINT32 SegOffset;
+ UINT64 Lba;
+ UINT64 TransferBuffer;
+ UINT32 ExtendedBlockCount; // Max 0xffffffff
+ UINT32 Zero3;
+} EDD_DEVICE_ADDRESS_PACKET;
+
+#define EDD_VERSION_30 0x30
+
+//
+// Int 13 BIOS Errors
+//
+#define BIOS_PASS 0x00
+#define BIOS_WRITE_PROTECTED 0x03
+#define BIOS_SECTOR_NOT_FOUND 0x04
+#define BIOS_RESET_FAILED 0x05
+#define BIOS_DISK_CHANGED 0x06
+#define BIOS_DRIVE_DOES_NOT_EXIST 0x07
+#define BIOS_DMA_ERROR 0x08
+#define BIOS_DATA_BOUNDRY_ERROR 0x09
+#define BIOS_BAD_SECTOR 0x0a
+#define BIOS_BAD_TRACK 0x0b
+#define BIOS_MEADIA_TYPE_NOT_FOUND 0x0c
+#define BIOS_INVALED_FORMAT 0x0d
+#define BIOS_ECC_ERROR 0x10
+#define BIOS_ECC_CORRECTED_ERROR 0x11
+#define BIOS_HARD_DRIVE_FAILURE 0x20
+#define BIOS_SEEK_FAILED 0x40
+#define BIOS_DRIVE_TIMEOUT 0x80
+#define BIOS_DRIVE_NOT_READY 0xaa
+#define BIOS_UNDEFINED_ERROR 0xbb
+#define BIOS_WRITE_FAULT 0xcc
+#define BIOS_SENSE_FAILED 0xff
+
+#define MAX_EDD11_XFER 0xfe00
+
+#pragma pack()
+//
+// Internal Data Structures
+//
+typedef struct {
+ CHAR8 Letter;
+ UINT8 Number;
+ UINT8 EddVersion;
+ BOOLEAN ExtendedInt13;
+ BOOLEAN DriveLockingAndEjecting;
+ BOOLEAN Edd;
+ BOOLEAN Extensions64Bit;
+ BOOLEAN ParametersValid;
+ UINT8 ErrorCode;
+ VOID *FdptPointer;
+ BOOLEAN Floppy;
+ BOOLEAN AtapiFloppy;
+ UINT8 MaxHead;
+ UINT8 MaxSector;
+ UINT16 MaxCylinder;
+ UINT16 Pad;
+ EDD_DRIVE_PARAMETERS Parameters;
+} BIOS_LEGACY_DRIVE;
+
+#define BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE SIGNATURE_32 ('b', 'b', 'i', 'o')
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE Handle;
+ EFI_HANDLE ControllerHandle;
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ EFI_BLOCK_IO_MEDIA BlockMedia;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+
+ BIOS_LEGACY_DRIVE Bios;
+
+} BIOS_BLOCK_IO_DEV;
+
+#define BIOS_BLOCK_IO_FROM_THIS(a) CR (a, BIOS_BLOCK_IO_DEV, BlockIo, BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE)
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
new file mode 100644
index 0000000000..06ef9d3345
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
@@ -0,0 +1,2365 @@
+/** @file
+ ConsoleOut Routines that speak VGA.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosKeyboard.h"
+
+//
+// EFI Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding = {
+ BiosKeyboardDriverBindingSupported,
+ BiosKeyboardDriverBindingStart,
+ BiosKeyboardDriverBindingStop,
+ 0x3,
+ NULL,
+ NULL
+};
+
+
+/**
+ Enqueue the key.
+
+ @param Queue The queue to be enqueued.
+ @param KeyData The key data to be enqueued.
+
+ @retval EFI_NOT_READY The queue is full.
+ @retval EFI_SUCCESS Successfully enqueued the key data.
+
+**/
+EFI_STATUS
+Enqueue (
+ IN SIMPLE_QUEUE *Queue,
+ IN EFI_KEY_DATA *KeyData
+ )
+{
+ if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) {
+ return EFI_NOT_READY;
+ }
+
+ CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));
+ Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Dequeue the key.
+
+ @param Queue The queue to be dequeued.
+ @param KeyData The key data to be dequeued.
+
+ @retval EFI_NOT_READY The queue is empty.
+ @retval EFI_SUCCESS Successfully dequeued the key data.
+
+**/
+EFI_STATUS
+Dequeue (
+ IN SIMPLE_QUEUE *Queue,
+ IN EFI_KEY_DATA *KeyData
+ )
+{
+ if (Queue->Front == Queue->Rear) {
+ return EFI_NOT_READY;
+ }
+
+ CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA));
+ Queue->Front = (Queue->Front + 1) % QUEUE_MAX_COUNT;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Check whether the queue is empty.
+
+ @param Queue The queue to be checked.
+
+ @retval EFI_NOT_READY The queue is empty.
+ @retval EFI_SUCCESS The queue is not empty.
+
+**/
+EFI_STATUS
+CheckQueue (
+ IN SIMPLE_QUEUE *Queue
+ )
+{
+ if (Queue->Front == Queue->Rear) {
+ return EFI_NOT_READY;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// EFI Driver Binding Protocol Functions
+//
+
+/**
+ Check whether the driver supports this device.
+
+ @param This The Udriver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval other This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
+ //
+ if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+/**
+ Starts the device with this driver.
+
+ @param This The driver binding instance.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS The controller is controlled by the driver.
+ @retval Other This controller cannot be started.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_IA32_REGISTER_SET Regs;
+ BOOLEAN CarryFlag;
+ EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
+ UINT8 Command;
+ EFI_STATUS_CODE_VALUE StatusCode;
+
+ BiosKeyboardPrivate = NULL;
+ IsaIo = NULL;
+ StatusCode = 0;
+
+ //
+ // Get Ps2 policy to set. Will be use if present.
+ //
+ gBS->LocateProtocol (
+ &gEfiPs2PolicyProtocolGuid,
+ NULL,
+ (VOID **) &Ps2Policy
+ );
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Open the IO Abstraction(s) needed
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate the private device structure
+ //
+ BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV));
+ if (NULL == BiosKeyboardPrivate) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Initialize the private device structure
+ //
+ BiosKeyboardPrivate->Signature = BIOS_KEYBOARD_DEV_SIGNATURE;
+ BiosKeyboardPrivate->Handle = Controller;
+ BiosKeyboardPrivate->LegacyBios = LegacyBios;
+ BiosKeyboardPrivate->IsaIo = IsaIo;
+
+ BiosKeyboardPrivate->SimpleTextIn.Reset = BiosKeyboardReset;
+ BiosKeyboardPrivate->SimpleTextIn.ReadKeyStroke = BiosKeyboardReadKeyStroke;
+
+ BiosKeyboardPrivate->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER;
+ BiosKeyboardPrivate->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER;
+ BiosKeyboardPrivate->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
+ BiosKeyboardPrivate->ExtendedKeyboard = TRUE;
+
+ BiosKeyboardPrivate->Queue.Front = 0;
+ BiosKeyboardPrivate->Queue.Rear = 0;
+ BiosKeyboardPrivate->SimpleTextInputEx.Reset = BiosKeyboardResetEx;
+ BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx;
+ BiosKeyboardPrivate->SimpleTextInputEx.SetState = BiosKeyboardSetState;
+ BiosKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify = BiosKeyboardRegisterKeyNotify;
+ BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify;
+ InitializeListHead (&BiosKeyboardPrivate->NotifyList);
+
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &BiosKeyboardPrivate->DevicePath
+ );
+
+ //
+ // Report that the keyboard is being enabled
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
+ BiosKeyboardPrivate->DevicePath
+ );
+
+ //
+ // Setup the WaitForKey event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ BiosKeyboardWaitForKey,
+ &(BiosKeyboardPrivate->SimpleTextIn),
+ &((BiosKeyboardPrivate->SimpleTextIn).WaitForKey)
+ );
+ if (EFI_ERROR (Status)) {
+ (BiosKeyboardPrivate->SimpleTextIn).WaitForKey = NULL;
+ goto Done;
+ }
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ BiosKeyboardWaitForKeyEx,
+ &(BiosKeyboardPrivate->SimpleTextInputEx),
+ &(BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx)
+ );
+ if (EFI_ERROR (Status)) {
+ BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL;
+ goto Done;
+ }
+
+ //
+ // Setup a periodic timer, used for reading keystrokes at a fixed interval
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ BiosKeyboardTimerHandler,
+ BiosKeyboardPrivate,
+ &BiosKeyboardPrivate->TimerEvent
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+ goto Done;
+ }
+
+ Status = gBS->SetTimer (
+ BiosKeyboardPrivate->TimerEvent,
+ TimerPeriodic,
+ KEYBOARD_TIMER_INTERVAL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+ goto Done;
+ }
+
+ //
+ // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
+ BiosKeyboardPrivate->DevicePath
+ );
+
+ //
+ // Reset the keyboard device
+ //
+ Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset (
+ &BiosKeyboardPrivate->SimpleTextInputEx,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
+ goto Done;
+ }
+ //
+ // Do platform specific policy like port swapping and keyboard light default
+ //
+ if (Ps2Policy != NULL) {
+
+ Ps2Policy->Ps2InitHardware (Controller);
+
+ Command = 0;
+ if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
+ Command |= 4;
+ }
+
+ if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
+ Command |= 2;
+ }
+
+ if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
+ Command |= 1;
+ }
+
+ KeyboardWrite (BiosKeyboardPrivate, 0xed);
+ KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);
+ KeyboardWrite (BiosKeyboardPrivate, Command);
+ //
+ // Call Legacy BIOS Protocol to set whatever is necessary
+ //
+ LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);
+ }
+ //
+ // Get Configuration
+ //
+ Regs.H.AH = 0xc0;
+ CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (
+ BiosKeyboardPrivate->LegacyBios,
+ 0x15,
+ &Regs
+ );
+
+ if (!CarryFlag) {
+ //
+ // Check bit 6 of Feature Byte 2.
+ // If it is set, then Int 16 Func 09 is supported
+ //
+ if (*(UINT8 *)(UINTN) ((Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) {
+ //
+ // Get Keyboard Functionality
+ //
+ Regs.H.AH = 0x09;
+ CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (
+ BiosKeyboardPrivate->LegacyBios,
+ 0x16,
+ &Regs
+ );
+
+ if (!CarryFlag) {
+ //
+ // Check bit 5 of AH.
+ // If it is set, then INT 16 Finc 10-12 are supported.
+ //
+ if ((Regs.H.AL & 0x40) != 0) {
+ //
+ // Set the flag to use INT 16 Func 10-12
+ //
+ BiosKeyboardPrivate->ExtendedKeyboard = TRUE;
+ }
+ }
+ }
+ }
+ //
+ // Install protocol interfaces for the keyboard device.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &BiosKeyboardPrivate->SimpleTextIn,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &BiosKeyboardPrivate->SimpleTextInputEx,
+ NULL
+ );
+
+Done:
+ if (StatusCode != 0) {
+ //
+ // Report an Error Code for failing to start the keyboard device
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ StatusCode,
+ BiosKeyboardPrivate->DevicePath
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+
+ if (BiosKeyboardPrivate != NULL) {
+ if ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) {
+ gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);
+ }
+
+ if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {
+ gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx);
+ }
+ BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);
+
+ if (BiosKeyboardPrivate->TimerEvent != NULL) {
+ gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);
+ }
+
+ FreePool (BiosKeyboardPrivate);
+ }
+
+ if (IsaIo != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Stop the device handled by this driver.
+
+ @param This The driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval Others Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn;
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+
+ //
+ // Disable Keyboard
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ (VOID **) &SimpleTextIn,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimpleTextInputExProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (SimpleTextIn);
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &BiosKeyboardPrivate->SimpleTextIn,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &BiosKeyboardPrivate->SimpleTextInputEx,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Release the IsaIo protocol on the controller handle
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Free other resources
+ //
+ gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);
+ gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);
+ gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx);
+ BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);
+
+ FreePool (BiosKeyboardPrivate);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer-empty state.
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+
+ @return The data byte read from output buffer of Keyboard Controller from data port which often is port 60H.
+
+**/
+UINT8
+KeyReadDataRegister (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate
+ )
+{
+ UINT8 Data;
+
+ //
+ // Use IsaIo protocol to perform IO operations
+ //
+ BiosKeyboardPrivate->IsaIo->Io.Read (
+ BiosKeyboardPrivate->IsaIo,
+ EfiIsaIoWidthUint8,
+ BiosKeyboardPrivate->DataRegisterAddress,
+ 1,
+ &Data
+ );
+
+ return Data;
+}
+
+/**
+ Read status byte from status register of Keyboard Controller without delay and waiting for buffer-empty state.
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+
+ @return The status byte read from status register of Keyboard Controller from command port which often is port 64H.
+
+**/
+UINT8
+KeyReadStatusRegister (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate
+ )
+{
+ UINT8 Data;
+
+ //
+ // Use IsaIo protocol to perform IO operations
+ //
+ BiosKeyboardPrivate->IsaIo->Io.Read (
+ BiosKeyboardPrivate->IsaIo,
+ EfiIsaIoWidthUint8,
+ BiosKeyboardPrivate->StatusRegisterAddress,
+ 1,
+ &Data
+ );
+
+ return Data;
+}
+
+/**
+ Write command byte to control register of Keyboard Controller without delay and waiting for buffer-empty state.
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+ @param Data Data byte to write.
+
+**/
+VOID
+KeyWriteCommandRegister (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ IN UINT8 Data
+ )
+{
+ //
+ // Use IsaIo protocol to perform IO operations
+ //
+ BiosKeyboardPrivate->IsaIo->Io.Write (
+ BiosKeyboardPrivate->IsaIo,
+ EfiIsaIoWidthUint8,
+ BiosKeyboardPrivate->CommandRegisterAddress,
+ 1,
+ &Data
+ );
+}
+
+/**
+ Write data byte to input buffer or input/output ports of Keyboard Controller without delay and waiting for buffer-empty state.
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+ @param Data Data byte to write.
+
+**/
+VOID
+KeyWriteDataRegister (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ IN UINT8 Data
+ )
+{
+ //
+ // Use IsaIo protocol to perform IO operations
+ //
+ BiosKeyboardPrivate->IsaIo->Io.Write (
+ BiosKeyboardPrivate->IsaIo,
+ EfiIsaIoWidthUint8,
+ BiosKeyboardPrivate->DataRegisterAddress,
+ 1,
+ &Data
+ );
+}
+
+/**
+ Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer-empty state.
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+ @param Data The pointer for data that being read out.
+
+ @retval EFI_SUCCESS The data byte read out successfully.
+ @retval EFI_TIMEOUT Timeout occurred during reading out data byte.
+
+**/
+EFI_STATUS
+KeyboardRead (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ OUT UINT8 *Data
+ )
+{
+ UINT32 TimeOut;
+ UINT32 RegFilled;
+
+ TimeOut = 0;
+ RegFilled = 0;
+
+ //
+ // wait till output buffer full then perform the read
+ //
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) {
+ RegFilled = 1;
+ *Data = KeyReadDataRegister (BiosKeyboardPrivate);
+ break;
+ }
+
+ gBS->Stall (30);
+ }
+
+ if (RegFilled == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state.
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+ @param Data Data byte to write.
+
+ @retval EFI_SUCCESS The data byte is written successfully.
+ @retval EFI_TIMEOUT Timeout occurred during writing.
+
+**/
+EFI_STATUS
+KeyboardWrite (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ IN UINT8 Data
+ )
+{
+ UINT32 TimeOut;
+ UINT32 RegEmptied;
+
+ TimeOut = 0;
+ RegEmptied = 0;
+
+ //
+ // wait for input buffer empty
+ //
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {
+ RegEmptied = 1;
+ break;
+ }
+
+ gBS->Stall (30);
+ }
+
+ if (RegEmptied == 0) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Write it
+ //
+ KeyWriteDataRegister (BiosKeyboardPrivate, Data);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write command byte to control register of Keyboard Controller with delay and waiting for buffer-empty state.
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+ @param Data Command byte to write.
+
+ @retval EFI_SUCCESS The command byte is written successfully.
+ @retval EFI_TIMEOUT Timeout occurred during writing.
+
+**/
+EFI_STATUS
+KeyboardCommand (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ IN UINT8 Data
+ )
+{
+ UINT32 TimeOut;
+ UINT32 RegEmptied;
+
+ TimeOut = 0;
+ RegEmptied = 0;
+
+ //
+ // Wait For Input Buffer Empty
+ //
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {
+ RegEmptied = 1;
+ break;
+ }
+
+ gBS->Stall (30);
+ }
+
+ if (RegEmptied == 0) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // issue the command
+ //
+ KeyWriteCommandRegister (BiosKeyboardPrivate, Data);
+
+ //
+ // Wait For Input Buffer Empty again
+ //
+ RegEmptied = 0;
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {
+ RegEmptied = 1;
+ break;
+ }
+
+ gBS->Stall (30);
+ }
+
+ if (RegEmptied == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wait for a specific value to be presented in
+ Data register of Keyboard Controller by keyboard and then read it,
+ used in keyboard commands ack
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+ @param Value The value to be waited for
+ @param WaitForValueTimeOut The limit of microseconds for timeout
+
+ @retval EFI_SUCCESS The command byte is written successfully.
+ @retval EFI_TIMEOUT Timeout occurred during writing.
+
+**/
+EFI_STATUS
+KeyboardWaitForValue (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ IN UINT8 Value,
+ IN UINTN WaitForValueTimeOut
+ )
+{
+ UINT8 Data;
+ UINT32 TimeOut;
+ UINT32 SumTimeOut;
+ UINT32 GotIt;
+
+ GotIt = 0;
+ TimeOut = 0;
+ SumTimeOut = 0;
+
+ //
+ // Make sure the initial value of 'Data' is different from 'Value'
+ //
+ Data = 0;
+ if (Data == Value) {
+ Data = 1;
+ }
+ //
+ // Read from 8042 (multiple times if needed)
+ // until the expected value appears
+ // use SumTimeOut to control the iteration
+ //
+ while (1) {
+ //
+ // Perform a read
+ //
+ for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) {
+ Data = KeyReadDataRegister (BiosKeyboardPrivate);
+ break;
+ }
+
+ gBS->Stall (30);
+ }
+
+ SumTimeOut += TimeOut;
+
+ if (Data == Value) {
+ GotIt = 1;
+ break;
+ }
+
+ if (SumTimeOut >= WaitForValueTimeOut) {
+ break;
+ }
+ }
+ //
+ // Check results
+ //
+ if (GotIt != 0) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_TIMEOUT;
+ }
+
+}
+
+/**
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existance of a keystroke via WaitForEvent () call.
+
+ @param BiosKeyboardPrivate Bioskeyboard driver private structure.
+ @param KeyData A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
+
+ @retval EFI_SUCCESS The keystroke information was returned.
+ @retval EFI_NOT_READY There was no keystroke data availiable.
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
+ hardware errors.
+ @retval EFI_INVALID_PARAMETER KeyData is NULL.
+
+**/
+EFI_STATUS
+KeyboardReadKeyStrokeWorker (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ OUT EFI_KEY_DATA *KeyData
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ if (KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Use TimerEvent callback funciton to check whether there's any key pressed
+ //
+
+ //
+ // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
+ // Csm will be used to check whether there is a key pending, but the csm will disable all
+ // interrupt before switch to compatibility16, which mean all the efiCompatibility timer
+ // event will stop work during the compatibility16. And If a caller recursivly invoke this function,
+ // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period,
+ // e.g. usb keyboard driver.
+ // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
+ // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
+ //
+ gBS->Stall (1000);
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ BiosKeyboardTimerHandler (NULL, BiosKeyboardPrivate);
+ //
+ // If there's no key, just return
+ //
+ Status = CheckQueue (&BiosKeyboardPrivate->Queue);
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (OldTpl);
+ return EFI_NOT_READY;
+ }
+
+ Status = Dequeue (&BiosKeyboardPrivate->Queue, KeyData);
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+}
+
+//
+// EFI Simple Text In Protocol Functions
+//
+/**
+ Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.
+
+ @param This Pointer of simple text Protocol.
+ @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.
+
+ @retval EFI_SUCCESS The command byte is written successfully.
+ @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardReset (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ UINT8 CommandByte;
+ BOOLEAN MouseEnable;
+ EFI_INPUT_KEY Key;
+
+ MouseEnable = FALSE;
+ BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);
+
+ //
+ // 1
+ // Report reset progress code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,
+ BiosKeyboardPrivate->DevicePath
+ );
+
+ //
+ // Report a Progress Code for clearing the keyboard buffer
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
+ BiosKeyboardPrivate->DevicePath
+ );
+
+ //
+ // 2
+ // Raise TPL to avoid mouse operation impact
+ //
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ //
+ // Exhaust output buffer data
+ //
+ do {
+ Status = BiosKeyboardReadKeyStroke (
+ This,
+ &Key
+ );
+ } while (!EFI_ERROR (Status));
+ //
+ // 3
+ // check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H
+ // if not skip step 4&5 and jump to step 6 to selftest KBC and report this
+ // else go step 4
+ //
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) {
+ //
+ // 4
+ // CheckMouseStatus to decide enable it later or not
+ //
+ //
+ // Read the command byte of KBC
+ //
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_CMDBYTE_R
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardRead (
+ BiosKeyboardPrivate,
+ &CommandByte
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // Check mouse enabled or not before
+ //
+ if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) {
+ MouseEnable = FALSE;
+ } else {
+ MouseEnable = TRUE;
+ }
+ //
+ // 5
+ // disable mouse (via KBC) and Keyborad device
+ //
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_AUX_DISABLE
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_KB_DISABLE
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ } else {
+ //
+ // 6
+ // KBC Self Test
+ //
+ //
+ // Report a Progress Code for performing a self test on the keyboard controller
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
+ BiosKeyboardPrivate->DevicePath
+ );
+
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_KBC_SLFTEST
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_KBCSLFTEST_OK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ }
+ //
+ // 7
+ // Disable Mouse interface, enable Keyboard interface and declare selftest success
+ //
+ // Mouse device will block keyboard interface before it be configured, so we should disable mouse first.
+ //
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_CMDBYTE_W
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ //
+ // Write 8042 Command Byte, set System Flag
+ // While at the same time:
+ // 1. disable mouse interface,
+ // 2. enable kbd interface,
+ // 3. enable PC/XT kbd translation mode
+ // 4. enable mouse and kbd interrupts
+ //
+ //Command Byte bits:
+ // 7: Reserved
+ // 6: PC/XT translation mode
+ // 5: Disable Auxiliary device interface
+ // 4: Disable keyboard interface
+ // 3: Reserved
+ // 2: System Flag
+ // 1: Enable Auxiliary device interrupt
+ // 0: Enable Keyboard interrupt
+ //
+ CommandByte = 0;
+ Status = KeyboardWrite (
+ BiosKeyboardPrivate,
+ (UINT8) ((CommandByte &
+ (~KB_CMMBYTE_DISABLE_KB)) |
+ KB_CMMBYTE_KSCAN2UNI_COV |
+ KB_CMMBYTE_ENABLE_AUXINT |
+ KB_CMMBYTE_ENABLE_KBINT |
+ KB_CMMBYTE_SLFTEST_SUCC |
+ KB_CMMBYTE_DISABLE_AUX)
+ );
+
+ //
+ // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
+ // so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped.
+ // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,
+ // Real reset will not do.
+ //
+ if (ExtendedVerification && CheckKeyboardConnect (BiosKeyboardPrivate)) {
+ //
+ // 8
+ // Send keyboard reset command then read ACK
+ //
+ Status = KeyboardWrite (
+ BiosKeyboardPrivate,
+ KBC_INPBUF_VIA60_KBRESET
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_ACK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // 9
+ // Wait for keyboard return test OK.
+ //
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_BATTEST_OK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // 10
+ // set keyboard scan code set = 02 (standard configuration)
+ //
+ Status = KeyboardWrite (
+ BiosKeyboardPrivate,
+ KBC_INPBUF_VIA60_KBSCODE
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_ACK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardWrite (
+ BiosKeyboardPrivate,
+ KBC_INPBUF_VIA60_SCODESET2
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_ACK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // 11
+ // enable keyboard itself (not via KBC) by writing CMD F4 via 60H
+ //
+ Status = KeyboardWrite (
+ BiosKeyboardPrivate,
+ KBC_INPBUF_VIA60_KBEN
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_ACK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // 12
+ // Additional validation, do it as follow:
+ // 1). check for status register of PARE && TIM via 64H
+ // 2). perform KB checking by writing ABh via 64H
+ //
+ if ((KeyReadStatusRegister (BiosKeyboardPrivate) & (KBC_STSREG_VIA64_PARE | KBC_STSREG_VIA64_TIM)) != 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_KB_CKECK
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_KBCHECK_OK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ }
+ //
+ // 13
+ // Done for validating keyboard. Enable keyboard (via KBC)
+ // and recover the command byte to proper value
+ //
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_KB_ENABLE
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ //
+ // 14
+ // conditionally enable mouse (via KBC)
+ //
+ if (MouseEnable) {
+ Status = KeyboardCommand (
+ BiosKeyboardPrivate,
+ KBC_CMDREG_VIA64_AUX_ENABLE
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+
+ }
+ }
+
+Exit:
+ //
+ // 15
+ // resume priority of task level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+
+}
+
+/**
+ Read out the scan code of the key that has just been stroked.
+
+ @param This Pointer of simple text Protocol.
+ @param Key Pointer for store the key that read out.
+
+ @retval EFI_SUCCESS The key is read out successfully.
+ @retval other The key reading failed.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ )
+{
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_STATUS Status;
+ EFI_KEY_DATA KeyData;
+
+ BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);
+
+ Status = KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, &KeyData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Waiting on the keyboard event, if there's any key pressed by the user, signal the event
+
+ @param Event The event that be siganlled when any key has been stroked.
+ @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
+
+**/
+VOID
+EFIAPI
+BiosKeyboardWaitForKey (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
+ // Csm will be used to check whether there is a key pending, but the csm will disable all
+ // interrupt before switch to compatibility16, which mean all the efiCompatibility timer
+ // event will stop work during the compatibility16. And If a caller recursivly invoke this function,
+ // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,
+ // e.g. usb keyboard driver.
+ // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
+ // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
+ //
+ gBS->Stall (1000);
+ //
+ // Use TimerEvent callback funciton to check whether there's any key pressed
+ //
+ BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context));
+
+ if (!EFI_ERROR (BiosKeyboardCheckForKey (Context))) {
+ gBS->SignalEvent (Event);
+ }
+}
+
+/**
+ Check key buffer to get the key stroke status.
+
+ @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.
+
+ @retval EFI_SUCCESS A key is being pressed now.
+ @retval Other No key is now pressed.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardCheckForKey (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
+ )
+{
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+
+ BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);
+
+ return CheckQueue (&BiosKeyboardPrivate->Queue);
+}
+//
+// Private worker functions
+//
+#define TABLE_END 0x0
+
+typedef struct _CONVERT_TABLE_ENTRY {
+ UINT16 ScanCode;
+ UINT16 EfiScanCode;
+} CONVERT_TABLE_ENTRY;
+
+CONVERT_TABLE_ENTRY mConvertTable[] = {
+ {
+ 0x47,
+ SCAN_HOME
+ },
+ {
+ 0x48,
+ SCAN_UP
+ },
+ {
+ 0x49,
+ SCAN_PAGE_UP
+ },
+ {
+ 0x4b,
+ SCAN_LEFT
+ },
+ {
+ 0x4d,
+ SCAN_RIGHT
+ },
+ {
+ 0x4f,
+ SCAN_END
+ },
+ {
+ 0x50,
+ SCAN_DOWN
+ },
+ {
+ 0x51,
+ SCAN_PAGE_DOWN
+ },
+ {
+ 0x52,
+ SCAN_INSERT
+ },
+ {
+ 0x53,
+ SCAN_DELETE
+ },
+ //
+ // Function Keys are only valid if KeyChar == 0x00
+ // This function does not require KeyChar to be 0x00
+ //
+ {
+ 0x3b,
+ SCAN_F1
+ },
+ {
+ 0x3c,
+ SCAN_F2
+ },
+ {
+ 0x3d,
+ SCAN_F3
+ },
+ {
+ 0x3e,
+ SCAN_F4
+ },
+ {
+ 0x3f,
+ SCAN_F5
+ },
+ {
+ 0x40,
+ SCAN_F6
+ },
+ {
+ 0x41,
+ SCAN_F7
+ },
+ {
+ 0x42,
+ SCAN_F8
+ },
+ {
+ 0x43,
+ SCAN_F9
+ },
+ {
+ 0x44,
+ SCAN_F10
+ },
+ {
+ 0x85,
+ SCAN_F11
+ },
+ {
+ 0x86,
+ SCAN_F12
+ },
+ //
+ // Convert ALT + Fn keys
+ //
+ {
+ 0x68,
+ SCAN_F1
+ },
+ {
+ 0x69,
+ SCAN_F2
+ },
+ {
+ 0x6a,
+ SCAN_F3
+ },
+ {
+ 0x6b,
+ SCAN_F4
+ },
+ {
+ 0x6c,
+ SCAN_F5
+ },
+ {
+ 0x6d,
+ SCAN_F6
+ },
+ {
+ 0x6e,
+ SCAN_F7
+ },
+ {
+ 0x6f,
+ SCAN_F8
+ },
+ {
+ 0x70,
+ SCAN_F9
+ },
+ {
+ 0x71,
+ SCAN_F10
+ },
+ {
+ TABLE_END,
+ SCAN_NULL
+ },
+};
+
+/**
+ Convert unicode combined with scan code of key to the counterpart of EFIScancode of it.
+
+ @param KeyChar Unicode of key.
+ @param ScanCode Scan code of key.
+
+ @return The value of EFI Scancode for the key.
+ @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key.
+
+**/
+UINT16
+ConvertToEFIScanCode (
+ IN CHAR16 KeyChar,
+ IN UINT16 ScanCode
+ )
+{
+ UINT16 EfiScanCode;
+ UINT16 Index;
+
+ if (KeyChar == CHAR_ESC) {
+ EfiScanCode = SCAN_ESC;
+ } else if (KeyChar == 0x00 || KeyChar == 0xe0) {
+ //
+ // Movement & Function Keys
+ //
+ for (Index = 0; (Index < sizeof (mConvertTable) / sizeof (CONVERT_TABLE_ENTRY)) && (mConvertTable[Index].ScanCode != TABLE_END); Index += 1) {
+ if (ScanCode == mConvertTable[Index].ScanCode) {
+ return mConvertTable[Index].EfiScanCode;
+ }
+ }
+ //
+ // Reach Table end, return default value
+ //
+ return SCAN_NULL;
+ } else {
+ return SCAN_NULL;
+ }
+
+ return EfiScanCode;
+}
+
+/**
+ Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
+ If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
+ should not be in system.
+
+ @param BiosKeyboardPrivate Keyboard Private Data Struture
+
+ @retval TRUE Keyboard in System.
+ @retval FALSE Keyboard not in System.
+
+**/
+BOOLEAN
+CheckKeyboardConnect (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ //
+ // enable keyboard itself and wait for its ack
+ // If can't receive ack, Keyboard should not be connected.
+ //
+ Status = KeyboardWrite (
+ BiosKeyboardPrivate,
+ KBC_INPBUF_VIA60_KBEN
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = KeyboardWaitForValue (
+ BiosKeyboardPrivate,
+ KBC_CMDECHO_ACK,
+ KEYBOARD_WAITFORVALUE_TIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Timer event handler: read a series of key stroke from 8042
+ and put them into memory key buffer.
+ It is registered as running under TPL_NOTIFY
+
+ @param Event The timer event
+ @param Context A BIOS_KEYBOARD_DEV pointer
+
+**/
+VOID
+EFIAPI
+BiosKeyboardTimerHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_TPL OldTpl;
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_IA32_REGISTER_SET Regs;
+ UINT8 KbFlag1; // 0040h:0017h - KEYBOARD - STATUS FLAGS 1
+ UINT8 KbFlag2; // 0040h:0018h - KEYBOARD - STATUS FLAGS 2
+ EFI_KEY_DATA KeyData;
+ LIST_ENTRY *Link;
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+
+ BiosKeyboardPrivate = Context;
+
+ //
+ // Enter critical section
+ //
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // if there is no key present, just return
+ //
+ if (BiosKeyboardPrivate->ExtendedKeyboard) {
+ Regs.H.AH = 0x11;
+ } else {
+ Regs.H.AH = 0x01;
+ }
+
+ BiosKeyboardPrivate->LegacyBios->Int86 (
+ BiosKeyboardPrivate->LegacyBios,
+ 0x16,
+ &Regs
+ );
+ if (Regs.X.Flags.ZF != 0) {
+ gBS->RestoreTPL (OldTpl);
+ return;
+ }
+
+ //
+ // Read the key
+ //
+ if (BiosKeyboardPrivate->ExtendedKeyboard) {
+ Regs.H.AH = 0x10;
+ } else {
+ Regs.H.AH = 0x00;
+ }
+
+ BiosKeyboardPrivate->LegacyBios->Int86 (
+ BiosKeyboardPrivate->LegacyBios,
+ 0x16,
+ &Regs
+ );
+
+ KeyData.Key.ScanCode = (UINT16) Regs.H.AH;
+ KeyData.Key.UnicodeChar = (UINT16) Regs.H.AL;
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
+ //
+ // Leagcy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB buffer in BDA (BIOS DATE AREA), then
+ // 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
+ // 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
+ // 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
+ // 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
+ // 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
+ // 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
+ // performance, like USB.
+ //
+ // 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
+ // 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
+ // 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
+ // CTRL and ALT.
+ //
+ // 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
+ // 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,
+ // which will let persist to press SHIFT has same effection as only press one time.
+ //
+ //0040h:0017h - KEYBOARD - STATUS FLAGS 1
+ // 7 INSert active
+ // 6 Caps Lock active
+ // 5 Num Lock active
+ // 4 Scroll Lock active
+ // 3 either Alt pressed
+ // 2 either Ctrl pressed
+ // 1 Left Shift pressed
+ // 0 Right Shift pressed
+
+
+ //
+ // Clear the CTRL and ALT BDA flag
+ //
+ KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1
+ KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2
+
+ //
+ // Record toggle state
+ //
+ if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) {
+ KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
+ }
+ if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) {
+ KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
+ }
+ if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) {
+ KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
+ }
+ //
+ // Record shift state
+ // BUGBUG: Need add Menu key and Left/Right Logo key state in the future
+ //
+ if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) {
+ KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) ? EFI_LEFT_ALT_PRESSED : EFI_RIGHT_ALT_PRESSED;
+ }
+ if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) {
+ KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) ? EFI_LEFT_CONTROL_PRESSED : EFI_RIGHT_CONTROL_PRESSED;
+ }
+ if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) {
+ KeyData.KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
+ }
+ if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) {
+ KeyData.KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
+ }
+
+ //
+ // Clear left alt and left ctrl BDA flag
+ //
+ KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED);
+ *((UINT8 *) (UINTN) 0x418) = KbFlag2;
+ KbFlag1 &= ~0x0C;
+ *((UINT8 *) (UINTN) 0x417) = KbFlag1;
+
+
+ //
+ // Output EFI input key and shift/toggle state
+ //
+ if (KeyData.Key.UnicodeChar == CHAR_NULL || KeyData.Key.UnicodeChar == CHAR_SCANCODE || KeyData.Key.UnicodeChar == CHAR_ESC) {
+ KeyData.Key.ScanCode = ConvertToEFIScanCode (KeyData.Key.UnicodeChar, KeyData.Key.ScanCode);
+ KeyData.Key.UnicodeChar = CHAR_NULL;
+ } else {
+ KeyData.Key.ScanCode = SCAN_NULL;
+ }
+
+ //
+ // CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back.
+ //
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
+ if (KeyData.Key.UnicodeChar >= 1 && KeyData.Key.UnicodeChar <= 26) {
+ if (((KeyData.KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) ==
+ ((KeyData.KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0)
+ ) {
+ KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'a' - 1);
+ } else {
+ KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'A' - 1);
+ }
+ }
+ }
+
+ //
+ // Need not return associated shift state if a class of printable characters that
+ // are normally adjusted by shift modifiers.
+ // e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'.
+ //
+ if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') ||
+ (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z')
+ ) {
+ KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
+ }
+
+ //
+ // Invoke notification functions if exist
+ //
+ for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
+ CurrentNotify->KeyNotificationFn (&KeyData);
+ }
+ }
+
+ //
+ // Convert the Ctrl+[a-z] to Ctrl+[1-26]
+ //
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
+ if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
+ KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + 1);
+ } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
+ KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + 1);
+ }
+ }
+ Enqueue (&BiosKeyboardPrivate->Queue, &KeyData);
+ //
+ // Leave critical section and return
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ return ;
+}
+
+/**
+ Free keyboard notify list.
+
+ @param ListHead The list head
+
+ @retval EFI_SUCCESS Free the notify list successfully
+ @retval EFI_INVALID_PARAMETER ListHead is invalid.
+
+**/
+EFI_STATUS
+BiosKeyboardFreeNotifyList (
+ IN OUT LIST_ENTRY *ListHead
+ )
+{
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
+
+ if (ListHead == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ while (!IsListEmpty (ListHead)) {
+ NotifyNode = CR (
+ ListHead->ForwardLink,
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ RemoveEntryList (ListHead->ForwardLink);
+ gBS->FreePool (NotifyNode);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if key is registered.
+
+ @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was registered.
+ @param InputData A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
+
+ @retval TRUE Key be pressed matches a registered key.
+ @retval FLASE Match failed.
+
+**/
+BOOLEAN
+IsKeyRegistered (
+ IN EFI_KEY_DATA *RegsiteredData,
+ IN EFI_KEY_DATA *InputData
+ )
+{
+ ASSERT (RegsiteredData != NULL && InputData != NULL);
+
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
+ return FALSE;
+ }
+
+ //
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
+ //
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
+ return FALSE;
+ }
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+/**
+ Waiting on the keyboard event, if there's any key pressed by the user, signal the event
+
+ @param Event The event that be siganlled when any key has been stroked.
+ @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+
+**/
+VOID
+EFIAPI
+BiosKeyboardWaitForKeyEx (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (Context);
+ BiosKeyboardWaitForKey (Event, &BiosKeyboardPrivate->SimpleTextIn);
+
+}
+
+/**
+ Reset the input device and optionaly run diagnostics
+
+ @param This Protocol instance pointer.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardResetEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
+
+ Status = BiosKeyboardPrivate->SimpleTextIn.Reset (
+ &BiosKeyboardPrivate->SimpleTextIn,
+ ExtendedVerification
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existance of a keystroke via WaitForEvent () call.
+
+ @param This Protocol instance pointer.
+ @param KeyData A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
+
+ @retval EFI_SUCCESS The keystroke information was returned.
+ @retval EFI_NOT_READY There was no keystroke data availiable.
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
+ hardware errors.
+ @retval EFI_INVALID_PARAMETER KeyData is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+ )
+{
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+
+ if (KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
+
+ return KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, KeyData);
+
+}
+
+/**
+ Set certain state for the input device.
+
+ @param This Protocol instance pointer.
+ @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
+ state for the input device.
+
+ @retval EFI_SUCCESS The device state was set successfully.
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
+ not have the setting adjusted.
+ @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
+ @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardSetState (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+ )
+{
+ EFI_STATUS Status;
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_TPL OldTpl;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINT8 Command;
+
+ if (KeyToggleState == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
+ return EFI_UNSUPPORTED;
+ }
+
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Enter critical section
+ //
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Command = 0;
+ if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
+ Command |= 4;
+ }
+ if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
+ Command |= 2;
+ }
+ if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
+ Command |= 1;
+ }
+
+ Status = KeyboardWrite (BiosKeyboardPrivate, 0xed);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ Status = KeyboardWrite (BiosKeyboardPrivate, Command);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Call Legacy BIOS Protocol to set whatever is necessary
+ //
+ LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Leave critical section and return
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+
+}
+
+/**
+ Register a notification function for a particular keystroke for the input device.
+
+ @param This Protocol instance pointer.
+ @param KeyData A pointer to a buffer that is filled in with the keystroke
+ information data for the key that was pressed.
+ @param KeyNotificationFunction Points to the function to be called when the key
+ sequence is typed specified by KeyData.
+ @param NotifyHandle Points to the unique handle assigned to the registered notification.
+
+
+ @retval EFI_SUCCESS The notification function was registered successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardRegisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+ )
+{
+ EFI_STATUS Status;
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_TPL OldTpl;
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
+ LIST_ENTRY *Link;
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
+
+ //
+ // Enter critical section
+ //
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
+ //
+ for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
+ *NotifyHandle = CurrentNotify->NotifyHandle;
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+ }
+
+ //
+ // Allocate resource to save the notification function
+ //
+
+ NewNotify = (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY));
+ if (NewNotify == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ NewNotify->Signature = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;
+ NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
+ InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);
+
+ *NotifyHandle = NewNotify->NotifyHandle;
+ Status = EFI_SUCCESS;
+
+Exit:
+ //
+ // Leave critical section and return
+ //
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Remove a registered notification function from a particular keystroke.
+
+ @param This Protocol instance pointer.
+ @param NotificationHandle The handle of the notification function being unregistered.
+
+ @retval EFI_SUCCESS The notification function was unregistered successfully.
+ @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardUnregisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ )
+{
+ EFI_STATUS Status;
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
+ EFI_TPL OldTpl;
+ LIST_ENTRY *Link;
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+
+ //
+ // Check incoming notification handle
+ //
+ if (NotificationHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
+
+ //
+ // Enter critical section
+ //
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {
+ //
+ // Remove the notification function from NotifyList and free resources
+ //
+ RemoveEntryList (&CurrentNotify->NotifyEntry);
+
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+
+ //
+ // Can not find the specified Notification Handle
+ //
+ Status = EFI_INVALID_PARAMETER;
+
+Exit:
+ //
+ // Leave critical section and return
+ //
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ The user Entry Point for module BiosKeyboard. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeBiosKeyboard(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gBiosKeyboardDriverBinding,
+ ImageHandle,
+ &gBiosKeyboardComponentName,
+ &gBiosKeyboardComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
new file mode 100644
index 0000000000..c9f86a1dbd
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
@@ -0,0 +1,744 @@
+/** @file
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BIOS_KEYBOARD_H_
+#define _BIOS_KEYBOARD_H_
+
+
+#include <FrameworkDxe.h>
+
+#include <Guid/StatusCodeDataTypeId.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/IsaIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/Ps2Policy.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+
+//
+// Driver Binding Externs
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2;
+
+
+#include <IndustryStandard/Pci.h>
+
+//
+// BISO Keyboard Defines
+//
+#define CHAR_SCANCODE 0xe0
+#define CHAR_ESC 0x1b
+
+#define KEYBOARD_8042_DATA_REGISTER 0x60
+#define KEYBOARD_8042_STATUS_REGISTER 0x64
+#define KEYBOARD_8042_COMMAND_REGISTER 0x64
+
+#define KEYBOARD_TIMEOUT 65536 // 0.07s
+#define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s
+#define KEYBOARD_BAT_TIMEOUT 4000000 // 4s
+#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s
+// KEYBOARD COMMAND BYTE -- read by writing command KBC_CMDREG_VIA64_CMDBYTE_R to 64H, then read from 60H
+// write by wrting command KBC_CMDREG_VIA64_CMDBYTE_W to 64H, then write to 60H
+// 7: Reserved
+// 6: PC/XT translation mode convert
+// 5: Disable Auxiliary device interface
+// 4: Disable keyboard interface
+// 3: Reserved
+// 2: System Flag: selftest successful
+// 1: Enable Auxiliary device interrupt
+// 0: Enable Keyboard interrupt )
+//
+#define KB_CMMBYTE_KSCAN2UNI_COV (0x1 << 6)
+#define KB_CMMBYTE_DISABLE_AUX (0x1 << 5)
+#define KB_CMMBYTE_DISABLE_KB (0x1 << 4)
+#define KB_CMMBYTE_SLFTEST_SUCC (0x1 << 2)
+#define KB_CMMBYTE_ENABLE_AUXINT (0x1 << 1)
+#define KB_CMMBYTE_ENABLE_KBINT (0x1 << 0)
+
+//
+// KEYBOARD CONTROLLER STATUS REGISTER - read from 64h
+// 7: Parity error
+// 6: General time out
+// 5: Output buffer holds data for AUX
+// 4: Keyboard is not locked
+// 3: Command written via 64h / Data written via 60h
+// 2: KBC self-test successful / Power-on reset
+// 1: Input buffer holds CPU data / empty
+// 0: Output buffer holds keyboard data / empty
+//
+#define KBC_STSREG_VIA64_PARE (0x1 << 7)
+#define KBC_STSREG_VIA64_TIM (0x1 << 6)
+#define KBC_STSREG_VIA64_AUXB (0x1 << 5)
+#define KBC_STSREG_VIA64_KEYL (0x1 << 4)
+#define KBC_STSREG_VIA64_C_D (0x1 << 3)
+#define KBC_STSREG_VIA64_SYSF (0x1 << 2)
+#define KBC_STSREG_VIA64_INPB (0x1 << 1)
+#define KBC_STSREG_VIA64_OUTB (0x1 << 0)
+
+//
+// COMMANDs of KEYBOARD CONTROLLER COMMAND REGISTER - write to 64h
+//
+#define KBC_CMDREG_VIA64_CMDBYTE_R 0x20
+#define KBC_CMDREG_VIA64_CMDBYTE_W 0x60
+#define KBC_CMDREG_VIA64_AUX_DISABLE 0xA7
+#define KBC_CMDREG_VIA64_AUX_ENABLE 0xA8
+#define KBC_CMDREG_VIA64_KBC_SLFTEST 0xAA
+#define KBC_CMDREG_VIA64_KB_CKECK 0xAB
+#define KBC_CMDREG_VIA64_KB_DISABLE 0xAD
+#define KBC_CMDREG_VIA64_KB_ENABLE 0xAE
+#define KBC_CMDREG_VIA64_INTP_LOW_R 0xC0
+#define KBC_CMDREG_VIA64_INTP_HIGH_R 0xC2
+#define KBC_CMDREG_VIA64_OUTP_R 0xD0
+#define KBC_CMDREG_VIA64_OUTP_W 0xD1
+#define KBC_CMDREG_VIA64_OUTB_KB_W 0xD2
+#define KBC_CMDREG_VIA64_OUTB_AUX_W 0xD3
+#define KBC_CMDREG_VIA64_AUX_W 0xD4
+
+//
+// echos of KEYBOARD CONTROLLER COMMAND - read from 60h
+//
+#define KBC_CMDECHO_KBCSLFTEST_OK 0x55
+#define KBC_CMDECHO_KBCHECK_OK 0x00
+#define KBC_CMDECHO_ACK 0xFA
+#define KBC_CMDECHO_BATTEST_OK 0xAA
+#define KBC_CMDECHO_BATTEST_FAILE 0xFC
+
+//
+// OUTPUT PORT COMMANDs - write port by writing KBC_CMDREG_VIA64_OUTP_W via 64H, then write the command to 60H
+// drive data and clock of KB to high for at least 500us for BAT needs
+//
+#define KBC_OUTPORT_DCHIGH_BAT 0xC0
+//
+// scan code set type
+//
+#define KBC_INPBUF_VIA60_SCODESET1 0x01
+#define KBC_INPBUF_VIA60_SCODESET2 0x02
+#define KBC_INPBUF_VIA60_SCODESET3 0x03
+
+//
+// COMMANDs written to INPUT BUFFER - write to 60h
+//
+#define KBC_INPBUF_VIA60_KBECHO 0xEE
+#define KBC_INPBUF_VIA60_KBSCODE 0xF0
+#define KBC_INPBUF_VIA60_KBTYPE 0xF2
+#define KBC_INPBUF_VIA60_KBDELAY 0xF3
+#define KBC_INPBUF_VIA60_KBEN 0xF4
+#define KBC_INPBUF_VIA60_KBSTDDIS 0xF5
+#define KBC_INPBUF_VIA60_KBSTDEN 0xF6
+#define KBC_INPBUF_VIA60_KBRESEND 0xFE
+#define KBC_INPBUF_VIA60_KBRESET 0xFF
+
+//
+// 0040h:0017h - KEYBOARD - STATUS FLAGS 1
+// 7 INSert active
+// 6 Caps Lock active
+// 5 Num Lock active
+// 4 Scroll Lock active
+// 3 either Alt pressed
+// 2 either Ctrl pressed
+// 1 Left Shift pressed
+// 0 Right Shift pressed
+//
+// 0040h:0018h - KEYBOARD - STATUS FLAGS 2
+// 7: insert key is depressed
+// 6: caps-lock key is depressed (does not work well)
+// 5: num-lock key is depressed (does not work well)
+// 4: scroll lock key is depressed (does not work well)
+// 3: suspend key has been toggled (does not work well)
+// 2: system key is pressed and held (does not work well)
+// 1: left ALT key is pressed
+// 0: left CTRL key is pressed
+//
+#define KB_INSERT_BIT (0x1 << 7)
+#define KB_CAPS_LOCK_BIT (0x1 << 6)
+#define KB_NUM_LOCK_BIT (0x1 << 5)
+#define KB_SCROLL_LOCK_BIT (0x1 << 4)
+#define KB_ALT_PRESSED (0x1 << 3)
+#define KB_CTRL_PRESSED (0x1 << 2)
+#define KB_LEFT_SHIFT_PRESSED (0x1 << 1)
+#define KB_RIGHT_SHIFT_PRESSED (0x1 << 0)
+
+#define KB_SUSPEND_PRESSED (0x1 << 3)
+#define KB_SYSREQ_PRESSED (0x1 << 2)
+#define KB_LEFT_ALT_PRESSED (0x1 << 1)
+#define KB_LEFT_CTRL_PRESSED (0x1 << 0)
+
+//
+// BIOS Keyboard Device Structure
+//
+#define BIOS_KEYBOARD_DEV_SIGNATURE SIGNATURE_32 ('B', 'K', 'B', 'D')
+#define BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('c', 'b', 'k', 'h')
+
+typedef struct _BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY {
+ UINTN Signature;
+ EFI_HANDLE NotifyHandle;
+ EFI_KEY_DATA KeyData;
+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn;
+ LIST_ENTRY NotifyEntry;
+} BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY;
+
+#define QUEUE_MAX_COUNT 32
+typedef struct {
+ UINTN Front;
+ UINTN Rear;
+ EFI_KEY_DATA Buffer[QUEUE_MAX_COUNT];
+} SIMPLE_QUEUE;
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInputEx;
+ UINT16 DataRegisterAddress;
+ UINT16 StatusRegisterAddress;
+ UINT16 CommandRegisterAddress;
+ BOOLEAN ExtendedKeyboard;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ //
+ // Buffer storing EFI_KEY_DATA
+ //
+ SIMPLE_QUEUE Queue;
+
+ //
+ // Notification Function List
+ //
+ LIST_ENTRY NotifyList;
+ EFI_EVENT TimerEvent;
+
+} BIOS_KEYBOARD_DEV;
+
+#define BIOS_KEYBOARD_DEV_FROM_THIS(a) CR (a, BIOS_KEYBOARD_DEV, SimpleTextIn, BIOS_KEYBOARD_DEV_SIGNATURE)
+#define TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS(a) \
+ CR (a, \
+ BIOS_KEYBOARD_DEV, \
+ SimpleTextInputEx, \
+ BIOS_KEYBOARD_DEV_SIGNATURE \
+ )
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding;
+
+//
+// Driver Binding Protocol functions
+//
+
+/**
+ Check whether the driver supports this device.
+
+ @param This The Udriver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval other This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starts the device with this driver.
+
+ @param This The driver binding instance.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS The controller is controlled by the driver.
+ @retval Other This controller cannot be started.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop the device handled by this driver.
+
+ @param This The driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval Others Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// Simple Text Input Protocol functions
+//
+/**
+ Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.
+
+ @param This Pointer of simple text Protocol.
+ @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.
+
+ @retval EFI_SUCCESS The command byte is written successfully.
+ @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardReset (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Read out the scan code of the key that has just been stroked.
+
+ @param This Pointer of simple text Protocol.
+ @param Key Pointer for store the key that read out.
+
+ @retval EFI_SUCCESS The key is read out successfully.
+ @retval other The key reading failed.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+//
+// Private worker functions
+//
+/**
+ Waiting on the keyboard event, if there's any key pressed by the user, signal the event
+
+ @param Event The event that be siganlled when any key has been stroked.
+ @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
+
+**/
+VOID
+EFIAPI
+BiosKeyboardWaitForKey (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Check key buffer to get the key stroke status.
+
+ @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.
+
+ @retval EFI_SUCCESS A key is being pressed now.
+ @retval Other No key is now pressed.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardCheckForKey (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
+ );
+
+/**
+ Convert unicode combined with scan code of key to the counterpart of EFIScancode of it.
+
+ @param KeyChar Unicode of key.
+ @param ScanCode Scan code of key.
+
+ @return The value of EFI Scancode for the key.
+ @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key.
+
+**/
+UINT16
+ConvertToEFIScanCode (
+ IN CHAR16 KeyChar,
+ IN UINT16 ScanCode
+ );
+
+/**
+ Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
+ If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
+ should not be in system.
+
+ @param BiosKeyboardPrivate Keyboard Private Data Struture
+
+ @retval TRUE Keyboard in System.
+ @retval FALSE Keyboard not in System.
+
+**/
+BOOLEAN
+CheckKeyboardConnect (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate
+ );
+
+/**
+ Timer event handler: read a series of key stroke from 8042
+ and put them into memory key buffer.
+ It is registered as running under TPL_NOTIFY
+
+ @param Event The timer event
+ @param Context A BIOS_KEYBOARD_DEV pointer
+
+**/
+VOID
+EFIAPI
+BiosKeyboardTimerHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Reset the input device and optionaly run diagnostics
+
+ @param This Protocol instance pointer.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardResetEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existance of a keystroke via WaitForEvent () call.
+
+ @param This Protocol instance pointer.
+ @param KeyData A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
+
+ @retval EFI_SUCCESS The keystroke information was returned.
+ @retval EFI_NOT_READY There was no keystroke data availiable.
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
+ hardware errors.
+ @retval EFI_INVALID_PARAMETER KeyData is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+ );
+
+/**
+ Set certain state for the input device.
+
+ @param This Protocol instance pointer.
+ @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
+ state for the input device.
+
+ @retval EFI_SUCCESS The device state was set successfully.
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
+ not have the setting adjusted.
+ @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
+ @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardSetState (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+ );
+
+/**
+ Register a notification function for a particular keystroke for the input device.
+
+ @param This Protocol instance pointer.
+ @param KeyData A pointer to a buffer that is filled in with the keystroke
+ information data for the key that was pressed.
+ @param KeyNotificationFunction Points to the function to be called when the key
+ sequence is typed specified by KeyData.
+ @param NotifyHandle Points to the unique handle assigned to the registered notification.
+
+
+ @retval EFI_SUCCESS The notification function was registered successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardRegisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+ );
+
+/**
+ Remove a registered notification function from a particular keystroke.
+
+ @param This Protocol instance pointer.
+ @param NotificationHandle The handle of the notification function being unregistered.
+
+ @retval EFI_SUCCESS The notification function was unregistered successfully.
+ @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardUnregisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ );
+
+/**
+ Wait for a specific value to be presented in
+ Data register of Keyboard Controller by keyboard and then read it,
+ used in keyboard commands ack
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+ @param Value The value to be waited for
+ @param WaitForValueTimeOut The limit of microseconds for timeout
+
+ @retval EFI_SUCCESS The command byte is written successfully.
+ @retval EFI_TIMEOUT Timeout occurred during writing.
+
+**/
+EFI_STATUS
+KeyboardWaitForValue (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ IN UINT8 Value,
+ IN UINTN WaitForValueTimeOut
+ );
+
+/**
+ Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state.
+
+ @param BiosKeyboardPrivate Keyboard instance pointer.
+ @param Data Data byte to write.
+
+ @retval EFI_SUCCESS The data byte is written successfully.
+ @retval EFI_TIMEOUT Timeout occurred during writing.
+
+**/
+EFI_STATUS
+KeyboardWrite (
+ IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,
+ IN UINT8 Data
+ );
+
+/**
+ Free keyboard notify list.
+
+ @param ListHead The list head
+
+ @retval EFI_SUCCESS Free the notify list successfully
+ @retval EFI_INVALID_PARAMETER ListHead is invalid.
+
+**/
+EFI_STATUS
+BiosKeyboardFreeNotifyList (
+ IN OUT LIST_ENTRY *ListHead
+ );
+
+/**
+ Check if key is registered.
+
+ @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was registered.
+ @param InputData A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
+
+ @retval TRUE Key be pressed matches a registered key.
+ @retval FLASE Match failed.
+
+**/
+BOOLEAN
+IsKeyRegistered (
+ IN EFI_KEY_DATA *RegsiteredData,
+ IN EFI_KEY_DATA *InputData
+ );
+
+/**
+ Waiting on the keyboard event, if there's any key pressed by the user, signal the event
+
+ @param Event The event that be siganlled when any key has been stroked.
+ @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+
+**/
+VOID
+EFIAPI
+BiosKeyboardWaitForKeyEx (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
+
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c
new file mode 100644
index 0000000000..caeecf70a7
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.c
@@ -0,0 +1,183 @@
+/** @file
+
+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.
+
+**/
+
+#include "BiosKeyboard.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName = {
+ BiosKeyboardComponentNameGetDriverName,
+ BiosKeyboardComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosKeyboardComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosKeyboardComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosKeyboardDriverNameTable[] = {
+ {
+ "eng;en",
+ L"BIOS[INT16] Keyboard Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mBiosKeyboardDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gBiosKeyboardComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h
new file mode 100644
index 0000000000..a20061b753
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/ComponentName.h
@@ -0,0 +1,153 @@
+/** @file
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BIOS_KEYBOARD_COMPONENT_NAME_H_
+#define _BIOS_KEYBOARD_COMPONENT_NAME_H_
+
+
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosKeyboardComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosKeyboardComponentName2;
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosKeyboardComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
new file mode 100644
index 0000000000..6166ba3ec3
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
@@ -0,0 +1,68 @@
+## @file
+# Component description file for BiosKeyboard module.
+#
+# Ps2 Keyboard driver by using Legacy Bios protocol service and IsaIo protocol service.
+# This dirver uses legacy INT16 to get the key stroke status.
+#
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions
+# of the BSD License which accompanies this distribution. The
+# full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = KeyboardDxe
+ FILE_GUID = 5479662B-6AE4-49e8-A6BD-6DE4B625811F
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeBiosKeyboard
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gBiosKeyboardDriverBinding
+# COMPONENT_NAME = gBiosKeyboardComponentName
+#
+
+[Sources]
+ ComponentName.c
+ ComponentName.h
+ BiosKeyboard.c
+ BiosKeyboard.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ ReportStatusCodeLib
+ BaseMemoryLib
+ UefiLib
+ DebugLib
+ BaseLib
+
+[Protocols]
+ gEfiIsaIoProtocolGuid # PROTOCOL TO_START
+ gEfiSimpleTextInProtocolGuid # PROTOCOL BY_START
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL BY_START
+ gEfiLegacyBiosProtocolGuid # PROTOCOL TO_START
+ gEfiPs2PolicyProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c
new file mode 100644
index 0000000000..2ae8daca73
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.c
@@ -0,0 +1,3507 @@
+/** @file
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosSnp16.h"
+
+
+///
+/// EFI Driver Binding Protocol Instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding = {
+ BiosSnp16DriverBindingSupported,
+ BiosSnp16DriverBindingStart,
+ BiosSnp16DriverBindingStop,
+ 0x3,
+ NULL,
+ NULL
+};
+
+///
+/// This boolean is used to determine if we should release the cached vector during an error condition.
+///
+BOOLEAN mCachedInt1A = FALSE;
+
+//
+// Private worker functions;
+//
+
+/**
+ Start the UNDI interface.
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+ @param Ax PCI address of Undi device.
+
+ @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
+ @retval Others Status of start 16 bit UNDI ROM.
+**/
+EFI_STATUS
+Undi16SimpleNetworkStartUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ UINT16 Ax
+ );
+
+/**
+ Start the UNDI interface
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+
+ @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
+ @retval Others Status of start 16 bit UNDI ROM.
+**/
+EFI_STATUS
+Undi16SimpleNetworkStopUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
+ );
+
+/**
+ Stop the UNDI interface
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+
+ @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM.
+ @retval Others Status of stop 16 bit UNDI ROM.
+**/
+EFI_STATUS
+Undi16SimpleNetworkCleanupUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
+ );
+
+/**
+ Get runtime information for Undi network interface
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_SUCCESS Sucess operation.
+ @retval Others Fail to get runtime information for Undi network interface.
+**/
+EFI_STATUS
+Undi16SimpleNetworkGetInformation (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ );
+
+/**
+ Get NIC type
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_SUCCESS Sucess operation.
+ @retval Others Fail to get NIC type.
+**/
+EFI_STATUS
+Undi16SimpleNetworkGetNicType (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ );
+
+/**
+ Get NDIS information
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_SUCCESS Sucess operation.
+ @retval Others Fail to get NDIS information.
+**/
+EFI_STATUS
+Undi16SimpleNetworkGetNdisInfo (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ );
+
+/**
+ Signal handlers for ExitBootServices event.
+
+ Clean up any Real-mode UNDI residue from the system
+
+ @param Event ExitBootServices event
+ @param Context
+**/
+VOID
+EFIAPI
+Undi16SimpleNetworkEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Loads the undi driver.
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+
+ @retval EFI_SUCCESS - Successfully loads undi driver.
+ @retval EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
+**/
+EFI_STATUS
+Undi16SimpleNetworkLoadUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
+ );
+
+/**
+ Unload 16 bit UNDI Option ROM from memory
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+Undi16SimpleNetworkUnloadUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
+ );
+
+/**
+ Entry point for EFI drivers.
+
+ @param ImageHandle Handle that identifies the loaded image.
+ @param SystemTable System Table for this image.
+
+ @return EFI_STATUS Return status from EfiLibInstallAllDriverProtocols.
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16DriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gBiosSnp16DriverBinding,
+ ImageHandle,
+ &gBiosSnp16ComponentName,
+ &gBiosSnp16ComponentName2
+ );
+}
+
+//
+// EFI Driver Binding Protocol Functions
+//
+/**
+ Tests to see if this driver supports a given controller.
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS The driver supports given controller.
+ @retval EFI_UNSUPPORT The driver doesn't support given controller.
+ @retval Other Other errors prevent driver finishing to test
+ if the driver supports given controller.
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // See if this is a PCI Network Controller by looking at the Command register and
+ // Class Code Register
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+/**
+ Starts the Snp device controller
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS - The device was started.
+ @retval EFI_DEVICE_ERROR - The device could not be started due to a device error.
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ EFI_DEV_PATH Node;
+ UINTN Index;
+ UINTN Index2;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ UINTN Flags;
+ UINT64 Supports;
+
+ SimpleNetworkDevice = NULL;
+ PciIo = NULL;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Open the IO Abstraction(s) needed
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Check to see if there is a legacy option ROM image associated with this PCI device
+ //
+ Status = LegacyBios->CheckPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ NULL,
+ &Flags
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Post the legacy option ROM if it is available.
+ //
+ Status = LegacyBios->InstallPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ &Flags,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Allocate memory for this SimpleNetwork device instance
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_SIMPLE_NETWORK_DEV),
+ (VOID **) &SimpleNetworkDevice
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ZeroMem (SimpleNetworkDevice, sizeof (EFI_SIMPLE_NETWORK_DEV));
+
+ //
+ // Initialize the SimpleNetwork device instance
+ //
+ SimpleNetworkDevice->Signature = EFI_SIMPLE_NETWORK_DEV_SIGNATURE;
+ SimpleNetworkDevice->LegacyBios = LegacyBios;
+ SimpleNetworkDevice->BaseDevicePath = DevicePath;
+ SimpleNetworkDevice->PciIo = PciIo;
+
+ //
+ // Initialize the Nii Protocol
+ //
+ SimpleNetworkDevice->Nii.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
+ SimpleNetworkDevice->Nii.Type = EfiNetworkInterfaceUndi;
+
+ CopyMem (&SimpleNetworkDevice->Nii.StringId, "UNDI", 4);
+
+ //
+ // Load 16 bit UNDI Option ROM into Memory
+ //
+ Status = Undi16SimpleNetworkLoadUndi (SimpleNetworkDevice);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "ERROR : Could not load UNDI. Status = %r\n", Status));
+ goto Done;
+ }
+
+ SimpleNetworkDevice->UndiLoaded = TRUE;
+
+ //
+ // Call PXENV_START_UNDI - Initilizes the UNID interface for use.
+ //
+ PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+ Status = Undi16SimpleNetworkStartUndi (
+ SimpleNetworkDevice,
+ (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function))
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "ERROR : Could not StartUndi. Status = %r\n", Status));
+ goto Done;
+ }
+ //
+ // Initialize the Simple Network Protocol
+ //
+ DEBUG ((DEBUG_NET, "Initialize SimpleNetworkDevice instance\n"));
+
+ SimpleNetworkDevice->SimpleNetwork.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
+ SimpleNetworkDevice->SimpleNetwork.Start = Undi16SimpleNetworkStart;
+ SimpleNetworkDevice->SimpleNetwork.Stop = Undi16SimpleNetworkStop;
+ SimpleNetworkDevice->SimpleNetwork.Initialize = Undi16SimpleNetworkInitialize;
+ SimpleNetworkDevice->SimpleNetwork.Reset = Undi16SimpleNetworkReset;
+ SimpleNetworkDevice->SimpleNetwork.Shutdown = Undi16SimpleNetworkShutdown;
+ SimpleNetworkDevice->SimpleNetwork.ReceiveFilters = Undi16SimpleNetworkReceiveFilters;
+ SimpleNetworkDevice->SimpleNetwork.StationAddress = Undi16SimpleNetworkStationAddress;
+ SimpleNetworkDevice->SimpleNetwork.Statistics = Undi16SimpleNetworkStatistics;
+ SimpleNetworkDevice->SimpleNetwork.MCastIpToMac = Undi16SimpleNetworkMCastIpToMac;
+ SimpleNetworkDevice->SimpleNetwork.NvData = Undi16SimpleNetworkNvData;
+ SimpleNetworkDevice->SimpleNetwork.GetStatus = Undi16SimpleNetworkGetStatus;
+ SimpleNetworkDevice->SimpleNetwork.Transmit = Undi16SimpleNetworkTransmit;
+ SimpleNetworkDevice->SimpleNetwork.Receive = Undi16SimpleNetworkReceive;
+ SimpleNetworkDevice->SimpleNetwork.Mode = &(SimpleNetworkDevice->SimpleNetworkMode);
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ Undi16SimpleNetworkWaitForPacket,
+ &SimpleNetworkDevice->SimpleNetwork,
+ &SimpleNetworkDevice->SimpleNetwork.WaitForPacket
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR : Could not create event. Status = %r\n", Status));
+ goto Done;
+ }
+ //
+ // Create an event to be signalled when ExitBootServices occurs in order
+ // to clean up nicely
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ Undi16SimpleNetworkEvent,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &SimpleNetworkDevice->EfiBootEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR : Could not create event. Status = %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Create an event to be signalled when Legacy Boot occurs to clean up the IVT
+ //
+ Status = EfiCreateEventLegacyBootEx(
+ TPL_NOTIFY,
+ Undi16SimpleNetworkEvent,
+ NULL,
+ &SimpleNetworkDevice->LegacyBootEvent
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR,"ERROR : Could not create event. Status = %r\n",Status));
+ goto Done;
+ }
+
+ //
+ // Initialize the SimpleNetwork Mode Information
+ //
+ DEBUG ((DEBUG_NET, "Initialize Mode Information\n"));
+
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;
+ SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize = 14;
+ SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable = TRUE;
+ SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported = TRUE;
+ SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+ SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount = MAXNUM_MCADDR;
+
+ //
+ // Initialize the SimpleNetwork Private Information
+ //
+ DEBUG ((DEBUG_NET, "Initialize Private Information\n"));
+
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1,
+ (VOID **) &SimpleNetworkDevice->Xmit
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ 1,
+ &SimpleNetworkDevice->TxRealModeMediaHeader
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ 1,
+ &SimpleNetworkDevice->TxRealModeDataBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ 1,
+ &SimpleNetworkDevice->TxDestAddr
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ SimpleNetworkDevice->Xmit->XmitOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) & 0x000f);
+
+ SimpleNetworkDevice->Xmit->XmitSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeMediaHeader) >> 4);
+
+ SimpleNetworkDevice->Xmit->DataBlkCount = 1;
+
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDPtrType = 1;
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDRsvdByte = 0;
+
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrOffset = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) & 0x000f);
+
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDDataPtrSegment = (UINT16) (((UINT32)(UINTN) SimpleNetworkDevice->TxRealModeDataBuffer) >> 4);
+
+ SimpleNetworkDevice->TxBufferFifo.First = 0;
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;
+
+ //
+ // Start() the SimpleNetwork device
+ //
+ DEBUG ((DEBUG_NET, "Start()\n"));
+
+ Status = Undi16SimpleNetworkStart (&SimpleNetworkDevice->SimpleNetwork);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // GetInformation() the SimpleNetwork device
+ //
+ DEBUG ((DEBUG_NET, "GetInformation()\n"));
+
+ Status = Undi16SimpleNetworkGetInformation (&SimpleNetworkDevice->SimpleNetwork);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Build the device path for the child device
+ //
+ ZeroMem (&Node, sizeof (Node));
+ Node.DevPath.Type = MESSAGING_DEVICE_PATH;
+ Node.DevPath.SubType = MSG_MAC_ADDR_DP;
+ SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));
+ CopyMem (
+ &Node.MacAddr.MacAddress,
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
+ sizeof (EFI_MAC_ADDRESS)
+ );
+ SimpleNetworkDevice->DevicePath = AppendDevicePathNode (
+ SimpleNetworkDevice->BaseDevicePath,
+ &Node.DevPath
+ );
+
+ //
+ // GetNicType() the SimpleNetwork device
+ //
+ DEBUG ((DEBUG_NET, "GetNicType()\n"));
+
+ Status = Undi16SimpleNetworkGetNicType (&SimpleNetworkDevice->SimpleNetwork);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // GetNdisInfo() the SimpleNetwork device
+ //
+ DEBUG ((DEBUG_NET, "GetNdisInfo()\n"));
+
+ Status = Undi16SimpleNetworkGetNdisInfo (&SimpleNetworkDevice->SimpleNetwork);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Stop() the SimpleNetwork device
+ //
+ DEBUG ((DEBUG_NET, "Stop()\n"));
+
+ Status = SimpleNetworkDevice->SimpleNetwork.Stop (&SimpleNetworkDevice->SimpleNetwork);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Print Mode information
+ //
+ DEBUG ((DEBUG_NET, "Mode->State = %d\n", SimpleNetworkDevice->SimpleNetworkMode.State));
+ DEBUG ((DEBUG_NET, "Mode->HwAddressSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize));
+ DEBUG ((DEBUG_NET, "Mode->MacAddressChangeable = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable));
+ DEBUG ((DEBUG_NET, "Mode->MultiplTxSupported = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MultipleTxSupported));
+ DEBUG ((DEBUG_NET, "Mode->NvRamSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamSize));
+ DEBUG ((DEBUG_NET, "Mode->NvRamAccessSize = %d\n", SimpleNetworkDevice->SimpleNetworkMode.NvRamAccessSize));
+ DEBUG ((DEBUG_NET, "Mode->ReceiveFilterSetting = %d\n", SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting));
+ DEBUG ((DEBUG_NET, "Mode->IfType = %d\n", SimpleNetworkDevice->SimpleNetworkMode.IfType));
+ DEBUG ((DEBUG_NET, "Mode->MCastFilterCount = %d\n", SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount));
+ for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; Index++) {
+ DEBUG ((DEBUG_NET, " Filter[%02d] = ", Index));
+ for (Index2 = 0; Index2 < 16; Index2++) {
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index].Addr[Index2]));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+ }
+
+ DEBUG ((DEBUG_NET, "CurrentAddress = "));
+ for (Index2 = 0; Index2 < 16; Index2++) {
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress.Addr[Index2]));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ DEBUG ((DEBUG_NET, "BroadcastAddress = "));
+ for (Index2 = 0; Index2 < 16; Index2++) {
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress.Addr[Index2]));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ DEBUG ((DEBUG_NET, "PermanentAddress = "));
+ for (Index2 = 0; Index2 < 16; Index2++) {
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress.Addr[Index2]));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ //
+ // The network device was started, information collected, and stopped.
+ // Install protocol interfaces for the SimpleNetwork device.
+ //
+ DEBUG ((DEBUG_NET, "Install Protocol Interfaces on network interface\n"));
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &SimpleNetworkDevice->Handle,
+ &gEfiSimpleNetworkProtocolGuid,
+ &SimpleNetworkDevice->SimpleNetwork,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid,
+ &SimpleNetworkDevice->Nii,
+ &gEfiDevicePathProtocolGuid,
+ SimpleNetworkDevice->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Open PCI I/O from the newly created child handle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ SimpleNetworkDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ DEBUG ((DEBUG_INIT, "UNDI16 Driver : EFI_SUCCESS\n"));
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if (SimpleNetworkDevice != NULL) {
+
+ Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
+ //
+ // CLOSE + SHUTDOWN
+ //
+ Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
+ //
+ // CLEANUP
+ //
+ Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
+ //
+ // STOP
+ //
+ if (SimpleNetworkDevice->UndiLoaded) {
+ Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
+ }
+
+ if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
+ gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
+ }
+
+ if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
+ gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
+ }
+
+ if (SimpleNetworkDevice->EfiBootEvent != NULL) {
+ gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
+ }
+
+ if (SimpleNetworkDevice->Xmit != NULL) {
+ gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
+ sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
+ );
+ }
+
+ if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
+ }
+
+ if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
+ }
+
+ if (SimpleNetworkDevice->TxDestAddr != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
+ }
+
+ gBS->FreePool (SimpleNetworkDevice);
+
+ //
+ // Only restore the vector if it was cached.
+ //
+ if (mCachedInt1A) {
+ RestoreCachedVectorAddress (0x1A);
+ mCachedInt1A = FALSE;
+ }
+ }
+
+ if (PciIo != NULL) {
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ Supports,
+ NULL
+ );
+ }
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+ return Status;
+}
+
+/**
+ Stops the device by given device controller.
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param ChildHandleBuffer An array of child handles to be freed. May be NULL if
+ NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS - The device was stopped.
+ @retval EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ BOOLEAN AllChildrenStopped;
+ EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Supports;
+
+ //
+ // Complete all outstanding transactions to Controller.
+ // Don't allow any new transaction to Controller to be started.
+ //
+ if (NumberOfChildren == 0) {
+ //
+ // Close the bus driver
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ Supports,
+ NULL
+ );
+ }
+ }
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+ return Status;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiSimpleNetworkProtocolGuid,
+ (VOID **) &SimpleNetwork,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SimpleNetwork);
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ SimpleNetworkDevice->Handle,
+ &gEfiSimpleNetworkProtocolGuid,
+ &SimpleNetworkDevice->SimpleNetwork,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid,
+ &SimpleNetworkDevice->Nii,
+ &gEfiDevicePathProtocolGuid,
+ SimpleNetworkDevice->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+
+ Undi16SimpleNetworkShutdown (&SimpleNetworkDevice->SimpleNetwork);
+ //
+ // CLOSE + SHUTDOWN
+ //
+ Undi16SimpleNetworkCleanupUndi (SimpleNetworkDevice);
+ //
+ // CLEANUP
+ //
+ Undi16SimpleNetworkStopUndi (SimpleNetworkDevice);
+ //
+ // STOP
+ //
+ if (SimpleNetworkDevice->UndiLoaded) {
+ Undi16SimpleNetworkUnloadUndi (SimpleNetworkDevice);
+ }
+
+ if (SimpleNetworkDevice->SimpleNetwork.WaitForPacket != NULL) {
+ gBS->CloseEvent (SimpleNetworkDevice->SimpleNetwork.WaitForPacket);
+ }
+
+ if (SimpleNetworkDevice->LegacyBootEvent != NULL) {
+ gBS->CloseEvent (SimpleNetworkDevice->LegacyBootEvent);
+ }
+
+ if (SimpleNetworkDevice->EfiBootEvent != NULL) {
+ gBS->CloseEvent (SimpleNetworkDevice->EfiBootEvent);
+ }
+
+ if (SimpleNetworkDevice->Xmit != NULL) {
+ gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->Xmit,
+ sizeof (PXENV_UNDI_TBD_T) / EFI_PAGE_SIZE + 1
+ );
+ }
+
+ if (SimpleNetworkDevice->TxRealModeMediaHeader != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeMediaHeader, 1);
+ }
+
+ if (SimpleNetworkDevice->TxRealModeDataBuffer != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxRealModeDataBuffer, 1);
+ }
+
+ if (SimpleNetworkDevice->TxDestAddr != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->TxDestAddr, 1);
+ }
+
+ gBS->FreePool (SimpleNetworkDevice);
+ }
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// FIFO Support Functions
+//
+/**
+ Judge whether transmit FIFO is full.
+
+ @param Fifo Point to trasmit FIFO structure.
+
+ @return BOOLEAN whether transmit FIFO is full.
+**/
+BOOLEAN
+SimpleNetworkTransmitFifoFull (
+ EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
+ )
+{
+ if (((Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE) == Fifo->First) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Judge whether transmit FIFO is empty.
+
+ @param Fifo Point to trasmit FIFO structure.
+
+ @return BOOLEAN whether transmit FIFO is empty.
+**/
+BOOLEAN
+SimpleNetworkTransmitFifoEmpty (
+ EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo
+ )
+{
+ if (Fifo->Last == Fifo->First) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Add data into transmit buffer.
+
+ @param Fifo Point to trasmit FIFO structure.
+ @param Data The data point want to be added.
+
+ @retval EFI_OUT_OF_RESOURCES FIFO is full
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+SimpleNetworkTransmitFifoAdd (
+ EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
+ VOID *Data
+ )
+{
+ if (SimpleNetworkTransmitFifoFull (Fifo)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Fifo->Data[Fifo->Last] = Data;
+ Fifo->Last = (Fifo->Last + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get a data and remove it from network transmit FIFO.
+
+ @param Fifo Point to trasmit FIFO structure.
+ @param Data On return, point to the data point want to be got and removed.
+
+ @retval EFI_OUT_OF_RESOURCES network transmit buffer is empty.
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+SimpleNetworkTransmitFifoRemove (
+ EFI_SIMPLE_NETWORK_DEV_FIFO *Fifo,
+ VOID **Data
+ )
+{
+ if (SimpleNetworkTransmitFifoEmpty (Fifo)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Data = Fifo->Data[Fifo->First];
+ Fifo->First = (Fifo->First + 1) % EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get recive filter setting according to EFI mask value.
+
+ @param ReceiveFilterSetting filter setting EFI mask value.
+
+ @return UINT16 Undi filter setting value.
+**/
+UINT16
+Undi16GetPacketFilterSetting (
+ UINTN ReceiveFilterSetting
+ )
+{
+ UINT16 PktFilter;
+
+ PktFilter = 0;
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
+ PktFilter |= FLTR_DIRECTED;
+ }
+
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
+ PktFilter |= FLTR_DIRECTED;
+ }
+
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
+ PktFilter |= FLTR_BRDCST;
+ }
+
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
+ PktFilter |= FLTR_PRMSCS;
+ }
+
+ if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
+ PktFilter |= FLTR_PRMSCS;
+ //
+ // @bug : Do not know if this is right????
+ //
+ }
+ //
+ // @bug : What is FLTR_SRC_RTG?
+ //
+ return PktFilter;
+}
+
+/**
+ Get filter setting from multi cast buffer .
+
+ @param Mode Point to mode structure.
+ @param McastBuffer The multi cast buffer
+ @param HwAddressSize Size of filter value.
+
+**/
+VOID
+Undi16GetMCastFilters (
+ IN EFI_SIMPLE_NETWORK_MODE *Mode,
+ IN OUT PXENV_UNDI_MCAST_ADDR_T *McastBuffer,
+ IN UINTN HwAddressSize
+ )
+{
+ UINTN Index;
+
+ //
+ // @bug : What if Mode->MCastFilterCount > MAXNUM_MCADDR?
+ //
+ McastBuffer->MCastAddrCount = (UINT16) Mode->MCastFilterCount;
+ for (Index = 0; Index < MAXNUM_MCADDR; Index++) {
+ if (Index < McastBuffer->MCastAddrCount) {
+ CopyMem (&McastBuffer->MCastAddr[Index], &Mode->MCastFilter[Index], HwAddressSize);
+ } else {
+ ZeroMem (&McastBuffer->MCastAddr[Index], HwAddressSize);
+ }
+ }
+}
+//
+// Load 16 bit UNDI Option ROM into memory
+//
+/**
+ Loads the undi driver.
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+
+ @retval EFI_SUCCESS - Successfully loads undi driver.
+ @retval EFI_NOT_FOUND - Doesn't find undi driver or undi driver load failure.
+**/
+EFI_STATUS
+Undi16SimpleNetworkLoadUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN RomAddress;
+ PCI_EXPANSION_ROM_HEADER *PciExpansionRomHeader;
+ PCI_DATA_STRUCTURE *PciDataStructure;
+ PCI_TYPE00 Pci;
+
+ if (!mCachedInt1A) {
+ Status = CacheVectorAddress (0x1A);
+ if (!EFI_ERROR (Status)) {
+ mCachedInt1A = TRUE;
+ }
+ }
+
+ PciIo = SimpleNetworkDevice->PciIo;
+
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+
+ for (RomAddress = 0xc0000; RomAddress < 0xfffff; RomAddress += 0x800) {
+
+ PciExpansionRomHeader = (PCI_EXPANSION_ROM_HEADER *) RomAddress;
+
+ if (PciExpansionRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+ continue;
+ }
+
+ DEBUG ((DEBUG_INIT, "Option ROM found at %X\n", RomAddress));
+
+ PciDataStructure = (PCI_DATA_STRUCTURE *) (RomAddress + PciExpansionRomHeader->PcirOffset);
+
+ if (PciDataStructure->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+ continue;
+ }
+
+ DEBUG ((DEBUG_INIT, "PCI Data Structure found at %X\n", PciDataStructure));
+
+ if (PciDataStructure->VendorId != Pci.Hdr.VendorId || PciDataStructure->DeviceId != Pci.Hdr.DeviceId) {
+ continue;
+ }
+
+ DEBUG (
+ (DEBUG_INIT,
+ "PCI device with matchinng VendorId and DeviceId (%d,%d)\n",
+ (UINTN) PciDataStructure->VendorId,
+ (UINTN) PciDataStructure->DeviceId)
+ );
+
+ Status = LaunchBaseCode (SimpleNetworkDevice, RomAddress);
+
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Unload 16 bit UNDI Option ROM from memory
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+Undi16SimpleNetworkUnloadUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
+ )
+{
+ if (SimpleNetworkDevice->UndiLoaderTable != NULL) {
+ ZeroMem (SimpleNetworkDevice->UndiLoaderTable, SimpleNetworkDevice->UndiLoaderTablePages << EFI_PAGE_SHIFT);
+ gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->UndiLoaderTable,
+ SimpleNetworkDevice->UndiLoaderTablePages
+ );
+ }
+
+ if (SimpleNetworkDevice->DestinationDataSegment != NULL) {
+ ZeroMem (
+ SimpleNetworkDevice->DestinationDataSegment,
+ SimpleNetworkDevice->DestinationDataSegmentPages << EFI_PAGE_SHIFT
+ );
+ gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationDataSegment,
+ SimpleNetworkDevice->DestinationDataSegmentPages
+ );
+ }
+
+ if (SimpleNetworkDevice->DestinationStackSegment != NULL) {
+ ZeroMem (
+ SimpleNetworkDevice->DestinationStackSegment,
+ SimpleNetworkDevice->DestinationStackSegmentPages << EFI_PAGE_SHIFT
+ );
+ gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationStackSegment,
+ SimpleNetworkDevice->DestinationStackSegmentPages
+ );
+ }
+
+ if (SimpleNetworkDevice->DestinationCodeSegment != NULL) {
+ ZeroMem (
+ SimpleNetworkDevice->DestinationCodeSegment,
+ SimpleNetworkDevice->DestinationCodeSegmentPages << EFI_PAGE_SHIFT
+ );
+ gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) SimpleNetworkDevice->DestinationCodeSegment,
+ SimpleNetworkDevice->DestinationCodeSegmentPages
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Start the UNDI interface.
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+ @param Ax PCI address of Undi device.
+
+ @retval EFI_DEVICE_ERROR Fail to start 16 bit UNDI ROM.
+ @retval Others Status of start 16 bit UNDI ROM.
+**/
+EFI_STATUS
+Undi16SimpleNetworkStartUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ UINT16 Ax
+ )
+{
+ EFI_STATUS Status;
+ PXENV_START_UNDI_T Start;
+
+ //
+ // Call 16 bit UNDI ROM to start the network interface
+ //
+ //
+ // @bug : What is this state supposed to be???
+ //
+ Start.Status = INIT_PXE_STATUS;
+ Start.Ax = Ax;
+ Start.Bx = 0x0000;
+ Start.Dx = 0x0000;
+ Start.Di = 0x0000;
+ Start.Es = 0x0000;
+
+ Status = PxeStartUndi (SimpleNetworkDevice, &Start);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Start.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+
+/**
+ Stop the UNDI interface
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+
+ @retval EFI_DEVICE_ERROR Fail to stop 16 bit UNDI ROM.
+ @retval Others Status of stop 16 bit UNDI ROM.
+**/
+EFI_STATUS
+Undi16SimpleNetworkStopUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
+ )
+{
+ EFI_STATUS Status;
+ PXENV_STOP_UNDI_T Stop;
+
+ //
+ // Call 16 bit UNDI ROM to start the network interface
+ //
+ Stop.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiStop (SimpleNetworkDevice, &Stop);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Stop.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+/**
+ Cleanup Unid network interface
+
+ @param SimpleNetworkDevice A pointer to EFI_SIMPLE_NETWORK_DEV data structure.
+
+ @retval EFI_DEVICE_ERROR Fail to cleanup 16 bit UNDI ROM.
+ @retval Others Status of cleanup 16 bit UNDI ROM.
+**/
+EFI_STATUS
+Undi16SimpleNetworkCleanupUndi (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice
+ )
+{
+ EFI_STATUS Status;
+ PXENV_UNDI_CLEANUP_T Cleanup;
+
+ //
+ // Call 16 bit UNDI ROM to cleanup the network interface
+ //
+ Cleanup.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiCleanup (SimpleNetworkDevice, &Cleanup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Cleanup.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+/**
+ Get runtime information for Undi network interface
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_SUCCESS Sucess operation.
+ @retval Others Fail to get runtime information for Undi network interface.
+**/
+EFI_STATUS
+Undi16SimpleNetworkGetInformation (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ UINTN Index;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkStarted:
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Call 16 bit UNDI ROM to start the network interface
+ //
+ ZeroMem (&SimpleNetworkDevice->GetInformation, sizeof (PXENV_UNDI_GET_INFORMATION_T));
+
+ SimpleNetworkDevice->GetInformation.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiGetInformation (SimpleNetworkDevice, &SimpleNetworkDevice->GetInformation);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((DEBUG_NET, " GetInformation.Status = %d\n", SimpleNetworkDevice->GetInformation.Status));
+ DEBUG ((DEBUG_NET, " GetInformation.BaseIo = %d\n", SimpleNetworkDevice->GetInformation.BaseIo));
+ DEBUG ((DEBUG_NET, " GetInformation.IntNumber = %d\n", SimpleNetworkDevice->GetInformation.IntNumber));
+ DEBUG ((DEBUG_NET, " GetInformation.MaxTranUnit = %d\n", SimpleNetworkDevice->GetInformation.MaxTranUnit));
+ DEBUG ((DEBUG_NET, " GetInformation.HwType = %d\n", SimpleNetworkDevice->GetInformation.HwType));
+ DEBUG ((DEBUG_NET, " GetInformation.HwAddrLen = %d\n", SimpleNetworkDevice->GetInformation.HwAddrLen));
+ DEBUG ((DEBUG_NET, " GetInformation.ROMAddress = %d\n", SimpleNetworkDevice->GetInformation.ROMAddress));
+ DEBUG ((DEBUG_NET, " GetInformation.RxBufCt = %d\n", SimpleNetworkDevice->GetInformation.RxBufCt));
+ DEBUG ((DEBUG_NET, " GetInformation.TxBufCt = %d\n", SimpleNetworkDevice->GetInformation.TxBufCt));
+
+ DEBUG ((DEBUG_NET, " GetInformation.CurNodeAddr ="));
+ for (Index = 0; Index < 16; Index++) {
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.CurrentNodeAddress[Index]));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ DEBUG ((DEBUG_NET, " GetInformation.PermNodeAddr ="));
+ for (Index = 0; Index < 16; Index++) {
+ DEBUG ((DEBUG_NET, "%02x ", SimpleNetworkDevice->GetInformation.PermNodeAddress[Index]));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (SimpleNetworkDevice->GetInformation.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // The information has been retrieved. Fill in Mode data.
+ //
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize = SimpleNetworkDevice->GetInformation.HwAddrLen;
+
+ SimpleNetworkDevice->SimpleNetworkMode.MaxPacketSize = SimpleNetworkDevice->GetInformation.MaxTranUnit;
+
+ SimpleNetworkDevice->SimpleNetworkMode.IfType = (UINT8) SimpleNetworkDevice->GetInformation.HwType;
+
+ ZeroMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
+ sizeof SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
+ );
+
+ CopyMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
+ &SimpleNetworkDevice->GetInformation.CurrentNodeAddress,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ ZeroMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
+ sizeof SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress
+ );
+
+ CopyMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
+ &SimpleNetworkDevice->GetInformation.PermNodeAddress,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ //
+ // hard code broadcast address - not avail in PXE2.1
+ //
+ ZeroMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
+ sizeof SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress
+ );
+
+ SetMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.BroadcastAddress,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
+ 0xff
+ );
+
+ return Status;
+}
+
+/**
+ Get NIC type
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_SUCCESS Sucess operation.
+ @retval Others Fail to get NIC type.
+**/
+EFI_STATUS
+Undi16SimpleNetworkGetNicType (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ ZeroMem (&SimpleNetworkDevice->GetNicType, sizeof (PXENV_UNDI_GET_NIC_TYPE_T));
+
+ SimpleNetworkDevice->GetNicType.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiGetNicType (SimpleNetworkDevice, &SimpleNetworkDevice->GetNicType);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((DEBUG_NET, " GetNicType.Status = %d\n", SimpleNetworkDevice->GetNicType.Status));
+ DEBUG ((DEBUG_NET, " GetNicType.NicType = %d\n", SimpleNetworkDevice->GetNicType.NicType));
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (SimpleNetworkDevice->GetNicType.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // The information has been retrieved. Fill in Mode data.
+ //
+ return Status;
+}
+
+/**
+ Get NDIS information
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_SUCCESS Sucess operation.
+ @retval Others Fail to get NDIS information.
+**/
+EFI_STATUS
+Undi16SimpleNetworkGetNdisInfo (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ ZeroMem (&SimpleNetworkDevice->GetNdisInfo, sizeof (PXENV_UNDI_GET_NDIS_INFO_T));
+
+ SimpleNetworkDevice->GetNdisInfo.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiGetNdisInfo (SimpleNetworkDevice, &SimpleNetworkDevice->GetNdisInfo);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((DEBUG_NET, " GetNdisInfo.Status = %d\n", SimpleNetworkDevice->GetNdisInfo.Status));
+ DEBUG ((DEBUG_NET, " GetNdisInfo.IfaceType = %a\n", SimpleNetworkDevice->GetNdisInfo.IfaceType));
+ DEBUG ((DEBUG_NET, " GetNdisInfo.LinkSpeed = %d\n", SimpleNetworkDevice->GetNdisInfo.LinkSpeed));
+ DEBUG ((DEBUG_NET, " GetNdisInfo.ServiceFlags = %08x\n", SimpleNetworkDevice->GetNdisInfo.ServiceFlags));
+
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (SimpleNetworkDevice->GetNdisInfo.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // The information has been retrieved. Fill in Mode data.
+ //
+ return Status;
+}
+
+/**
+ Call Undi ROM 16bit ISR() to check interrupt cause.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param FrameLength The length of frame buffer.
+ @param FrameHeaderLength The length of frame buffer's header if has.
+ @param Frame The frame buffer to process network interrupt.
+ @param ProtType The type network transmit protocol
+ @param PktType The type of package.
+
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM's ISR, or status is invalid.
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+Undi16SimpleNetworkIsr (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ IN UINTN *FrameLength,
+ IN UINTN *FrameHeaderLength, OPTIONAL
+ IN UINT8 *Frame, OPTIONAL
+ IN UINT8 *ProtType, OPTIONAL
+ IN UINT8 *PktType OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ BOOLEAN FrameReceived;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ FrameReceived = FALSE;
+
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_NET, "Isr() IsrValid = %d\n", SimpleNetworkDevice->IsrValid));
+
+ if (!SimpleNetworkDevice->IsrValid) {
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
+ SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS;
+ SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
+
+ DEBUG ((DEBUG_NET, "Isr() START\n"));
+
+ Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // There have been no events on this UNDI interface, so return EFI_NOT_READY
+ //
+ if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_NOT_OURS) {
+ return EFI_SUCCESS;
+ }
+ //
+ // There is data to process, so call until all events processed.
+ //
+ ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
+ SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS;
+ SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
+
+ DEBUG ((DEBUG_NET, "Isr() PROCESS\n"));
+
+ Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SimpleNetworkDevice->IsrValid = TRUE;
+ }
+ //
+ // Call UNDI GET_NEXT until DONE
+ //
+ while (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE) {
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // UNDI is busy. Caller will have to call again.
+ // This should never happen with a polled mode driver.
+ //
+ if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
+ DEBUG ((DEBUG_NET, " BUSY\n"));
+ return EFI_SUCCESS;
+ }
+ //
+ // Check for invalud UNDI FuncFlag
+ //
+ if (SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE &&
+ SimpleNetworkDevice->Isr.FuncFlag != PXENV_UNDI_ISR_OUT_TRANSMIT
+ ) {
+ DEBUG ((DEBUG_NET, " Invalid SimpleNetworkDevice->Isr.FuncFlag value %d\n", SimpleNetworkDevice->Isr.FuncFlag));
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Check for Transmit Event
+ //
+ if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
+ DEBUG ((DEBUG_NET, " TRANSMIT\n"));
+ SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
+ }
+ //
+ // Check for Receive Event
+ //
+ else if (SimpleNetworkDevice->Isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
+ //
+ // note - this code will hang on a receive interrupt in a GetStatus loop
+ //
+ DEBUG ((DEBUG_NET, " RECEIVE\n"));
+ SimpleNetworkDevice->InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.BufferLength = %d\n", SimpleNetworkDevice->Isr.BufferLength));
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameLength = %d\n", SimpleNetworkDevice->Isr.FrameLength));
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.FrameHeaderLength = %d\n", SimpleNetworkDevice->Isr.FrameHeaderLength));
+ DEBUG (
+ (
+ DEBUG_NET, "SimpleNetworkDevice->Isr.Frame = %04x:%04x\n", SimpleNetworkDevice->Isr.FrameSegSel,
+ SimpleNetworkDevice->Isr.FrameOffset
+ )
+ );
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.ProtType = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
+ DEBUG ((DEBUG_NET, "SimpleNetworkDevice->Isr.PktType = 0x%02x\n", SimpleNetworkDevice->Isr.BufferLength));
+
+ if (FrameReceived) {
+ return EFI_SUCCESS;
+ }
+
+ if ((Frame == NULL) || (SimpleNetworkDevice->Isr.FrameLength > *FrameLength)) {
+ DEBUG ((DEBUG_NET, "return EFI_BUFFER_TOO_SMALL *FrameLength = %08x\n", *FrameLength));
+ *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *FrameLength = SimpleNetworkDevice->Isr.FrameLength;
+ if (FrameHeaderLength != NULL) {
+ *FrameHeaderLength = SimpleNetworkDevice->Isr.FrameHeaderLength;
+ }
+
+ if (ProtType != NULL) {
+ *ProtType = SimpleNetworkDevice->Isr.ProtType;
+ }
+
+ if (PktType != NULL) {
+ *PktType = SimpleNetworkDevice->Isr.PktType;
+ }
+
+ CopyMem (
+ Frame,
+ (VOID *)(UINTN) ((SimpleNetworkDevice->Isr.FrameSegSel << 4) + SimpleNetworkDevice->Isr.FrameOffset),
+ SimpleNetworkDevice->Isr.BufferLength
+ );
+ Frame = Frame + SimpleNetworkDevice->Isr.BufferLength;
+ if (SimpleNetworkDevice->Isr.BufferLength == SimpleNetworkDevice->Isr.FrameLength) {
+ FrameReceived = TRUE;
+ }
+ }
+ //
+ // There is data to process, so call until all events processed.
+ //
+ ZeroMem (&SimpleNetworkDevice->Isr, sizeof (PXENV_UNDI_ISR_T));
+ SimpleNetworkDevice->Isr.Status = INIT_PXE_STATUS;
+ SimpleNetworkDevice->Isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
+
+ DEBUG ((DEBUG_NET, "Isr() GET NEXT\n"));
+
+ Status = PxeUndiIsr (SimpleNetworkDevice, &SimpleNetworkDevice->Isr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ // if (SimpleNetworkDevice->Isr.Status != PXENV_STATUS_SUCCESS) {
+ // return EFI_DEVICE_ERROR;
+ // }
+ //
+ }
+
+ SimpleNetworkDevice->IsrValid = FALSE;
+ return EFI_SUCCESS;
+}
+//
+// ///////////////////////////////////////////////////////////////////////////////////////
+// Simple Network Protocol Interface Functions using 16 bit UNDI Option ROMs
+/////////////////////////////////////////////////////////////////////////////////////////
+//
+// Start()
+//
+/**
+ Call 16 bit UNDI ROM to start the network interface
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_DEVICE_ERROR Network interface has not be initialized.
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
+ @retval EFI_SUCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkStart (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_STARTUP_T Startup;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkStopped:
+ break;
+
+ case EfiSimpleNetworkStarted:
+ case EfiSimpleNetworkInitialized:
+ return EFI_ALREADY_STARTED;
+
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Call 16 bit UNDI ROM to start the network interface
+ //
+ Startup.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiStartup (SimpleNetworkDevice, &Startup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Startup.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // The UNDI interface has been started, so update the State.
+ //
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
+
+ //
+ //
+ //
+ SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = 0;
+ SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = 0;
+
+ return Status;
+}
+//
+// Stop()
+//
+/**
+ Call 16 bit UNDI ROM to stop the network interface
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_DEVICE_ERROR Network interface has not be initialized.
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
+ @retval EFI_SUCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkStop (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkStarted:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkInitialized:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStopped;
+
+ return Status;
+}
+
+//
+// Initialize()
+//
+/**
+ Initialize network interface
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param ExtraRxBufferSize The size of extra request receive buffer.
+ @param ExtraTxBufferSize The size of extra request transmit buffer.
+
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
+ @retval EFI_SUCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkInitialize (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINTN ExtraRxBufferSize OPTIONAL,
+ IN UINTN ExtraTxBufferSize OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_INITIALIZE_T Initialize;
+ PXENV_UNDI_OPEN_T Open;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkStarted:
+ break;
+
+ case EfiSimpleNetworkInitialized:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Call 16 bit UNDI ROM to start the network interface
+ //
+ Initialize.Status = INIT_PXE_STATUS;
+ Initialize.ProtocolIni = 0;
+
+ Status = PxeUndiInitialize (SimpleNetworkDevice, &Initialize);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Status = %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "Initialize.Status == %xh\n", Initialize.Status));
+
+ if (Initialize.Status == PXENV_STATUS_UNDI_MEDIATEST_FAILED) {
+ Status = EFI_NO_MEDIA;
+ }
+
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Initialize.Status != PXENV_STATUS_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiInitialize() - Initialize.Status = %04x\n", Initialize.Status));
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ Open.Status = INIT_PXE_STATUS;
+ Open.OpenFlag = 0;
+ Open.PktFilter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
+ Undi16GetMCastFilters (
+ &SimpleNetworkDevice->SimpleNetworkMode,
+ &Open.McastBuffer,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Status = %r\n", Status));
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Open.Status != PXENV_STATUS_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PxeUndiOpen() - Open.Status = %04x\n", Open.Status));
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // The UNDI interface has been initialized, so update the State.
+ //
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkInitialized;
+
+ //
+ // If initialize succeeds, then assume that media is present.
+ //
+ SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = TRUE;
+
+ //
+ // Reset the recycled transmit buffer FIFO
+ //
+ SimpleNetworkDevice->TxBufferFifo.First = 0;
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;
+ SimpleNetworkDevice->IsrValid = FALSE;
+
+ return Status;
+}
+//
+// Reset()
+//
+/**
+ Reset network interface.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param ExtendedVerification Need extended verfication.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkReset (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_RESET_T Reset;
+ UINT16 Rx_filter;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ Reset.Status = INIT_PXE_STATUS;
+
+ Rx_filter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
+
+ Undi16GetMCastFilters (
+ &SimpleNetworkDevice->SimpleNetworkMode,
+ &Reset.R_Mcast_Buf,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ Status = PxeUndiResetNic (SimpleNetworkDevice, &Reset, Rx_filter);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Reset.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Reset the recycled transmit buffer FIFO
+ //
+ SimpleNetworkDevice->TxBufferFifo.First = 0;
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;
+ SimpleNetworkDevice->IsrValid = FALSE;
+
+ return Status;
+}
+//
+// Shutdown()
+//
+/**
+ Shutdown network interface.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkShutdown (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_CLOSE_T Close;
+ PXENV_UNDI_SHUTDOWN_T Shutdown;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ SimpleNetworkDevice->IsrValid = FALSE;
+
+ //
+ // Call 16 bit UNDI ROM to start the network interface
+ //
+ Close.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiClose (SimpleNetworkDevice, &Close);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Close.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ Shutdown.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiShutdown (SimpleNetworkDevice, &Shutdown);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Shutdown.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // The UNDI interface has been initialized, so update the State.
+ //
+ SimpleNetworkDevice->SimpleNetworkMode.State = EfiSimpleNetworkStarted;
+
+ //
+ // If shutdown succeeds, then assume that media is not present.
+ //
+ SimpleNetworkDevice->SimpleNetworkMode.MediaPresent = FALSE;
+
+ //
+ // Reset the recycled transmit buffer FIFO
+ //
+ SimpleNetworkDevice->TxBufferFifo.First = 0;
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;
+
+ //
+ // A short delay. Without this an initialize immediately following
+ // a shutdown will cause some versions of UNDI-16 to stop operating.
+ //
+ gBS->Stall (250000);
+
+ return Status;
+}
+//
+// ReceiveFilters()
+//
+/**
+ Reset network interface.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param Enable Enable mask value
+ @param Disable Disable mask value
+ @param ResetMCastFilter Whether reset multi cast filter or not
+ @param MCastFilterCnt Count of mutli cast filter for different MAC address
+ @param MCastFilter Buffer for mustli cast filter for different MAC address.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkReceiveFilters (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ IN UINT32 Enable,
+ IN UINT32 Disable,
+ IN BOOLEAN ResetMCastFilter,
+ IN UINTN MCastFilterCnt OPTIONAL,
+ IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINT32 NewFilter;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_CLOSE_T Close;
+ PXENV_UNDI_OPEN_T Open;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // First deal with possible filter setting changes
+ //
+ if ((Enable == 0) && (Disable == 0) && !ResetMCastFilter) {
+ return EFI_SUCCESS;
+ }
+
+ NewFilter = (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting | Enable) &~Disable;
+
+ if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
+ if ((MCastFilterCnt == 0) || (MCastFilter == 0) || MCastFilterCnt > SimpleNetworkDevice->SimpleNetworkMode.MaxMCastFilterCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Call 16 bit UNDI ROM to close the network interface
+ //
+ Close.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiClose (SimpleNetworkDevice, &Close);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Close.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ //
+ // Reset the recycled transmit buffer FIFO
+ //
+ SimpleNetworkDevice->TxBufferFifo.First = 0;
+ SimpleNetworkDevice->TxBufferFifo.Last = 0;
+
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ ZeroMem (&Open, sizeof Open);
+
+ Open.Status = INIT_PXE_STATUS;
+ Open.PktFilter = Undi16GetPacketFilterSetting (NewFilter);
+
+ if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
+ //
+ // Copy the MAC addresses into the UNDI open parameter structure
+ //
+ Open.McastBuffer.MCastAddrCount = (UINT16) MCastFilterCnt;
+ for (Index = 0; Index < MCastFilterCnt; ++Index) {
+ CopyMem (
+ Open.McastBuffer.MCastAddr[Index],
+ &MCastFilter[Index],
+ sizeof Open.McastBuffer.MCastAddr[Index]
+ );
+ }
+ } else if (!ResetMCastFilter) {
+ for (Index = 0; Index < SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount; ++Index) {
+ CopyMem (
+ Open.McastBuffer.MCastAddr[Index],
+ &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
+ sizeof Open.McastBuffer.MCastAddr[Index]
+ );
+ }
+ }
+
+ Status = PxeUndiOpen (SimpleNetworkDevice, &Open);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (Open.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ SimpleNetworkDevice->IsrValid = FALSE;
+ SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting = NewFilter;
+
+ if ((NewFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
+ SimpleNetworkDevice->SimpleNetworkMode.MCastFilterCount = (UINT32) MCastFilterCnt;
+ for (Index = 0; Index < MCastFilterCnt; ++Index) {
+ CopyMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.MCastFilter[Index],
+ &MCastFilter[Index],
+ sizeof (EFI_MAC_ADDRESS)
+ );
+ }
+ }
+ //
+ // Read back multicast addresses.
+ //
+ return EFI_SUCCESS;
+}
+//
+// StationAddress()
+//
+/**
+ Set new MAC address.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param Reset Whether reset station MAC address to permenent address
+ @param New A pointer to New address
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkStationAddress (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ IN BOOLEAN Reset,
+ IN EFI_MAC_ADDRESS * New OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_SET_STATION_ADDR_T SetStationAddr;
+ //
+ // EFI_DEVICE_PATH_PROTOCOL *OldDevicePath;
+ //
+ PXENV_UNDI_CLOSE_T Close;
+ PXENV_UNDI_OPEN_T Open;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ SetStationAddr.Status = INIT_PXE_STATUS;
+
+ if (Reset) {
+ //
+ // If we are reseting the Station Address to the permanent address, and the
+ // Station Address is not programmable, then just return EFI_SUCCESS.
+ //
+ if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
+ return EFI_SUCCESS;
+ }
+ //
+ // If the address is already the permanent address, then just return success.
+ //
+ if (CompareMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
+ &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ ) == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Copy the adapters permanent address to the new station address
+ //
+ CopyMem (
+ &SetStationAddr.StationAddress,
+ &SimpleNetworkDevice->SimpleNetworkMode.PermanentAddress,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+ } else {
+ //
+ // If we are setting the Station Address, and the
+ // Station Address is not programmable, return invalid parameter.
+ //
+ if (!SimpleNetworkDevice->SimpleNetworkMode.MacAddressChangeable) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // If the address is already the new address, then just return success.
+ //
+ if (CompareMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
+ New,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ ) == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Copy New to the new station address
+ //
+ CopyMem (
+ &SetStationAddr.StationAddress,
+ New,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ }
+ //
+ // Call 16 bit UNDI ROM to stop the network interface
+ //
+ Close.Status = INIT_PXE_STATUS;
+
+ PxeUndiClose (SimpleNetworkDevice, &Close);
+
+ //
+ // Call 16-bit UNDI ROM to set the station address
+ //
+ SetStationAddr.Status = PXENV_STATUS_SUCCESS;
+
+ Status = PxeUndiSetStationAddr (SimpleNetworkDevice, &SetStationAddr);
+
+ //
+ // Call 16-bit UNDI ROM to start the network interface
+ //
+ Open.Status = PXENV_STATUS_SUCCESS;
+ Open.OpenFlag = 0;
+ Open.PktFilter = Undi16GetPacketFilterSetting (SimpleNetworkDevice->SimpleNetworkMode.ReceiveFilterSetting);
+ Undi16GetMCastFilters (
+ &SimpleNetworkDevice->SimpleNetworkMode,
+ &Open.McastBuffer,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ PxeUndiOpen (SimpleNetworkDevice, &Open);
+
+ //
+ // Check status from station address change
+ //
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (SetStationAddr.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ CopyMem (
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress,
+ &SetStationAddr.StationAddress,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+#if 0 /* The device path is based on the permanent address not the current address. */
+ //
+ // The station address was changed, so update the device path with the new MAC address.
+ //
+ OldDevicePath = SimpleNetworkDevice->DevicePath;
+ SimpleNetworkDevice->DevicePath = DuplicateDevicePath (SimpleNetworkDevice->BaseDevicePath);
+ SimpleNetworkAppendMacAddressDevicePath (
+ &SimpleNetworkDevice->DevicePath,
+ &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress
+ );
+
+ Status = LibReinstallProtocolInterfaces (
+ SimpleNetworkDevice->Handle,
+ &DevicePathProtocol,
+ OldDevicePath,
+ SimpleNetworkDevice->DevicePath,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to reinstall the DevicePath protocol for the Simple Network Device\n"));
+ DEBUG ((DEBUG_ERROR, " Status = %r\n", Status));
+ }
+
+ FreePool (OldDevicePath);
+#endif /* 0 */
+
+ return Status;
+}
+//
+// Statistics()
+//
+/**
+ Resets or collects the statistics on a network interface.
+
+ @param This Protocol instance pointer.
+ @param Reset Set to TRUE to reset the statistics for the network interface.
+ @param StatisticsSize On input the size, in bytes, of StatisticsTable. On
+ output the size, in bytes, of the resulting table of
+ statistics.
+ @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
+ contains the statistics.
+
+ @retval EFI_SUCCESS The statistics were collected from the network interface.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
+ size needed to hold the statistics is returned in
+ StatisticsSize.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkStatistics (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ IN BOOLEAN Reset,
+ IN OUT UINTN *StatisticsSize OPTIONAL,
+ OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_CLEAR_STATISTICS_T ClearStatistics;
+ PXENV_UNDI_GET_STATISTICS_T GetStatistics;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((StatisticsSize != NULL) && (*StatisticsSize != 0) && (StatisticsTable == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If Reset is TRUE, then clear all the statistics.
+ //
+ if (Reset) {
+
+ DEBUG ((DEBUG_NET, " RESET Statistics\n"));
+
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ ClearStatistics.Status = INIT_PXE_STATUS;
+
+ Status = PxeUndiClearStatistics (SimpleNetworkDevice, &ClearStatistics);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (ClearStatistics.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_NET, " RESET Statistics Complete"));
+ }
+
+ if (StatisticsSize != NULL) {
+ EFI_NETWORK_STATISTICS LocalStatisticsTable;
+
+ DEBUG ((DEBUG_NET, " GET Statistics\n"));
+
+ //
+ // If the size if valid, then see if the table is valid
+ //
+ if (StatisticsTable == NULL) {
+ DEBUG ((DEBUG_NET, " StatisticsTable is NULL\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ GetStatistics.Status = INIT_PXE_STATUS;
+ GetStatistics.XmtGoodFrames = 0;
+ GetStatistics.RcvGoodFrames = 0;
+ GetStatistics.RcvCRCErrors = 0;
+ GetStatistics.RcvResourceErrors = 0;
+
+ Status = PxeUndiGetStatistics (SimpleNetworkDevice, &GetStatistics);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (GetStatistics.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Fill in the Statistics Table with the collected values.
+ //
+ SetMem (&LocalStatisticsTable, sizeof LocalStatisticsTable, 0xff);
+
+ LocalStatisticsTable.TxGoodFrames = GetStatistics.XmtGoodFrames;
+ LocalStatisticsTable.RxGoodFrames = GetStatistics.RcvGoodFrames;
+ LocalStatisticsTable.RxCrcErrorFrames = GetStatistics.RcvCRCErrors;
+ LocalStatisticsTable.RxDroppedFrames = GetStatistics.RcvResourceErrors;
+
+ CopyMem (StatisticsTable, &LocalStatisticsTable, *StatisticsSize);
+
+ DEBUG (
+ (DEBUG_NET,
+ " Statistics Collected : Size=%d Buf=%08x\n",
+ *StatisticsSize,
+ StatisticsTable)
+ );
+
+ DEBUG ((DEBUG_NET, " GET Statistics Complete"));
+
+ if (*StatisticsSize < sizeof LocalStatisticsTable) {
+ DEBUG ((DEBUG_NET, " BUFFER TOO SMALL\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *StatisticsSize = sizeof LocalStatisticsTable;
+
+ return Status;
+
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// MCastIpToMac()
+//
+/**
+ Translate IP address to MAC address.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param IPv6 IPv6 or IPv4
+ @param IP A pointer to given Ip address.
+ @param MAC On return, translated MAC address.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_INVALID_PARAMETER Invalid IP address.
+ @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address.
+ @retval EFI_UNSUPPORTED Do not support IPv6
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkMCastIpToMac (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN IPv6,
+ IN EFI_IP_ADDRESS *IP,
+ OUT EFI_MAC_ADDRESS *MAC
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_GET_MCAST_ADDR_T GetMcastAddr;
+
+ if (This == NULL || IP == NULL || MAC == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // 16 bit UNDI Option ROMS do not support IPv6. Check for IPv6 usage.
+ //
+ if (IPv6) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Call 16 bit UNDI ROM to open the network interface
+ //
+ GetMcastAddr.Status = INIT_PXE_STATUS;
+ CopyMem (&GetMcastAddr.InetAddr, IP, 4);
+
+ Status = PxeUndiGetMcastAddr (SimpleNetworkDevice, &GetMcastAddr);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ if (GetMcastAddr.Status != PXENV_STATUS_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Copy the MAC address from the returned data structure.
+ //
+ CopyMem (
+ MAC,
+ &GetMcastAddr.MediaAddr,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ return Status;
+}
+//
+// NvData()
+//
+/**
+ Performs read and write operations on the NVRAM device attached to a
+ network interface.
+
+ @param This The protocol instance pointer.
+ @param ReadWrite TRUE for read operations, FALSE for write operations.
+ @param Offset Byte offset in the NVRAM device at which to start the read or
+ write operation. This must be a multiple of NvRamAccessSize and
+ less than NvRamSize.
+ @param BufferSize The number of bytes to read or write from the NVRAM device.
+ This must also be a multiple of NvramAccessSize.
+ @param Buffer A pointer to the data buffer.
+
+ @retval EFI_SUCCESS The NVRAM access was performed.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkNvData (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN ReadWrite,
+ IN UINTN Offset,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+//
+// GetStatus()
+//
+/**
+ Reads the current interrupt status and recycled transmit buffer status from
+ a network interface.
+
+ @param This The protocol instance pointer.
+ @param InterruptStatus A pointer to the bit mask of the currently active interrupts
+ If this is NULL, the interrupt status will not be read from
+ the device. If this is not NULL, the interrupt status will
+ be read from the device. When the interrupt status is read,
+ it will also be cleared. Clearing the transmit interrupt
+ does not empty the recycled transmit buffer array.
+ @param TxBuf Recycled transmit buffer address. The network interface will
+ not transmit if its internal recycled transmit buffer array
+ is full. Reading the transmit buffer does not clear the
+ transmit interrupt. If this is NULL, then the transmit buffer
+ status will not be read. If there are no transmit buffers to
+ recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
+
+ @retval EFI_SUCCESS The status of the network interface was retrieved.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkGetStatus (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ OUT UINT32 *InterruptStatus OPTIONAL,
+ OUT VOID **TxBuf OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ UINTN FrameLength;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (InterruptStatus == NULL && TxBuf == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FrameLength = 0;
+ Status = Undi16SimpleNetworkIsr (This, &FrameLength, NULL, NULL, NULL, NULL);
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // See if the caller wants interrupt info.
+ //
+ if (InterruptStatus != NULL) {
+ *InterruptStatus = SimpleNetworkDevice->InterruptStatus;
+ SimpleNetworkDevice->InterruptStatus = 0;
+ }
+ //
+ // See if the caller wants transmit buffer status info.
+ //
+ if (TxBuf != NULL) {
+ *TxBuf = 0;
+ SimpleNetworkTransmitFifoRemove (&(SimpleNetworkDevice->TxBufferFifo), TxBuf);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Places a packet in the transmit queue of a network interface.
+
+ @param This The protocol instance pointer.
+ @param HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then it
+ must be equal to This->Mode->MediaHeaderSize and the DestAddr
+ and Protocol parameters must not be NULL.
+ @param BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param Buffer A pointer to the packet (media header followed by data) to be
+ transmitted. This parameter cannot be NULL. If HeaderSize is zero,
+ then the media header in Buffer must already be filled in by the
+ caller. If HeaderSize is non-zero, then the media header will be
+ filled in by the Transmit() function.
+ @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter
+ is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
+ This->Mode->CurrentAddress is used for the source HW MAC address.
+ @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this
+ parameter is ignored.
+ @param Protocol The type of header to build. If HeaderSize is zero, then this
+ parameter is ignored. See RFC 1700, section "Ether Types", for
+ examples.
+
+ @retval EFI_SUCCESS The packet was placed on the transmit queue.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkTransmit (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINTN HeaderSize,
+ IN UINTN BufferSize,
+ IN VOID *Buffer,
+ IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
+ IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,
+ IN UINT16 *Protocol OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ PXENV_UNDI_TRANSMIT_T XmitInfo;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize < SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (HeaderSize != 0) {
+ if (HeaderSize != SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddr == NULL || Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddr != NULL) {
+ CopyMem (
+ Buffer,
+ DestAddr,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+ }
+
+ if (SrcAddr == NULL) {
+ SrcAddr = &SimpleNetworkDevice->SimpleNetworkMode.CurrentAddress;
+ }
+
+ CopyMem (
+ (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize,
+ SrcAddr,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ if (Protocol != NULL) {
+ *(UINT16 *) ((UINT8 *) Buffer + 2 * SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize) = (UINT16) (((*Protocol & 0xFF) << 8) | ((*Protocol >> 8) & 0xFF));
+ }
+ }
+ //
+ // See if the recycled transmit buffer FIFO is full.
+ // If it is full, then we can not transmit until the caller calls GetStatus() to pull
+ // off recycled transmit buffers.
+ //
+ if (SimpleNetworkTransmitFifoFull (&(SimpleNetworkDevice->TxBufferFifo))) {
+ return EFI_NOT_READY;
+ }
+ //
+ // Output debug trace message.
+ //
+ DEBUG ((DEBUG_NET, "Undi16SimpleNetworkTransmit\n\r "));
+
+ //
+ // Initialize UNDI WRITE parameter structure.
+ //
+ XmitInfo.Status = INIT_PXE_STATUS;
+ XmitInfo.Protocol = P_UNKNOWN;
+ XmitInfo.XmitFlag = XMT_DESTADDR;
+ XmitInfo.DestAddrOffset = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr & 0x000f);
+ XmitInfo.DestAddrSegment = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->TxDestAddr >> 4);
+ XmitInfo.TBDOffset = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit & 0x000f);
+ XmitInfo.TBDSegment = (UINT16) ((UINT32)(UINTN) SimpleNetworkDevice->Xmit >> 4);
+ XmitInfo.Reserved[0] = 0;
+ XmitInfo.Reserved[1] = 0;
+
+ CopyMem (
+ SimpleNetworkDevice->TxDestAddr,
+ Buffer,
+ SimpleNetworkDevice->SimpleNetworkMode.HwAddressSize
+ );
+
+ CopyMem (
+ SimpleNetworkDevice->TxRealModeMediaHeader,
+ Buffer,
+ SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize
+ );
+
+ SimpleNetworkDevice->Xmit->ImmedLength = (UINT16) SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize;
+
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen = (UINT16) (BufferSize - SimpleNetworkDevice->Xmit->ImmedLength);
+
+ CopyMem (
+ SimpleNetworkDevice->TxRealModeDataBuffer,
+ (UINT8 *) Buffer + SimpleNetworkDevice->SimpleNetworkMode.MediaHeaderSize,
+ SimpleNetworkDevice->Xmit->DataBlock[0].TDDataLen
+ );
+
+ //
+ // Make API call to UNDI TRANSMIT
+ //
+ XmitInfo.Status = 0;
+
+ Status = PxeUndiTransmit (SimpleNetworkDevice, &XmitInfo);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check the status code from the 16 bit UNDI ROM
+ //
+ switch (XmitInfo.Status) {
+ case PXENV_STATUS_OUT_OF_RESOURCES:
+ return EFI_NOT_READY;
+
+ case PXENV_STATUS_SUCCESS:
+ break;
+
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Add address of Buffer to the recycled transmit buffer FIFO
+ //
+ SimpleNetworkTransmitFifoAdd (&(SimpleNetworkDevice->TxBufferFifo), Buffer);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Receives a packet from a network interface.
+
+ @param This The protocol instance pointer.
+ @param HeaderSize The size, in bytes, of the media header received on the network
+ interface. If this parameter is NULL, then the media header size
+ will not be returned.
+ @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
+ bytes, of the packet that was received on the network interface.
+ @param Buffer A pointer to the data buffer to receive both the media header and
+ the data.
+ @param SrcAddr The source HW MAC address. If this parameter is NULL, the
+ HW MAC source address will not be extracted from the media
+ header.
+ @param DestAddr The destination HW MAC address. If this parameter is NULL,
+ the HW MAC destination address will not be extracted from the
+ media header.
+ @param Protocol The media header type. If this parameter is NULL, then the
+ protocol will not be extracted from the media header. See
+ RFC 1700 section "Ether Types" for examples.
+
+ @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has
+ been updated to the number of bytes received.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit
+ request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkReceive (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ OUT UINTN *HeaderSize OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer,
+ OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
+ OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,
+ OUT UINT16 *Protocol OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ UINTN MediaAddrSize;
+ UINT8 ProtType;
+
+ if (This == NULL || BufferSize == NULL || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = Undi16SimpleNetworkIsr (
+ This,
+ BufferSize,
+ HeaderSize,
+ Buffer,
+ &ProtType,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) == 0) {
+ return EFI_NOT_READY;
+
+ }
+
+ SimpleNetworkDevice->InterruptStatus &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+
+ MediaAddrSize = This->Mode->HwAddressSize;
+
+ if (SrcAddr != NULL) {
+ CopyMem (SrcAddr, (UINT8 *) Buffer + MediaAddrSize, MediaAddrSize);
+ }
+
+ if (DestAddr != NULL) {
+ CopyMem (DestAddr, Buffer, MediaAddrSize);
+ }
+
+ if (Protocol != NULL) {
+ *((UINT8 *) Protocol) = *((UINT8 *) Buffer + (2 * MediaAddrSize) + 1);
+ *((UINT8 *) Protocol + 1) = *((UINT8 *) Buffer + (2 * MediaAddrSize));
+ }
+
+ DEBUG ((DEBUG_NET, "Packet Received: BufferSize=%d HeaderSize = %d\n", *BufferSize, *HeaderSize));
+
+ return Status;
+
+}
+//
+// WaitForPacket()
+//
+/**
+ wait for a packet to be received.
+
+ @param Event Event used with WaitForEvent() to wait for a packet to be received.
+ @param Context Event Context
+
+**/
+VOID
+EFIAPI
+Undi16SimpleNetworkWaitForPacket (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // Someone is waiting on the receive packet event, if there's
+ // a packet pending, signal the event
+ //
+ if (!EFI_ERROR (Undi16SimpleNetworkCheckForPacket (Context))) {
+ gBS->SignalEvent (Event);
+ }
+}
+//
+// CheckForPacket()
+//
+/**
+ Check whether packet is ready for receive.
+
+ @param This The protocol instance pointer.
+
+ @retval EFI_SUCCESS Receive data is ready.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit
+ request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+**/
+EFI_STATUS
+Undi16SimpleNetworkCheckForPacket (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice;
+ UINTN FrameLength;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ SimpleNetworkDevice = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
+
+ if (SimpleNetworkDevice == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Verify that the current state of the adapter is valid for this call.
+ //
+ switch (SimpleNetworkDevice->SimpleNetworkMode.State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return EFI_NOT_STARTED;
+
+ case EfiSimpleNetworkStarted:
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ FrameLength = 0;
+ Status = Undi16SimpleNetworkIsr (
+ This,
+ &FrameLength,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return ((SimpleNetworkDevice->InterruptStatus & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT) != 0) ? EFI_SUCCESS : EFI_NOT_READY;
+}
+
+/**
+ Signal handlers for ExitBootServices event.
+
+ Clean up any Real-mode UNDI residue from the system
+
+ @param Event ExitBootServices event
+ @param Context
+**/
+VOID
+EFIAPI
+Undi16SimpleNetworkEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // NOTE: This is not the only way to effect this cleanup. The prescribed mechanism
+ // would be to perform an UNDI STOP command. This strategam has been attempted
+ // but results in problems making some of the EFI core services from TPL_CALLBACK.
+ // This issue needs to be resolved, but the other alternative has been to perform
+ // the unchain logic explicitly, as done below.
+ //
+ RestoreCachedVectorAddress (0x1A);
+}
+
+/**
+ Allocate buffer below 1M for real mode.
+
+ @param NumPages The number pages want to be allocated.
+ @param Buffer On return, allocated buffer.
+
+ @return Status of allocating pages.
+**/
+EFI_STATUS
+BiosSnp16AllocatePagesBelowOneMb (
+ UINTN NumPages,
+ VOID **Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+
+ PhysicalAddress = 0x000fffff;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiRuntimeServicesData,
+ NumPages,
+ &PhysicalAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *Buffer = (VOID *) (UINTN) PhysicalAddress;
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h
new file mode 100644
index 0000000000..b29059f685
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/BiosSnp16.h
@@ -0,0 +1,1655 @@
+/** @file
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BIOS_SNP_16_H_
+#define _BIOS_SNP_16_H_
+
+#include <Uefi.h>
+
+#include <Protocol/LegacyBios.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/NetworkInterfaceIdentifier.h>
+#include <Protocol/DevicePath.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/EventGroup.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include "Pxe.h"
+
+//
+// BIOS Simple Network Protocol Device Structure
+//
+#define EFI_SIMPLE_NETWORK_DEV_SIGNATURE SIGNATURE_32 ('s', 'n', '1', '6')
+
+#define INIT_PXE_STATUS 0xabcd
+
+#define EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE 64
+
+typedef struct {
+ UINT32 First;
+ UINT32 Last;
+ VOID * Data[EFI_SIMPLE_NETWORK_MAX_TX_FIFO_SIZE];
+} EFI_SIMPLE_NETWORK_DEV_FIFO;
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork;
+ EFI_SIMPLE_NETWORK_MODE SimpleNetworkMode;
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL Nii;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+
+ //
+ // Local Data for Simple Network Protocol interface goes here
+ //
+ BOOLEAN UndiLoaded;
+ EFI_EVENT EfiBootEvent;
+ EFI_EVENT LegacyBootEvent;
+ UINT16 PxeEntrySegment;
+ UINT16 PxeEntryOffset;
+ EFI_SIMPLE_NETWORK_DEV_FIFO TxBufferFifo;
+ EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath;
+ PXE_T *Pxe; ///< Pointer to !PXE structure
+ PXENV_UNDI_GET_INFORMATION_T GetInformation; ///< Data from GET INFORMATION
+ PXENV_UNDI_GET_NIC_TYPE_T GetNicType; ///< Data from GET NIC TYPE
+ PXENV_UNDI_GET_NDIS_INFO_T GetNdisInfo; ///< Data from GET NDIS INFO
+ BOOLEAN IsrValid; ///< TRUE if Isr contains valid data
+ PXENV_UNDI_ISR_T Isr; ///< Data from ISR
+ PXENV_UNDI_TBD_T *Xmit; //
+ VOID *TxRealModeMediaHeader; ///< < 1 MB Size = 0x100
+ VOID *TxRealModeDataBuffer; ///< < 1 MB Size = GetInformation.MaxTranUnit
+ VOID *TxDestAddr; ///< < 1 MB Size = 16
+ UINT8 InterruptStatus; ///< returned/cleared by GetStatus, set in ISR
+ UINTN UndiLoaderTablePages;
+ UINTN DestinationDataSegmentPages;
+ UINTN DestinationStackSegmentPages;
+ UINTN DestinationCodeSegmentPages;
+ VOID *UndiLoaderTable;
+ VOID *DestinationDataSegment;
+ VOID *DestinationStackSegment;
+ VOID *DestinationCodeSegment;
+} EFI_SIMPLE_NETWORK_DEV;
+
+#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) \
+ CR (a, \
+ EFI_SIMPLE_NETWORK_DEV, \
+ SimpleNetwork, \
+ EFI_SIMPLE_NETWORK_DEV_SIGNATURE \
+ )
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosSnp16DriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2;
+
+
+//
+// Driver Binding Protocol functions
+//
+/**
+ Tests to see if this driver supports a given controller.
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS The driver supports given controller.
+ @retval EFI_UNSUPPORT The driver doesn't support given controller.
+ @retval Other Other errors prevent driver finishing to test
+ if the driver supports given controller.
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ Starts the Snp device controller
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS - The device was started.
+ @retval EFI_DEVICE_ERROR - The device could not be started due to a device error.
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ Stops the device by given device controller.
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The handle of the controller to test.
+ @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param ChildHandleBuffer An array of child handles to be freed. May be NULL if
+ NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS - The device was stopped.
+ @retval EFI_DEVICE_ERROR - The device could not be stopped due to a device error.
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+;
+
+//
+// Simple Network Protocol functions
+//
+/**
+ Call 16 bit UNDI ROM to start the network interface
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_DEVICE_ERROR Network interface has not be initialized.
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
+ @retval EFI_SUCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkStart (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+;
+
+/**
+ Call 16 bit UNDI ROM to stop the network interface
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_DEVICE_ERROR Network interface has not be initialized.
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
+ @retval EFI_SUCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkStop (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+;
+
+/**
+ Initialize network interface
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param ExtraRxBufferSize The size of extra request receive buffer.
+ @param ExtraTxBufferSize The size of extra request transmit buffer.
+
+ @retval EFI_DEVICE_ERROR Fail to execute 16 bit ROM call.
+ @retval EFI_SUCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkInitialize (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINTN ExtraRxBufferSize OPTIONAL,
+ IN UINTN ExtraTxBufferSize OPTIONAL
+ )
+;
+
+/**
+ Reset network interface.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param ExtendedVerification Need extended verfication.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkReset (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+;
+
+/**
+ Shutdown network interface.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkShutdown (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+;
+
+/**
+ Reset network interface.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param Enable Enable mask value
+ @param Disable Disable mask value
+ @param ResetMCastFilter Whether reset multi cast filter or not
+ @param MCastFilterCnt Count of mutli cast filter for different MAC address
+ @param MCastFilter Buffer for mustli cast filter for different MAC address.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkReceiveFilters (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ IN UINT32 Enable,
+ IN UINT32 Disable,
+ IN BOOLEAN ResetMCastFilter,
+ IN UINTN MCastFilterCnt OPTIONAL,
+ IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL
+ )
+;
+
+/**
+ Set new MAC address.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param Reset Whether reset station MAC address to permenent address
+ @param New A pointer to New address
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkStationAddress (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ IN BOOLEAN Reset,
+ IN EFI_MAC_ADDRESS * New OPTIONAL
+ )
+;
+
+/**
+ Collect statistics.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param Reset Whether cleanup old statistics data.
+ @param StatisticsSize The buffer of statistics table.
+ @param StatisticsTable A pointer to statistics buffer.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkStatistics (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ IN BOOLEAN Reset,
+ IN OUT UINTN *StatisticsSize OPTIONAL,
+ OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL
+ )
+;
+
+/**
+ Translate IP address to MAC address.
+
+ @param This A pointer to EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @param IPv6 IPv6 or IPv4
+ @param IP A pointer to given Ip address.
+ @param MAC On return, translated MAC address.
+
+ @retval EFI_INVALID_PARAMETER Invalid This paramter.
+ @retval EFI_INVALID_PARAMETER Invalid IP address.
+ @retval EFI_INVALID_PARAMETER Invalid return buffer for holding MAC address.
+ @retval EFI_UNSUPPORTED Do not support IPv6
+ @retval EFI_DEVICE_ERROR Network device has not been initialized.
+ @retval EFI_NOT_STARTED Network device has been stopped.
+ @retval EFI_DEVICE_ERROR Invalid status for network device
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkMCastIpToMac (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN IPv6,
+ IN EFI_IP_ADDRESS *IP,
+ OUT EFI_MAC_ADDRESS *MAC
+ )
+;
+
+/**
+ Performs read and write operations on the NVRAM device attached to a
+ network interface.
+
+ @param This The protocol instance pointer.
+ @param ReadWrite TRUE for read operations, FALSE for write operations.
+ @param Offset Byte offset in the NVRAM device at which to start the read or
+ write operation. This must be a multiple of NvRamAccessSize and
+ less than NvRamSize.
+ @param BufferSize The number of bytes to read or write from the NVRAM device.
+ This must also be a multiple of NvramAccessSize.
+ @param Buffer A pointer to the data buffer.
+
+ @retval EFI_SUCCESS The NVRAM access was performed.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkNvData (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN UINTN Offset,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer
+ )
+;
+
+/**
+ Reads the current interrupt status and recycled transmit buffer status from
+ a network interface.
+
+ @param This The protocol instance pointer.
+ @param InterruptStatus A pointer to the bit mask of the currently active interrupts
+ If this is NULL, the interrupt status will not be read from
+ the device. If this is not NULL, the interrupt status will
+ be read from the device. When the interrupt status is read,
+ it will also be cleared. Clearing the transmit interrupt
+ does not empty the recycled transmit buffer array.
+ @param TxBuf Recycled transmit buffer address. The network interface will
+ not transmit if its internal recycled transmit buffer array
+ is full. Reading the transmit buffer does not clear the
+ transmit interrupt. If this is NULL, then the transmit buffer
+ status will not be read. If there are no transmit buffers to
+ recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
+
+ @retval EFI_SUCCESS The status of the network interface was retrieved.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkGetStatus (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * This,
+ OUT UINT32 *InterruptStatus OPTIONAL,
+ OUT VOID **TxBuf OPTIONAL
+ )
+;
+
+/**
+ Places a packet in the transmit queue of a network interface.
+
+ @param This The protocol instance pointer.
+ @param HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then it
+ must be equal to This->Mode->MediaHeaderSize and the DestAddr
+ and Protocol parameters must not be NULL.
+ @param BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param Buffer A pointer to the packet (media header followed by data) to be
+ transmitted. This parameter cannot be NULL. If HeaderSize is zero,
+ then the media header in Buffer must already be filled in by the
+ caller. If HeaderSize is non-zero, then the media header will be
+ filled in by the Transmit() function.
+ @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter
+ is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
+ This->Mode->CurrentAddress is used for the source HW MAC address.
+ @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this
+ parameter is ignored.
+ @param Protocol The type of header to build. If HeaderSize is zero, then this
+ parameter is ignored. See RFC 1700, section "Ether Types", for
+ examples.
+
+ @retval EFI_SUCCESS The packet was placed on the transmit queue.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkTransmit (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINTN HeaderSize,
+ IN UINTN BufferSize,
+ IN VOID *Buffer,
+ IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
+ IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,
+ IN UINT16 *Protocol OPTIONAL
+ )
+;
+
+/**
+ Receives a packet from a network interface.
+
+ @param This The protocol instance pointer.
+ @param HeaderSize The size, in bytes, of the media header received on the network
+ interface. If this parameter is NULL, then the media header size
+ will not be returned.
+ @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
+ bytes, of the packet that was received on the network interface.
+ @param Buffer A pointer to the data buffer to receive both the media header and
+ the data.
+ @param SrcAddr The source HW MAC address. If this parameter is NULL, the
+ HW MAC source address will not be extracted from the media
+ header.
+ @param DestAddr The destination HW MAC address. If this parameter is NULL,
+ the HW MAC destination address will not be extracted from the
+ media header.
+ @param Protocol The media header type. If this parameter is NULL, then the
+ protocol will not be extracted from the media header. See
+ RFC 1700 section "Ether Types" for examples.
+
+ @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has
+ been updated to the number of bytes received.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit
+ request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+Undi16SimpleNetworkReceive (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ OUT UINTN *HeaderSize OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer,
+ OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
+ OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,
+ OUT UINT16 *Protocol OPTIONAL
+ )
+;
+
+/**
+ wait for a packet to be received.
+
+ @param Event Event used with WaitForEvent() to wait for a packet to be received.
+ @param Context Event Context
+
+**/
+VOID
+EFIAPI
+Undi16SimpleNetworkWaitForPacket (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+;
+
+/**
+ Check whether packet is ready for receive.
+
+ @param This The protocol instance pointer.
+
+ @retval EFI_SUCCESS Receive data is ready.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit
+ request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+**/
+EFI_STATUS
+Undi16SimpleNetworkCheckForPacket (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+;
+
+/**
+ Cache Interrupt verctor address converted from IVT number.
+
+ @param VectorNumber IVT number
+
+ @retval EFI_SUCCESS Success to operation.
+**/
+EFI_STATUS
+CacheVectorAddress (
+ UINT8 VectorNumber
+ )
+;
+
+/**
+ Get interrupt vector address according to IVT number.
+
+ @param VectorNumber Given IVT number
+
+ @return cached interrupt vector address.
+**/
+EFI_STATUS
+RestoreCachedVectorAddress (
+ UINT8 VectorNumber
+ )
+;
+
+/**
+ If available, launch the BaseCode from a NIC option ROM.
+ This should install the !PXE and PXENV+ structures in memory for
+ subsequent use.
+
+
+ @param SimpleNetworkDevice Simple network device instance
+ @param RomAddress The ROM base address for NIC rom.
+
+ @retval EFI_NOT_FOUND The check sum does not match
+ @retval EFI_NOT_FOUND Rom ID offset is wrong
+ @retval EFI_NOT_FOUND No Rom ID structure is found
+**/
+EFI_STATUS
+LaunchBaseCode (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ UINTN RomAddress
+ )
+;
+
+/**
+ PXE
+ START UNDI
+ Op-Code: PXENV_START_UNDI (0000h)
+ Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is
+ responsible for saving the information it needs to communicate with the hardware.
+ This service is also responsible for hooking the Int 1Ah service routine
+ Note: This API service must be called only once during UNDI Option ROM boot.
+ The UNDI driver is responsible for saving this information and using it every time
+ PXENV_UNDI_STARTUP is called.
+ Service cannot be used in protected mode.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 AX;
+ UINT16 BX;
+ UINT16 DX;
+ UINT16 DI;
+ UINT16 ES;
+ } PXENV_START_UNDI_T;
+ Set before calling API service
+ AX, BX, DX, DI, ES: BIOS initialization parameter registers. These
+ fields should contain the same information passed to the option ROM
+ initialization routine by the Host System BIOS. Information about the
+ contents of these registers can be found in the [PnP], [PCI] and
+ [BBS] specifications.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeStartUndi (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_START_UNDI_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI STARTUP
+ Op-Code: PXENV_UNDI_STARTUP (0001h)
+ Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the
+ caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper
+ operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used
+ to complete this initialization. The rest of the UNDI APIs will not be available until this call has
+ been completed.
+ Note: PXENV_UNDI_STARTUP must not be called again without first calling
+ PXENV_UNDI_SHUTDOWN.
+ PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for
+ chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and
+ PXENV_STOP_UNDI API calls.
+ This service cannot be used in protected mode.
+ typedef struct
+ {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_STARTUP_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiStartup (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI CLEANUP
+ Op-Code: PXENV_UNDI_CLEANUP (0002h)
+ Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field
+ in the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be
+ made just before unloading the Universal NIC Driver. The rest of the API will not be available
+ after this call executes.
+ This service cannot be used in protected mode.
+ typedef struct {
+ PXENX_STATUS Status;
+ } PXENV_UNDI_CLEANUP_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiCleanup (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI INITIALIZE
+ Op-Code: PXENV_UNDI_INITIALIZE (0003h)
+ Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the
+ caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the adapter and programs it with default parameters. The default parameters used
+ are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the
+ receive and transmit units of the network adapter to readily receive or transmit packets. The
+ application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network.
+ This call must be made by an application to establish an interface to the network adapter driver.
+ Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for
+ the Protocol field in the parameter structure.
+ typedef struct {
+ PXENV_STATUS Status;
+ ADDR32 ProtocolIni;
+ UINT8 reserved[8];
+ } PXENV_UNDI_INITIALIZE_T;
+ Set before calling API service
+ ProtocolIni: Physical address of a memory copy of the driver
+ module from the protocol.ini file obtained from the protocol manager
+ driver (refer to the NDIS 2.0 specification). This parameter is
+ supported for the universal NDIS driver to pass the information
+ contained in the protocol.ini file to the NIC driver for any specific
+ configuration of the NIC. (Note that the module identification in the
+ protocol.ini file was done by NDIS.) This value can be NULL for any
+ other application interfacing to the universal NIC driver
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance.
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiInitialize (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable
+ )
+;
+
+/**
+ Wrapper routine for reset adapter.
+
+ PXE
+ UNDI RESET ADAPTER
+ Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h)
+ Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to
+ Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the
+ network. This routine cannot be used to replace Initialize or Shutdown calls.
+ typedef struct {
+ PXENV_STATUS Status;
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_RESET_T;
+
+ #define MAXNUM_MCADDR 8
+
+ typedef struct {
+ UINT16 MCastAddrCount;
+ MAC_ADDR McastAddr[MAXNUM_MCADDR];
+ } PXENV_UNDI_MCAST_ADDRESS_t;
+
+ Set before calling API service
+ R_Mcast_Buf: This is a structure of MCastAddrCount and
+ McastAddr.
+ MCastAddrCount: Number of multicast MAC addresses in the
+ buffer.
+ McastAddr: List of up to MAXNUM_MCADDR multicast MAC
+ addresses.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance.
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+ @param RxFilter Filter setting mask value for PXE recive .
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiResetNic (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_RESET_T *PxeUndiTable,
+ IN UINT16 RxFilter
+ )
+;
+
+/**
+ PXE
+ UNDI SHUTDOWN
+ Op-Code: PXENV_UNDI_SHUTDOWN (0005h)
+ Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the network adapter and leaves it in a safe state for another driver to program it.
+ Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the
+ Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again.
+ typedef struct
+ {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_SHUTDOWN_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiShutdown (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI OPEN
+ Op-Code: PXENV_UNDI_OPEN (0006h)
+ Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call activates the adapter network connection and sets the adapter ready to accept packets
+ for transmit and receive.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 OpenFlag;
+ UINT16 PktFilter;
+ #define FLTR_DIRECTED 0x0001
+ #define FLTR_BRDCST 0x0002
+ #define FLTR_PRMSCS 0x0004
+ #define FLTR_SRC_RTG 0x0008
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_OPEN_T;
+ Set before calling API service
+ OpenFlag: This is an adapter specific input parameter. This is
+ supported for the universal NDIS 2.0 driver to pass in the open flags
+ provided by the protocol driver. (See the NDIS 2.0 specification.)
+ This can be zero.
+ PktFilter: Filter for receiving packets. This can be one, or more, of
+ the FLTR_xxx constants. Multiple values are arithmetically or-ed
+ together.
+ directed packets are packets that may come to your MAC address
+ or the multicast MAC address.
+ R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h).
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiOpen (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI CLOSE
+ Op-Code: PXENV_UNDI_CLOSE (0007h)
+ Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or
+ received until the network adapter is open again.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_CLOSE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiClose (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI TRANSMIT PACKET
+ Op-Code: PXENV_UNDI_TRANSMIT (0008h)
+ Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that
+ has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX.
+ The status code must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call transmits a buffer to the network. The media header
+ for the packet can be filled by the calling protocol, but it might not be.
+ The network adapter driver will fill it if required by the values in the
+ parameter block. The packet is buffered for transmission provided there is
+ an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no
+ buffer is available the function returns PXENV_EXIT_FAILURE with a status
+ code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is
+ implementation-dependent. An interrupt is generated on completion of the
+ transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is
+ permitted in the context of a transmit complete interrupt.
+
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT8 Protocol;
+ #define P_UNKNOWN 0
+ #define P_IP 1
+ #define P_ARP 2
+ #define P_RARP 3
+ UINT8 XmitFlag;
+ #define XMT_DESTADDR 0x0000
+ #define XMT_BROADCAST 0x0001
+ SEGOFF16 DestAddr;
+ SEGOFF16 TBD;
+ UINT32 Reserved[2];
+ } t_PXENV_UNDI_TRANSMIT;
+
+ #define MAX_DATA_BLKS 8
+
+ typedef struct {
+ UINT16 ImmedLength;
+ SEGOFF16 Xmit;
+ UINT16 DataBlkCount;
+ struct DataBlk {
+ UINT8 TDPtrType;
+ UINT8 TDRsvdByte;
+ UINT16 TDDataLen;
+ SEGOFF16 TDDataPtr;
+ } DataBlock[MAX_DATA_BLKS];
+ } PXENV_UNDI_TBD_T
+
+ Set before calling API service
+ Protocol: This is the protocol of the upper layer that is calling UNDI
+ TRANSMIT call. If the upper layer has filled the media header, this
+ field must be P_UNKNOWN.
+ XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a
+ pointer to the destination media address in the field DestAddr. If
+ XMT_BROADCAST, the NIC driver fills the broadcast address for the
+ destination.
+ TBD: Segment:Offset address of the transmit buffer descriptor.
+ ImmedLength: Length of the immediate transmit buffer: Xmit.
+ Xmit: Segment:Offset of the immediate transmit buffer.
+ DataBlkCount: Number of blocks in this transmit buffer.
+ TDPtrType:
+ 0 => 32-bit physical address in TDDataPtr (not supported in this
+ version of PXE)
+ 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit
+ protected mode pointer
+ TDRsvdByte: Reserved must be zero.
+ TDDatalen: Data block length in bytes.
+ TDDataPtr: Segment:Offset of the transmit block.
+ DataBlock: Array of transmit data blocks.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiTransmit (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI SET MULTICAST ADDRESS
+ Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h)
+ Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call changes the current list of multicast addresses to the input list and resets the network
+ adapter to accept it. If the number of multicast addresses is zero, multicast is disabled.
+ typedef struct {
+ PXENV_STATUS Status;
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_SET_MCAST_ADDR_T;
+ Set before calling API service
+ R_Mcast_Buf: See description in the UNDI RESET ADAPTER
+ (0004h) API.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetMcastAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI SET STATION ADDRESS
+ Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah)
+ Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call sets the MAC address to be the input value and is called before opening the network
+ adapter. Later, the open call uses this variable as a temporary MAC address to program the
+ adapter individual address registers.
+ typedef struct {
+ PXENV_STATUS Status;
+ MAC_ADDR StationAddress;
+ } PXENV_UNDI_SET_STATION_ADDR_T;
+ Set before calling API service
+ StationAddress: Temporary MAC address to be used for
+ transmit and receive.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetStationAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI SET PACKET FILTER
+ Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh)
+ Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with
+ the open call.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT8 filter;
+ } PXENV_UNDI_SET_PACKET_FILTER_T;
+ Set before calling API service
+ Filter: See the receive filter values in the UNDI OPEN
+ (0006h) API description.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetPacketFilter (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET INFORMATION
+ Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch)
+ Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call copies the network adapter variables, including the MAC address, into the input buffer.
+ Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and
+ PXENV_UNDI_STARTUP have been issued. All other fields must be valid after
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been
+ called.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 BaseIo;
+ UINT16 IntNumber;
+ UINT16 MaxTranUnit;
+ UINT16 HwType;
+ #define ETHER_TYPE 1
+ #define EXP_ETHER_TYPE 2
+ #define IEEE_TYPE 6
+ #define ARCNET_TYPE 7
+ UINT16 HwAddrLen;
+ MAC_ADDR CurrentNodeAddress;
+ MAC_ADDR PermNodeAddress;
+ SEGSEL ROMAddress;
+ UINT16 RxBufCt;
+ UINT16 TxBufCt;
+ } PXENV_UNDI_GET_INFORMATION_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ BaseIO: Adapter base I/O address.
+ IntNumber: Adapter IRQ number.
+ MaxTranUnit: Adapter maximum transmit unit.
+ HWType: Type of protocol at the hardware level.
+ HWAddrLen: Length of the hardware address.
+ CurrentNodeAddress: Current hardware address.
+ PermNodeAddress: Permanent hardware address.
+ ROMAddress: Real mode ROM segment address.
+ RxBufCnt: Receive queue length.
+ TxBufCnt: Transmit queue length.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetInformation (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET STATISTICS
+ Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh)
+ Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call reads statistical information from the network adapter, and returns.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT32 XmtGoodFrames;
+ UINT32 RcvGoodFrames;
+ UINT32 RcvCRCErrors;
+ UINT32 RcvResourceErrors;
+ } PXENV_UNDI_GET_STATISTICS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ XmtGoodFrames: Number of successful transmissions.
+ RcvGoodFrames: Number of good frames received.
+ RcvCRCErrors: Number of frames received with CRC
+ error.
+ RcvResourceErrors: Number of frames discarded
+ because receive queue was full.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetStatistics (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI CLEAR STATISTICS
+ Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh)
+ Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call clears the statistical information from the network adapter.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_CLEAR_STATISTICS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiClearStatistics (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI INITIATE DIAGS
+ Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh)
+ Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run
+ hardware diagnostics and to update its status information.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_INITIATE_DIAGS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiInitiateDiags (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI FORCE INTERRUPT
+ Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h)
+ Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the
+ network adapter driver usually queues the packet and calls the application's callback receive
+ routine with a pointer to the packet received. Then, the callback routine either can copy the packet
+ to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied,
+ the network adapter driver does not remove it from the input queue. When the application wants to
+ copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive
+ interrupt.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_FORCE_INTERRUPT_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiForceInterrupt (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET MULTICAST ADDRESS
+ Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h)
+ Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call converts the given IP multicast address to a hardware multicast address.
+ typedef struct {
+ PXENV_STATUS Status;
+ IP4 InetAddr;
+ MAC_ADDR MediaAddr;
+ } PXENV_UNDI_GET_MCAST_ADDR_T;
+ Set before calling API service
+ InetAddr: IP multicast address.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ MediaAddr: MAC multicast address.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetMcastAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET NIC TYPE
+ Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h)
+ Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE_T parameter structure that has been initialized by
+ the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the
+ NIC information.
+ Description: This call, if successful, provides the NIC-specific information necessary to identify the network
+ adapter that is used to boot the system.
+ Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if
+ the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific
+ information can be obtained from the DHCPDISCOVER packet itself.
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called
+ before the information provided is valid.
+ typedef {
+ PXENV_STATUS Status;
+ UINT8 NicType;
+ #define PCI_NIC 2
+ #define PnP_NIC 3
+ #define CardBus_NIC 4
+ Union {
+ Struct {
+ UINT16 Vendor_ID;
+ UINT16 Dev_ID;
+ UINT8 Base_Class;
+ UINT8 Sub_Class;
+ UINT8 Prog_Intf;
+ UINT8 Rev;
+ UINT16 BusDevFunc;
+ UINT16 SubVendor_ID;
+ UINT16 SubDevice_ID;
+ } pci, cardbus;
+ struct {
+ UINT32 EISA_Dev_ID;
+ UINT8 Base_Class;
+ UINT8 Sub_Class;
+ UINT8 Prog_Intf;
+ UINT16 CardSelNum;
+ } pnp;
+ } info;
+ } PXENV_UNDI_GET_NIC_TYPE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ NICType: Type of NIC information stored in the parameter
+ structure.
+ Info: Information about the fields in this union can be found
+ in the [PnP] and [PCI] specifications
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetNicType (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET IFACE INFO
+ Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h)
+ Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the
+ interface specific information.
+ Description: This call, if successful, provides the network interface specific information such as the interface
+ type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the
+ universal drivers such as NDIS or Miniport to communicate to the upper protocol modules.
+ Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the
+ universal driver to translate/convert this information into a format that is required in its specification
+ or to suit the expectation of the upper level protocol modules.
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called
+ before the information provided is valid.
+ typedef struct {
+ PXENV_STATUS Status
+ UINT8 IfaceType[16];
+ UINT32 LinkSpeed;
+ UINT32 ServiceFlags;
+ UINT32 Reserved[4];
+ } PXENV_UNDI_GET_NDIS_INFO_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ IfaceType: Name of MAC type in ASCIIZ format. This is
+ used by the universal NDIS driver to specify its driver type
+ to the protocol driver.
+ LinkSpeed: Defined in the NDIS 2.0 specification.
+ ServiceFlags: Defined in the NDIS 2.0 specification.
+ Reserved: Must be zero.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetNdisInfo (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI ISR
+ Op-Code: PXENV_UNDI_ISR (0014h)
+ Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in
+ the parameter block indicates the operation to be performed for the call. This field is filled with the
+ status of that operation on return.
+ Note: Interrupt Service Routine Operation:
+ In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the
+ application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR
+ API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing
+ (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT).
+ When the Network Interface HW generates an interrupt the protocol driver interrupt service
+ routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then
+ calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for
+ the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface
+ level and read any status values required to further process the interrupt. UNDI must return as
+ quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or
+ PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the
+ interrupt was generated by this particular Network Interface or not.
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was
+ not generated by our NIC, and interrupt processing is complete.
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start
+ a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is
+ now complete.
+ The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to
+ PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and
+ return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the
+ first buffer pointer of that frame in the parameter block.
+ The protocol driver calls UNDI repeatedly with the FuncFlag equal to
+ PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received
+ frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l
+ remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous
+ buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter
+ block. Otherwise it must return the first buffer in the next frame.
+ If there is no received frame pending to be processed, UNDI processes the transmit completes and
+ if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the
+ NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag.
+ IMPORTANT: It is possible for the protocol driver to be interrupted again while in the
+ strategy routine when the UNDI re-enables interrupts.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiIsr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_ISR_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ STOP UNDI
+ Op-Code: PXENV_STOP_UNDI (0015h)
+ Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This routine is responsible for unhooking the Int 1Ah service routine.
+ Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid
+ status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from
+ base memory. Also, UNDI must not be removed from base memory if BC is not removed from base
+ memory.
+ Service cannot be used in protected mode.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_STOP_UNDI_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiStop (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_STOP_UNDI_T *PxeUndiTable
+ )
+;
+
+/**
+ PXE
+ UNDI GET STATE
+ Op-Code: PXENV_UNDI_GET_STATE (0015h)
+ Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state
+ constants
+ Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call
+ sequences
+ typedef struct {
+ #define PXE_UNDI_GET_STATE_STARTED 1
+ #define PXE_UNDI_GET_STATE_INITIALIZED 2
+ #define PXE_UNDI_GET_STATE_OPENED 3
+ PXENV_STATUS Status;
+ UINT8 UNDIstate;
+ } PXENV_UNDI_GET_STATE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ State: See definitions of the state constants.
+ Note. UNDI implementation is responsible for maintaining
+ internal state machine.
+ UNDI ISR
+ Op-Code: PXENV_UNDI_ISR (0014h)
+ Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in
+ the parameter block indicates the operation to be performed for the call. This field is filled with the
+ status of that operation on return.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetState (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable
+ )
+;
+
+/**
+ Effect the Far Call into the PXE Layer
+
+ Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API
+ services will not work, unless there are three 16-bit parameters pushed onto the stack.
+ push DS ;Far pointer to parameter structure
+ push offset pxe_data_call_struct ;is pushed onto stack.
+ push Index ;UINT16 is pushed onto stack.
+ call dword ptr (s_PXE ptr es:[di]).EntryPointSP
+ add sp, 6 ;Caller cleans up stack.
+
+ @param SimpleNetworkDevice Device instance for simple network
+ @param Table Point to parameter/retun value table for legacy far call
+ @param TableSize The size of paramter/return value table
+ @param CallIndex The index of legacy call.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+MakePxeCall (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT VOID *Table,
+ IN UINTN TableSize,
+ IN UINT16 CallIndex
+ )
+;
+
+/**
+ Allocate buffer below 1M for real mode.
+
+ @param NumPages The number pages want to be allocated.
+ @param Buffer On return, allocated buffer.
+
+ @return Status of allocating pages.
+**/
+EFI_STATUS
+BiosSnp16AllocatePagesBelowOneMb (
+ UINTN NumPages,
+ VOID **Buffer
+ )
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c
new file mode 100644
index 0000000000..a95d83459d
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/ComponentName.c
@@ -0,0 +1,309 @@
+/** @file
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosSnp16.h"
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16ComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosSnp16ComponentName = {
+ BiosSnp16ComponentNameGetDriverName,
+ BiosSnp16ComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosSnp16ComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosSnp16ComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosSnp16ComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosSnp16DriverNameTable[] = {
+ {
+ "eng;en",
+ L"BIOS[UNDI] Simple Network Protocol Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16ComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mBiosSnp16DriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gBiosSnp16ComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosSnp16ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c
new file mode 100644
index 0000000000..0b3543e12c
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Misc.c
@@ -0,0 +1,956 @@
+/** @file
+ Helper Routines that use a PXE-enabled NIC option ROM.
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosSnp16.h"
+
+#define TO_SEGMENT(x) ((UINT16) (RShiftU64 ((UINT32)(UINTN) (x), 4) & 0xF000))
+#define TO_OFFSET(x) ((UINT16) ((UINT32)(UINTN) (x) & 0xFFFF))
+#define PARAGRAPH_SIZE 0x10
+#define IVT_BASE 0x00000000
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Signature; ///< 0xaa55
+ UINT8 ROMlength; ///< size of this ROM in 512 byte blocks
+ UINT8 InitEntryPoint[4]; ///< a jump to the initialization routine
+ UINT8 Reserved[0xf]; ///< various
+ UINT16 PxeRomIdOffset; ///< offset of UNDI, $BC$, or BUSD ROM ID structure
+ UINT16 PcirHeaderOffset; ///< offset of PCI Expansion Header
+ UINT16 PnpHeaderOffset; ///< offset of Plug and Play Expansion Header
+} OPTION_ROM_HEADER;
+#pragma pack()
+
+UINT32 CachedVectorAddress[0x100];
+
+/**
+ Cache Interrupt verctor address converted from IVT number.
+
+ @param VectorNumber IVT number
+
+ @retval EFI_SUCCESS Success to operation.
+**/
+EFI_STATUS
+CacheVectorAddress (
+ UINT8 VectorNumber
+ )
+{
+ UINT32 *Address;
+
+ Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4);
+ CachedVectorAddress[VectorNumber] = *Address;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get interrupt vector address according to IVT number.
+
+ @param VectorNumber Given IVT number
+
+ @return cached interrupt vector address.
+**/
+EFI_STATUS
+RestoreCachedVectorAddress (
+ UINT8 VectorNumber
+ )
+{
+ UINT32 *Address;
+
+ Address = (UINT32 *)(UINTN) (IVT_BASE + VectorNumber * 4);
+ *Address = CachedVectorAddress[VectorNumber];
+ return EFI_SUCCESS;
+}
+
+/**
+ Print Undi loader table.
+
+ @param UndiLoaderStructure Point to Undi Loader table structure.
+
+**/
+VOID
+Print_Undi_Loader_Table (
+ VOID *UndiLoaderStructure
+ )
+{
+ UNDI_LOADER_T *DisplayPointer;
+
+ DisplayPointer = (UNDI_LOADER_T *) UndiLoaderStructure;
+
+ DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n"));
+ DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) UndiLoaderStructure));
+
+ DEBUG ((DEBUG_NET, "\n\rStatus = 0x%X\n\r", DisplayPointer->Status));
+ DEBUG ((DEBUG_NET, "\t_AX_= 0x%X\n\r", DisplayPointer->Ax));
+ DEBUG ((DEBUG_NET, "\t_BX_= 0x%X\n\r", DisplayPointer->Bx));
+ DEBUG ((DEBUG_NET, "\t_DX_= 0x%X\n\r", DisplayPointer->Dx));
+ DEBUG ((DEBUG_NET, "\t_DI_= 0x%X\n\r", DisplayPointer->Di));
+ DEBUG ((DEBUG_NET, "\t_ES_= 0x%X\n\r", DisplayPointer->Es));
+ DEBUG ((DEBUG_NET, "\tUNDI_DS= 0x%X\n\r", DisplayPointer->Undi_Ds));
+ DEBUG ((DEBUG_NET, "\tUNDI_CS= 0x%X\n\r", DisplayPointer->Undi_Cs));
+ DEBUG ((DEBUG_NET, "\tPXEptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Segment));
+ DEBUG ((DEBUG_NET, "\tPXEptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXEptr.Offset));
+ DEBUG ((DEBUG_NET, "\tPXENVptr:SEG= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Segment));
+ DEBUG ((DEBUG_NET, "\tPXENVptr:OFF= 0x%X\n\r", (UINT16) DisplayPointer->PXENVptr.Offset));
+}
+
+/**
+ Simple table dumper. The ROMID table is necessary in order to effect
+ the "Early UNDI" trick. Herein, the UNDI layer can be loaded in the
+ pre-boot phase without having to download a Network Boot Program
+ across the wire. It is required in the implementation in that we
+ are not using PXE.
+
+ @param RomIDStructure Point to RomID structure.
+
+**/
+VOID
+Print_ROMID_Table (
+ IN VOID *RomIDStructure
+ )
+{
+ UNDI_ROMID_T *DisplayPointer;
+
+ DisplayPointer = (UNDI_ROMID_T *) RomIDStructure;
+
+ DEBUG ((DEBUG_NET, "Before Parsing the table contents, the table itself lives\n"));
+ DEBUG ((DEBUG_NET, "\tat the address 0x%X\n\r", (UINT32)(UINTN) RomIDStructure));
+
+ DEBUG (
+ (DEBUG_NET,
+ "\n\rROMID %c%c%c%c\n\r",
+ DisplayPointer->Signature[0],
+ DisplayPointer->Signature[1],
+ DisplayPointer->Signature[2],
+ DisplayPointer->Signature[3])
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "Length of this structure in bytes = 0x%X\n\r",
+ DisplayPointer->StructLength)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Use to make byte checksum of this structure == zero is = 0x%X\n\r",
+ DisplayPointer->StructCksum)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Structure format revision number= 0x%X\n\r",
+ DisplayPointer->StructRev)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "API Revision number = 0x%X 0x%X 0x%X\n\r",
+ DisplayPointer->UNDI_Rev[0],
+ DisplayPointer->UNDI_Rev[1],
+ DisplayPointer->UNDI_Rev[2])
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Offset of UNDI loader routine in the option ROM image= 0x%X\n\r",
+ DisplayPointer->UNDI_Loader)
+ );
+ DEBUG ((DEBUG_NET, "From the data above, the absolute entry point of the UNDI loader is\n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "\tat address 0x%X\n\r",
+ (UINT32) (DisplayPointer->UNDI_Loader + ((UINT32) (UINTN)(DisplayPointer - 0x20) & 0xFFFF0)))
+ );
+ DEBUG ((DEBUG_NET, "Minimum stack segment size, in bytes,\n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "needed to load and run the UNDI= 0x%X \n\r",
+ DisplayPointer->StackSize)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "UNDI runtime code and data = 0x%X\n\r",
+ DisplayPointer->DataSize)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Segment size = 0x%X\n\r",
+ DisplayPointer->CodeSize)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "\n\rBus Type = %c%c%c%c\n\r",
+ DisplayPointer->BusType[0],
+ DisplayPointer->BusType[1],
+ DisplayPointer->BusType[2],
+ DisplayPointer->BusType[3])
+ );
+}
+
+/**
+ Print PXE table.
+
+ @param PxeTable Point to PXE table structure
+
+**/
+VOID
+Print_PXE_Table (
+ IN VOID* PxeTable
+ )
+{
+ PXE_T *DisplayPointer;
+ UINTN Index;
+ UINT8 *Dptr;
+
+ DisplayPointer = (PXE_T *) PxeTable;
+ Dptr = (UINT8 *) PxeTable;
+
+ DEBUG ((DEBUG_NET, "This is the PXE table at address 0x%X\n\r", PxeTable));
+
+ DEBUG ((DEBUG_NET, "A dump of the 0x%X bytes is:\n\r", sizeof (PXE_T)));
+
+ for (Index = 0; Index < sizeof (PXE_T); Index++) {
+ if ((Index % 0x10) == 0) {
+ DEBUG ((DEBUG_NET, "\t\n\r"));
+ }
+
+ DEBUG ((DEBUG_NET, " 0x%X ", *Dptr++));
+ }
+
+ DEBUG ((DEBUG_NET, "\n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "\n\rPXE %c%c%c%c%c%c\n\r",
+ DisplayPointer->Signature[0],
+ DisplayPointer->Signature[1],
+ DisplayPointer->Signature[2],
+ DisplayPointer->Signature[3])
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Length of this structure in bytes = 0x%X\n\r",
+ DisplayPointer->StructLength)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Use to make byte checksum of this structure == zero is = 0x%X\n\r",
+ DisplayPointer->StructCksum)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Structure format revision number = 0x%X\n\r",
+ DisplayPointer->StructRev)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Must be zero, is equal to 0x%X\n\r",
+ DisplayPointer->Reserved1)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Far pointer to UNDI ROMID = 0x%X\n\r",
+ (UINT32) (DisplayPointer->Undi.Segment << 0x4 | DisplayPointer->Undi.Offset))
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Far pointer to base-code ROMID = 0x%X\n\r",
+ (UINT32) ((DisplayPointer->Base.Segment << 0x04) | DisplayPointer->Base.Offset))
+ );
+ DEBUG ((DEBUG_NET, "16bit stack segment API entry point. This will be seg:off in \n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "real mode and sel:off in 16:16 protected mode = 0x%X:0x%X\n\r",
+ DisplayPointer->EntryPointSP.Segment,
+ DisplayPointer->EntryPointSP.Offset)
+ );
+
+ DEBUG ((DEBUG_NET, "\n\tNOTE to the implementer\n\tThis is the entry to use for call-ins\n\r"));
+
+ DEBUG ((DEBUG_NET, "32bit stack Segment API entry point. This will be sel:off. \n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "In real mode, sel == 0 = 0x%X:0x%X\n\r",
+ DisplayPointer->EntryPointESP.Segment,
+ DisplayPointer->EntryPointESP.Offset)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Reserved2 value, must be zero, is equal to 0x%X\n\r",
+ DisplayPointer->Reserved2)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Number of segment descriptors in this structur = 0x%X\n\r",
+ (UINT8) DisplayPointer->SegDescCnt)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "First segment descriptor in GDT assigned to PXE = 0x%X\n\r",
+ (UINT16) DisplayPointer->FirstSelector)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->Stack.Seg_Addr,
+ (UINT32) DisplayPointer->Stack.Phy_Addr,
+ (UINT16) DisplayPointer->Stack.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The UNDIData is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->UNDIData.Seg_Addr,
+ (UINT32) DisplayPointer->UNDIData.Phy_Addr,
+ (UINT16) DisplayPointer->UNDIData.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The UNDICodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->UNDICode.Seg_Addr,
+ (UINT32) DisplayPointer->UNDICode.Phy_Addr,
+ (UINT16) DisplayPointer->UNDICode.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The Stack is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->UNDICodeWrite.Seg_Addr,
+ (UINT32) DisplayPointer->UNDICodeWrite.Phy_Addr,
+ (UINT16) DisplayPointer->UNDICodeWrite.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The BC_Data is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->BC_Data.Seg_Addr,
+ (UINT32) DisplayPointer->BC_Data.Phy_Addr,
+ (UINT16) DisplayPointer->BC_Data.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The BC_Code is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->BC_Code.Seg_Addr,
+ (UINT32) DisplayPointer->BC_Code.Phy_Addr,
+ (UINT16) DisplayPointer->BC_Code.Seg_Size)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The BC_CodeWrite is \n\r\tSegment Addr = 0x%X\n\r\tPhysical Addr = 0x%X\n\r\tSeg Size = 0x%X\n\r",
+ (UINT16) DisplayPointer->BC_CodeWrite.Seg_Addr,
+ (UINT32) DisplayPointer->BC_CodeWrite.Phy_Addr,
+ (UINT16) DisplayPointer->BC_CodeWrite.Seg_Size)
+ );
+}
+
+/**
+ Print PXENV table.
+
+ @param PxenvTable Point to PXENV
+
+**/
+VOID
+Print_PXENV_Table (
+ IN VOID *PxenvTable
+ )
+{
+ PXENV_T *DisplayPointer;
+
+ DisplayPointer = (PXENV_T *) PxenvTable;
+
+ DEBUG (
+ (DEBUG_NET,
+ "\n\rPXENV+ %c%c%c%c%c%c\n\r",
+ DisplayPointer->Signature[0],
+ DisplayPointer->Signature[1],
+ DisplayPointer->Signature[2],
+ DisplayPointer->Signature[3],
+ DisplayPointer->Signature[4],
+ DisplayPointer->Signature[5])
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "PXE version number. \n\r\tLSB is minor version. \n\r\tMSB is major version = 0x%X\n\r",
+ DisplayPointer->Version)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Length of PXE-2.0 Entry Point structure in bytes = 0x%X\n\r",
+ DisplayPointer->StructLength)
+ );
+ DEBUG ((DEBUG_NET, "Used to make structure checksum equal zero is now = 0x%X\n\r", DisplayPointer->StructCksum));
+ DEBUG ((DEBUG_NET, "Real mode API entry point segment:Offset. = 0x%X\n\r", DisplayPointer->RMEntry));
+ DEBUG ((DEBUG_NET, "Protected mode API entry point = 0x%X\n\r", DisplayPointer->PMEntryOff));
+ DEBUG ((DEBUG_NET, " segment:Offset. This will always be zero. \n\r"));
+ DEBUG ((DEBUG_NET, "Protected mode API calls = 0x%X\n\r", DisplayPointer->PMEntrySeg));
+ DEBUG ((DEBUG_NET, "Real mode stack segment = 0x%X\n\r", DisplayPointer->StackSeg));
+ DEBUG ((DEBUG_NET, "Stack segment size in bytes = 0x%X\n\r", DisplayPointer->StackSize));
+ DEBUG ((DEBUG_NET, "Real mode base-code code segment = 0x%X\n\r", DisplayPointer->BaseCodeSeg));
+ DEBUG ((DEBUG_NET, "Base-code code segment size = 0x%X\n\r", DisplayPointer->BaseCodeSize));
+ DEBUG ((DEBUG_NET, "Real mode base-code data segment = 0x%X\n\r", DisplayPointer->BaseDataSeg));
+ DEBUG ((DEBUG_NET, "Base-code data segment size = 0x%X\n\r", DisplayPointer->BaseDataSize));
+
+ DEBUG (
+ (DEBUG_NET,
+ "UNDI code segment size in bytes = 0x%X\n\r",
+ DisplayPointer->UNDICodeSize)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "Real mode segment:Offset pointer \n\r\tto PXE Runtime ID structure, address = 0x%X\n\r",
+ DisplayPointer->RuntimePtr)
+ );
+ DEBUG (
+ (
+ DEBUG_NET,
+ "From above, we have a linear address of 0x%X\n\r",
+ (UINT32)
+ (
+ ((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF) +
+ (((UINT32)(UINTN)(DisplayPointer->RuntimePtr) & 0xFFFF0000) >> 12)
+ )
+ )
+ );
+}
+
+
+#define OPTION_ROM_PTR ((OPTION_ROM_HEADER *) RomAddress)
+
+/**
+ If available, launch the BaseCode from a NIC option ROM.
+ This should install the !PXE and PXENV+ structures in memory for
+ subsequent use.
+
+
+ @param SimpleNetworkDevice Simple network device instance
+ @param RomAddress The ROM base address for NIC rom.
+
+ @retval EFI_NOT_FOUND The check sum does not match
+ @retval EFI_NOT_FOUND Rom ID offset is wrong
+ @retval EFI_NOT_FOUND No Rom ID structure is found
+**/
+EFI_STATUS
+LaunchBaseCode (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ UINTN RomAddress
+ )
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET InOutRegs;
+ UNDI_ROMID_T *RomIdTableAddress;
+ UNDI_LOADER_T *UndiLoaderTable;
+ UINT16 Segment;
+ UINT16 *StackPointer;
+ VOID *Buffer;
+ UINTN Size;
+ PXE_T *Pxe;
+ UINT32 RomLength;
+ UINTN PciSegment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ BOOLEAN ThunkFailed;
+
+ DEBUG ((DEBUG_NET, "\n\r\n\rCheck for the UNDI ROMID Signature\n\r"));
+
+ //
+ // paranoia - check structures for validity
+ //
+ RomLength = OPTION_ROM_PTR->ROMlength << 9;
+ if (CalculateSum8 ((UINT8 *) RomAddress, RomLength) != 0) {
+ DEBUG ((DEBUG_ERROR, "ROM Header Checksum Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ RomIdTableAddress = (UNDI_ROMID_T *) (RomAddress + OPTION_ROM_PTR->PxeRomIdOffset);
+
+ if ((UINTN) (OPTION_ROM_PTR->PxeRomIdOffset + RomIdTableAddress->StructLength) > RomLength) {
+ DEBUG ((DEBUG_ERROR, "ROM ID Offset Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // see if this is a header for an UNDI ROM ID structure (vs. a $BC$ or BUSD type)
+ //
+ if (CompareMem (RomIdTableAddress->Signature, UNDI_ROMID_SIG, sizeof RomIdTableAddress->Signature) != 0) {
+ DEBUG ((DEBUG_ERROR, "No ROM ID Structure found....\n\r"));
+ return EFI_NOT_FOUND;
+ //
+ // its not - keep looking
+ //
+ }
+
+ if (CalculateSum8 ((UINT8 *) RomIdTableAddress, RomIdTableAddress->StructLength) != 0) {
+ DEBUG ((DEBUG_ERROR, "ROM ID Checksum Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ Print_ROMID_Table (RomIdTableAddress);
+
+ DEBUG (
+ (DEBUG_NET,
+ "The ROM ID is located at 0x%X\n\r",
+ RomIdTableAddress)
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "With an UNDI Loader located at 0x%X\n\r",
+ RomAddress + RomIdTableAddress->UNDI_Loader)
+ );
+
+ //
+ // found an UNDI ROM ID structure
+ //
+ SimpleNetworkDevice->Nii.ImageAddr = RomAddress;
+ SimpleNetworkDevice->Nii.ImageSize = RomLength;
+ SimpleNetworkDevice->Nii.MajorVer = RomIdTableAddress->UNDI_Rev[2];
+ SimpleNetworkDevice->Nii.MinorVer = RomIdTableAddress->UNDI_Rev[1];
+
+ DEBUG ((DEBUG_NET, "Allocate area for the UNDI_LOADER_T structure\n\r"));
+ //
+ // Allocate 1 page below 1MB to put real mode thunk code in
+ //
+ // Undi Loader Table is a PXE Specification prescribed data structure
+ // that is used to transfer information into and out of the Undi layer.
+ // Note how it must be located below 1 MB.
+ //
+ SimpleNetworkDevice->UndiLoaderTablePages = EFI_SIZE_TO_PAGES (PARAGRAPH_SIZE + sizeof (UNDI_LOADER_T));
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ SimpleNetworkDevice->UndiLoaderTablePages,
+ &SimpleNetworkDevice->UndiLoaderTable
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UndiLoaderTable = SimpleNetworkDevice->UndiLoaderTable;
+
+ DEBUG ((DEBUG_NET, "Allocate area for the real-mode stack whose sole purpose\n\r"));
+ DEBUG ((DEBUG_NET, "in life right now is to store a SEG:OFFSET combo pair that\n\r"));
+ DEBUG ((DEBUG_NET, "points to an Undi_Loader_t table structure\n\r"));
+
+ Size = 0x100;
+ Status = gBS->AllocatePool (EfiLoaderData, Size, &Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Now we want to put a pointer to the Under Loader Table in our MemPage
+ // Buffer. This will be the argument stack for the call into the Undi Loader
+ //
+ StackPointer = (UINT16 *) Buffer;
+ *StackPointer++ = TO_OFFSET (UndiLoaderTable);
+ //
+ // push the OFFSET
+ //
+ *StackPointer++ = TO_SEGMENT (UndiLoaderTable);
+ //
+ // push the SEGMENT
+ //
+ StackPointer = (UINT16 *) Buffer;
+ //
+ // reset the stack pointer
+ //
+ DEBUG (
+ (DEBUG_NET,
+ "After the fixups, the stack pointer is 0x%X\n\r",
+ (UINT64)(UINTN) StackPointer)
+ );
+
+ //
+ // Allocate memory for the Deployed UNDI.
+ // The UNDI is essentially telling us how much space it needs, and
+ // it is up to the EFI driver to allocate sufficient, boot-time
+ // persistent resources for the call
+ //
+ SimpleNetworkDevice->DestinationDataSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->DataSize);
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ SimpleNetworkDevice->DestinationDataSegmentPages,
+ &SimpleNetworkDevice->DestinationDataSegment
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return Status;
+ }
+
+ UndiLoaderTable->Undi_Ds = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationDataSegment >> 4);
+
+ //
+ // Allocate memory for the Deployed UNDI stack
+ // The UNDI is essentially telling us how much space it needs, and
+ // it is up to the EFI driver to allocate sufficient, boot-time
+ // persistent resources for the call
+ //
+ SimpleNetworkDevice->DestinationStackSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->StackSize);
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ SimpleNetworkDevice->DestinationStackSegmentPages,
+ &SimpleNetworkDevice->DestinationStackSegment
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return Status;
+ }
+ //
+ // Allocate memory for the Deployed UNDI.
+ // The UNDI is essentially telling us how much space it needs, and
+ // it is up to the EFI driver to allocate sufficient, boot-time
+ // persistent resources for the call
+ //
+ SimpleNetworkDevice->DestinationCodeSegmentPages = EFI_SIZE_TO_PAGES (RomIdTableAddress->CodeSize);
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ SimpleNetworkDevice->DestinationCodeSegmentPages,
+ &SimpleNetworkDevice->DestinationCodeSegment
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return Status;
+ }
+
+ UndiLoaderTable->Undi_Cs = (UINT16) ((UINTN) SimpleNetworkDevice->DestinationCodeSegment >> 4);
+
+ //
+ // these are in the Input and Output Parameter to be sent to the UNDI Loader code
+ //
+ UndiLoaderTable->Status = 0xAA55;
+ //
+ // -------------------- Changed by Michael_Huang@3Com.com -----------------
+ // UndiLoaderTable->_AX is AX value when UNDI ROM is initialized by BIOS, it is the PCI bus device
+ // function of the NIC. Please refer to PXE Spec for detail info.
+ // old code is:
+ // UndiLoaderTable->Ax = 0x0;
+ // -----------------------------------------------------------------------
+ //
+ SimpleNetworkDevice->PciIo->GetLocation (
+ SimpleNetworkDevice->PciIo,
+ &PciSegment,
+ &Bus,
+ &Device,
+ &Function
+ );
+ UndiLoaderTable->Ax = (UINT16) ((Bus << 0x8) | (Device << 0x3) | (Function));
+ UndiLoaderTable->Bx = 0x0;
+ UndiLoaderTable->Dx = 0x0;
+ UndiLoaderTable->Di = 0x0;
+ UndiLoaderTable->Es = 0x0;
+
+ //
+ // set these OUT values to zero in order to ensure that
+ // uninitialized memory is not mistaken for display data
+ //
+ UndiLoaderTable->PXEptr.Offset = 0;
+ UndiLoaderTable->PXEptr.Segment = 0;
+ UndiLoaderTable->PXENVptr.Segment = 0;
+ UndiLoaderTable->PXENVptr.Offset = 0;
+
+ DEBUG (
+ (DEBUG_INIT,
+ "The NIC is located at Bus 0x%X, Device 0x%X, Function 0x%X\n\r",
+ Bus,
+ Device,
+ Function)
+ );
+
+ //
+ // These are the values that set up the ACTUAL IA32 machine state, whether in
+ // Real16 in EFI32 or the IVE for IA64
+ // register values are unused except for CS:IP and SS:SP
+ //
+ InOutRegs.X.AX = 0;
+ InOutRegs.X.BX = 0;
+ InOutRegs.X.CX = 0;
+ InOutRegs.X.DX = 0;
+ InOutRegs.X.SI = 0;
+ InOutRegs.X.DI = 0;
+ InOutRegs.X.BP = 0;
+ InOutRegs.X.DS = 0;
+ InOutRegs.X.ES = 0;
+ //
+ // just to be clean
+ //
+ DEBUG ((DEBUG_NET, "The way this game works is that the SS:SP +4 should point\n\r"));
+ DEBUG ((DEBUG_NET, "to the contents of the UndiLoaderTable\n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "The Undi Loader Table is at address = 0x%X\n\r",
+ (UINT32)(UINTN) UndiLoaderTable)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "The segment and offsets are 0x%X and 0x%X, resp\n",
+ TO_SEGMENT (UndiLoaderTable),
+ TO_OFFSET (UndiLoaderTable))
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "The Linear Address of the UNDI Loader entry is 0x%X\n",
+ RomAddress + RomIdTableAddress->UNDI_Loader)
+ );
+
+ DEBUG (
+ (DEBUG_NET,
+ "The Address offset of the UNDI Loader entry is 0x%X\n",
+ RomIdTableAddress->UNDI_Loader)
+ );
+
+ DEBUG ((DEBUG_NET, "Before the call, we have...\n\r"));
+ Print_Undi_Loader_Table (UndiLoaderTable);
+
+ Segment = ((UINT16) (RShiftU64 (RomAddress, 4) & 0xFFFF));
+ DEBUG ((DEBUG_NET, "The Segment of the call is 0x%X\n\r", Segment));
+
+ //
+ // make the call into the UNDI Code
+ //
+ DEBUG ((DEBUG_INIT, "Make the call into the UNDI code now\n\r"));
+
+ DEBUG ((DEBUG_NET, "\nThe 20-BIt address of the Call, and the location \n\r"));
+ DEBUG ((DEBUG_NET, "\twhere we should be able to set a breakpoint is \n\r"));
+ DEBUG (
+ (DEBUG_NET,
+ "\t\t0x%X, from SEG:OFF 0x%X:0x%X\n\r\n\r",
+ Segment * 0x10 + RomIdTableAddress->UNDI_Loader,
+ Segment,
+ RomIdTableAddress->UNDI_Loader)
+ );
+
+ ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 (
+ SimpleNetworkDevice->LegacyBios,
+ Segment, // Input segment
+ (UINT16) RomIdTableAddress->UNDI_Loader, // Offset
+ &InOutRegs, // Ptr to Regs
+ Buffer, // Reference to Stack
+ Size // Size of the Stack
+ );
+ if (ThunkFailed) {
+ return EFI_ABORTED;
+ }
+
+ DEBUG (
+ (DEBUG_NET,
+ "The return code UndiLoaderTable->Status is = 0x%X\n\r",
+ UndiLoaderTable->Status)
+ );
+ DEBUG (
+ (DEBUG_NET,
+ "This error code should match eax, which is = 0x%X\n\r",
+ InOutRegs.X.AX)
+ );
+
+ DEBUG ((DEBUG_NET, "Now returned from the UNDI code\n\r"));
+
+ DEBUG ((DEBUG_NET, "After the call, we have...\n\r"));
+ Print_Undi_Loader_Table (UndiLoaderTable);
+
+ DEBUG ((DEBUG_NET, "Display the PXENV+ and !PXE tables exported by NIC\n\r"));
+ Print_PXENV_Table ((VOID *)(UINTN)((UndiLoaderTable->PXENVptr.Segment << 4) | UndiLoaderTable->PXENVptr.Offset));
+ Print_PXE_Table ((VOID *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset));
+
+ Pxe = (PXE_T *)(UINTN)((UndiLoaderTable->PXEptr.Segment << 4) + UndiLoaderTable->PXEptr.Offset);
+ SimpleNetworkDevice->Nii.Id = (UINT64)(UINTN) Pxe;
+
+ //
+ // FreePool (Buffer);
+ // paranoia - make sure a valid !PXE structure
+ //
+ if (CompareMem (Pxe->Signature, PXE_SIG, sizeof Pxe->Signature) != 0) {
+ DEBUG ((DEBUG_ERROR, "!PXE Structure not found....\n\r"));
+ return EFI_NOT_FOUND;
+ //
+ // its not - keep looking
+ //
+ }
+
+ if (CalculateSum8 ((UINT8 *) Pxe, Pxe->StructLength) != 0) {
+ DEBUG ((DEBUG_ERROR, "!PXE Checksum Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ if (Pxe->StructLength < (UINT8 *) &Pxe->FirstSelector - (UINT8 *) Pxe->Signature) {
+ DEBUG ((DEBUG_ERROR, "!PXE Length Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ if ((((UINTN) Pxe->Undi.Segment) << 4) + Pxe->Undi.Offset != (UINTN) RomIdTableAddress) {
+ DEBUG ((DEBUG_ERROR, "!PXE RomId Address Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // This is the magic to bind the global PXE interface
+ // This dirtiness is for non-protocol shrouded access
+ //
+ SimpleNetworkDevice->PxeEntrySegment = Pxe->EntryPointSP.Segment;
+
+ if (SimpleNetworkDevice->PxeEntrySegment == 0) {
+ DEBUG ((DEBUG_ERROR, "!PXE EntryPointSP segment Error\n\r"));
+ return EFI_NOT_FOUND;
+ }
+
+ SimpleNetworkDevice->PxeEntryOffset = Pxe->EntryPointSP.Offset;
+
+ DEBUG (
+ (
+ DEBUG_NET, "The entry point is 0x%X:0x%X\n\r", SimpleNetworkDevice->PxeEntrySegment, SimpleNetworkDevice->
+ PxeEntryOffset
+ )
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Effect the Far Call into the PXE Layer
+
+ Note: When using a 32-bit stack segment do not push 32-bit words onto the stack. The PXE API
+ services will not work, unless there are three 16-bit parameters pushed onto the stack.
+ push DS ;Far pointer to parameter structure
+ push offset pxe_data_call_struct ;is pushed onto stack.
+ push Index ;UINT16 is pushed onto stack.
+ call dword ptr (s_PXE ptr es:[di]).EntryPointSP
+ add sp, 6 ;Caller cleans up stack.
+
+ @param SimpleNetworkDevice Device instance for simple network
+ @param Table Point to parameter/retun value table for legacy far call
+ @param TableSize The size of paramter/return value table
+ @param CallIndex The index of legacy call.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+MakePxeCall (
+ EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT VOID *Table,
+ IN UINTN TableSize,
+ IN UINT16 CallIndex
+ )
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET InOutRegs;
+ UINT16 *BPtr;
+ VOID *Buffer;
+ UINTN Size;
+ VOID *MemPageAddress;
+ UINTN Index;
+ BOOLEAN ThunkFailed;
+
+ DEBUG ((DEBUG_NET, "MakePxeCall(CallIndex = %02x, Table = %X, TableSize = %d)\n", CallIndex, Table, TableSize));
+
+ if (SimpleNetworkDevice->PxeEntrySegment == 0 && SimpleNetworkDevice->PxeEntryOffset == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Allocate a transient data structure for the argument table
+ // This table needs to have the input XXX_t structure copied into here.
+ // The PXE UNDI can only grab this table when it's below one-MB, and
+ // this implementation will not try to push this table on the stack
+ // (although this is a possible optimization path since EFI always allocates
+ // 4K as a minimum page size...............)
+ //
+ Status = BiosSnp16AllocatePagesBelowOneMb (
+ TableSize / EFI_PAGE_SIZE + 1,
+ &MemPageAddress
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "We had a failure in AllocatePages, status code = 0x%X\n", Status));
+ return Status;
+ }
+ //
+ // Copy the > 1MB pool table to a sub-1MB buffer
+ //
+ CopyMem (MemPageAddress, Table, TableSize);
+
+ //
+ // Allocate space for IA-32 register context
+ //
+ ZeroMem (&InOutRegs, sizeof (InOutRegs));
+ InOutRegs.X.ES = SimpleNetworkDevice->PxeEntrySegment;
+ InOutRegs.X.DI = SimpleNetworkDevice->PxeEntryOffset;
+
+ //
+ // The game here is to build the stack which will subsequently
+ // get copied down below 1 MB by the FarCall primitive.
+ // This is now our working stack
+ //
+ Size = 6;
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ Size,
+ &Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BPtr = (UINT16 *) Buffer;
+ *BPtr++ = CallIndex;
+ //
+ // SP + 2
+ //
+ *BPtr++ = TO_OFFSET (MemPageAddress);
+ *BPtr++ = TO_SEGMENT (MemPageAddress);
+
+ DEBUG ((DEBUG_NET, "State before FarCall86\n"));
+ DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer));
+ BPtr = (UINT16 *) Buffer;
+ DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2)));
+ DEBUG ((DEBUG_NET, " MemPage = "));
+ for (Index = 0; Index < TableSize; Index++) {
+ DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index)));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ ThunkFailed = SimpleNetworkDevice->LegacyBios->FarCall86 (
+ SimpleNetworkDevice->LegacyBios,
+ SimpleNetworkDevice->PxeEntrySegment, // Input segment
+ SimpleNetworkDevice->PxeEntryOffset,
+ &InOutRegs, // Ptr to Regs
+ Buffer, // Reference to Stack
+ 6 // Size of the Stack
+ );
+ if (ThunkFailed) {
+ return EFI_ABORTED;
+ }
+
+ DEBUG ((DEBUG_NET, "State after FarCall86\n"));
+ DEBUG ((DEBUG_NET, "The Buffer is at 0x%X\n\r", Buffer));
+ BPtr = (UINT16 *) Buffer;
+ DEBUG ((DEBUG_NET, " Buffer = %04X %04X %04X", *BPtr, *(BPtr + 1), *(BPtr + 2)));
+ DEBUG ((DEBUG_NET, " MemPage = "));
+ for (Index = 0; Index < TableSize; Index++) {
+ DEBUG ((DEBUG_NET, " %02x", *((UINT8 *) MemPageAddress + Index)));
+ }
+
+ DEBUG ((DEBUG_NET, "\n"));
+
+ //
+ // Copy the sub 1MB table to > 1MB table
+ //
+ CopyMem (Table, MemPageAddress, TableSize);
+
+ //
+ // For PXE UNDI call, AX contains the return status.
+ // Convert the PXE UNDI Status to EFI_STATUS type
+ //
+ if (InOutRegs.X.AX == PXENV_EXIT_SUCCESS) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ //
+ // Clean up house
+ //
+ gBS->FreePool (Buffer);
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) MemPageAddress, TableSize / EFI_PAGE_SIZE + 1);
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h
new file mode 100644
index 0000000000..54503a840f
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Pxe.h
@@ -0,0 +1,613 @@
+/** @file
+ These are PXE Specification 2.1-compliant data structures and defines.
+
+ This file relies upon the existence of a PXE-compliant ROM
+ in memory, as defined by the Preboot Execution Environment
+ Specification (PXE), Version 2.1, located at
+
+ http://developer.intel.com/ial/wfm/wfmspecs.htm
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PXEDEF_H_
+#define _PXEDEF_H_
+
+#pragma pack(1)
+
+//
+// PXE structure signatures
+//
+#define BC_ROMID_SIG "$BC$"
+#define UNDI_ROMID_SIG "UNDI"
+#define BUSD_ROMID_SIG "BUSD"
+
+#define PXE_SIG "!PXE"
+#define PXENV_SIG "PXENV+"
+
+#define BC_ROMID_REV 0x00
+#define UNDI_ROMID_REV 0x00
+#define BUSD_ROMID_REV 0x00
+
+#define PXE_REV 0x00
+#define PXENV_REV 0x0201
+
+#define PXENV_PTR SIGNATURE_32 ('P', 'X', 'E', 'N')
+#define PXE_PTR SIGNATURE_32 ('!', 'P', 'X', 'E')
+#define UNDI_ROMID_SIG_PTR SIGNATURE_32 ('U', 'N', 'D', 'I')
+
+typedef UINT16 SEGSEL; // Real mode segment or protected mode selector.
+typedef UINT16 OFF16; // Unsigned 16bit offset.
+typedef UINT32 ADDR32;
+
+//
+// Bus types
+//
+#define PXENV_BUS_ISA 0
+#define PXENV_BUS_EISA 1
+#define PXENV_BUS_MCA 2
+#define PXENV_BUS_PCI 3
+#define PXENV_BUS_VESA 4
+#define PXENV_BUS_PCMCIA 5
+
+//
+//
+// Result codes returned in AX by a PXENV API service.
+//
+#define PXENV_EXIT_SUCCESS 0x0000
+#define PXENV_EXIT_FAILURE 0x0001
+
+//
+// Status codes returned in the status word of PXENV API parameter structures.
+//
+// Generic API errors - these do not match up with the M0x or E0x messages
+// that are reported by the loader.
+//
+#define PXENV_STATUS_SUCCESS 0x00
+#define PXENV_STATUS_FAILURE 0x01
+#define PXENV_STATUS_BAD_FUNC 0x02
+#define PXENV_STATUS_UNSUPPORTED 0x03
+#define PXENV_STATUS_KEEP_UNDI 0x04
+#define PXENV_STATUS_KEEP_ALL 0x05
+#define PXENV_STATUS_OUT_OF_RESOURCES 0x06
+
+typedef enum {
+ PxeEnvStatus_Success,
+ PxeEnvStatus_Failure,
+ PxeEnvStatus_BadFunc,
+ PxeEnvStatus_Unsupported,
+ PxeEnvStatus_KeepUndi,
+ PxeEnvStatus_KeepAll
+} EFI_PXE_STATUS;
+
+/* Driver errors (0x60 to 0x6F) */
+
+// These errors are for UNDI compatible NIC drivers.
+#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60
+#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61
+#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64
+#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65
+#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66
+#define PXENV_STATUS_UNDI_BAD_MAC_ADDR 0x67
+#define PXENV_STATUS_UNDI_BAD_EEPROM_CKSUM 0x68
+#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69
+#define PXENV_STATUS_UNDI_INVALID_STATE 0x6A
+#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B
+#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C
+
+typedef struct {
+ UINT16 Seg_Addr;
+ UINT32 Phy_Addr;
+ UINT16 Seg_Size;
+} NEWSEGDESC_T;
+
+typedef struct {
+ OFF16 Offset;
+ SEGSEL Segment;
+} SEGOFF16;
+
+typedef struct {
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.
+ UINT8 StructLength; ///< Length of this structure in bytes.
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.
+ UINT8 StructRev; ///< Structure format revision number.
+ UINT8 UNDI_Rev[3]; ///< API revision number stored in Intel order.
+ //
+ // Revision 2.1.0 == 0x00, 0x01, 0x02
+ //
+ UINT16 UNDI_Loader; ///< Offset of UNDI loader routine in the option ROM image.
+ UINT16 StackSize; ///< Minimum stack segment size, in bytes, needed to load and run the UNDI.
+ UINT16 DataSize; ///< UNDI runtime code and data
+ UINT16 CodeSize; ///< segment sizes.
+ UINT8 BusType[4]; ///< 'ISAR', 'EISA', 'PCIR', 'PCCR'
+} UNDI_ROMID_T;
+
+typedef struct {
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.
+ UINT8 StructLength; ///< Length of this structure in bytes.
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.
+ UINT8 StructRev; ///< Structure format revision number.
+ UINT8 BC_Rev[3]; ///< API revision number stored in Intel order.
+ //
+ // Revision 2.1.0 == 0x00, 0x01, 0x02
+ //
+ UINT16 BC_Loader; ///< Offset of base-code loader routine in the option ROM image.
+ UINT16 StackSize; ///< Minimum stack segment size (bytes) needed to load/run base-code.
+ UINT16 DataSize; ///< Base-code runtime code and data
+ UINT16 CodeSize; ///< segment sizes.
+} BC_ROMID_T;
+
+typedef struct {
+ UINT8 Signature[4]; ///< Structure signature is not NULL terminated.
+ UINT8 StructLength; ///< Length of this structure in bytes.
+ UINT8 StructCksum; ///< Use to make byte checksum of this structure == zero.
+ UINT8 StructRev; ///< Structure format revision number.
+ UINT8 Reserved1; ///< must be zero
+ ///
+ /// UNDI_ROMID_T __FAR *UNDI;// Far pointer to UNDI ROMID
+ ///
+ SEGOFF16 Undi;
+
+ ///
+ /// BC_ROMID_T __FAR *Base; // Far pointer to base-code ROMID
+ ///
+ SEGOFF16 Base;
+
+ ///
+ /// UINT16 (__FAR __CDECL *EntryPointSP)(UINT16 func, VOID __FAR *param);
+ /// 16bit stack segment API entry point. This will be seg:off in
+ /// real mode and sel:off in 16:16 protected mode.
+ ///
+ SEGOFF16 EntryPointSP;
+
+ ///
+ /// UINT16 (__FAR __CDECL *EntryPointESP)(UINT16 func, VOID __FAR *param);
+ /// 32bit stack segment API entry point. This will be sel:off.
+ /// In real mode, sel == 0
+ ///
+ SEGOFF16 EntryPointESP;
+ ///
+ /// UINT16 (__FAR __CDECL *StatusCallout)(UINT16 param);
+ /// Address of DHCP/TFTP status callout routine.
+ ///
+ SEGOFF16 StatusCallout;
+ UINT8 Reserved2; ///< must be zero
+ UINT8 SegDescCnt; ///< Number of segment descriptors in this structure.
+ UINT16 FirstSelector; ///< First segment descriptor in GDT assigned to PXE.
+ NEWSEGDESC_T Stack;
+ NEWSEGDESC_T UNDIData;
+ NEWSEGDESC_T UNDICode;
+ NEWSEGDESC_T UNDICodeWrite;
+ NEWSEGDESC_T BC_Data;
+ NEWSEGDESC_T BC_Code;
+ NEWSEGDESC_T BC_CodeWrite;
+} PXE_T;
+
+typedef struct {
+ CHAR8 Signature[6]; ///< "PXENV+"
+ UINT16 Version; ///< PXE version number. LSB is minor version. MSB is major version.
+ UINT8 StructLength; ///< Length of PXE-2.0 Entry Point structure in bytes.
+ UINT8 StructCksum; ///< Used to make structure checksum equal zero.
+ UINT32 RMEntry; ///< Real mode API entry point segment:offset.
+ UINT32 PMEntryOff; ///< Protected mode API entry point
+ UINT16 PMEntrySeg; ///< segment:offset. This will always be zero. Protected mode API calls
+ ///< must be made through the API entry points in the PXE Runtime ID structure.
+
+ UINT16 StackSeg; ///< Real mode stack segment.
+ UINT16 StackSize; ///< Stack segment size in bytes.
+ UINT16 BaseCodeSeg; ///< Real mode base-code code segment.
+ UINT16 BaseCodeSize; ///< Base-code code segment size
+ UINT16 BaseDataSeg; ///< Real mode base-code data segment.
+ UINT16 BaseDataSize; ///< Base-code data segment size
+ UINT16 UNDIDataSeg; ///< Real mode UNDI data segment.
+ UINT16 UNDIDataSize; ///< UNDI data segment size in bytes.
+ UINT16 UNDICodeSeg; ///< Real mode UNDI code segment.
+ UINT16 UNDICodeSize; ///< UNDI code segment size in bytes.
+ PXE_T *RuntimePtr; ///< Real mode segment:offset pointer to PXE Runtime ID structure.
+} PXENV_T;
+
+typedef struct {
+ OUT UINT16 Status;
+ IN OUT UINT16 Ax;
+ IN OUT UINT16 Bx;
+ IN OUT UINT16 Dx;
+ IN OUT UINT16 Di;
+ IN OUT UINT16 Es;
+ IN OUT UINT16 Undi_Ds;
+ IN OUT UINT16 Undi_Cs;
+ OUT SEGOFF16 PXEptr;
+ OUT SEGOFF16 PXENVptr;
+} UNDI_LOADER_T;
+
+//
+// Put in some UNDI-specific arguments
+//
+#define PXENV_START_UNDI 0x0000
+#define PXENV_UNDI_STARTUP 0x0001
+#define PXENV_UNDI_CLEANUP 0x0002
+#define PXENV_UNDI_INITIALIZE 0x0003
+#define PXENV_UNDI_RESET_NIC 0x0004
+#define PXENV_UNDI_SHUTDOWN 0x0005
+#define PXENV_UNDI_OPEN 0x0006
+#define PXENV_UNDI_CLOSE 0x0007
+#define PXENV_UNDI_TRANSMIT 0x0008
+#define PXENV_UNDI_SET_MCAST_ADDR 0x0009
+#define PXENV_UNDI_SET_STATION_ADDR 0x000A
+#define PXENV_UNDI_SET_PACKET_FILTER 0x000B
+#define PXENV_UNDI_GET_INFORMATION 0x000C
+#define PXENV_UNDI_GET_STATISTICS 0x000D
+#define PXENV_UNDI_CLEAR_STATISTICS 0x000E
+#define PXENV_UNDI_INITIATE_DIAGS 0x000F
+#define PXENV_UNDI_FORCE_INTERRUPT 0x0010
+#define PXENV_UNDI_GET_MCAST_ADDR 0x0011
+#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+#define PXENV_UNDI_GET_NDIS_INFO 0x0013
+#define PXENV_UNDI_ISR 0x0014
+#define PXENV_STOP_UNDI 0x0015
+#define PXENV_UNDI_GET_STATE 0x0016
+
+#define ADDR_LEN 16
+#define MAXNUM_MCADDR 8
+#define IPLEN 4 ///< length of an IP address
+#define XMT_DESTADDR 0x0000 ///< destination address given
+#define XMT_BROADCAST 0x0001 ///< use broadcast address
+
+typedef struct {
+ UINT16 MCastAddrCount; ///< In: Number of multi-cast
+
+ /* addresses. */
+ UINT8 MCastAddr[MAXNUM_MCADDR][ADDR_LEN]; /* In: */
+
+ /* list of multi-cast addresses. */
+
+ /* Each address can take up to */
+
+ /* ADDR_LEN bytes and a maximum */
+
+ /* of MAXNUM_MCADDR address can */
+
+ /* be provided*/
+} PXENV_UNDI_MCAST_ADDR_T;
+
+/* Definitions of TFTP API parameter structures.
+ */
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN UINT16 Ax; ///< In: These register fields must be
+ IN UINT16 Bx; ///< filled in with the same data
+ IN UINT16 Dx; ///< that was passed to the MLID
+ IN UINT16 Di; ///< option ROM boot code by the
+ IN UINT16 Es; ///< system BIOS.
+} PXENV_START_UNDI_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_STARTUP_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_CLEANUP_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+
+ ///
+ /// This is an input parameter and is a 32-bit physical address of
+ /// a memory copy of the driver module in the protocol.ini file
+ /// obtained from the Protocol Manager driver(refer to NDIS 2.0
+ /// specifications). This parameter is basically supported for
+ /// the universal NDIS driver to pass the information contained in
+ /// protocol.ini file to the NIC driver for any specific
+ /// configuration of the NIC. (Note that the module
+ /// identification in the protocol.ini file was done by NDIS
+ /// itself.) This value can be NULL for for any other application
+ /// interfacing to the Universal NIC Driver.
+ ///
+ IN UINT32 ProtocolIni;
+ UINT8 Reserved[8];
+} PXENV_UNDI_INITIALIZE_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN PXENV_UNDI_MCAST_ADDR_T R_Mcast_Buf; ///< multicast address list
+ /* see note below */
+} PXENV_UNDI_RESET_T;
+
+/*++
+ Note: The NIC driver does not remember the multicast
+ addresses provided in any call. So the application must
+ provide the multicast address list with all the calls that
+ reset the receive unit of the adapter.
+ --*/
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_SHUTDOWN_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+
+ ///
+ /// This is an input parameter and is adapter specific. This is
+ /// supported for Universal NDIS 2.0 driver to pass down the Open
+ /// flags provided by the protocol driver (See NDIS 2.0
+ /// specifications). This can be zero.
+ ///
+ IN UINT16 OpenFlag; ///< In: See description below
+ IN UINT16 PktFilter; ///< In: Filter for receiving
+
+ /* packet. It takes the following */
+
+ /* values, multiple values can be */
+
+ /* ORed together. */
+#define FLTR_DIRECTED 0x0001 ///< directed/multicast
+#define FLTR_BRDCST 0x0002 ///< broadcast packets
+#define FLTR_PRMSCS 0x0004 ///< any packet on LAN
+#define FLTR_SRC_RTG 0x0008 ///< source routing packet
+ IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; /* In: */
+ /* See t_PXENV_UNDI_MCAST_ADDR. */
+} PXENV_UNDI_OPEN_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_CLOSE_T;
+
+#define MAX_DATA_BLKS 8
+
+typedef struct {
+ IN UINT16 ImmedLength; ///< In: Data buffer length in
+
+ /* bytes. */
+ UINT16 XmitOffset; ///< 16-bit segment & offset of the
+ UINT16 XmitSegment; ///< immediate data buffer.
+ UINT16 DataBlkCount; ///< In: Number of data blocks.
+ struct DataBlk {
+ UINT8 TDPtrType; ///< 0 => 32 bit Phys pointer in TDDataPtr, not supported in this version of LSA
+ ///< 1 => seg:offser in TDDataPtr which can be a real mode or 16-bit protected mode pointer
+ UINT8 TDRsvdByte; ///< Reserved, must be zero.
+ UINT16 TDDataLen; ///< Data block length in bytes.
+ UINT16 TDDataPtrOffset; ///< Far pointer to data buffer.
+ UINT16 TDDataPtrSegment; ///< Far pointer to data buffer.
+ } DataBlock[MAX_DATA_BLKS];
+}
+PXENV_UNDI_TBD_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+
+ ///
+ /// This is the protocol of the upper layer that is calling
+ /// NICTransmit call. If the upper layer has filled the media
+ /// header this field must be 0.
+ ///
+ IN UINT8 Protocol;
+#define P_UNKNOWN 0
+#define P_IP 1
+#define P_ARP 2
+#define P_RARP 3
+
+ ///
+ /// If this flag is 0, the NIC driver expects a pointer to the
+ /// destination media address in the field DestMediaAddr. If 1,
+ /// the NIC driver fills the broadcast address for the
+ /// destination.
+ ///
+ IN UINT8 XmitFlag;
+#define XMT_DESTADDR 0x0000 ///< destination address given
+#define XMT_BROADCAST 0x0001 ///< use broadcast address
+
+ ///
+ /// This is a pointer to the hardware address of the destination
+ /// media. It can be null if the destination is not known in
+ /// which case the XmitFlag contains 1 for broadcast. Destination
+ /// media address must be obtained by the upper level protocol
+ /// (with Address Resolution Protocol) and NIC driver does not do
+ /// any address resolution.
+ ///
+ IN UINT16 DestAddrOffset; ///< 16-bit segment & offset of the
+ IN UINT16 DestAddrSegment; ///< destination media address
+
+
+ IN UINT16 TBDOffset; ///< 16-bit segment & offset of the
+ IN UINT16 TBDSegment; ///< transmit buffer descriptor of type
+
+ /// XmitBufferDesc
+ IN UINT32 Reserved[2];
+} PXENV_UNDI_TRANSMIT_T;
+
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN PXENV_UNDI_MCAST_ADDR_T McastBuffer; ///< In:
+} PXENV_UNDI_SET_MCAST_ADDR_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN UINT8 StationAddress[ADDR_LEN]; ///< new address to be set
+} PXENV_UNDI_SET_STATION_ADDR_T;
+
+typedef struct s_PXENV_UNDI_SET_PACKET_FILTER {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN UINT8 Filter; ///< In: Receive filter value.
+} PXENV_UNDI_SET_PACKET_FILTER_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ OUT UINT16 BaseIo; ///< Out: Adapter's Base IO
+ OUT UINT16 IntNumber; ///< Out: IRQ number
+ OUT UINT16 MaxTranUnit; ///< Out: MTU
+ OUT UINT16 HwType; ///< Out: type of protocol at hardware level
+
+#define ETHER_TYPE 1
+#define EXP_ETHER_TYPE 2
+#define IEEE_TYPE 6
+#define ARCNET_TYPE 7
+ /*++
+ other numbers can be obtained from rfc1010 for "Assigned
+ Numbers". This number may not be validated by the application
+ and hence adding new numbers to the list should be fine at any
+ time.
+ --*/
+ OUT UINT16 HwAddrLen; ///< Out: actual length of hardware address
+ OUT UINT8 CurrentNodeAddress[ADDR_LEN]; ///< Out: Current hardware address
+ OUT UINT8 PermNodeAddress[ADDR_LEN]; ///< Out: Permanent hardware address
+ OUT UINT16 ROMAddress; ///< Out: ROM address
+ OUT UINT16 RxBufCt; ///< Out: receive Queue length
+ OUT UINT16 TxBufCt; ///< Out: Transmit Queue length
+} PXENV_UNDI_GET_INFORMATION_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ OUT UINT32 XmtGoodFrames; ///< Out: No. of good transmissions
+ OUT UINT32 RcvGoodFrames; ///< Out: No. of good frames received
+ OUT UINT32 RcvCRCErrors; ///< Out: No. of frames with CRC error
+ OUT UINT32 RcvResourceErrors; ///< Out: no. of frames discarded
+ /* Out: receive Queue full */
+} PXENV_UNDI_GET_STATISTICS_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_CLEAR_STATISTICS_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_INITIATE_DIAGS_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_UNDI_FORCE_INTERRUPT_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ IN UINT32 InetAddr; ///< In: IP Multicast Address
+ OUT UINT8 MediaAddr[ADDR_LEN]; ///< Out: corresponding hardware
+ /* multicast address */
+} PXENV_UNDI_GET_MCAST_ADDR_T;
+
+typedef struct {
+ OUT UINT16 Vendor_ID; ///< OUT:
+ OUT UINT16 Dev_ID; ///< OUT:
+ OUT UINT8 Base_Class; ///< OUT:
+ OUT UINT8 Sub_Class; ///< OUT:
+ OUT UINT8 Prog_Intf; ///< OUT: program interface
+ OUT UINT8 Rev; ///< OUT: Revision number
+ OUT UINT16 BusDevFunc; ///< OUT: Bus, Device & Function numbers
+ OUT UINT16 SubVendor_ID; ///< OUT:
+ OUT UINT16 SubDevice_ID; ///< OUT:
+} PCI_INFO_T;
+
+typedef struct {
+ OUT UINT32 EISA_Dev_ID; ///< Out:
+ OUT UINT8 Base_Class; ///< OUT:
+ OUT UINT8 Sub_Class; ///< OUT:
+ OUT UINT8 Prog_Intf; ///< OUT: program interface
+ OUT UINT16 CardSelNum; ///< OUT: Card Selector Number
+ OUT UINT8 Reserved; ///< to make it 10 bytes
+} PNP_INFO_T;
+
+
+typedef union {
+ PCI_INFO_T Pci;
+ PNP_INFO_T Pnp;
+} PCI_PNP_INFO_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx
+ OUT UINT8 NicType; ///< OUT: 2=PCI, 3=PnP
+ PCI_PNP_INFO_T PciPnpInfo;
+} PXENV_UNDI_GET_NIC_TYPE_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx
+ OUT UINT8 IfaceType[16]; ///< OUT: Type name of MAC, AsciiZ
+
+ /* format. This is used by the */
+
+ /* Universal NDIS Driver to fill */
+
+ /* the driver type in it's MAC */
+
+ /* Service specific */
+
+ /* characteristic table */
+ OUT UINT32 LinkSpeed; ///< OUT:
+ OUT UINT32 ServiceFlags; ///< OUT: as defined in NDIS Spec 2.0X
+ OUT UINT32 Reserved[4]; ///< OUT: will be filled with 0s till defined
+} PXENV_UNDI_GET_NDIS_INFO_T;
+
+typedef struct {
+ OUT UINT16 Status; ///< OUT: PXENV_STATUS_xxx
+ IN OUT UINT16 FuncFlag; ///< In: PXENV_UNDI_ISR_IN_xxx
+
+ /* Out: PXENV_UNDI_ISR_OUT_xxx */
+ OUT UINT16 BufferLength;
+ OUT UINT16 FrameLength;
+ OUT UINT16 FrameHeaderLength;
+ OUT UINT16 FrameOffset;
+ OUT UINT16 FrameSegSel;
+ OUT UINT8 ProtType;
+ OUT UINT8 PktType;
+} PXENV_UNDI_ISR_T;
+
+#define PXENV_UNDI_ISR_IN_START 1 /* This function must be first */
+
+/* when an interrupt is received. */
+
+/* It will tell us if the intr */
+
+/* was generated by our device. */
+#define PXENV_UNDI_ISR_IN_PROCESS 2 /* Call to start processing one of */
+
+/* our interrupts. */
+#define PXENV_UNDI_ISR_IN_GET_NEXT 3 /* Call to start/continue receiving */
+
+/* data from receive buffer(s). */
+
+/*++
+
+ Possible responses from PXENV_UNDI_ISR_IN_START
+
+ --*/
+#define PXENV_UNDI_ISR_OUT_OURS 0 ///< This is our interrupt. Deal with it.
+#define PXENV_UNDI_ISR_OUT_NOT_OURS 1 ///< This is not our interrupt.
+
+/*++
+
+ Possible responses from PXENV_UNDI_ISR_IN_PROCESS and
+ PXENV_UNDI_ISR_IN_PROCESS
+
+--*/
+#define PXENV_UNDI_ISR_OUT_DONE 0 ///< We are done processing this interrupt.
+#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 ///< We completed a transmit interrupt.
+#define PXENV_UNDI_ISR_OUT_RECEIVE 3 ///< Get data from receive buffer.
+
+#define PXENV_UNDI_ISR_OUT_BUSY 4 /* ? */
+
+typedef struct {
+ UINT16 Status; ///< Out: PXENV_STATUS_xxx
+} PXENV_STOP_UNDI_T;
+
+#define PXENV_UNDI_STARTED 1 ///< not even initialized
+#define PXENV_UNDI_INITIALIZED 2 ///< initialized and closed (not opened)
+#define PXENV_UNDI_OPENED 3 ///< initialized & opened
+
+typedef struct {
+ OUT UINT16 Status; ///< Out: PXENV_STATUS_xxx
+ UINT16 UNDI_State;
+} PXENV_UNDI_GET_STATE_T;
+
+#pragma pack()
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c
new file mode 100644
index 0000000000..d35fc3f430
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/PxeUndi.c
@@ -0,0 +1,1254 @@
+/** @file
+ Wrapper routines that use a PXE-enabled NIC option ROM to
+ supply internal routines for an EFI SNI (Simple Network
+ Interface) Protocol.
+
+ This file relies upon the existence of a PXE-compliant ROM
+ in memory, as defined by the Preboot Execution Environment
+ Specification (PXE), Version 2.1, located at
+
+ http://developer.intel.com/ial/wfm/wfmspecs.htm
+
+Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosSnp16.h"
+
+/**
+ PXE
+ START UNDI
+ Op-Code: PXENV_START_UNDI (0000h)
+ Input: Far pointer to a PXENV_START_UNDI_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This service is used to pass the BIOS parameter registers to the UNDI driver. The UNDI driver is
+ responsible for saving the information it needs to communicate with the hardware.
+ This service is also responsible for hooking the Int 1Ah service routine
+ Note: This API service must be called only once during UNDI Option ROM boot.
+ The UNDI driver is responsible for saving this information and using it every time
+ PXENV_UNDI_STARTUP is called.
+ Service cannot be used in protected mode.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 AX;
+ UINT16 BX;
+ UINT16 DX;
+ UINT16 DI;
+ UINT16 ES;
+ } PXENV_START_UNDI_T;
+ Set before calling API service
+ AX, BX, DX, DI, ES: BIOS initialization parameter registers. These
+ fields should contain the same information passed to the option ROM
+ initialization routine by the Host System BIOS. Information about the
+ contents of these registers can be found in the [PnP], [PCI] and
+ [BBS] specifications.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeStartUndi (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_START_UNDI_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_START_UNDI_T),
+ PXENV_START_UNDI
+ );
+}
+
+/**
+ PXE
+ UNDI STARTUP
+ Op-Code: PXENV_UNDI_STARTUP (0001h)
+ Input: Far pointer to a PXENV_UNDI_STARTUP_T parameter structure that has been initialized by the
+ caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This API is responsible for initializing the contents of the UNDI code & data segment for proper
+ operation. Information from the !PXE structure and the first PXENV_START_UNDI API call is used
+ to complete this initialization. The rest of the UNDI APIs will not be available until this call has
+ been completed.
+ Note: PXENV_UNDI_STARTUP must not be called again without first calling
+ PXENV_UNDI_SHUTDOWN.
+ PXENV_UNDI_STARTUP and PXENV_UNDI_SHUTDOWN are no longer responsible for
+ chaining interrupt 1Ah. This must be done by the PXENV_START_UNDI and
+ PXENV_STOP_UNDI API calls.
+ This service cannot be used in protected mode.
+ typedef struct
+ {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_STARTUP_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiStartup (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_STARTUP_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_STARTUP_T),
+ PXENV_UNDI_STARTUP
+ );
+}
+
+/**
+ PXE
+ UNDI CLEANUP
+ Op-Code: PXENV_UNDI_CLEANUP (0002h)
+ Input: Far pointer to a PXENV_UNDI_CLEANUP_T parameter structure.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field
+ in the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call will prepare the network adapter driver to be unloaded from memory. This call must be
+ made just before unloading the Universal NIC Driver. The rest of the API will not be available
+ after this call executes.
+ This service cannot be used in protected mode.
+ typedef struct {
+ PXENX_STATUS Status;
+ } PXENV_UNDI_CLEANUP_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiCleanup (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLEANUP_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_CLEANUP_T),
+ PXENV_UNDI_CLEANUP
+ );
+}
+
+/**
+ PXE
+ UNDI INITIALIZE
+ Op-Code: PXENV_UNDI_INITIALIZE (0003h)
+ Input: Far pointer to a PXENV_UNDI_INITIALIZE_T parameter structure that has been initialized by the
+ caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the adapter and programs it with default parameters. The default parameters used
+ are those supplied to the most recent UNDI_STARTUP call. This routine does not enable the
+ receive and transmit units of the network adapter to readily receive or transmit packets. The
+ application must call PXENV_UNDI_OPEN to logically connect the network adapter to the network.
+ This call must be made by an application to establish an interface to the network adapter driver.
+ Note: When the PXE code makes this call to initialize the network adapter, it passes a NULL pointer for
+ the Protocol field in the parameter structure.
+ typedef struct {
+ PXENV_STATUS Status;
+ ADDR32 ProtocolIni;
+ UINT8 reserved[8];
+ } PXENV_UNDI_INITIALIZE_T;
+ Set before calling API service
+ ProtocolIni: Physical address of a memory copy of the driver
+ module from the protocol.ini file obtained from the protocol manager
+ driver (refer to the NDIS 2.0 specification). This parameter is
+ supported for the universal NDIS driver to pass the information
+ contained in the protocol.ini file to the NIC driver for any specific
+ configuration of the NIC. (Note that the module identification in the
+ protocol.ini file was done by NDIS.) This value can be NULL for any
+ other application interfacing to the universal NIC driver
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiInitialize (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_INITIALIZE_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_INITIALIZE_T),
+ PXENV_UNDI_INITIALIZE
+ );
+}
+
+/**
+ Wrapper routine for reset adapter.
+
+ PXE
+ UNDI RESET ADAPTER
+ Op-Code: PXENV_UNDI_RESET_ADAPTER (0004h)
+ Input: Far pointer to a PXENV_UNDI_RESET_ADAPTER_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets and reinitializes the network adapter with the same set of parameters supplied to
+ Initialize Routine. Unlike Initialize, this call opens the adapter that is, it connects logically to the
+ network. This routine cannot be used to replace Initialize or Shutdown calls.
+ typedef struct {
+ PXENV_STATUS Status;
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_RESET_T;
+
+ #define MAXNUM_MCADDR 8
+
+ typedef struct {
+ UINT16 MCastAddrCount;
+ MAC_ADDR McastAddr[MAXNUM_MCADDR];
+ } PXENV_UNDI_MCAST_ADDRESS_t;
+
+ Set before calling API service
+ R_Mcast_Buf: This is a structure of MCastAddrCount and
+ McastAddr.
+ MCastAddrCount: Number of multicast MAC addresses in the
+ buffer.
+ McastAddr: List of up to MAXNUM_MCADDR multicast MAC
+ addresses.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance.
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+ @param RxFilter Filter setting mask value for PXE recive .
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiResetNic (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_RESET_T *PxeUndiTable,
+ IN UINT16 RxFilter
+ )
+{
+ PXENV_UNDI_OPEN_T Open;
+ PXENV_UNDI_CLOSE_T Close;
+ UINTN Status;
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_RESET_T),
+ PXENV_UNDI_RESET_NIC
+ );
+ if (!EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Close.Status = PXENV_STATUS_SUCCESS;
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ &Close,
+ sizeof (Close),
+ PXENV_UNDI_CLOSE
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_RESET_T),
+ PXENV_UNDI_RESET_NIC
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Open.Status = PXENV_STATUS_SUCCESS;
+ Open.OpenFlag = 0;
+ Open.PktFilter = RxFilter;
+ CopyMem (
+ &Open.McastBuffer,
+ &PxeUndiTable->R_Mcast_Buf,
+ sizeof (PXENV_UNDI_MCAST_ADDR_T)
+ );
+
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ &Open,
+ sizeof (Open),
+ PXENV_UNDI_OPEN
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ PXE
+ UNDI SHUTDOWN
+ Op-Code: PXENV_UNDI_SHUTDOWN (0005h)
+ Input: Far pointer to a PXENV_UNDI_SHUTDOWN_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the network adapter and leaves it in a safe state for another driver to program it.
+ Note: The contents of the PXENV_UNDI_STARTUP parameter structure need to be saved by the
+ Universal NIC Driver in case PXENV_UNDI_INITIALIZE is called again.
+ typedef struct
+ {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_SHUTDOWN_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiShutdown (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SHUTDOWN_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_SHUTDOWN_T),
+ PXENV_UNDI_SHUTDOWN
+ );
+}
+
+/**
+ PXE
+ UNDI OPEN
+ Op-Code: PXENV_UNDI_OPEN (0006h)
+ Input: Far pointer to a PXENV_UNDI_OPEN_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call activates the adapter network connection and sets the adapter ready to accept packets
+ for transmit and receive.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 OpenFlag;
+ UINT16 PktFilter;
+ #define FLTR_DIRECTED 0x0001
+ #define FLTR_BRDCST 0x0002
+ #define FLTR_PRMSCS 0x0004
+ #define FLTR_SRC_RTG 0x0008
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_OPEN_T;
+ Set before calling API service
+ OpenFlag: This is an adapter specific input parameter. This is
+ supported for the universal NDIS 2.0 driver to pass in the open flags
+ provided by the protocol driver. (See the NDIS 2.0 specification.)
+ This can be zero.
+ PktFilter: Filter for receiving packets. This can be one, or more, of
+ the FLTR_xxx constants. Multiple values are arithmetically or-ed
+ together.
+ directed packets are packets that may come to your MAC address
+ or the multicast MAC address.
+ R_Mcast_Buf: See definition in UNDI RESET ADAPTER (0004h).
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiOpen (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_OPEN_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_OPEN_T),
+ PXENV_UNDI_OPEN
+ );
+}
+
+/**
+ PXE
+ UNDI CLOSE
+ Op-Code: PXENV_UNDI_CLOSE (0007h)
+ Input: Far pointer to a PXENV_UNDI_CLOSE_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call disconnects the network adapter from the network. Packets cannot be transmitted or
+ received until the network adapter is open again.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_CLOSE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiClose (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLOSE_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_CLOSE_T),
+ PXENV_UNDI_CLOSE
+ );
+}
+
+/**
+ PXE
+ UNDI TRANSMIT PACKET
+ Op-Code: PXENV_UNDI_TRANSMIT (0008h)
+ Input: Far pointer to a PXENV_UNDI_TRANSMIT_T parameter structure that
+ has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX.
+ The status code must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call transmits a buffer to the network. The media header
+ for the packet can be filled by the calling protocol, but it might not be.
+ The network adapter driver will fill it if required by the values in the
+ parameter block. The packet is buffered for transmission provided there is
+ an available buffer, and the function returns PXENV_EXIT_SUCCESS. If no
+ buffer is available the function returns PXENV_EXIT_FAILURE with a status
+ code of PXE_UNDI_STATUS__OUT OF_RESOURCE. The number of buffers is
+ implementation-dependent. An interrupt is generated on completion of the
+ transmission of one or more packets. A call to PXENV_UNDI_TRANSMIT is
+ permitted in the context of a transmit complete interrupt.
+
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT8 Protocol;
+ #define P_UNKNOWN 0
+ #define P_IP 1
+ #define P_ARP 2
+ #define P_RARP 3
+ UINT8 XmitFlag;
+ #define XMT_DESTADDR 0x0000
+ #define XMT_BROADCAST 0x0001
+ SEGOFF16 DestAddr;
+ SEGOFF16 TBD;
+ UINT32 Reserved[2];
+ } t_PXENV_UNDI_TRANSMIT;
+
+ #define MAX_DATA_BLKS 8
+
+ typedef struct {
+ UINT16 ImmedLength;
+ SEGOFF16 Xmit;
+ UINT16 DataBlkCount;
+ struct DataBlk {
+ UINT8 TDPtrType;
+ UINT8 TDRsvdByte;
+ UINT16 TDDataLen;
+ SEGOFF16 TDDataPtr;
+ } DataBlock[MAX_DATA_BLKS];
+ } PXENV_UNDI_TBD_T
+
+ Set before calling API service
+ Protocol: This is the protocol of the upper layer that is calling UNDI
+ TRANSMIT call. If the upper layer has filled the media header, this
+ field must be P_UNKNOWN.
+ XmitFlag: If this flag is XMT_DESTADDR, the NIC driver expects a
+ pointer to the destination media address in the field DestAddr. If
+ XMT_BROADCAST, the NIC driver fills the broadcast address for the
+ destination.
+ TBD: Segment:Offset address of the transmit buffer descriptor.
+ ImmedLength: Length of the immediate transmit buffer: Xmit.
+ Xmit: Segment:Offset of the immediate transmit buffer.
+ DataBlkCount: Number of blocks in this transmit buffer.
+ TDPtrType:
+ 0 => 32-bit physical address in TDDataPtr (not supported in this
+ version of PXE)
+ 1 => segment:offset in TDDataPtr which can be a real mode or 16-bit
+ protected mode pointer
+ TDRsvdByte: Reserved must be zero.
+ TDDatalen: Data block length in bytes.
+ TDDataPtr: Segment:Offset of the transmit block.
+ DataBlock: Array of transmit data blocks.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiTransmit (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_TRANSMIT_T *PxeUndiTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_TRANSMIT_T),
+ PXENV_UNDI_TRANSMIT
+ );
+ if (Status == EFI_SUCCESS) {
+ return EFI_SUCCESS;
+ }
+
+ switch (PxeUndiTable->Status) {
+ case PXENV_STATUS_OUT_OF_RESOURCES:
+ return EFI_NOT_READY;
+
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+/**
+ PXE
+ UNDI SET MULTICAST ADDRESS
+ Op-Code: PXENV_UNDI_SET_MCAST_ADDRESS (0009h)
+ Input: Far pointer to a PXENV_TFTP_SET_MCAST_ADDRESS_t parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call changes the current list of multicast addresses to the input list and resets the network
+ adapter to accept it. If the number of multicast addresses is zero, multicast is disabled.
+ typedef struct {
+ PXENV_STATUS Status;
+ PXENV_UNDI_MCAST_ADDRESS_t R_Mcast_Buf;
+ } PXENV_UNDI_SET_MCAST_ADDR_T;
+ Set before calling API service
+ R_Mcast_Buf: See description in the UNDI RESET ADAPTER
+ (0004h) API.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetMcastAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_MCAST_ADDR_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_SET_MCAST_ADDR_T),
+ PXENV_UNDI_SET_MCAST_ADDR
+ );
+}
+
+/**
+ PXE
+ UNDI SET STATION ADDRESS
+ Op-Code: PXENV_UNDI_SET_STATION_ADDRESS (000Ah)
+ Input: Far pointer to a PXENV_UNDI_SET_STATION_ADDRESS_t parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call sets the MAC address to be the input value and is called before opening the network
+ adapter. Later, the open call uses this variable as a temporary MAC address to program the
+ adapter individual address registers.
+ typedef struct {
+ PXENV_STATUS Status;
+ MAC_ADDR StationAddress;
+ } PXENV_UNDI_SET_STATION_ADDR_T;
+ Set before calling API service
+ StationAddress: Temporary MAC address to be used for
+ transmit and receive.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetStationAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_STATION_ADDR_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_SET_STATION_ADDR_T),
+ PXENV_UNDI_SET_STATION_ADDR
+ );
+}
+
+/**
+ PXE
+ UNDI SET PACKET FILTER
+ Op-Code: PXENV_UNDI_SET_PACKET_FILTER (000Bh)
+ Input: Far pointer to a PXENV_UNDI_SET_PACKET_FILTER_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call resets the adapter's receive unit to accept a new filter, different from the one provided with
+ the open call.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT8 filter;
+ } PXENV_UNDI_SET_PACKET_FILTER_T;
+ Set before calling API service
+ Filter: See the receive filter values in the UNDI OPEN
+ (0006h) API description.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiSetPacketFilter (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_SET_PACKET_FILTER_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_SET_PACKET_FILTER_T),
+ PXENV_UNDI_SET_PACKET_FILTER
+ );
+}
+
+/**
+ PXE
+ UNDI GET INFORMATION
+ Op-Code: PXENV_UNDI_GET_INFORMATION (000Ch)
+ Input: Far pointer to a PXENV_UNDI_GET_INFORMATION_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call copies the network adapter variables, including the MAC address, into the input buffer.
+ Note: The PermNodeAddress field must be valid after PXENV_START_UNDI and
+ PXENV_UNDI_STARTUP have been issued. All other fields must be valid after
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE have been
+ called.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT16 BaseIo;
+ UINT16 IntNumber;
+ UINT16 MaxTranUnit;
+ UINT16 HwType;
+ #define ETHER_TYPE 1
+ #define EXP_ETHER_TYPE 2
+ #define IEEE_TYPE 6
+ #define ARCNET_TYPE 7
+ UINT16 HwAddrLen;
+ MAC_ADDR CurrentNodeAddress;
+ MAC_ADDR PermNodeAddress;
+ SEGSEL ROMAddress;
+ UINT16 RxBufCt;
+ UINT16 TxBufCt;
+ } PXENV_UNDI_GET_INFORMATION_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ BaseIO: Adapter base I/O address.
+ IntNumber: Adapter IRQ number.
+ MaxTranUnit: Adapter maximum transmit unit.
+ HWType: Type of protocol at the hardware level.
+ HWAddrLen: Length of the hardware address.
+ CurrentNodeAddress: Current hardware address.
+ PermNodeAddress: Permanent hardware address.
+ ROMAddress: Real mode ROM segment address.
+ RxBufCnt: Receive queue length.
+ TxBufCnt: Transmit queue length.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetInformation (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_INFORMATION_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_INFORMATION_T),
+ PXENV_UNDI_GET_INFORMATION
+ );
+}
+
+/**
+ PXE
+ UNDI GET STATISTICS
+ Op-Code: PXENV_UNDI_GET_STATISTICS (000Dh)
+ Input: Far pointer to a PXENV_UNDI_GET_STATISTICS_T parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call reads statistical information from the network adapter, and returns.
+ typedef struct {
+ PXENV_STATUS Status;
+ UINT32 XmtGoodFrames;
+ UINT32 RcvGoodFrames;
+ UINT32 RcvCRCErrors;
+ UINT32 RcvResourceErrors;
+ } PXENV_UNDI_GET_STATISTICS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ XmtGoodFrames: Number of successful transmissions.
+ RcvGoodFrames: Number of good frames received.
+ RcvCRCErrors: Number of frames received with CRC
+ error.
+ RcvResourceErrors: Number of frames discarded
+ because receive queue was full.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetStatistics (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_STATISTICS_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_STATISTICS_T),
+ PXENV_UNDI_GET_STATISTICS
+ );
+}
+
+/**
+ PXE
+ UNDI CLEAR STATISTICS
+ Op-Code: PXENV_UNDI_CLEAR_STATISTICS (000Eh)
+ Input: Far pointer to a PXENV_UNDI_CLEAR_STATISTICS_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call clears the statistical information from the network adapter.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_CLEAR_STATISTICS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiClearStatistics (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_CLEAR_STATISTICS_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_CLEAR_STATISTICS_T),
+ PXENV_UNDI_CLEAR_STATISTICS
+ );
+}
+
+/**
+ PXE
+ UNDI INITIATE DIAGS
+ Op-Code: PXENV_UNDI_INITIATE_DIAGS (000Fh)
+ Input: Far pointer to a PXENV_UNDI_INITIATE_DIAGS_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the
+ PXENV_STATUS_xxx constants.
+ Description: This call can be used to initiate the run-time diagnostics. It causes the network adapter to run
+ hardware diagnostics and to update its status information.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_INITIATE_DIAGS_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiInitiateDiags (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_INITIATE_DIAGS_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_INITIATE_DIAGS_T),
+ PXENV_UNDI_INITIATE_DIAGS
+ );
+}
+
+/**
+ PXE
+ UNDI FORCE INTERRUPT
+ Op-Code: PXENV_UNDI_FORCE_INTERRUPT (0010h)
+ Input: Far pointer to a PXENV_UNDI_FORCE_INTERRUPT_T parameter structure that has been
+ initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call forces the network adapter to generate an interrupt. When a receive interrupt occurs, the
+ network adapter driver usually queues the packet and calls the application's callback receive
+ routine with a pointer to the packet received. Then, the callback routine either can copy the packet
+ to its buffer or can decide to delay the copy to a later time. If the packet is not immediately copied,
+ the network adapter driver does not remove it from the input queue. When the application wants to
+ copy the packet, it can call the PXENV_UNDI_FORCE_INTERRUPT routine to simulate the receive
+ interrupt.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_UNDI_FORCE_INTERRUPT_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiForceInterrupt (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_FORCE_INTERRUPT_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_FORCE_INTERRUPT_T),
+ PXENV_UNDI_FORCE_INTERRUPT
+ );
+}
+
+/**
+ PXE
+ UNDI GET MULTICAST ADDRESS
+ Op-Code: PXENV_UNDI_GET_MCAST_ADDRESS (0011h)
+ Input: Far pointer to a PXENV_GET_MCAST_ADDRESS_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This call converts the given IP multicast address to a hardware multicast address.
+ typedef struct {
+ PXENV_STATUS Status;
+ IP4 InetAddr;
+ MAC_ADDR MediaAddr;
+ } PXENV_UNDI_GET_MCAST_ADDR_T;
+ Set before calling API service
+ InetAddr: IP multicast address.
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ MediaAddr: MAC multicast address.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetMcastAddr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_MCAST_ADDR_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_MCAST_ADDR_T),
+ PXENV_UNDI_GET_MCAST_ADDR
+ );
+}
+
+/**
+ PXE
+ UNDI GET NIC TYPE
+ Op-Code: PXENV_UNDI_GET_NIC_TYPE (0012h)
+ Input: Far pointer to a PXENV_UNDI_GET_NIC_TYPE parameter structure that has been initialized by
+ the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. If the PXENV_EXIT_SUCCESS is returned the parameter structure must contain the
+ NIC information.
+ Description: This call, if successful, provides the NIC-specific information necessary to identify the network
+ adapter that is used to boot the system.
+ Note: The application first gets the DHCPDISCOVER packet using GET_CACHED_INFO and checks if
+ the UNDI is supported before making this call. If the UNDI is not supported, the NIC-specific
+ information can be obtained from the DHCPDISCOVER packet itself.
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called
+ before the information provided is valid.
+ typedef {
+ PXENV_STATUS Status;
+ UINT8 NicType;
+ #define PCI_NIC 2
+ #define PnP_NIC 3
+ #define CardBus_NIC 4
+ Union {
+ Struct {
+ UINT16 Vendor_ID;
+ UINT16 Dev_ID;
+ UINT8 Base_Class;
+ UINT8 Sub_Class;
+ UINT8 Prog_Intf;
+ UINT8 Rev;
+ UINT16 BusDevFunc;
+ UINT16 SubVendor_ID;
+ UINT16 SubDevice_ID;
+ } pci, cardbus;
+ struct {
+ UINT32 EISA_Dev_ID;
+ UINT8 Base_Class;
+ UINT8 Sub_Class;
+ UINT8 Prog_Intf;
+ UINT16 CardSelNum;
+ } pnp;
+ } info;
+ } PXENV_UNDI_GET_NIC_TYPE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ NICType: Type of NIC information stored in the parameter
+ structure.
+ Info: Information about the fields in this union can be found
+ in the [PnP] and [PCI] specifications
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetNicType (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_NIC_TYPE_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_NIC_TYPE_T),
+ PXENV_UNDI_GET_NIC_TYPE
+ );
+}
+
+/**
+ PXE
+ UNDI GET IFACE INFO
+ Op-Code: PXENV_UNDI_GET_IFACE_INFO (0013h)
+ Input: Far pointer to a PXENV_UNDI_GET_IFACE_INFO_t parameter structure that has been initialized
+ by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. If the PXENV_EXIT_SUCCESS is returned, the parameter structure must contain the
+ interface specific information.
+ Description: This call, if successful, provides the network interface specific information such as the interface
+ type at the link layer (Ethernet, Tokenring) and the link speed. This information can be used in the
+ universal drivers such as NDIS or Miniport to communicate to the upper protocol modules.
+ Note: UNDI follows the NDIS2 specification in giving this information. It is the responsibility of the
+ universal driver to translate/convert this information into a format that is required in its specification
+ or to suit the expectation of the upper level protocol modules.
+ PXENV_START_UNDI, PXENV_UNDI_STARTUP and PXENV_UNDI_INITIALIZE must be called
+ before the information provided is valid.
+ typedef struct {
+ PXENV_STATUS Status
+ UINT8 IfaceType[16];
+ UINT32 LinkSpeed;
+ UINT32 ServiceFlags;
+ UINT32 Reserved[4];
+ } PXENV_UNDI_GET_NDIS_INFO_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ IfaceType: Name of MAC type in ASCIIZ format. This is
+ used by the universal NDIS driver to specify its driver type
+ to the protocol driver.
+ LinkSpeed: Defined in the NDIS 2.0 specification.
+ ServiceFlags: Defined in the NDIS 2.0 specification.
+ Reserved: Must be zero.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetNdisInfo (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_NDIS_INFO_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_NDIS_INFO_T),
+ PXENV_UNDI_GET_NDIS_INFO
+ );
+}
+
+/**
+ PXE
+ UNDI ISR
+ Op-Code: PXENV_UNDI_ISR (0014h)
+ Input: Far pointer to a PXENV_UNDI_ISR_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in
+ the parameter block indicates the operation to be performed for the call. This field is filled with the
+ status of that operation on return.
+ Note: Interrupt Service Routine Operation:
+ In this design the UNDI does not hook the interrupt for the Network Interface. Instead, the
+ application or the protocol driver hooks the interrupt and calls UNDI with the PXENV_UNDI_ISR
+ API call for interrupt verification (PXENV_UNDI_ISR_IN_START) and processing
+ (PXENV_UNDI_ISR_IN_PROCESS and PXENV_UNDI_ISR_GET_NEXT).
+ When the Network Interface HW generates an interrupt the protocol driver interrupt service
+ routine (ISR) gets control and takes care of the interrupt processing at the PIC level. The ISR then
+ calls the UNDI using the PXENV_UNDI_ISR API with the value PXENV_UNDI_ISR_IN_START for
+ the FuncFlag parameter. At this time UNDI must disable the interrupts at the Network Interface
+ level and read any status values required to further process the interrupt. UNDI must return as
+ quickly as possible with one of the two values, PXENV_UNDI_ISR_OUT_OURS or
+ PXENV_UNDI_ISR_OUT_NOT_OURS, for the parameter FuncFlag depending on whether the
+ interrupt was generated by this particular Network Interface or not.
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_NOT_OURS, then the interrupt was
+ not generated by our NIC, and interrupt processing is complete.
+ If the value returned in FuncFlag is PXENV_UNDI_ISR_OUT_OURS, the protocol driver must start
+ a handler thread and send an end-of-interrupt (EOI) command to the PIC. Interrupt processing is
+ now complete.
+ The protocol driver strategy routine will call UNDI using this same API with FuncFlag equal to
+ PXENV_UNDI_ISR_IN_PROCESS. At this time UNDI must find the cause of this interrupt and
+ return the status in the FuncFlag. It first checks if there is a frame received and if so it returns the
+ first buffer pointer of that frame in the parameter block.
+ The protocol driver calls UNDI repeatedly with the FuncFlag equal to
+ PXENV_UNDI_ISR_IN_GET_NEXT to get all the buffers in a frame and also all the received
+ frames in the queue. On this call, UNDI must remember the previous buffer given to the protoco,l
+ remove it from the receive queue and recycle it. In case of a multi-buffered frame, if the previous
+ buffer is not the last buffer in the frame it must return the next buffer in the frame in the parameter
+ block. Otherwise it must return the first buffer in the next frame.
+ If there is no received frame pending to be processed, UNDI processes the transmit completes and
+ if there is no other interrupt status to be processed, UNDI re-enables the interrupt at the
+ NETWORK INTERFACE level and returns PXENV_UNDI_ISR_OUT_DONE in the FuncFlag.
+ IMPORTANT: It is possible for the protocol driver to be interrupted again while in the
+ strategy routine when the UNDI re-enables interrupts.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiIsr (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_ISR_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_ISR_T),
+ PXENV_UNDI_ISR
+ );
+}
+
+/**
+ PXE
+ STOP UNDI
+ Op-Code: PXENV_STOP_UNDI (0015h)
+ Input: Far pointer to a PXENV_STOP_UNDI_T parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This routine is responsible for unhooking the Int 1Ah service routine.
+ Note: This API service must be called only once at the end of UNDI Option ROM boot. One of the valid
+ status codes is PXENV_STATUS_KEEP. If this status is returned, UNDI must not be removed from
+ base memory. Also, UNDI must not be removed from base memory if BC is not removed from base
+ memory.
+ Service cannot be used in protected mode.
+ typedef struct {
+ PXENV_STATUS Status;
+ } PXENV_STOP_UNDI_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiStop (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_STOP_UNDI_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_STOP_UNDI_T),
+ PXENV_STOP_UNDI
+ );
+}
+
+/**
+ PXE
+ UNDI GET STATE
+ Op-Code: PXENV_UNDI_GET_STATE (0015h)
+ Input: Far pointer to a PXENV_UNDI_GET_STATE_T parameter.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants. The UNDI_STATE field in the parameter structure must be set to one of the valid state
+ constants
+ Description: This call can be used to obtain state of the UNDI engine in order to avoid issuing adverse call
+ sequences
+ typedef struct {
+ #define PXE_UNDI_GET_STATE_STARTED 1
+ #define PXE_UNDI_GET_STATE_INITIALIZED 2
+ #define PXE_UNDI_GET_STATE_OPENED 3
+ PXENV_STATUS Status;
+ UINT8 UNDIstate;
+ } PXENV_UNDI_GET_STATE_T;
+ Set before calling API service
+ N/A
+ Returned from API service
+ Status: See the PXENV_STATUS_xxx constants.
+ State: See definitions of the state constants.
+ Note. UNDI implementation is responsible for maintaining
+ internal state machine.
+ UNDI ISR
+ Op-Code: PXENV_UNDI_ISR (0014h)
+ Input: Far pointer to a t_PXENV_UNDI_ISR parameter structure that has been initialized by the caller.
+ Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be returned in AX. The status field in
+ the parameter structure must be set to one of the values represented by the PXENV_STATUS_xxx
+ constants.
+ Description: This API function will be called at different levels of processing the interrupt. The FuncFlag field in
+ the parameter block indicates the operation to be performed for the call. This field is filled with the
+ status of that operation on return.
+
+ @param SimpleNetworkDevice Device instance
+ @param PxeUndiTable Point to structure which hold paramter and return value
+ for option ROM call.
+
+ @return Return value of PXE option ROM far call.
+**/
+EFI_STATUS
+PxeUndiGetState (
+ IN EFI_SIMPLE_NETWORK_DEV *SimpleNetworkDevice,
+ IN OUT PXENV_UNDI_GET_STATE_T *PxeUndiTable
+ )
+{
+ return MakePxeCall (
+ SimpleNetworkDevice,
+ PxeUndiTable,
+ sizeof (PXENV_UNDI_GET_STATE_T),
+ PXENV_UNDI_GET_STATE
+ );
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf
new file mode 100644
index 0000000000..c37c4abb86
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf
@@ -0,0 +1,67 @@
+## @file
+# Thunk wrapper UEFI driver to produce EFI SNP protocol based on legacy 16 NIC ROM.
+#
+# Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions
+# of the BSD License which accompanies this distribution. The
+# full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ BASE_NAME = BiosSnp16
+ FILE_GUID = D0CAA91E-2DE4-4b0d-B3DC-09C67E854E34
+ MODULE_TYPE = UEFI_DRIVER
+ INF_VERSION = 0x00010005
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BiosSnp16DriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gBiosSnp16DriverBinding
+# COMPONENT_NAME = gBiosSnp16ComponentName
+#
+
+[Sources]
+ BiosSnp16.h
+ BiosSnp16.c
+ Misc.c
+ Pxe.h
+ PxeUndi.c
+ ComponentName.c
+
+
+[Libraryclasses]
+ UefiDriverEntryPoint
+ DebugLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ UefiLib
+ BaseLib
+ DevicePathLib
+ MemoryAllocationLib
+
+[Guids]
+ gEfiEventExitBootServicesGuid
+
+[Protocols]
+ gEfiNetworkInterfaceIdentifierProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiSimpleNetworkProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiLegacyBiosProtocolGuid
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c
new file mode 100644
index 0000000000..76591e7a47
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c
@@ -0,0 +1,3164 @@
+/** @file
+ ConsoleOut Routines that speak VGA.
+
+Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BiosVideo.h"
+
+//
+// EFI Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {
+ BiosVideoDriverBindingSupported,
+ BiosVideoDriverBindingStart,
+ BiosVideoDriverBindingStop,
+ 0x3,
+ NULL,
+ NULL
+};
+
+//
+// Global lookup tables for VGA graphics modes
+//
+UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
+
+UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
+
+UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = {
+ { 0x00, 0x00, 0x00, 0x00 },
+ { 0x98, 0x00, 0x00, 0x00 },
+ { 0x00, 0x98, 0x00, 0x00 },
+ { 0x98, 0x98, 0x00, 0x00 },
+ { 0x00, 0x00, 0x98, 0x00 },
+ { 0x98, 0x00, 0x98, 0x00 },
+ { 0x00, 0x98, 0x98, 0x00 },
+ { 0x98, 0x98, 0x98, 0x00 },
+ { 0x10, 0x10, 0x10, 0x00 },
+ { 0xff, 0x10, 0x10, 0x00 },
+ { 0x10, 0xff, 0x10, 0x00 },
+ { 0xff, 0xff, 0x10, 0x00 },
+ { 0x10, 0x10, 0xff, 0x00 },
+ { 0xf0, 0x10, 0xff, 0x00 },
+ { 0x10, 0xff, 0xff, 0x00 },
+ { 0xff, 0xff, 0xff, 0x00 }
+};
+
+//
+// Standard timing defined by VESA EDID
+//
+VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = {
+ //
+ // Established Timing I
+ //
+ {800, 600, 60},
+ {800, 600, 56},
+ {640, 480, 75},
+ {640, 480, 72},
+ {640, 480, 67},
+ {640, 480, 60},
+ {720, 400, 88},
+ {720, 400, 70},
+ //
+ // Established Timing II
+ //
+ {1280, 1024, 75},
+ {1024, 768, 75},
+ {1024, 768, 70},
+ {1024, 768, 60},
+ {1024, 768, 87},
+ {832, 624, 75},
+ {800, 600, 75},
+ {800, 600, 72},
+ //
+ // Established Timing III
+ //
+ {1152, 870, 75}
+};
+
+/**
+ Supported.
+
+ @param This Pointer to driver binding protocol
+ @param Controller Controller handle to connect
+ @param RemainingDevicePath A pointer to the remaining portion of a device
+ path
+
+ @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this
+ driver, Otherwise, this controller cannot be
+ managed by this driver
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ EFI_DEV_PATH *Node;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ if (Status == EFI_ALREADY_STARTED) {
+ //
+ // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure,
+ // because VgaMiniPort protocol is installed on controller handle directly.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiVgaMiniPortProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return EFI_ALREADY_STARTED;
+ }
+ }
+ //
+ // See if this is a PCI Graphics Controller by looking at the Command register and
+ // Class Code Register
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {
+
+ Status = EFI_SUCCESS;
+ //
+ // If this is a graphics controller,
+ // go further check RemainingDevicePath validation
+ //
+ if (RemainingDevicePath != NULL) {
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;
+ //
+ // Check if RemainingDevicePath is the End of Device Path Node,
+ // if yes, return EFI_SUCCESS
+ //
+ if (!IsDevicePathEnd (Node)) {
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node,
+ // check its validation
+ //
+ if (Node->DevPath.Type != ACPI_DEVICE_PATH ||
+ Node->DevPath.SubType != ACPI_ADR_DP ||
+ DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+ }
+ }
+
+Done:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+
+/**
+ Install Graphics Output Protocol onto VGA device handles.
+
+ @param This Pointer to driver binding protocol
+ @param Controller Controller handle to connect
+ @param RemainingDevicePath A pointer to the remaining portion of a device
+ path
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Flags;
+ UINT64 OriginalPciAttributes;
+ UINT64 Supports;
+ BOOLEAN PciAttributesSaved;
+
+ //
+ // Initialize local variables
+ //
+ PciIo = NULL;
+ ParentDevicePath = NULL;
+
+ //
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open the IO Abstraction(s) needed
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ PciAttributesSaved = FALSE;
+ //
+ // Save original PCI attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &OriginalPciAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ PciAttributesSaved = TRUE;
+
+ //
+ // Get supported PCI attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
+ if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ //
+ // Prepare for status code
+ //
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,
+ ParentDevicePath
+ );
+ //
+ // Enable the device and make sure VGA cycles are being forwarded to this VGA device
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Supports,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,
+ ParentDevicePath
+ );
+ goto Done;
+ }
+ //
+ // Check to see if there is a legacy option ROM image associated with this PCI device
+ //
+ Status = LegacyBios->CheckPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ NULL,
+ &Flags
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Post the legacy option ROM if it is available.
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_RESET,
+ ParentDevicePath
+ );
+ Status = LegacyBios->InstallPciRom (
+ LegacyBios,
+ Controller,
+ NULL,
+ &Flags,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
+ ParentDevicePath
+ );
+ goto Done;
+ }
+
+ if (RemainingDevicePath != NULL) {
+ if (IsDevicePathEnd (RemainingDevicePath) &&
+ (FeaturePcdGet (PcdBiosVideoCheckVbeEnable) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable))) {
+ //
+ // If RemainingDevicePath is the End of Device Path Node,
+ // don't create any child device and return EFI_SUCESS
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ }
+
+ //
+ // Create child handle and install GraphicsOutputProtocol on it
+ //
+ Status = BiosVideoChildHandleInstall (
+ This,
+ Controller,
+ PciIo,
+ LegacyBios,
+ ParentDevicePath,
+ RemainingDevicePath,
+ OriginalPciAttributes
+ );
+
+Done:
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,
+ ParentDevicePath
+ );
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,
+ ParentDevicePath
+ );
+ if (PciAttributesSaved) {
+ //
+ // Restore original PCI attributes
+ //
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSet,
+ OriginalPciAttributes,
+ NULL
+ );
+ }
+ //
+ // Release PCI I/O Protocols on the controller handle.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ return Status;
+}
+
+
+/**
+ Stop.
+
+ @param This Pointer to driver binding protocol
+ @param Controller Controller handle to connect
+ @param NumberOfChildren Number of children handle created by this driver
+ @param ChildHandleBuffer Buffer containing child handle created
+
+ @retval EFI_SUCCESS Driver disconnected successfully from controller
+ @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+
+ AllChildrenStopped = TRUE;
+
+ if (NumberOfChildren == 0) {
+ //
+ // Close PCI I/O protocol on the controller handle
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Install child handles if the Handle supports MBR format.
+
+ @param This Calling context.
+ @param ParentHandle Parent Handle
+ @param ParentPciIo Parent PciIo interface
+ @param ParentLegacyBios Parent LegacyBios interface
+ @param ParentDevicePath Parent Device Path
+ @param RemainingDevicePath Remaining Device Path
+ @param OriginalPciAttributes Original PCI Attributes
+
+ @retval EFI_SUCCESS If a child handle was added
+ @retval other A child handle was not added
+
+**/
+EFI_STATUS
+BiosVideoChildHandleInstall (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ParentHandle,
+ IN EFI_PCI_IO_PROTOCOL *ParentPciIo,
+ IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ IN UINT64 OriginalPciAttributes
+ )
+{
+ EFI_STATUS Status;
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ PCI_TYPE00 Pci;
+ ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
+ BOOLEAN ProtocolInstalled;
+
+ //
+ // Allocate the private device structure for video device
+ //
+ BiosVideoPrivate = (BIOS_VIDEO_DEV *) AllocateZeroPool (
+ sizeof (BIOS_VIDEO_DEV)
+ );
+ if (NULL == BiosVideoPrivate) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // See if this is a VGA compatible controller or not
+ //
+ Status = ParentPciIo->Pci.Read (
+ ParentPciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
+ ParentDevicePath
+ );
+ goto Done;
+ }
+ BiosVideoPrivate->VgaCompatible = FALSE;
+ if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) {
+ BiosVideoPrivate->VgaCompatible = TRUE;
+ }
+
+ if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) {
+ BiosVideoPrivate->VgaCompatible = TRUE;
+ }
+
+ if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {
+ //
+ // Create EXIT_BOOT_SERIVES Event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ BiosVideoNotifyExitBootServices,
+ BiosVideoPrivate,
+ &gEfiEventExitBootServicesGuid,
+ &BiosVideoPrivate->ExitBootServicesEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Initialize the child private structure
+ //
+ BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;
+
+ //
+ // Fill in Graphics Output specific mode structures
+ //
+ BiosVideoPrivate->HardwareNeedsStarting = TRUE;
+ BiosVideoPrivate->ModeData = NULL;
+ BiosVideoPrivate->LineBuffer = NULL;
+ BiosVideoPrivate->VgaFrameBuffer = NULL;
+ BiosVideoPrivate->VbeFrameBuffer = NULL;
+
+ //
+ // Fill in the Graphics Output Protocol
+ //
+ BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;
+ BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;
+
+
+ //
+ // Allocate buffer for Graphics Output Protocol mode information
+ //
+ BiosVideoPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (
+ sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)
+ );
+ if (NULL == BiosVideoPrivate->GraphicsOutput.Mode) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
+ );
+ if (NULL == BiosVideoPrivate->GraphicsOutput.Mode->Info) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Assume that Graphics Output Protocol will be produced until proven otherwise
+ //
+ BiosVideoPrivate->ProduceGraphicsOutput = TRUE;
+
+ //
+ // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
+ //
+ if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {
+ if (RemainingDevicePath == NULL) {
+ ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
+ AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
+ AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
+ AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
+ SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
+
+ BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
+ );
+ } else {
+ BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
+ }
+
+ //
+ // Creat child handle and device path protocol firstly
+ //
+ BiosVideoPrivate->Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &BiosVideoPrivate->Handle,
+ &gEfiDevicePathProtocolGuid,
+ BiosVideoPrivate->GopDevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Fill in the VGA Mini Port Protocol fields
+ //
+ BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode;
+ BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000;
+ BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;
+ BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5;
+ BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+ BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+ BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;
+
+ //
+ // Child handle need to consume the Legacy Bios protocol
+ //
+ BiosVideoPrivate->LegacyBios = ParentLegacyBios;
+
+ //
+ // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
+ //
+ BiosVideoPrivate->PciIo = ParentPciIo;
+ BiosVideoPrivate->OriginalPciAttributes = OriginalPciAttributes;
+
+ //
+ // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
+ //
+ if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable)) {
+ Status = BiosVideoCheckForVbe (BiosVideoPrivate);
+ DEBUG ((EFI_D_INFO, "BiosVideoCheckForVbe - %r\n", Status));
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ if (EFI_ERROR (Status)) {
+ //
+ // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support
+ // for the standard 640x480 16 color VGA mode
+ //
+ DEBUG ((EFI_D_INFO, "VgaCompatible - %x\n", BiosVideoPrivate->VgaCompatible));
+ if (BiosVideoPrivate->VgaCompatible) {
+ if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable)) {
+ Status = BiosVideoCheckForVga (BiosVideoPrivate);
+ DEBUG ((EFI_D_INFO, "BiosVideoCheckForVga - %r\n", Status));
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
+ // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.
+ //
+ BiosVideoPrivate->ProduceGraphicsOutput = FALSE;
+
+ //
+ // INT services are available, so on the 80x25 and 80x50 text mode are supported
+ //
+ BiosVideoPrivate->VgaMiniPort.MaxMode = 2;
+ }
+ }
+
+ ProtocolInstalled = FALSE;
+
+ if (BiosVideoPrivate->ProduceGraphicsOutput) {
+ //
+ // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &BiosVideoPrivate->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &BiosVideoPrivate->GraphicsOutput,
+ &gEfiEdidDiscoveredProtocolGuid,
+ &BiosVideoPrivate->EdidDiscovered,
+ &gEfiEdidActiveProtocolGuid,
+ &BiosVideoPrivate->EdidActive,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Open the Parent Handle for the child
+ //
+ Status = gBS->OpenProtocol (
+ ParentHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &BiosVideoPrivate->PciIo,
+ This->DriverBindingHandle,
+ BiosVideoPrivate->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ ProtocolInstalled = TRUE;
+ }
+ }
+
+ if (!ProtocolInstalled) {
+ //
+ // Install VGA Mini Port Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ParentHandle,
+ &gEfiVgaMiniPortProtocolGuid,
+ &BiosVideoPrivate->VgaMiniPort,
+ NULL
+ );
+ }
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if ((BiosVideoPrivate != NULL) && (BiosVideoPrivate->ExitBootServicesEvent != NULL)) {
+ gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);
+ }
+ //
+ // Free private data structure
+ //
+ BiosVideoDeviceReleaseResource (BiosVideoPrivate);
+ }
+
+ return Status;
+}
+
+
+/**
+ Deregister an video child handle and free resources.
+
+ @param This Protocol instance pointer.
+ @param Controller Video controller handle
+ @param Handle Video child handle
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+BiosVideoChildHandleUninstall (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET Regs;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ BiosVideoPrivate = NULL;
+ GraphicsOutput = NULL;
+ PciIo = NULL;
+ Status = EFI_UNSUPPORTED;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
+ }
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiVgaMiniPortProtocolGuid,
+ (VOID **) &VgaMiniPort,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);
+ }
+ }
+
+ if (BiosVideoPrivate == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Set the 80x25 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x03;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x14;
+ Regs.H.BL = 0;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ //
+ // Restore original PCI attributes
+ //
+ Status = BiosVideoPrivate->PciIo->Attributes (
+ BiosVideoPrivate->PciIo,
+ EfiPciIoAttributeOperationSet,
+ BiosVideoPrivate->OriginalPciAttributes,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Close PCI I/O protocol that opened by child handle
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ //
+ // Uninstall protocols on child handle
+ //
+ if (BiosVideoPrivate->ProduceGraphicsOutput) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ BiosVideoPrivate->Handle,
+ &gEfiDevicePathProtocolGuid,
+ BiosVideoPrivate->GopDevicePath,
+ &gEfiGraphicsOutputProtocolGuid,
+ &BiosVideoPrivate->GraphicsOutput,
+ &gEfiEdidDiscoveredProtocolGuid,
+ &BiosVideoPrivate->EdidDiscovered,
+ &gEfiEdidActiveProtocolGuid,
+ &BiosVideoPrivate->EdidActive,
+ NULL
+ );
+ }
+ if (!BiosVideoPrivate->ProduceGraphicsOutput) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiVgaMiniPortProtocolGuid,
+ &BiosVideoPrivate->VgaMiniPort,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {
+ //
+ // Close EXIT_BOOT_SERIVES Event
+ //
+ gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);
+ }
+
+ //
+ // Release all allocated resources
+ //
+ BiosVideoDeviceReleaseResource (BiosVideoPrivate);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Release resource for biso video instance.
+
+ @param BiosVideoPrivate Video child device private data structure
+
+**/
+VOID
+BiosVideoDeviceReleaseResource (
+ BIOS_VIDEO_DEV *BiosVideoPrivate
+ )
+{
+ if (BiosVideoPrivate == NULL) {
+ return ;
+ }
+
+ //
+ // Release all the resourses occupied by the BIOS_VIDEO_DEV
+ //
+
+ //
+ // Free VGA Frame Buffer
+ //
+ if (BiosVideoPrivate->VgaFrameBuffer != NULL) {
+ FreePool (BiosVideoPrivate->VgaFrameBuffer);
+ }
+ //
+ // Free VBE Frame Buffer
+ //
+ if (BiosVideoPrivate->VbeFrameBuffer != NULL) {
+ FreePool (BiosVideoPrivate->VbeFrameBuffer);
+ }
+ //
+ // Free line buffer
+ //
+ if (BiosVideoPrivate->LineBuffer != NULL) {
+ FreePool (BiosVideoPrivate->LineBuffer);
+ }
+ //
+ // Free mode data
+ //
+ if (BiosVideoPrivate->ModeData != NULL) {
+ FreePool (BiosVideoPrivate->ModeData);
+ }
+ //
+ // Free memory allocated below 1MB
+ //
+ if (BiosVideoPrivate->PagesBelow1MB != 0) {
+ gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);
+ }
+
+ if (BiosVideoPrivate->VbeSaveRestorePages != 0) {
+ gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);
+ }
+
+ //
+ // Free graphics output protocol occupied resource
+ //
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
+ }
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
+ }
+ //
+ // Free EDID discovered protocol occupied resource
+ //
+ if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {
+ FreePool (BiosVideoPrivate->EdidDiscovered.Edid);
+ }
+ //
+ // Free EDID active protocol occupied resource
+ //
+ if (BiosVideoPrivate->EdidActive.Edid != NULL) {
+ FreePool (BiosVideoPrivate->EdidActive.Edid);
+ }
+
+ if (BiosVideoPrivate->GopDevicePath!= NULL) {
+ FreePool (BiosVideoPrivate->GopDevicePath);
+ }
+
+ FreePool (BiosVideoPrivate);
+
+ return ;
+}
+
+
+/**
+ Generate a search key for a specified timing data.
+
+ @param EdidTiming Pointer to EDID timing
+
+ @return The 32 bit unique key for search.
+
+**/
+UINT32
+CalculateEdidKey (
+ VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming
+ )
+{
+ UINT32 Key;
+
+ //
+ // Be sure no conflicts for all standard timing defined by VESA.
+ //
+ Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;
+ return Key;
+}
+
+
+/**
+ Parse the Established Timing and Standard Timing in EDID data block.
+
+ @param EdidBuffer Pointer to EDID data block
+ @param ValidEdidTiming Valid EDID timing information
+
+ @retval TRUE The EDID data is valid.
+ @retval FALSE The EDID data is invalid.
+
+**/
+BOOLEAN
+ParseEdidData (
+ UINT8 *EdidBuffer,
+ VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming
+ )
+{
+ UINT8 CheckSum;
+ UINT32 Index;
+ UINT32 ValidNumber;
+ UINT32 TimingBits;
+ UINT8 *BufferIndex;
+ UINT16 HorizontalResolution;
+ UINT16 VerticalResolution;
+ UINT8 AspectRatio;
+ UINT8 RefreshRate;
+ VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming;
+ VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock;
+
+ EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer;
+
+ //
+ // Check the checksum of EDID data
+ //
+ CheckSum = 0;
+ for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) {
+ CheckSum = (UINT8) (CheckSum + EdidBuffer[Index]);
+ }
+ if (CheckSum != 0) {
+ return FALSE;
+ }
+
+ ValidNumber = 0;
+ gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0);
+
+ if ((EdidDataBlock->EstablishedTimings[0] != 0) ||
+ (EdidDataBlock->EstablishedTimings[1] != 0) ||
+ (EdidDataBlock->EstablishedTimings[2] != 0)
+ ) {
+ //
+ // Established timing data
+ //
+ TimingBits = EdidDataBlock->EstablishedTimings[0] |
+ (EdidDataBlock->EstablishedTimings[1] << 8) |
+ ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;
+ for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {
+ if ((TimingBits & 0x1) != 0) {
+ ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);
+ ValidNumber ++;
+ }
+ TimingBits = TimingBits >> 1;
+ }
+ } else {
+ //
+ // If no Established timing data, read the standard timing data
+ //
+ BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];
+ for (Index = 0; Index < 8; Index ++) {
+ if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){
+ //
+ // A valid Standard Timing
+ //
+ HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);
+ AspectRatio = (UINT8) (BufferIndex[1] >> 6);
+ switch (AspectRatio) {
+ case 0:
+ VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);
+ break;
+ case 1:
+ VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);
+ break;
+ case 2:
+ VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);
+ break;
+ case 3:
+ VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);
+ break;
+ default:
+ VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);
+ break;
+ }
+ RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);
+ TempTiming.HorizontalResolution = HorizontalResolution;
+ TempTiming.VerticalResolution = VerticalResolution;
+ TempTiming.RefreshRate = RefreshRate;
+ ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);
+ ValidNumber ++;
+ }
+ BufferIndex += 2;
+ }
+ }
+
+ ValidEdidTiming->ValidNumber = ValidNumber;
+ return TRUE;
+}
+
+
+/**
+ Search a specified Timing in all the valid EDID timings.
+
+ @param ValidEdidTiming All valid EDID timing information.
+ @param EdidTiming The Timing to search for.
+
+ @retval TRUE Found.
+ @retval FALSE Not found.
+
+**/
+BOOLEAN
+SearchEdidTiming (
+ VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming,
+ VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming
+ )
+{
+ UINT32 Index;
+ UINT32 Key;
+
+ Key = CalculateEdidKey (EdidTiming);
+
+ for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {
+ if (Key == ValidEdidTiming->Key[Index]) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Check for VBE device.
+
+ @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure
+
+ @retval EFI_SUCCESS VBE device found
+
+**/
+EFI_STATUS
+BiosVideoCheckForVbe (
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate
+ )
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET Regs;
+ UINT16 *ModeNumberPtr;
+ BOOLEAN ModeFound;
+ BOOLEAN EdidFound;
+ BIOS_VIDEO_MODE_DATA *ModeBuffer;
+ BIOS_VIDEO_MODE_DATA *CurrentModeData;
+ UINTN PreferMode;
+ UINTN ModeNumber;
+ VESA_BIOS_EXTENSIONS_EDID_TIMING Timing;
+ VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming;
+ EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride;
+ UINT32 EdidAttributes;
+ BOOLEAN EdidOverrideFound;
+ UINTN EdidOverrideDataSize;
+ UINT8 *EdidOverrideDataBlock;
+ UINTN EdidActiveDataSize;
+ UINT8 *EdidActiveDataBlock;
+
+ EdidFound = TRUE;
+ EdidOverrideFound = FALSE;
+ EdidOverrideDataBlock = NULL;
+ EdidActiveDataSize = 0;
+ EdidActiveDataBlock = NULL;
+
+ //
+ // Allocate buffer under 1MB for VBE data structures
+ //
+ BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (
+ sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +
+ sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +
+ sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +
+ sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)
+ );
+
+ BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ BiosVideoPrivate->NumberOfPagesBelow1MB,
+ &BiosVideoPrivate->PagesBelow1MB
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));
+
+ //
+ // Fill in the VBE related data structures
+ //
+ BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);
+ BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);
+ BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);
+ BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1);
+ BiosVideoPrivate->VbeSaveRestorePages = 0;
+ BiosVideoPrivate->VbeSaveRestoreBuffer = 0;
+
+ //
+ // Test to see if the Video Adapter is compliant with VBE 3.0
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;
+ gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);
+ BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);
+
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Status = EFI_DEVICE_ERROR;
+
+ //
+ // See if the VESA call succeeded
+ //
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
+ return Status;
+ }
+ //
+ // Check for 'VESA' signature
+ //
+ if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {
+ return Status;
+ }
+ //
+ // Check to see if this is VBE 2.0 or higher
+ //
+ if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {
+ return Status;
+ }
+
+ EdidFound = FALSE;
+ EdidAttributes = 0xff;
+ EdidOverrideDataSize = 0;
+
+ //
+ // Find EDID Override protocol firstly, this protocol is installed by platform if needed.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiEdidOverrideProtocolGuid,
+ NULL,
+ (VOID **) &EdidOverride
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow
+ //
+ EdidOverrideDataBlock = AllocatePool (sizeof (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2));
+ if (NULL == EdidOverrideDataBlock) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = EdidOverride->GetEdid (
+ EdidOverride,
+ BiosVideoPrivate->Handle,
+ &EdidAttributes,
+ &EdidOverrideDataSize,
+ (UINT8 **) &EdidOverrideDataBlock
+ );
+ if (!EFI_ERROR (Status) &&
+ EdidAttributes == 0 &&
+ EdidOverrideDataSize != 0) {
+ //
+ // Succeeded to get EDID Override Data
+ //
+ EdidOverrideFound = TRUE;
+ }
+ }
+
+ if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) {
+ //
+ // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,
+ // read EDID information through INT10 call
+ //
+
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;
+ Regs.X.BX = 1;
+ Regs.X.CX = 0;
+ Regs.X.DX = 0;
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);
+
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+ //
+ // See if the VESA call succeeded
+ //
+ if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
+ //
+ // Set EDID Discovered Data
+ //
+ BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;
+ BiosVideoPrivate->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool (
+ VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,
+ BiosVideoPrivate->VbeEdidDataBlock
+ );
+
+ if (NULL == BiosVideoPrivate->EdidDiscovered.Edid) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ EdidFound = TRUE;
+ }
+ }
+
+ if (EdidFound) {
+ EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;
+ EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid;
+ } else if (EdidOverrideFound) {
+ EdidActiveDataSize = EdidOverrideDataSize;
+ EdidActiveDataBlock = EdidOverrideDataBlock;
+ EdidFound = TRUE;
+ }
+
+ if (EdidFound) {
+ //
+ // Parse EDID data structure to retrieve modes supported by monitor
+ //
+ if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) {
+ //
+ // Copy EDID Override Data to EDID Active Data
+ //
+ BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize;
+ BiosVideoPrivate->EdidActive.Edid = (UINT8 *) AllocateCopyPool (
+ EdidActiveDataSize,
+ EdidActiveDataBlock
+ );
+ if (NULL == BiosVideoPrivate->EdidActive.Edid) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ }
+ } else {
+ BiosVideoPrivate->EdidActive.SizeOfEdid = 0;
+ BiosVideoPrivate->EdidActive.Edid = NULL;
+ EdidFound = FALSE;
+ }
+
+ //
+ // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
+ //
+ ModeNumberPtr = (UINT16 *)
+ (
+ (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |
+ ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)
+ );
+
+ PreferMode = 0;
+ ModeNumber = 0;
+
+ for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {
+ //
+ // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
+ //
+ if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {
+ continue;
+ }
+ //
+ // Get the information about the mode
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;
+ Regs.X.CX = *ModeNumberPtr;
+ gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);
+
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ //
+ // See if the call succeeded. If it didn't, then try the next mode.
+ //
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
+ continue;
+ }
+ //
+ // See if the mode supports color. If it doesn't then try the next mode.
+ //
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {
+ continue;
+ }
+ //
+ // See if the mode supports graphics. If it doesn't then try the next mode.
+ //
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {
+ continue;
+ }
+ //
+ // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
+ //
+ if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {
+ continue;
+ }
+ //
+ // See if the mode supports 32 bit color. If it doesn't then try the next mode.
+ // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
+ // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
+ //
+ if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {
+ continue;
+ }
+
+ if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {
+ continue;
+ }
+
+ if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {
+ continue;
+ }
+ //
+ // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
+ //
+ if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {
+ continue;
+ }
+
+ if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {
+ //
+ // EDID exist, check whether this mode match with any mode in EDID
+ //
+ Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;
+ Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;
+ if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) {
+ continue;
+ }
+ }
+
+ //
+ // Select a reasonable mode to be set for current display mode
+ //
+ ModeFound = FALSE;
+
+ if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&
+ BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768
+ ) {
+ ModeFound = TRUE;
+ }
+ if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&
+ BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600
+ ) {
+ ModeFound = TRUE;
+ PreferMode = ModeNumber;
+ }
+ if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&
+ BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480
+ ) {
+ ModeFound = TRUE;
+ }
+
+ if ((!EdidFound) && (!ModeFound)) {
+ //
+ // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
+ //
+ continue;
+ }
+
+ //
+ // Add mode to the list of available modes
+ //
+ ModeNumber ++;
+ ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (
+ ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA)
+ );
+ if (NULL == ModeBuffer) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ if (ModeNumber > 1) {
+ CopyMem (
+ ModeBuffer,
+ BiosVideoPrivate->ModeData,
+ (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)
+ );
+ }
+
+ if (BiosVideoPrivate->ModeData != NULL) {
+ FreePool (BiosVideoPrivate->ModeData);
+ }
+
+ CurrentModeData = &ModeBuffer[ModeNumber - 1];
+ CurrentModeData->VbeModeNumber = *ModeNumberPtr;
+ if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {
+ CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;
+ CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;
+ CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);
+ CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;
+ CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);
+ CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;
+ CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);
+ CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;
+ CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);
+ } else {
+ CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;
+ CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;
+ CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);
+ CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;
+ CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);
+ CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;
+ CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);
+ CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;
+ CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);
+ }
+
+ CurrentModeData->PixelFormat = PixelBitMask;
+ if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&
+ (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {
+ if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {
+ CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
+ } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {
+ CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+ }
+ }
+
+ CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;
+ CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;
+ CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;
+ CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;
+ CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;
+
+ CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;
+ CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;
+ CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;
+
+ CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;
+
+ BiosVideoPrivate->ModeData = ModeBuffer;
+ }
+ //
+ // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
+ //
+ if (ModeNumber == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Assign Gop's Blt function
+ //
+ BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;
+
+ BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = (UINT32) ModeNumber;
+ //
+ // Current mode is unknow till now, set it to an invalid mode.
+ //
+ BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
+
+ //
+ // Find the best mode to initialize
+ //
+ Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);
+ if (EFI_ERROR (Status)) {
+ for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {
+ Status = BiosVideoGraphicsOutputSetMode (
+ &BiosVideoPrivate->GraphicsOutput,
+ (UINT32) PreferMode
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ if (PreferMode == ModeNumber) {
+ //
+ // None mode is set successfully.
+ //
+ goto Done;
+ }
+ }
+
+Done:
+ //
+ // If there was an error, then free the mode structure
+ //
+ if (EFI_ERROR (Status)) {
+ if (BiosVideoPrivate->ModeData != NULL) {
+ FreePool (BiosVideoPrivate->ModeData);
+ BiosVideoPrivate->ModeData = NULL;
+ BiosVideoPrivate->MaxMode = 0;
+ }
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;
+ }
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
+ BiosVideoPrivate->GraphicsOutput.Mode= NULL;
+ }
+ if (EdidOverrideDataBlock != NULL) {
+ FreePool (EdidOverrideDataBlock);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Check for VGA device.
+
+ @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure
+
+ @retval EFI_SUCCESS Standard VGA device found
+
+**/
+EFI_STATUS
+BiosVideoCheckForVga (
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate
+ )
+{
+ EFI_STATUS Status;
+ BIOS_VIDEO_MODE_DATA *ModeBuffer;
+
+ Status = EFI_UNSUPPORTED;
+
+ //
+ // Assign Gop's Blt function
+ //
+ BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;
+
+ //
+ // Add mode to the list of available modes
+ // caller should guarantee that Mode has been allocated.
+ //
+ ASSERT (BiosVideoPrivate->GraphicsOutput.Mode != NULL);
+ BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;
+
+ ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (
+ sizeof (BIOS_VIDEO_MODE_DATA)
+ );
+ if (NULL == ModeBuffer) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ModeBuffer->VbeModeNumber = 0x0012;
+ ModeBuffer->BytesPerScanLine = 640;
+ ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);
+ ModeBuffer->HorizontalResolution = 640;
+ ModeBuffer->VerticalResolution = 480;
+ ModeBuffer->PixelFormat = PixelBltOnly;
+ ModeBuffer->BitsPerPixel = 8;
+ ModeBuffer->ColorDepth = 32;
+ ModeBuffer->RefreshRate = 60;
+
+ BiosVideoPrivate->ModeData = ModeBuffer;
+
+ //
+ // Test to see if the Video Adapter support the 640x480 16 color mode
+ //
+ BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
+ Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);
+
+Done:
+ //
+ // If there was an error, then free the mode structure
+ //
+ if (EFI_ERROR (Status)) {
+ if (BiosVideoPrivate->ModeData != NULL) {
+ FreePool (BiosVideoPrivate->ModeData);
+ BiosVideoPrivate->ModeData = NULL;
+ }
+ if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
+ if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
+ BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;
+ }
+ FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
+ BiosVideoPrivate->GraphicsOutput.Mode = NULL;
+ }
+ }
+ return Status;
+}
+
+//
+// Graphics Output Protocol Member Functions for VESA BIOS Extensions
+//
+
+/**
+ Graphics Output protocol interface to get video mode.
+
+ @param This Protocol instance pointer.
+ @param ModeNumber The mode number to return information on.
+ @param SizeOfInfo A pointer to the size, in bytes, of the Info
+ buffer.
+ @param Info Caller allocated buffer that returns information
+ about ModeNumber.
+
+ @retval EFI_SUCCESS Mode information returned.
+ @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
+ video mode.
+ @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
+ @retval EFI_INVALID_PARAMETER One of the input args was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ BIOS_VIDEO_MODE_DATA *ModeData;
+
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+ if (BiosVideoPrivate->HardwareNeedsStarting) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,
+ BiosVideoPrivate->GopDevicePath
+ );
+ return EFI_NOT_STARTED;
+ }
+
+ if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
+ );
+ if (NULL == *Info) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ ModeData = &BiosVideoPrivate->ModeData[ModeNumber];
+ (*Info)->Version = 0;
+ (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
+ (*Info)->VerticalResolution = ModeData->VerticalResolution;
+ (*Info)->PixelFormat = ModeData->PixelFormat;
+ CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));
+
+ (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Worker function to set video mode.
+
+ @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV.
+ @param ModeData The mode data to be set.
+ @param DevicePath Pointer to Device Path Protocol.
+
+ @retval EFI_SUCCESS Graphics mode was changed.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the
+ request.
+ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
+
+**/
+EFI_STATUS
+BiosVideoSetModeWorker (
+ IN BIOS_VIDEO_DEV *BiosVideoPrivate,
+ IN BIOS_VIDEO_MODE_DATA *ModeData,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_IA32_REGISTER_SET Regs;
+
+ if (BiosVideoPrivate->LineBuffer != NULL) {
+ FreePool (BiosVideoPrivate->LineBuffer);
+ }
+
+ if (BiosVideoPrivate->VgaFrameBuffer != NULL) {
+ FreePool (BiosVideoPrivate->VgaFrameBuffer);
+ }
+
+ if (BiosVideoPrivate->VbeFrameBuffer != NULL) {
+ FreePool (BiosVideoPrivate->VbeFrameBuffer);
+ }
+
+ BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool (
+ ModeData->BytesPerScanLine
+ );
+ if (NULL == BiosVideoPrivate->LineBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Clear all registers
+ //
+ ZeroMem (&Regs, sizeof (Regs));
+
+ if (ModeData->VbeModeNumber < 0x100) {
+ //
+ // Allocate a working buffer for BLT operations to the VGA frame buffer
+ //
+ BiosVideoPrivate->VgaFrameBuffer = (UINT8 *) AllocatePool (4 * 480 * 80);
+ if (NULL == BiosVideoPrivate->VgaFrameBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Set VGA Mode
+ //
+ Regs.X.AX = ModeData->VbeModeNumber;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ } else {
+ //
+ // Allocate a working buffer for BLT operations to the VBE frame buffer
+ //
+ BiosVideoPrivate->VbeFrameBuffer =
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (
+ ModeData->BytesPerScanLine * ModeData->VerticalResolution
+ );
+ if (NULL == BiosVideoPrivate->VbeFrameBuffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Set VBE mode
+ //
+ Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;
+ Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);
+ ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK));
+ Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);
+ Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ //
+ // Check to see if the call succeeded
+ //
+ if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,
+ DevicePath
+ );
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Initialize the state of the VbeFrameBuffer
+ //
+ Status = BiosVideoPrivate->PciIo->Mem.Read (
+ BiosVideoPrivate->PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) ModeData->LinearFrameBuffer,
+ (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,
+ BiosVideoPrivate->VbeFrameBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Graphics Output protocol interface to set video mode.
+
+ @param This Protocol instance pointer.
+ @param ModeNumber The mode number to be set.
+
+ @retval EFI_SUCCESS Graphics mode was changed.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the
+ request.
+ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
+ IN UINT32 ModeNumber
+ )
+{
+ EFI_STATUS Status;
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ BIOS_VIDEO_MODE_DATA *ModeData;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+ ModeData = &BiosVideoPrivate->ModeData[ModeNumber];
+
+ if (ModeNumber >= This->Mode->MaxMode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (ModeNumber == This->Mode->Mode) {
+ //
+ // Clear screen to black
+ //
+ ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ BiosVideoGraphicsOutputVbeBlt (
+ This,
+ &Background,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ 0,
+ ModeData->HorizontalResolution,
+ ModeData->VerticalResolution,
+ 0
+ );
+ return EFI_SUCCESS;
+ }
+
+ Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->GopDevicePath);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ This->Mode->Mode = ModeNumber;
+ This->Mode->Info->Version = 0;
+ This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
+ This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
+ This->Mode->Info->PixelFormat = ModeData->PixelFormat;
+ CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask));
+ This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
+ This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ //
+ // Frame BufferSize remain unchanged
+ //
+ This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer;
+ This->Mode->FrameBufferSize = ModeData->FrameBufferSize;
+
+ BiosVideoPrivate->HardwareNeedsStarting = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
+
+ @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
+ @param VbeBuffer The data to transfer to screen
+ @param MemAddress Physical frame buffer base address
+ @param DestinationX The X coordinate of the destination for BltOperation
+ @param DestinationY The Y coordinate of the destination for BltOperation
+ @param TotalBytes The total bytes of copy
+ @param VbePixelWidth Bytes per pixel
+ @param BytesPerScanLine Bytes per scan line
+
+**/
+VOID
+CopyVideoBuffer (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 *VbeBuffer,
+ IN VOID *MemAddress,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN TotalBytes,
+ IN UINT32 VbePixelWidth,
+ IN UINTN BytesPerScanLine
+ )
+{
+ UINTN FrameBufferAddr;
+ UINTN CopyBlockNum;
+ UINTN RemainingBytes;
+ UINTN UnalignedBytes;
+ EFI_STATUS Status;
+
+ FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;
+
+ //
+ // If TotalBytes is less than 4 bytes, only start byte copy.
+ //
+ if (TotalBytes < 4) {
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) FrameBufferAddr,
+ TotalBytes,
+ VbeBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ //
+ // If VbeBuffer is not 4-byte aligned, start byte copy.
+ //
+ UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;
+
+ if (UnalignedBytes != 0) {
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) FrameBufferAddr,
+ UnalignedBytes,
+ VbeBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ FrameBufferAddr += UnalignedBytes;
+ VbeBuffer += UnalignedBytes;
+ }
+
+ //
+ // Calculate 4-byte block count and remaining bytes.
+ //
+ CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;
+ RemainingBytes = (TotalBytes - UnalignedBytes) & 3;
+
+ //
+ // Copy 4-byte block and remaining bytes to physical frame buffer.
+ //
+ if (CopyBlockNum != 0) {
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) FrameBufferAddr,
+ CopyBlockNum,
+ VbeBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (RemainingBytes != 0) {
+ FrameBufferAddr += (CopyBlockNum << 2);
+ VbeBuffer += (CopyBlockNum << 2);
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) FrameBufferAddr,
+ RemainingBytes,
+ VbeBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+/**
+ Worker function to block transfer for VBE device.
+
+ @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV
+ @param BltBuffer The data to transfer to screen
+ @param BltOperation The operation to perform
+ @param SourceX The X coordinate of the source for BltOperation
+ @param SourceY The Y coordinate of the source for BltOperation
+ @param DestinationX The X coordinate of the destination for
+ BltOperation
+ @param DestinationY The Y coordinate of the destination for
+ BltOperation
+ @param Width The width of a rectangle in the blt rectangle in
+ pixels
+ @param Height The height of a rectangle in the blt rectangle in
+ pixels
+ @param Delta Not used for EfiBltVideoFill and
+ EfiBltVideoToVideo operation. If a Delta of 0 is
+ used, the entire BltBuffer will be operated on. If
+ a subrectangle of the BltBuffer is used, then
+ Delta represents the number of bytes in a row of
+ the BltBuffer.
+ @param Mode Mode data.
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in
+ @retval EFI_SUCCESS Blt operation success
+
+**/
+EFI_STATUS
+BiosVideoVbeBltWorker (
+ IN BIOS_VIDEO_DEV *BiosVideoPrivate,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta,
+ IN BIOS_VIDEO_MODE_DATA *Mode
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_TPL OriginalTPL;
+ UINTN DstY;
+ UINTN SrcY;
+ UINTN DstX;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ VOID *MemAddress;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
+ UINTN BytesPerScanLine;
+ UINTN Index;
+ UINT8 *VbeBuffer;
+ UINT8 *VbeBuffer1;
+ UINT8 *BltUint8;
+ UINT32 VbePixelWidth;
+ UINT32 Pixel;
+ UINTN TotalBytes;
+
+ PciIo = BiosVideoPrivate->PciIo;
+
+ VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;
+ MemAddress = Mode->LinearFrameBuffer;
+ BytesPerScanLine = Mode->BytesPerScanLine;
+ VbePixelWidth = Mode->BitsPerPixel / 8;
+ BltUint8 = (UINT8 *) BltBuffer;
+ TotalBytes = Width * VbePixelWidth;
+
+ if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width == 0 || Height == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // We need to fill the Virtual Screen buffer with the blt data.
+ // The virtual screen is upside down, as the first row is the bootom row of
+ // the image.
+ //
+ if (BltOperation == EfiBltVideoToBltBuffer) {
+ //
+ // Video to BltBuffer: Source is Video, destination is BltBuffer
+ //
+ if (SourceY + Height > Mode->VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SourceX + Width > Mode->HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // BltBuffer to Video: Source is BltBuffer, destination is Video
+ //
+ if (DestinationY + Height > Mode->VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestinationX + Width > Mode->HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // If Delta is zero, then the entire BltBuffer is being used, so Delta
+ // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
+ // the number of bytes in each row can be computed.
+ //
+ if (Delta == 0) {
+ Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ }
+ //
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+ // We would not want a timer based event (Cursor, ...) to come in while we are
+ // doing this operation.
+ //
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+ switch (BltOperation) {
+ case EfiBltVideoToBltBuffer:
+ for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ //
+ // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
+ //
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));
+ for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
+ Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;
+ Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);
+ Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);
+ Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);
+ Blt->Reserved = 0;
+ Blt++;
+ VbeBuffer += VbePixelWidth;
+ }
+
+ }
+ break;
+
+ case EfiBltVideoToVideo:
+ for (Index = 0; Index < Height; Index++) {
+ if (DestinationY <= SourceY) {
+ SrcY = SourceY + Index;
+ DstY = DestinationY + Index;
+ } else {
+ SrcY = SourceY + Height - Index - 1;
+ DstY = DestinationY + Height - Index - 1;
+ }
+
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);
+ VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);
+
+ gBS->CopyMem (
+ VbeBuffer,
+ VbeBuffer1,
+ TotalBytes
+ );
+
+ //
+ // Update physical frame buffer.
+ //
+ CopyVideoBuffer (
+ PciIo,
+ VbeBuffer,
+ MemAddress,
+ DestinationX,
+ DstY,
+ TotalBytes,
+ VbePixelWidth,
+ BytesPerScanLine
+ );
+ }
+ break;
+
+ case EfiBltVideoFill:
+ VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;
+ //
+ // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
+ //
+ Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
+ (
+ (Blt->Green & Mode->Green.Mask) <<
+ Mode->Green.Position
+ ) |
+ ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
+
+ for (Index = 0; Index < Width; Index++) {
+ gBS->CopyMem (
+ VbeBuffer,
+ &Pixel,
+ VbePixelWidth
+ );
+ VbeBuffer += VbePixelWidth;
+ }
+
+ VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
+ for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {
+ gBS->CopyMem (
+ (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
+ VbeBuffer,
+ TotalBytes
+ );
+ }
+
+ for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
+ //
+ // Update physical frame buffer.
+ //
+ CopyVideoBuffer (
+ PciIo,
+ VbeBuffer,
+ MemAddress,
+ DestinationX,
+ DstY,
+ TotalBytes,
+ VbePixelWidth,
+ BytesPerScanLine
+ );
+ }
+ break;
+
+ case EfiBltBufferToVideo:
+ for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
+ for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
+ //
+ // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
+ //
+ Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
+ ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |
+ ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
+ gBS->CopyMem (
+ VbeBuffer,
+ &Pixel,
+ VbePixelWidth
+ );
+ Blt++;
+ VbeBuffer += VbePixelWidth;
+ }
+
+ VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
+
+ //
+ // Update physical frame buffer.
+ //
+ CopyVideoBuffer (
+ PciIo,
+ VbeBuffer,
+ MemAddress,
+ DestinationX,
+ DstY,
+ TotalBytes,
+ VbePixelWidth,
+ BytesPerScanLine
+ );
+ }
+ break;
+
+ default: ;
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Graphics Output protocol instance to block transfer for VBE device.
+
+ @param This Pointer to Graphics Output protocol instance
+ @param BltBuffer The data to transfer to screen
+ @param BltOperation The operation to perform
+ @param SourceX The X coordinate of the source for BltOperation
+ @param SourceY The Y coordinate of the source for BltOperation
+ @param DestinationX The X coordinate of the destination for
+ BltOperation
+ @param DestinationY The Y coordinate of the destination for
+ BltOperation
+ @param Width The width of a rectangle in the blt rectangle in
+ pixels
+ @param Height The height of a rectangle in the blt rectangle in
+ pixels
+ @param Delta Not used for EfiBltVideoFill and
+ EfiBltVideoToVideo operation. If a Delta of 0 is
+ used, the entire BltBuffer will be operated on. If
+ a subrectangle of the BltBuffer is used, then
+ Delta represents the number of bytes in a row of
+ the BltBuffer.
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in
+ @retval EFI_SUCCESS Blt operation success
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputVbeBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ )
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ BIOS_VIDEO_MODE_DATA *Mode;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
+ Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];
+
+ return BiosVideoVbeBltWorker (
+ BiosVideoPrivate,
+ BltBuffer,
+ BltOperation,
+ SourceX,
+ SourceY,
+ DestinationX,
+ DestinationY,
+ Width,
+ Height,
+ Delta,
+ Mode
+ );
+}
+
+/**
+ Write graphics controller registers.
+
+ @param PciIo Pointer to PciIo protocol instance of the
+ controller
+ @param Address Register address
+ @param Data Data to be written to register
+
+ @return None
+
+**/
+VOID
+WriteGraphicsController (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN Address,
+ IN UINTN Data
+ )
+{
+ Address = Address | (Data << 8);
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,
+ 1,
+ &Address
+ );
+}
+
+
+/**
+ Read the four bit plane of VGA frame buffer.
+
+ @param PciIo Pointer to PciIo protocol instance of the
+ controller
+ @param HardwareBuffer Hardware VGA frame buffer address
+ @param MemoryBuffer Memory buffer address
+ @param WidthInBytes Number of bytes in a line to read
+ @param Height Height of the area to read
+
+ @return None
+
+**/
+VOID
+VgaReadBitPlanes (
+ EFI_PCI_IO_PROTOCOL *PciIo,
+ UINT8 *HardwareBuffer,
+ UINT8 *MemoryBuffer,
+ UINTN WidthInBytes,
+ UINTN Height
+ )
+{
+ UINTN BitPlane;
+ UINTN Rows;
+ UINTN FrameBufferOffset;
+ UINT8 *Source;
+ UINT8 *Destination;
+
+ //
+ // Program the Mode Register Write mode 0, Read mode 0
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
+ );
+
+ for (BitPlane = 0, FrameBufferOffset = 0;
+ BitPlane < VGA_NUMBER_OF_BIT_PLANES;
+ BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE
+ ) {
+ //
+ // Program the Read Map Select Register to select the correct bit plane
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,
+ BitPlane
+ );
+
+ Source = HardwareBuffer;
+ Destination = MemoryBuffer + FrameBufferOffset;
+
+ for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) Source,
+ WidthInBytes,
+ (VOID *) Destination
+ );
+ }
+ }
+}
+
+
+/**
+ Internal routine to convert VGA color to Grahpics Output color.
+
+ @param MemoryBuffer Buffer containing VGA color
+ @param CoordinateX The X coordinate of pixel on screen
+ @param CoordinateY The Y coordinate of pixel on screen
+ @param BltBuffer Buffer to contain converted Grahpics Output color
+
+ @return None
+
+**/
+VOID
+VgaConvertToGraphicsOutputColor (
+ UINT8 *MemoryBuffer,
+ UINTN CoordinateX,
+ UINTN CoordinateY,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ )
+{
+ UINTN Mask;
+ UINTN Bit;
+ UINTN Color;
+
+ MemoryBuffer += ((CoordinateY << 6) + (CoordinateY << 4) + (CoordinateX >> 3));
+ Mask = mVgaBitMaskTable[CoordinateX & 0x07];
+ for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {
+ if ((*MemoryBuffer & Mask) != 0) {
+ Color |= Bit;
+ }
+ }
+
+ *BltBuffer = mVgaColorToGraphicsOutputColor[Color];
+}
+
+/**
+ Internal routine to convert Grahpics Output color to VGA color.
+
+ @param BltBuffer buffer containing Grahpics Output color
+
+ @return Converted VGA color
+
+**/
+UINT8
+VgaConvertColor (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ )
+{
+ UINT8 Color;
+
+ Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));
+ if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {
+ Color |= 0x08;
+ }
+
+ return Color;
+}
+
+
+/**
+ Grahpics Output protocol instance to block transfer for VGA device.
+
+ @param This Pointer to Grahpics Output protocol instance
+ @param BltBuffer The data to transfer to screen
+ @param BltOperation The operation to perform
+ @param SourceX The X coordinate of the source for BltOperation
+ @param SourceY The Y coordinate of the source for BltOperation
+ @param DestinationX The X coordinate of the destination for
+ BltOperation
+ @param DestinationY The Y coordinate of the destination for
+ BltOperation
+ @param Width The width of a rectangle in the blt rectangle in
+ pixels
+ @param Height The height of a rectangle in the blt rectangle in
+ pixels
+ @param Delta Not used for EfiBltVideoFill and
+ EfiBltVideoToVideo operation. If a Delta of 0 is
+ used, the entire BltBuffer will be operated on. If
+ a subrectangle of the BltBuffer is used, then
+ Delta represents the number of bytes in a row of
+ the BltBuffer.
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in
+ @retval EFI_SUCCESS Blt operation success
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputVgaBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ )
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_TPL OriginalTPL;
+ UINT8 *MemAddress;
+ UINTN BytesPerScanLine;
+ UINTN Bit;
+ UINTN Index;
+ UINTN Index1;
+ UINTN StartAddress;
+ UINTN Bytes;
+ UINTN Offset;
+ UINT8 LeftMask;
+ UINT8 RightMask;
+ UINTN Address;
+ UINTN AddressFix;
+ UINT8 *Address1;
+ UINT8 *SourceAddress;
+ UINT8 *DestinationAddress;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Data;
+ UINT8 PixelColor;
+ UINT8 *VgaFrameBuffer;
+ UINTN SourceOffset;
+ UINTN SourceWidth;
+ UINTN Rows;
+ UINTN Columns;
+ UINTN CoordinateX;
+ UINTN CoordinateY;
+ UINTN CurrentMode;
+
+ if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+ CurrentMode = This->Mode->Mode;
+ PciIo = BiosVideoPrivate->PciIo;
+ MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;
+ BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;
+ VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;
+
+
+ if (Width == 0 || Height == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // We need to fill the Virtual Screen buffer with the blt data.
+ // The virtual screen is upside down, as the first row is the bootom row of
+ // the image.
+ //
+ if (BltOperation == EfiBltVideoToBltBuffer) {
+ //
+ // Video to BltBuffer: Source is Video, destination is BltBuffer
+ //
+ if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // BltBuffer to Video: Source is BltBuffer, destination is Video
+ //
+ if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // If Delta is zero, then the entire BltBuffer is being used, so Delta
+ // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
+ // the number of bytes in each row can be computed.
+ //
+ if (Delta == 0) {
+ Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ }
+ //
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+ // We would not want a timer based event (Cursor, ...) to come in while we are
+ // doing this operation.
+ //
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Compute some values we need for VGA
+ //
+ switch (BltOperation) {
+ case EfiBltVideoToBltBuffer:
+
+ SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);
+ SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;
+
+ //
+ // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
+ //
+ VgaReadBitPlanes (
+ PciIo,
+ MemAddress + SourceOffset,
+ VgaFrameBuffer + SourceOffset,
+ SourceWidth,
+ Height
+ );
+
+ //
+ // Convert VGA Bit Planes to a Graphics Output 32-bit color value
+ //
+ BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);
+ for (Rows = 0, CoordinateY = SourceY; Rows < Height; Rows++, CoordinateY++, BltBuffer += (Delta >> 2)) {
+ for (Columns = 0, CoordinateX = SourceX; Columns < Width; Columns++, CoordinateX++, BltBuffer++) {
+ VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, CoordinateY, BltBuffer);
+ }
+
+ BltBuffer -= Width;
+ }
+
+ break;
+
+ case EfiBltVideoToVideo:
+ //
+ // Check for an aligned Video to Video operation
+ //
+ if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {
+ //
+ // Program the Mode Register Write mode 1, Read mode 0
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
+ );
+
+ SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));
+ DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
+ Bytes = Width >> 3;
+ for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {
+ PciIo->CopyMem (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) (DestinationAddress + Offset),
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) (SourceAddress + Offset),
+ Bytes
+ );
+ }
+ } else {
+ SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);
+ SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;
+
+ //
+ // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
+ //
+ VgaReadBitPlanes (
+ PciIo,
+ MemAddress + SourceOffset,
+ VgaFrameBuffer + SourceOffset,
+ SourceWidth,
+ Height
+ );
+ }
+
+ break;
+
+ case EfiBltVideoFill:
+ StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
+ Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);
+ LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];
+ RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];
+ if (Bytes == 0) {
+ LeftMask = (UINT8) (LeftMask & RightMask);
+ RightMask = 0;
+ }
+
+ if (LeftMask == 0xff) {
+ StartAddress--;
+ Bytes++;
+ LeftMask = 0;
+ }
+
+ if (RightMask == 0xff) {
+ Bytes++;
+ RightMask = 0;
+ }
+
+ PixelColor = VgaConvertColor (BltBuffer);
+
+ //
+ // Program the Mode Register Write mode 2, Read mode 0
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
+ );
+
+ //
+ // Program the Data Rotate/Function Select Register to replace
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
+ );
+
+ if (LeftMask != 0) {
+ //
+ // Program the BitMask register with the Left column mask
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
+ LeftMask
+ );
+
+ for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {
+ //
+ // Read data from the bit planes into the latches
+ //
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) Address,
+ 1,
+ &Data
+ );
+ //
+ // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
+ //
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) Address,
+ 1,
+ &PixelColor
+ );
+ }
+ }
+
+ if (Bytes > 1) {
+ //
+ // Program the BitMask register with the middle column mask of 0xff
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
+ 0xff
+ );
+
+ for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthFillUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) Address,
+ Bytes - 1,
+ &PixelColor
+ );
+ }
+ }
+
+ if (RightMask != 0) {
+ //
+ // Program the BitMask register with the Right column mask
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
+ RightMask
+ );
+
+ for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {
+ //
+ // Read data from the bit planes into the latches
+ //
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) Address,
+ 1,
+ &Data
+ );
+ //
+ // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
+ //
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) Address,
+ 1,
+ &PixelColor
+ );
+ }
+ }
+ break;
+
+ case EfiBltBufferToVideo:
+ StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
+ LeftMask = mVgaBitMaskTable[DestinationX & 0x07];
+
+ //
+ // Program the Mode Register Write mode 2, Read mode 0
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
+ );
+
+ //
+ // Program the Data Rotate/Function Select Register to replace
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,
+ VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
+ );
+
+ for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {
+ for (Index1 = 0; Index1 < Width; Index1++) {
+ BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);
+ }
+ AddressFix = Address;
+
+ for (Bit = 0; Bit < 8; Bit++) {
+ //
+ // Program the BitMask register with the Left column mask
+ //
+ WriteGraphicsController (
+ PciIo,
+ VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
+ LeftMask
+ );
+
+ for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {
+ //
+ // Read data from the bit planes into the latches
+ //
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) Address1,
+ 1,
+ &Data
+ );
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) (UINTN) Address1,
+ 1,
+ &BiosVideoPrivate->LineBuffer[Index1]
+ );
+ }
+
+ LeftMask = (UINT8) (LeftMask >> 1);
+ if (LeftMask == 0) {
+ LeftMask = 0x80;
+ AddressFix++;
+ }
+ }
+ }
+
+ break;
+
+ default: ;
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return EFI_SUCCESS;
+}
+
+//
+// VGA Mini Port Protocol Functions
+//
+
+/**
+ VgaMiniPort protocol interface to set mode.
+
+ @param This Pointer to VgaMiniPort protocol instance
+ @param ModeNumber The index of the mode
+
+ @retval EFI_UNSUPPORTED The requested mode is not supported
+ @retval EFI_SUCCESS The requested mode is set successfully
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoVgaMiniPortSetMode (
+ IN EFI_VGA_MINI_PORT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ )
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_IA32_REGISTER_SET Regs;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Make sure the ModeNumber is a valid value
+ //
+ if (ModeNumber >= This->MaxMode) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the device structure for this device
+ //
+ BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);
+
+ switch (ModeNumber) {
+ case 0:
+ //
+ // Set the 80x25 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x83;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x14;
+ Regs.H.BL = 0;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+ break;
+
+ case 1:
+ //
+ // Set the 80x50 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x83;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x12;
+ Regs.H.BL = 0;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Event handler for Exit Boot Service.
+
+ @param Event The event that be siganlled when exiting boot service.
+ @param Context Pointer to instance of BIOS_VIDEO_DEV.
+
+**/
+VOID
+EFIAPI
+BiosVideoNotifyExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ BIOS_VIDEO_DEV *BiosVideoPrivate;
+ EFI_IA32_REGISTER_SET Regs;
+
+ BiosVideoPrivate = (BIOS_VIDEO_DEV *)Context;
+
+ //
+ // Set the 80x25 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x03;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x83;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x04;
+ Regs.H.BL = 0;
+ BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
+}
+
+/**
+ The user Entry Point for module UefiBiosVideo. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gBiosVideoDriverBinding,
+ ImageHandle,
+ &gBiosVideoComponentName,
+ &gBiosVideoComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver
+ //
+ return gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiLegacyBiosGuid,
+ NULL,
+ NULL
+ );
+}
+
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h
new file mode 100644
index 0000000000..45a75b9cd0
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.h
@@ -0,0 +1,532 @@
+/** @file
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BIOS_GRAPHICS_OUTPUT_H_
+#define _BIOS_GRAPHICS_OUTPUT_H_
+
+#include <FrameworkDxe.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/EdidActive.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/EdidDiscovered.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/VgaMiniPort.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/EdidOverride.h>
+
+#include <Guid/StatusCodeDataTypeId.h>
+#include <Guid/LegacyBios.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <IndustryStandard/Pci.h>
+#include "VesaBiosExtensions.h"
+
+//
+// Packed format support: The number of bits reserved for each of the colors and the actual
+// position of RGB in the frame buffer is specified in the VBE Mode information
+//
+typedef struct {
+ UINT8 Position; // Position of the color
+ UINT8 Mask; // The number of bits expressed as a mask
+} BIOS_VIDEO_COLOR_PLACEMENT;
+
+//
+// BIOS Graphics Output Graphical Mode Data
+//
+typedef struct {
+ UINT16 VbeModeNumber;
+ UINT16 BytesPerScanLine;
+ VOID *LinearFrameBuffer;
+ UINTN FrameBufferSize;
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ UINT32 BitsPerPixel;
+ BIOS_VIDEO_COLOR_PLACEMENT Red;
+ BIOS_VIDEO_COLOR_PLACEMENT Green;
+ BIOS_VIDEO_COLOR_PLACEMENT Blue;
+ BIOS_VIDEO_COLOR_PLACEMENT Reserved;
+ EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
+ EFI_PIXEL_BITMASK PixelBitMask;
+} BIOS_VIDEO_MODE_DATA;
+
+//
+// BIOS video child handle private data Structure
+//
+#define BIOS_VIDEO_DEV_SIGNATURE SIGNATURE_32 ('B', 'V', 'M', 'p')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+
+ //
+ // Consumed Protocols
+ //
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ //
+ // Original PCI attributes
+ //
+ UINT64 OriginalPciAttributes;
+
+ //
+ // Produced Protocols
+ //
+ EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput;
+ EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered;
+ EFI_EDID_ACTIVE_PROTOCOL EdidActive;
+ EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort;
+
+ //
+ // General fields
+ //
+ BOOLEAN VgaCompatible;
+ BOOLEAN ProduceGraphicsOutput;
+
+ //
+ // Graphics Output Protocol related fields
+ //
+ BOOLEAN HardwareNeedsStarting;
+ UINTN CurrentMode;
+ UINTN MaxMode;
+ BIOS_VIDEO_MODE_DATA *ModeData;
+ UINT8 *LineBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
+ UINT8 *VgaFrameBuffer;
+
+ //
+ // VESA Bios Extensions related fields
+ //
+ UINTN NumberOfPagesBelow1MB; // Number of 4KB pages in PagesBelow1MB
+ EFI_PHYSICAL_ADDRESS PagesBelow1MB; // Buffer for all VBE Information Blocks
+ VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *VbeInformationBlock; // 0x200 bytes. Must be allocated below 1MB
+ VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; // 0x100 bytes. Must be allocated below 1MB
+ VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *VbeEdidDataBlock; // 0x80 bytes. Must be allocated below 1MB
+ VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; // 59 bytes. Must be allocated below 1MB
+ UINTN VbeSaveRestorePages; // Number of 4KB pages in VbeSaveRestoreBuffer
+ EFI_PHYSICAL_ADDRESS VbeSaveRestoreBuffer; // Must be allocated below 1MB
+ //
+ // Status code
+ //
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+
+ EFI_EVENT ExitBootServicesEvent;
+} BIOS_VIDEO_DEV;
+
+#define BIOS_VIDEO_DEV_FROM_PCI_IO_THIS(a) CR (a, BIOS_VIDEO_DEV, PciIo, BIOS_VIDEO_DEV_SIGNATURE)
+#define BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS(a) CR (a, BIOS_VIDEO_DEV, GraphicsOutput, BIOS_VIDEO_DEV_SIGNATURE)
+#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV, VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE)
+
+#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2;
+
+//
+// Driver Binding Protocol functions
+//
+
+/**
+ Supported.
+
+ @param This Pointer to driver binding protocol
+ @param Controller Controller handle to connect
+ @param RemainingDevicePath A pointer to the remaining portion of a device
+ path
+
+ @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this
+ driver, Otherwise, this controller cannot be
+ managed by this driver
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+
+/**
+ Install Graphics Output Protocol onto VGA device handles.
+
+ @param This Pointer to driver binding protocol
+ @param Controller Controller handle to connect
+ @param RemainingDevicePath A pointer to the remaining portion of a device
+ path
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+
+/**
+ Stop.
+
+ @param This Pointer to driver binding protocol
+ @param Controller Controller handle to connect
+ @param NumberOfChildren Number of children handle created by this driver
+ @param ChildHandleBuffer Buffer containing child handle created
+
+ @retval EFI_SUCCESS Driver disconnected successfully from controller
+ @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Private worker functions
+//
+
+/**
+ Check for VBE device.
+
+ @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure
+
+ @retval EFI_SUCCESS VBE device found
+
+**/
+EFI_STATUS
+BiosVideoCheckForVbe (
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate
+ );
+
+
+/**
+ Check for VGA device.
+
+ @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure
+
+ @retval EFI_SUCCESS Standard VGA device found
+
+**/
+EFI_STATUS
+BiosVideoCheckForVga (
+ IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate
+ );
+
+
+
+
+/**
+ Release resource for biso video instance.
+
+ @param BiosVideoPrivate Video child device private data structure
+
+**/
+VOID
+BiosVideoDeviceReleaseResource (
+ BIOS_VIDEO_DEV *BiosVideoPrivate
+ );
+
+//
+// BIOS Graphics Output Protocol functions
+//
+
+/**
+ Graphics Output protocol interface to get video mode.
+
+ @param This Protocol instance pointer.
+ @param ModeNumber The mode number to return information on.
+ @param SizeOfInfo A pointer to the size, in bytes, of the Info
+ buffer.
+ @param Info Caller allocated buffer that returns information
+ about ModeNumber.
+
+ @retval EFI_SUCCESS Mode information returned.
+ @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
+ @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
+ video mode.
+ @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
+ @retval EFI_INVALID_PARAMETER One of the input args was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ );
+
+
+/**
+ Graphics Output protocol interface to set video mode.
+
+ @param This Protocol instance pointer.
+ @param ModeNumber The mode number to be set.
+
+ @retval EFI_SUCCESS Graphics mode was changed.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the
+ request.
+ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
+ IN UINT32 ModeNumber
+ );
+
+
+/**
+ Graphics Output protocol instance to block transfer for VBE device.
+
+ @param This Pointer to Graphics Output protocol instance
+ @param BltBuffer The data to transfer to screen
+ @param BltOperation The operation to perform
+ @param SourceX The X coordinate of the source for BltOperation
+ @param SourceY The Y coordinate of the source for BltOperation
+ @param DestinationX The X coordinate of the destination for
+ BltOperation
+ @param DestinationY The Y coordinate of the destination for
+ BltOperation
+ @param Width The width of a rectangle in the blt rectangle in
+ pixels
+ @param Height The height of a rectangle in the blt rectangle in
+ pixels
+ @param Delta Not used for EfiBltVideoFill and
+ EfiBltVideoToVideo operation. If a Delta of 0 is
+ used, the entire BltBuffer will be operated on. If
+ a subrectangle of the BltBuffer is used, then
+ Delta represents the number of bytes in a row of
+ the BltBuffer.
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in
+ @retval EFI_SUCCESS Blt operation success
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputVbeBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ );
+
+
+/**
+ Grahpics Output protocol instance to block transfer for VGA device.
+
+ @param This Pointer to Grahpics Output protocol instance
+ @param BltBuffer The data to transfer to screen
+ @param BltOperation The operation to perform
+ @param SourceX The X coordinate of the source for BltOperation
+ @param SourceY The Y coordinate of the source for BltOperation
+ @param DestinationX The X coordinate of the destination for
+ BltOperation
+ @param DestinationY The Y coordinate of the destination for
+ BltOperation
+ @param Width The width of a rectangle in the blt rectangle in
+ pixels
+ @param Height The height of a rectangle in the blt rectangle in
+ pixels
+ @param Delta Not used for EfiBltVideoFill and
+ EfiBltVideoToVideo operation. If a Delta of 0 is
+ used, the entire BltBuffer will be operated on. If
+ a subrectangle of the BltBuffer is used, then
+ Delta represents the number of bytes in a row of
+ the BltBuffer.
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter passed in
+ @retval EFI_SUCCESS Blt operation success
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoGraphicsOutputVgaBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ );
+
+//
+// BIOS VGA Mini Port Protocol functions
+//
+
+/**
+ VgaMiniPort protocol interface to set mode.
+
+ @param This Pointer to VgaMiniPort protocol instance
+ @param ModeNumber The index of the mode
+
+ @retval EFI_UNSUPPORTED The requested mode is not supported
+ @retval EFI_SUCCESS The requested mode is set successfully
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoVgaMiniPortSetMode (
+ IN EFI_VGA_MINI_PORT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ );
+
+/**
+ Event handler for Exit Boot Service.
+
+ @param Event The event that be siganlled when exiting boot service.
+ @param Context Pointer to instance of BIOS_VIDEO_DEV.
+
+**/
+VOID
+EFIAPI
+BiosVideoNotifyExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+//
+// Standard VGA Definitions
+//
+#define VGA_HORIZONTAL_RESOLUTION 640
+#define VGA_VERTICAL_RESOLUTION 480
+#define VGA_NUMBER_OF_BIT_PLANES 4
+#define VGA_PIXELS_PER_BYTE 8
+#define VGA_BYTES_PER_SCAN_LINE (VGA_HORIZONTAL_RESOLUTION / VGA_PIXELS_PER_BYTE)
+#define VGA_BYTES_PER_BIT_PLANE (VGA_VERTICAL_RESOLUTION * VGA_BYTES_PER_SCAN_LINE)
+
+#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER 0x3ce
+#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER 0x3cf
+
+#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER 0x00
+
+#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01
+
+#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER 0x02
+
+#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER 0x03
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE 0x00
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND 0x08
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR 0x10
+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR 0x18
+
+#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER 0x04
+
+#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER 0x05
+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0 0x00
+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1 0x08
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 0x00
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 0x01
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 0x02
+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3 0x03
+
+#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER 0x06
+
+#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER 0x07
+
+#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER 0x08
+
+/**
+ Install child handles if the Handle supports MBR format.
+
+ @param This Calling context.
+ @param ParentHandle Parent Handle
+ @param ParentPciIo Parent PciIo interface
+ @param ParentLegacyBios Parent LegacyBios interface
+ @param ParentDevicePath Parent Device Path
+ @param RemainingDevicePath Remaining Device Path
+ @param OriginalPciAttributes Original PCI Attributes
+
+ @retval EFI_SUCCESS If a child handle was added
+ @retval other A child handle was not added
+
+**/
+EFI_STATUS
+BiosVideoChildHandleInstall (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ParentHandle,
+ IN EFI_PCI_IO_PROTOCOL *ParentPciIo,
+ IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ IN UINT64 OriginalPciAttributes
+ );
+
+/**
+ Deregister an video child handle and free resources.
+
+ @param This Protocol instance pointer.
+ @param Controller Video controller handle
+ @param Handle Video child handle
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+BiosVideoChildHandleUninstall (
+ EFI_DRIVER_BINDING_PROTOCOL *This,
+ EFI_HANDLE Controller,
+ EFI_HANDLE Handle
+ );
+
+/**
+ Release resource for biso video instance.
+
+ @param BiosVideoPrivate Video child device private data structure
+
+**/
+VOID
+BiosVideoDeviceReleaseResource (
+ BIOS_VIDEO_DEV *BiosVideoPrivate
+ );
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c
new file mode 100644
index 0000000000..1d70e5c4a3
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/ComponentName.c
@@ -0,0 +1,313 @@
+/** @file
+
+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.
+
+**/
+
+#include "BiosVideo.h"
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName = {
+ BiosVideoComponentNameGetDriverName,
+ BiosVideoComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosVideoComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosVideoComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = {
+ {
+ "eng;en",
+ L"BIOS[INT10] Video Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mBiosVideoDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gBiosVideoComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+BiosVideoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h
new file mode 100644
index 0000000000..dcda3fcd5a
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h
@@ -0,0 +1,451 @@
+/** @file
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _VESA_BIOS_EXTENSIONS_H_
+#define _VESA_BIOS_EXTENSIONS_H_
+
+//
+// Turn on byte packing of data structures
+//
+#pragma pack(1)
+//
+// VESA BIOS Extensions status codes
+//
+#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f
+
+//
+// VESA BIOS Extensions Services
+//
+#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION 0x4f00
+
+/*++
+
+ Routine Description:
+ Function 00 : Return Controller Information
+
+ Arguments:
+ Inputs:
+ AX = 0x4f00
+ ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure
+ Outputs:
+ AX = Return Status
+
+--*/
+#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION 0x4f01
+
+/*++
+
+ Routine Description:
+ Function 01 : Return Mode Information
+
+ Arguments:
+ Inputs:
+ AX = 0x4f01
+ CX = Mode Number
+ ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure
+ Outputs:
+ AX = Return Status
+
+--*/
+#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02
+
+/*++
+
+ Routine Description:
+ Function 02 : Set Mode
+
+ Arguments:
+ Inputs:
+ AX = 0x4f02
+ BX = Desired mode to set
+ D0-D8 = Mode Number
+ D9-D10 = Reserved (must be 0)
+ D11 = 0 - Use current default refresh rate
+ = 1 - Use user specfieid CRTC values for refresh rate
+ D12-D13 = Reserved (must be 0)
+ D14 = 0 - Use windowed frame buffer model
+ = 1 - Use linear/flat frame buffer model
+ D15 = 0 - Clear display memory
+ = 1 - Don't clear display memory
+ ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure
+ Outputs:
+ AX = Return Status
+
+--*/
+#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE 0x4f03
+
+/*++
+
+ Routine Description:
+ Function 03 : Return Current Mode
+
+ Arguments:
+ Inputs:
+ AX = 0x4f03
+ Outputs:
+ AX = Return Status
+ BX = Current mode
+ D0-D13 = Mode Number
+ D14 = 0 - Windowed frame buffer model
+ = 1 - Linear/flat frame buffer model
+ D15 = 0 - Memory cleared at last mode set
+ = 1 - Memory not cleared at last mode set
+
+--*/
+#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04
+
+/*++
+
+ Routine Description:
+ Function 04 : Save/Restore State
+
+ Arguments:
+ Inputs:
+ AX = 0x4f03
+ DL = 0x00 - Return Save/Restore State buffer size
+ = 0x01 - Save State
+ = 0x02 - Restore State
+ CX = Requested Status
+ D0 = Save/Restore controller hardware state
+ D1 = Save/Restore BIOS data state
+ D2 = Save/Restore DAC state
+ D3 = Save/Restore Regsiter state
+ ES:BX = Pointer to buffer if DL=1 or DL=2
+ Outputs:
+ AX = Return Status
+ BX = Number of 64 byte blocks to hold the state buffer if DL=0
+
+--*/
+#define VESA_BIOS_EXTENSIONS_EDID 0x4f15
+
+/*++
+
+ Routine Description:
+ Function 15 : implement VBE/DDC service
+
+ Arguments:
+ Inputs:
+ AX = 0x4f15
+ BL = 0x00 - Report VBE/DDC Capabilities
+ CX = 0x00 - Controller unit number (00 = primary controller)
+ ES:DI = Null pointer, must be 0:0 in version 1.0
+ Outputs:
+ AX = Return Status
+ BH = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes)
+ BL = DDC level supported
+ D0 = 0 DDC1 not supported
+ = 1 DDC1 supported
+ D1 = 0 DDC2 not supported
+ = 1 DDC2 supported
+ D2 = 0 Screen not blanked during data transfer
+ = 1 Screen blanked during data transfer
+
+ Inputs:
+ AX = 0x4f15
+ BL = 0x01 - Read EDID
+ CX = 0x00 - Controller unit number (00 = primary controller)
+ DX = 0x00 - EDID block number
+ ES:DI = Pointer to buffer in which the EDID block is returned
+ Outputs:
+ AX = Return Status
+--*/
+
+//
+// Timing data from EDID data block
+//
+#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE 128
+#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17
+
+typedef struct {
+ UINT16 HorizontalResolution;
+ UINT16 VerticalResolution;
+ UINT16 RefreshRate;
+} VESA_BIOS_EXTENSIONS_EDID_TIMING;
+
+typedef struct {
+ UINT32 ValidNumber;
+ UINT32 Key[VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER];
+} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING;
+
+typedef struct {
+ UINT8 Header[8]; //EDID header "00 FF FF FF FF FF FF 00"
+ UINT16 ManufactureName; //EISA 3-character ID
+ UINT16 ProductCode; //Vendor assigned code
+ UINT32 SerialNumber; //32-bit serial number
+ UINT8 WeekOfManufacture; //Week number
+ UINT8 YearOfManufacture; //Year
+ UINT8 EdidVersion; //EDID Structure Version
+ UINT8 EdidRevision; //EDID Structure Revision
+ UINT8 VideoInputDefinition;
+ UINT8 MaxHorizontalImageSize; //cm
+ UINT8 MaxVerticalImageSize; //cm
+ UINT8 DisplayTransferCharacteristic;
+ UINT8 FeatureSupport;
+ UINT8 RedGreenLowBits; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0
+ UINT8 BlueWhiteLowBits; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0
+ UINT8 RedX; //Red-x Bits 9 - 2
+ UINT8 RedY; //Red-y Bits 9 - 2
+ UINT8 GreenX; //Green-x Bits 9 - 2
+ UINT8 GreenY; //Green-y Bits 9 - 2
+ UINT8 BlueX; //Blue-x Bits 9 - 2
+ UINT8 BlueY; //Blue-y Bits 9 - 2
+ UINT8 WhiteX; //White-x Bits 9 - 2
+ UINT8 WhiteY; //White-x Bits 9 - 2
+ UINT8 EstablishedTimings[3];
+ UINT8 StandardTimingIdentification[16];
+ UINT8 DetailedTimingDescriptions[72];
+ UINT8 ExtensionFlag; //Number of (optional) 128-byte EDID extension blocks to follow
+ UINT8 Checksum;
+} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK;
+
+//
+// Super VGA Information Block
+//
+typedef struct {
+ UINT32 VESASignature; // 'VESA' 4 byte signature
+ UINT16 VESAVersion; // VBE version number
+ UINT32 OEMStringPtr; // Pointer to OEM string
+ UINT32 Capabilities; // Capabilities of video card
+ UINT32 VideoModePtr; // Pointer to an array of 16-bit supported modes values terminated by 0xFFFF
+ UINT16 TotalMemory; // Number of 64kb memory blocks
+ UINT16 OemSoftwareRev; // VBE implementation Software revision
+ UINT32 OemVendorNamePtr; // VbeFarPtr to Vendor Name String
+ UINT32 OemProductNamePtr; // VbeFarPtr to Product Name String
+ UINT32 OemProductRevPtr; // VbeFarPtr to Product Revision String
+ UINT8 Reserved[222]; // Reserved for VBE implementation scratch area
+ UINT8 OemData[256]; // Data area for OEM strings. Pad to 512 byte block size
+} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK;
+
+//
+// Super VGA Information Block VESASignature values
+//
+#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE SIGNATURE_32 ('V', 'E', 'S', 'A')
+#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE SIGNATURE_32 ('V', 'B', 'E', '2')
+
+//
+// Super VGA Information Block VESAVersion values
+//
+#define VESA_BIOS_EXTENSIONS_VERSION_1_2 0x0102
+#define VESA_BIOS_EXTENSIONS_VERSION_2_0 0x0200
+#define VESA_BIOS_EXTENSIONS_VERSION_3_0 0x0300
+
+//
+// Super VGA Information Block Capabilities field bit defintions
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01 // 0: DAC width is fixed at 6 bits/color
+// 1: DAC width switchable to 8 bits/color
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02 // 0: Controller is VGA compatible
+// 1: Controller is not VGA compatible
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04 // 0: Normal RAMDAC operation
+// 1: Use blank bit in function 9 to program RAMDAC
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC 0x08 // 0: No hardware stereoscopic signal support
+// 1: Hardware stereoscopic signal support
+//
+#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC 0x10 // 0: Stero signaling supported via external VESA stereo connector
+// 1: Stero signaling supported via VESA EVC connector
+//
+// Super VGA mode number bite field definitions
+//
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100 // 0: Not a VESA defined VBE mode
+// 1: A VESA defined VBE mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800 // 0: Use current BIOS default referesh rate
+// 1: Use the user specified CRTC values for refresh rate
+//
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER 0x4000 // 0: Use a banked/windowed frame buffer
+// 1: Use a linear/flat frame buffer
+//
+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY 0x8000 // 0: Clear display memory
+// 1: Preseve display memory
+//
+// Super VGA Information Block mode list terminator value
+//
+#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff
+
+//
+// Window Function
+//
+typedef
+VOID
+(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) (
+ VOID
+ );
+
+//
+// Super VGA Mode Information Block
+//
+typedef struct {
+ //
+ // Manadory fields for all VESA Bios Extensions revisions
+ //
+ UINT16 ModeAttributes; // Mode attributes
+ UINT8 WinAAttributes; // Window A attributes
+ UINT8 WinBAttributes; // Window B attributes
+ UINT16 WinGranularity; // Window granularity in k
+ UINT16 WinSize; // Window size in k
+ UINT16 WinASegment; // Window A segment
+ UINT16 WinBSegment; // Window B segment
+ UINT32 WindowFunction; // Pointer to window function
+ UINT16 BytesPerScanLine; // Bytes per scanline
+ //
+ // Manadory fields for VESA Bios Extensions 1.2 and above
+ //
+ UINT16 XResolution; // Horizontal resolution
+ UINT16 YResolution; // Vertical resolution
+ UINT8 XCharSize; // Character cell width
+ UINT8 YCharSize; // Character cell height
+ UINT8 NumberOfPlanes; // Number of memory planes
+ UINT8 BitsPerPixel; // Bits per pixel
+ UINT8 NumberOfBanks; // Number of CGA style banks
+ UINT8 MemoryModel; // Memory model type
+ UINT8 BankSize; // Size of CGA style banks
+ UINT8 NumberOfImagePages; // Number of images pages
+ UINT8 Reserved1; // Reserved
+ UINT8 RedMaskSize; // Size of direct color red mask
+ UINT8 RedFieldPosition; // Bit posn of lsb of red mask
+ UINT8 GreenMaskSize; // Size of direct color green mask
+ UINT8 GreenFieldPosition; // Bit posn of lsb of green mask
+ UINT8 BlueMaskSize; // Size of direct color blue mask
+ UINT8 BlueFieldPosition; // Bit posn of lsb of blue mask
+ UINT8 RsvdMaskSize; // Size of direct color res mask
+ UINT8 RsvdFieldPosition; // Bit posn of lsb of res mask
+ UINT8 DirectColorModeInfo; // Direct color mode attributes
+ //
+ // Manadory fields for VESA Bios Extensions 2.0 and above
+ //
+ UINT32 PhysBasePtr; // Physical Address for flat memory frame buffer
+ UINT32 Reserved2; // Reserved
+ UINT16 Reserved3; // Reserved
+ //
+ // Manadory fields for VESA Bios Extensions 3.0 and above
+ //
+ UINT16 LinBytesPerScanLine; // Bytes/scan line for linear modes
+ UINT8 BnkNumberOfImagePages; // Number of images for banked modes
+ UINT8 LinNumberOfImagePages; // Number of images for linear modes
+ UINT8 LinRedMaskSize; // Size of direct color red mask (linear mode)
+ UINT8 LinRedFieldPosition; // Bit posiiton of lsb of red mask (linear modes)
+ UINT8 LinGreenMaskSize; // Size of direct color green mask (linear mode)
+ UINT8 LinGreenFieldPosition; // Bit posiiton of lsb of green mask (linear modes)
+ UINT8 LinBlueMaskSize; // Size of direct color blue mask (linear mode)
+ UINT8 LinBlueFieldPosition; // Bit posiiton of lsb of blue mask (linear modes)
+ UINT8 LinRsvdMaskSize; // Size of direct color reserved mask (linear mode)
+ UINT8 LinRsvdFieldPosition; // Bit posiiton of lsb of reserved mask (linear modes)
+ UINT32 MaxPixelClock; // Maximum pixel clock (in Hz) for graphics mode
+ UINT8 Pad[190]; // Pad to 256 byte block size
+} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK;
+
+//
+// Super VGA Mode Information Block ModeAttributes field bit defintions
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE 0x0001 // 0: Mode not supported in handware
+// 1: Mode supported in handware
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004 // 0: TTY Output functions not supported by BIOS
+// 1: TTY Output functions supported by BIOS
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008 // 0: Monochrome mode
+// 1: Color mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS 0x0010 // 0: Text mode
+// 1: Graphics mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020 // 0: VGA compatible mode
+// 1: Not a VGA compatible mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED 0x0040 // 0: VGA compatible windowed memory mode
+// 1: Not a VGA compatible windowed memory mode
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080 // 0: No linear fram buffer mode available
+// 1: Linear frame buffer mode available
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100 // 0: No double scan mode available
+// 1: Double scan mode available
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED 0x0200 // 0: No interlaced mode is available
+// 1: Interlaced mode is available
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400 // 0: No hardware triple buffer mode support available
+// 1: Hardware triple buffer mode support available
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC 0x0800 // 0: No hardware steroscopic display support
+// 1: Hardware steroscopic display support
+//
+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY 0x1000 // 0: No dual display start address support
+// 1: Dual display start address support
+//
+// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit defintions
+//
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01 // 0: Single non-relocatable window only
+// 1: Relocatable window(s) are supported
+//
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE 0x02 // 0: Window is not readable
+// 1: Window is readable
+//
+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE 0x04 // 0: Window is not writable
+// 1: Window is writable
+//
+// Super VGA Mode Information Block DirectColorMode field bit defintions
+//
+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP 0x01 // 0: Color ram is fixed
+// 1: Color ramp is programmable
+//
+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE 0x02 // 0: Bits in Rsvd field are reserved
+// 1: Bits in Rsdv field are usable
+//
+// Super VGA Memory Models
+//
+typedef enum {
+ MemPL = 3, // Planar memory model
+ MemPK = 4, // Packed pixel memory model
+ MemRGB= 6, // Direct color RGB memory model
+ MemYUV= 7 // Direct color YUV memory model
+} VESA_BIOS_EXTENSIONS_MEMORY_MODELS;
+
+//
+// Super VGA CRTC Information Block
+//
+typedef struct {
+ UINT16 HorizontalTotal; // Horizontal total in pixels
+ UINT16 HorizontalSyncStart; // Horizontal sync start in pixels
+ UINT16 HorizontalSyncEnd; // Horizontal sync end in pixels
+ UINT16 VericalTotal; // Vertical total in pixels
+ UINT16 VericalSyncStart; // Vertical sync start in pixels
+ UINT16 VericalSyncEnd; // Vertical sync end in pixels
+ UINT8 Flags; // Flags (Interlaced/DoubleScan/etc).
+ UINT32 PixelClock; // Pixel clock in units of Hz
+ UINT16 RefreshRate; // Refresh rate in units of 0.01 Hz
+ UINT8 Reserved[40]; // Pad
+} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK;
+
+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01 // 0: Graphics mode is not souble scanned
+// 1: Graphics mode is double scanned
+//
+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02 // 0: Graphics mode is not interlaced
+// 1: Graphics mode is interlaced
+//
+#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE 0x04 // 0: Horizontal sync polarity is positive(+)
+// 0: Horizontal sync polarity is negative(-)
+//
+#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08 // 0: Verical sync polarity is positive(+)
+// 0: Verical sync polarity is negative(-)
+//
+// Turn off byte packing of data structures
+//
+#pragma pack()
+
+#endif
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf
new file mode 100644
index 0000000000..bf5f255dcf
--- /dev/null
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf
@@ -0,0 +1,80 @@
+## @file
+# Video driver based on legacy bios.
+#
+# This driver by using Legacy Bios protocol service to support csm Video
+# and produce Graphics Output Protocol.
+#
+# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions
+# of the BSD License which accompanies this distribution. The
+# full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BiosVideoDxe
+ FILE_GUID = 0B04B2ED-861C-42cd-A22F-C3AAFACCB896
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BiosVideoEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gBiosVideoDriverBinding
+# COMPONENT_NAME = gBiosVideoComponentName
+#
+
+[Sources]
+ BiosVideo.c
+ BiosVideo.h
+ ComponentName.c
+ VesaBiosExtensions.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ DevicePathLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ ReportStatusCodeLib
+ DebugLib
+ PcdLib
+
+
+[Guids]
+ gEfiLegacyBiosGuid # ALWAYS_PRODUCED
+ gEfiEventExitBootServicesGuid
+
+[Protocols]
+ gEfiVgaMiniPortProtocolGuid # PROTOCOL BY_START
+ gEfiEdidDiscoveredProtocolGuid # PROTOCOL BY_START
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL BY_START
+ gEfiEdidActiveProtocolGuid # PROTOCOL BY_START
+ gEfiLegacyBiosProtocolGuid # PROTOCOL TO_START
+ gEfiPciIoProtocolGuid # PROTOCOL TO_START
+ gEfiDevicePathProtocolGuid # PROTOCOL TO_START
+ gEfiEdidOverrideProtocolGuid # PROTOCOL TO_START
+
+[Pcd]
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable