]> git.proxmox.com Git - mirror_edk2.git/commitdiff
CorebootModulePkg: Remove DuetPkg references
authorLeahy, Leroy P <leroy.p.leahy@intel.com>
Mon, 2 May 2016 19:59:17 +0000 (12:59 -0700)
committerPrince Agyeman <prince.agyeman@intel.com>
Mon, 2 May 2016 22:46:44 +0000 (15:46 -0700)
Remove the references to DuetPkg.  Copy the files from revision
ffea0a2ce21e8e9878587de2419959a7bfea4021 of DuetPkg into
CorebootModulePkg.  The components include:
* PciBusNoEnumerationDxe
* PciRootBridgeNoEnumerationDxe
* SataControllerDxe

TEST=Build and run on Galileo Gen2

Change-Id: Id07185f7e226749e5f7c6b6cb427bcef7eac8496
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-by: Maurice Ma <maurice.ma@intel.com>
Reviewed-by: Prince Agyeman <prince.agyeman@intel.com>
39 files changed:
CorebootModulePkg/PciBusNoEnumerationDxe/ComponentName.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciBus.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciBus.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciCommand.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciCommand.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciDeviceSupport.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciDeviceSupport.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciDriverOverride.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciDriverOverride.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumerator.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumerator.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciIo.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciIo.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciPowerManagement.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciPowerManagement.h [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciRomTable.c [new file with mode: 0644]
CorebootModulePkg/PciBusNoEnumerationDxe/PciRomTable.h [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf [new file with mode: 0644]
CorebootModulePkg/PciRootBridgeNoEnumerationDxe/X64/PcatIo.c [new file with mode: 0644]
CorebootModulePkg/SataControllerDxe/ComponentName.c [new file with mode: 0644]
CorebootModulePkg/SataControllerDxe/SataController.c [new file with mode: 0644]
CorebootModulePkg/SataControllerDxe/SataController.h [new file with mode: 0644]
CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf [new file with mode: 0644]
CorebootPayloadPkg/CorebootPayloadPkg.fdf
CorebootPayloadPkg/CorebootPayloadPkgIa32.dsc
CorebootPayloadPkg/CorebootPayloadPkgIa32X64.dsc

diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/ComponentName.c b/CorebootModulePkg/PciBusNoEnumerationDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..9419f9a
--- /dev/null
@@ -0,0 +1,161 @@
+/*++
+
+Copyright (c) 2005 - 2007, 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.
+
+Module Name:
+  ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "PciBus.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetControllerName (
+  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 gPciBusComponentName = {
+  PciBusComponentNameGetDriverName,
+  PciBusComponentNameGetControllerName,
+  "eng"
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControllerName,
+  "en"
+};
+
+
+EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {
+  { "eng;en", L"PCI Bus Driver" },
+  { NULL, NULL }
+};
+
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+/*++
+
+  Routine Description:
+    Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+  Arguments:
+    This       - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+    Language   - A pointer to a three character ISO 639-2 language identifier.
+                 This is the language of the driver name that that the caller 
+                 is requesting, and it must match one of the languages specified
+                 in SupportedLanguages.  The number of languages supported by a 
+                 driver is up to the driver writer.
+    DriverName - A pointer to the Unicode string to return.  This Unicode string
+                 is the name of the driver specified by This in the language 
+                 specified by Language.
+
+  Returns:
+    EFI_SUCCESS           - The Unicode string for the Driver specified by This
+                            and the language specified by Language was returned 
+                            in DriverName.
+    EFI_INVALID_PARAMETER - Language is NULL.
+    EFI_INVALID_PARAMETER - DriverName is NULL.
+    EFI_UNSUPPORTED       - The driver specified by This does not support the 
+                            language specified by Language.
+
+--*/
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mPciBusDriverNameTable, 
+           DriverName,
+           (BOOLEAN)(This == &gPciBusComponentName)
+           );
+}
+
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  EFI_HANDLE                   ControllerHandle,
+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **ControllerName
+  )
+/*++
+
+  Routine Description:
+    Retrieves a Unicode string that is the user readable name of the controller
+    that is being managed by an EFI Driver.
+
+  Arguments:
+    This             - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+    ControllerHandle - The handle of a controller that the driver specified by
+                       This is managing.  This handle specifies the controller
+                       whose name is to be returned.
+    ChildHandle      - The handle of the child controller to retrieve the name
+                       of.  This is an optional parameter that may be NULL.  It
+                       will be NULL for device drivers.  It will also be NULL 
+                       for a bus drivers that wish to retrieve the name of the 
+                       bus controller.  It will not be NULL for a bus driver 
+                       that wishes to retrieve the name of a child controller.
+    Language         - A pointer to a three character ISO 639-2 language 
+                       identifier.  This is the language of the controller name
+                       that that the caller is requesting, and it must match one
+                       of the languages specified in SupportedLanguages.  The 
+                       number of languages supported by a driver is up to the 
+                       driver writer.
+    ControllerName   - A pointer to the Unicode string to return.  This Unicode
+                       string is the name of the controller specified by 
+                       ControllerHandle and ChildHandle in the language specified
+                       by Language from the point of view of the driver specified
+                       by This. 
+
+  Returns:
+    EFI_SUCCESS           - The Unicode string for the user readable name in the
+                            language specified by Language for the driver 
+                            specified by This was returned in DriverName.
+    EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+    EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+    EFI_INVALID_PARAMETER - Language is NULL.
+    EFI_INVALID_PARAMETER - ControllerName is NULL.
+    EFI_UNSUPPORTED       - The driver specified by This is not currently managing 
+                            the controller specified by ControllerHandle and 
+                            ChildHandle.
+    EFI_UNSUPPORTED       - The driver specified by This does not support the 
+                            language specified by Language.
+
+--*/
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciBus.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciBus.c
new file mode 100644 (file)
index 0000000..aa33162
--- /dev/null
@@ -0,0 +1,346 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciBus.c
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+--*/
+
+#include "PciBus.h"
+
+//
+// PCI Bus Support Function Prototypes
+//
+
+EFI_STATUS
+EFIAPI
+PciBusEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  );
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  );
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  );
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
+  IN  EFI_HANDLE                    Controller,
+  IN  UINTN                         NumberOfChildren,
+  IN  EFI_HANDLE                    *ChildHandleBuffer
+  );
+
+
+//
+// PCI Bus Driver Global Variables
+//
+
+EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {
+  PciBusDriverBindingSupported,
+  PciBusDriverBindingStart,
+  PciBusDriverBindingStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+BOOLEAN gFullEnumeration;
+
+UINT64 gAllOne    = 0xFFFFFFFFFFFFFFFFULL;
+UINT64 gAllZero   = 0;
+//
+// PCI Bus Driver Support Functions
+//
+EFI_STATUS
+EFIAPI
+PciBusEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+/*++
+
+Routine Description:
+
+  Initialize the global variables
+  publish the driver binding protocol
+
+Arguments:
+
+  IN EFI_HANDLE     ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+
+Returns:
+
+  EFI_SUCCESS 
+  EFI_DEVICE_ERROR 
+
+--*/
+{
+  EFI_STATUS         Status;
+
+  //
+  // Initialize the EFI Driver Library
+  //
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gPciBusDriverBinding,
+             ImageHandle,
+             &gPciBusComponentName,
+             &gPciBusComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+  
+  InitializePciDevicePool ();
+
+  gFullEnumeration = TRUE;
+  
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+/*++
+
+Routine Description:
+
+  Check to see if pci bus driver supports the given controller
+
+Arguments:
+  
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+
+Returns:
+
+  EFI_SUCCESS
+
+--*/
+{
+  EFI_STATUS                      Status;
+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+  EFI_DEV_PATH_PTR                Node;
+
+  if (RemainingDevicePath != NULL) {
+    Node.DevPath = RemainingDevicePath;
+    if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
+        Node.DevPath->SubType != HW_PCI_DP         ||
+        DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+  //
+  // Open the IO Abstraction(s) needed to perform the supported test
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (Status == EFI_ALREADY_STARTED) {
+    return EFI_SUCCESS;
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiDevicePathProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **) &PciRootBridgeIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (Status == EFI_ALREADY_STARTED) {
+    return EFI_SUCCESS;
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->CloseProtocol (
+         Controller,
+         &gEfiPciRootBridgeIoProtocolGuid,
+         This->DriverBindingHandle,
+         Controller
+         );
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+/*++
+
+Routine Description:
+
+  Start to management the controller passed in
+
+Arguments:
+  
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+
+Returns:
+
+--*/
+{
+  EFI_STATUS                          Status;
+
+  //
+  // Enumerate the entire host bridge
+  // After enumeration, a database that records all the device information will be created
+  //
+  //
+  Status = PciEnumerator (Controller);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  //
+  // Enable PCI device specified by remaining device path. BDS or other driver can call the
+  // start more than once.
+  //
+  
+  StartPciDevices (Controller, RemainingDevicePath);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
+  IN  EFI_HANDLE                    Controller,
+  IN  UINTN                         NumberOfChildren,
+  IN  EFI_HANDLE                    *ChildHandleBuffer
+  )
+/*++
+
+Routine Description:
+
+  Stop one or more children created at start of pci bus driver
+  if all the the children get closed, close the protocol
+
+Arguments:
+  
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
+  IN  EFI_HANDLE                    Controller,
+  IN  UINTN                         NumberOfChildren,
+  IN  EFI_HANDLE                    *ChildHandleBuffer
+
+Returns:
+
+  
+--*/
+{
+  EFI_STATUS  Status;
+  UINTN       Index;
+  BOOLEAN     AllChildrenStopped;
+
+  if (NumberOfChildren == 0) {
+    //
+    // Close the bus driver
+    //
+    gBS->CloseProtocol (
+           Controller,
+           &gEfiDevicePathProtocolGuid,
+           This->DriverBindingHandle,
+           Controller
+           );
+    gBS->CloseProtocol (
+           Controller,
+           &gEfiPciRootBridgeIoProtocolGuid,
+           This->DriverBindingHandle,
+           Controller
+           );
+
+    DestroyRootBridgeByHandle (
+      Controller
+      );
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Stop all the children
+  //
+
+  AllChildrenStopped = TRUE;
+
+  for (Index = 0; Index < NumberOfChildren; Index++) {
+
+    //
+    // De register all the pci device
+    //
+    Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);
+
+    if (EFI_ERROR (Status)) {
+      AllChildrenStopped = FALSE;
+    }
+  }
+
+  if (!AllChildrenStopped) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciBus.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciBus.h
new file mode 100644 (file)
index 0000000..9c18208
--- /dev/null
@@ -0,0 +1,225 @@
+/*++
+
+Copyright (c) 2005 - 2007, 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.             
+
+Module Name:
+
+  PciBus.h
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_BUS_H
+#define _EFI_PCI_BUS_H
+
+#include <PiDxe.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/Decompress.h>
+#include <Protocol/UgaIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+
+#include <Guid/PciOptionRomTable.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/PeImage.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib.h>
+
+//
+// Driver Produced Protocol Prototypes
+//
+
+#define VGABASE1  0x3B0
+#define VGALIMIT1 0x3BB
+
+#define VGABASE2  0x3C0
+#define VGALIMIT2 0x3DF
+
+#define ISABASE   0x100
+#define ISALIMIT  0x3FF
+
+typedef enum {
+  PciBarTypeUnknown = 0,
+  PciBarTypeIo16,
+  PciBarTypeIo32,
+  PciBarTypeMem32,
+  PciBarTypePMem32,
+  PciBarTypeMem64,
+  PciBarTypePMem64,
+  PciBarTypeIo,
+  PciBarTypeMem,
+  PciBarTypeMaxType
+} PCI_BAR_TYPE;
+
+typedef struct {
+  UINT64        BaseAddress;
+  UINT64        Length;
+  UINT64        Alignment;
+  PCI_BAR_TYPE  BarType;
+  BOOLEAN       Prefetchable;
+  UINT8         MemType;
+  UINT8         Offset;
+} PCI_BAR;
+
+#define PCI_IO_DEVICE_SIGNATURE   SIGNATURE_32 ('p','c','i','o')
+
+#define EFI_BRIDGE_IO32_DECODE_SUPPORTED        0x0001 
+#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED      0x0002 
+#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED      0x0004 
+#define EFI_BRIDGE_IO16_DECODE_SUPPORTED        0x0008  
+#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED   0x0010  
+#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED       0x0020
+#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED       0x0040
+
+
+typedef struct _PCI_IO_DEVICE {
+  UINT32                                    Signature;
+  EFI_HANDLE                                Handle;
+  EFI_PCI_IO_PROTOCOL                       PciIo;
+  LIST_ENTRY                            Link;
+
+  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;
+  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *PciRootBridgeIo;
+
+  //
+  // PCI configuration space header type
+  //
+  PCI_TYPE00                                Pci;
+
+  //
+  // Bus number, Device number, Function number
+  //
+  UINT8                                     BusNumber;
+  UINT8                                     DeviceNumber;
+  UINT8                                     FunctionNumber;
+
+  //
+  // BAR for this PCI Device
+  //
+  PCI_BAR                                   PciBar[PCI_MAX_BAR];
+
+  //
+  // The bridge device this pci device is subject to
+  //
+  struct _PCI_IO_DEVICE                     *Parent;
+
+  //
+  // A linked list for children Pci Device if it is bridge device
+  //
+  LIST_ENTRY                            ChildList;
+
+  //
+  // TURE if the PCI bus driver creates the handle for this PCI device
+  //
+  BOOLEAN                                   Registered;
+
+  //
+  // TRUE if the PCI bus driver successfully allocates the resource required by
+  // this PCI device
+  //
+  BOOLEAN                                   Allocated;
+
+  //
+  // The attribute this PCI device currently set
+  //
+  UINT64                                    Attributes;
+
+  //
+  // The attributes this PCI device actually supports
+  //
+  UINT64                                    Supports;
+
+  //
+  // The resource decode the bridge supports
+  //
+  UINT32                                    Decodes;
+
+  //
+  // The OptionRom Size
+  //
+  UINT64                                    RomSize;
+
+  //
+  // TRUE if there is any EFI driver in the OptionRom
+  //
+  BOOLEAN                                   BusOverride;
+
+  //
+  //  A list tracking reserved resource on a bridge device
+  //
+  LIST_ENTRY                            ReservedResourceList;
+
+  //
+  // A list tracking image handle of platform specific overriding driver
+  //
+  LIST_ENTRY                            OptionRomDriverList;
+
+  BOOLEAN                                   IsPciExp;
+
+} PCI_IO_DEVICE;
+
+
+#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
+  CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE)
+
+#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \
+  CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE)
+
+#define PCI_IO_DEVICE_FROM_LINK(a) \
+  CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL  gPciBusComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL  gPciBusDriverBinding;
+
+extern BOOLEAN                     gFullEnumeration;
+extern UINT64                      gAllOne;
+extern UINT64                      gAllZero;
+
+#include "PciIo.h"
+#include "PciCommand.h"
+#include "PciDeviceSupport.h"
+#include "PciEnumerator.h"
+#include "PciEnumeratorSupport.h"
+#include "PciDriverOverride.h"
+#include "PciRomTable.h"
+#include "PciOptionRomSupport.h"
+#include "PciPowerManagement.h"
+
+
+#define IS_ISA_BRIDGE(_p)       IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA)  
+#define IS_INTEL_ISA_BRIDGE(_p) (IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE) && ((_p)->Hdr.VendorId == 0x8086) && ((_p)->Hdr.DeviceId == 0x7110))
+#define IS_PCI_GFX(_p)     IS_CLASS2 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_OTHER)
+
+#endif
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf b/CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
new file mode 100644 (file)
index 0000000..b6ec9c0
--- /dev/null
@@ -0,0 +1,72 @@
+## @file
+# 
+# Copyright (c) 2005 - 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.             
+#
+#  Module Name:
+#
+#  Abstract:
+#
+##
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PciBusNoEnumerationDxe
+  FILE_GUID                      = 35C0C168-2607-4e51-BB53-448E3ED1A87F
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = PciBusEntryPoint
+
+[Packages]
+  MdePkg/MdePkg.dec
+  DuetPkg/DuetPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  BaseLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  BaseMemoryLib
+  ReportStatusCodeLib
+  DevicePathLib
+  PeCoffLib
+
+[Sources]
+  PciBus.h
+  PciIo.h
+  PciCommand.h
+  PciDeviceSupport.h
+  PciEnumerator.h
+  PciEnumeratorSupport.h
+  PciOptionRomSupport.h
+  PciRomTable.h
+  PciPowerManagement.h
+  PciPowerManagement.c
+  PciRomTable.c
+  PciDriverOverride.h
+  PciDriverOverride.c
+  PciOptionRomSupport.c
+  PciEnumerator.c
+  PciEnumeratorSupport.c
+  PciCommand.c
+  ComponentName.c
+  PciDeviceSupport.c
+  PciBus.c
+  PciIo.c
+
+[Protocols]
+  gEfiPciRootBridgeIoProtocolGuid
+  gEfiPciIoProtocolGuid
+  gEfiDevicePathProtocolGuid
+  gEfiBusSpecificDriverOverrideProtocolGuid
+  gEfiDecompressProtocolGuid
+  
+[Guids]
+  gEfiPciOptionRomTableGuid
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciCommand.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciCommand.c
new file mode 100644 (file)
index 0000000..6682830
--- /dev/null
@@ -0,0 +1,453 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciCommand.c
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+
+EFI_STATUS 
+PciReadCommandRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  OUT UINT16       *Command
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+
+  *Command = 0;
+  PciIo = &PciIoDevice->PciIo;
+
+  return PciIo->Pci.Read (
+                PciIo, 
+                EfiPciIoWidthUint16, 
+                PCI_COMMAND_OFFSET, 
+                1, 
+                Command
+                );
+}
+  
+EFI_STATUS 
+PciSetCommandRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT16                Temp;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+  
+  Temp = Command;
+  PciIo = &PciIoDevice->PciIo;
+
+  return PciIo->Pci.Write (
+              PciIo, 
+              EfiPciIoWidthUint16, 
+              PCI_COMMAND_OFFSET, 
+              1, 
+              &Temp
+              );
+  
+}
+
+
+EFI_STATUS 
+PciEnableCommandRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT16  OldCommand;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+
+  OldCommand = 0;
+  PciIo = &PciIoDevice->PciIo;
+
+  PciIo->Pci.Read (
+          PciIo, 
+          EfiPciIoWidthUint16, 
+          PCI_COMMAND_OFFSET, 
+          1, 
+          &OldCommand
+          );
+
+  OldCommand = (UINT16) (OldCommand | Command);
+
+  return PciIo->Pci.Write (
+              PciIo, 
+              EfiPciIoWidthUint16, 
+              PCI_COMMAND_OFFSET, 
+              1, 
+              &OldCommand
+              );
+  
+}
+
+
+EFI_STATUS 
+PciDisableCommandRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT16  OldCommand;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+
+  OldCommand = 0;
+  PciIo = &PciIoDevice->PciIo;
+
+  PciIo->Pci.Read (
+          PciIo, 
+          EfiPciIoWidthUint16, 
+          PCI_COMMAND_OFFSET, 
+          1, 
+          &OldCommand
+          );
+
+  OldCommand = (UINT16) (OldCommand & ~(Command));
+
+  return PciIo->Pci.Write (
+            PciIo, 
+            EfiPciIoWidthUint16, 
+            PCI_COMMAND_OFFSET, 
+            1, 
+            &OldCommand
+           );
+  
+}
+
+
+
+EFI_STATUS 
+PciSetBridgeControlRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT16                Temp;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+
+  Temp = Command;
+  PciIo = &PciIoDevice->PciIo;
+
+  return PciIo->Pci.Write (
+                PciIo, 
+                EfiPciIoWidthUint16, 
+                PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 
+                1, 
+                &Temp
+               );
+}
+
+
+EFI_STATUS 
+PciEnableBridgeControlRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT16  OldCommand;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+
+  OldCommand = 0;
+  PciIo = &PciIoDevice->PciIo;
+
+  PciIo->Pci.Read (
+          PciIo, 
+          EfiPciIoWidthUint16, 
+          PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 
+          1, 
+          &OldCommand
+          );
+
+  OldCommand = (UINT16) (OldCommand | Command);
+
+  return PciIo->Pci.Write (
+              PciIo, 
+              EfiPciIoWidthUint16, 
+              PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 
+              1, 
+              &OldCommand
+             );
+  
+}
+
+EFI_STATUS 
+PciDisableBridgeControlRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT16  OldCommand;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+
+  OldCommand = 0;
+  PciIo = &PciIoDevice->PciIo;
+
+  PciIo->Pci.Read (
+          PciIo, 
+          EfiPciIoWidthUint16, 
+          PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 
+          1, 
+          &OldCommand
+          );
+
+  OldCommand = (UINT16) (OldCommand & ~(Command));
+
+  return PciIo->Pci.Write (
+              PciIo, 
+              EfiPciIoWidthUint16, 
+              PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 
+              1, 
+              &OldCommand
+              );
+}
+
+
+
+EFI_STATUS 
+PciReadBridgeControlRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  OUT UINT16       *Command
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+
+  *Command = 0;
+  PciIo = &PciIoDevice->PciIo;
+
+  return PciIo->Pci.Read (
+                PciIo, 
+                EfiPciIoWidthUint16, 
+                PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 
+                1, 
+                Command
+                );
+}
+
+BOOLEAN
+PciCapabilitySupport (
+  IN PCI_IO_DEVICE  *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+  
+  None
+
+--*/
+// TODO:    PciIoDevice - add argument and description to function comment
+{
+
+  if (PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+EFI_STATUS
+LocateCapabilityRegBlock (
+  IN     PCI_IO_DEVICE *PciIoDevice,
+  IN     UINT8         CapId,
+  IN OUT UINT8         *Offset,
+     OUT UINT8         *NextRegBlock OPTIONAL
+  )
+/*++
+
+Routine Description:
+
+  Locate Capability register.
+
+Arguments:
+
+  PciIoDevice         - A pointer to the PCI_IO_DEVICE.
+  CapId               - The capability ID.
+  Offset              - A pointer to the offset. 
+                        As input: the default offset; 
+                        As output: the offset of the found block.
+  NextRegBlock        - An optional pointer to return the value of next block.
+
+Returns:
+  
+  EFI_UNSUPPORTED     - The Pci Io device is not supported.
+  EFI_NOT_FOUND       - The Pci Io device cannot be found.
+  EFI_SUCCESS         - The Pci Io device is successfully located.
+
+--*/
+{
+  UINT8   CapabilityPtr;
+  UINT16  CapabilityEntry;
+  UINT8   CapabilityID;
+
+  //
+  // To check the capability of this device supports
+  //
+  if (!PciCapabilitySupport (PciIoDevice)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (*Offset != 0) {
+    CapabilityPtr = *Offset;
+  } else {
+
+    CapabilityPtr = 0;
+    if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+      PciIoDevice->PciIo.Pci.Read (
+                               &PciIoDevice->PciIo,
+                               EfiPciIoWidthUint8,
+                               EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,
+                               1,
+                               &CapabilityPtr
+                               );
+    } else {
+
+      PciIoDevice->PciIo.Pci.Read (
+                               &PciIoDevice->PciIo,
+                               EfiPciIoWidthUint8,
+                               PCI_CAPBILITY_POINTER_OFFSET,
+                               1,
+                               &CapabilityPtr
+                               );
+    }
+  }
+
+  while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {
+    PciIoDevice->PciIo.Pci.Read (
+                             &PciIoDevice->PciIo,
+                             EfiPciIoWidthUint16,
+                             CapabilityPtr,
+                             1,
+                             &CapabilityEntry
+                             );
+
+    CapabilityID = (UINT8) CapabilityEntry;
+
+    if (CapabilityID == CapId) {
+      *Offset = CapabilityPtr;
+      if (NextRegBlock != NULL) {
+        *NextRegBlock = (UINT8) (CapabilityEntry >> 8);
+      }
+
+      return EFI_SUCCESS;
+    }
+
+    CapabilityPtr = (UINT8) (CapabilityEntry >> 8);
+  }
+
+  return EFI_NOT_FOUND;
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciCommand.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciCommand.h
new file mode 100644 (file)
index 0000000..da67b78
--- /dev/null
@@ -0,0 +1,167 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+  
+    PciCommand.h
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_COMMAND_H
+#define _EFI_PCI_COMMAND_H
+
+#include "PciBus.h"
+
+//
+// The PCI Command register bits owned by PCI Bus driver.
+//
+// They should be cleared at the beginning. The other registers
+// are owned by chipset, we should not touch them.
+//
+#define EFI_PCI_COMMAND_BITS_OWNED                          ( \
+                EFI_PCI_COMMAND_IO_SPACE                    | \
+                EFI_PCI_COMMAND_MEMORY_SPACE                | \
+                EFI_PCI_COMMAND_BUS_MASTER                  | \
+                EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \
+                EFI_PCI_COMMAND_VGA_PALETTE_SNOOP           | \
+                EFI_PCI_COMMAND_FAST_BACK_TO_BACK             \
+                )
+
+//
+// The PCI Bridge Control register bits owned by PCI Bus driver.
+// 
+// They should be cleared at the beginning. The other registers
+// are owned by chipset, we should not touch them.
+//
+#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED                   ( \
+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \
+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \
+                EFI_PCI_BRIDGE_CONTROL_VGA_16               | \
+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \
+                )
+
+//
+// The PCCard Bridge Control register bits owned by PCI Bus driver.
+// 
+// They should be cleared at the beginning. The other registers
+// are owned by chipset, we should not touch them.
+//
+#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED                ( \
+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \
+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \
+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \
+                )
+
+EFI_STATUS 
+PciReadCommandRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  OUT UINT16       *Command
+);
+
+  
+EFI_STATUS 
+PciSetCommandRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+);
+
+EFI_STATUS 
+PciEnableCommandRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+);
+
+EFI_STATUS 
+PciDisableCommandRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+);
+
+EFI_STATUS 
+PciDisableBridgeControlRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+);
+
+
+EFI_STATUS 
+PciEnableBridgeControlRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINT16        Command
+);
+
+EFI_STATUS 
+PciReadBridgeControlRegister (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  OUT UINT16       *Command
+);
+
+BOOLEAN
+PciCapabilitySupport (
+  IN PCI_IO_DEVICE  *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  PciIoDevice - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+LocateCapabilityRegBlock (
+  IN     PCI_IO_DEVICE *PciIoDevice,
+  IN     UINT8         CapId,
+  IN OUT UINT8         *Offset,
+     OUT UINT8         *NextRegBlock OPTIONAL
+  )
+/*++
+
+Routine Description:
+
+  Locate Capability register.
+
+Arguments:
+
+  PciIoDevice         - A pointer to the PCI_IO_DEVICE.
+  CapId               - The capability ID.
+  Offset              - A pointer to the offset. 
+                        As input: the default offset; 
+                        As output: the offset of the found block.
+  NextRegBlock        - An optional pointer to return the value of next block.
+
+Returns:
+  
+  EFI_UNSUPPORTED     - The Pci Io device is not supported.
+  EFI_NOT_FOUND       - The Pci Io device cannot be found.
+  EFI_SUCCESS         - The Pci Io device is successfully located.
+
+--*/
+;
+
+
+#endif
+
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciDeviceSupport.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciDeviceSupport.c
new file mode 100644 (file)
index 0000000..97a4e01
--- /dev/null
@@ -0,0 +1,973 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciDeviceSupport.c
+  
+Abstract:
+
+  This file provides routine to support Pci device node manipulation
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+//
+// This device structure is serviced as a header.
+// Its Next field points to the first root bridge device node
+//
+LIST_ENTRY  gPciDevicePool;
+
+EFI_STATUS
+InitializePciDevicePool (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Initialize the gPciDevicePool
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  InitializeListHead (&gPciDevicePool);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InsertRootBridge (
+  IN PCI_IO_DEVICE *RootBridge
+  )
+/*++
+
+Routine Description:
+
+  Insert a root bridge into PCI device pool
+
+Arguments:
+
+  RootBridge    - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+  None
+
+--*/
+{
+  InsertTailList (&gPciDevicePool, &(RootBridge->Link));
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InsertPciDevice (
+  PCI_IO_DEVICE *Bridge,
+  PCI_IO_DEVICE *PciDeviceNode
+  )
+/*++
+
+Routine Description:
+
+  This function is used to insert a PCI device node under
+  a bridge
+
+Arguments:
+  Bridge        - A pointer to the PCI_IO_DEVICE.
+  PciDeviceNode - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+  None
+
+--*/
+
+{
+
+  InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));
+  PciDeviceNode->Parent = Bridge;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DestroyRootBridge (
+  IN PCI_IO_DEVICE *RootBridge
+  )
+/*++
+
+Routine Description:
+
+  
+Arguments:
+
+  RootBridge   - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+  None
+
+--*/
+{
+  DestroyPciDeviceTree (RootBridge);
+
+  gBS->FreePool (RootBridge);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DestroyPciDeviceTree (
+  IN PCI_IO_DEVICE *Bridge
+  )
+/*++
+
+Routine Description:
+
+  Destroy all the pci device node under the bridge.
+  Bridge itself is not included.
+
+Arguments:
+
+  Bridge   - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+  None
+
+--*/
+{
+  LIST_ENTRY  *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+
+  while (!IsListEmpty (&Bridge->ChildList)) {
+
+    CurrentLink = Bridge->ChildList.ForwardLink;
+
+    //
+    // Remove this node from the linked list
+    //
+    RemoveEntryList (CurrentLink);
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (IS_PCI_BRIDGE (&(Temp->Pci))) {
+      DestroyPciDeviceTree (Temp);
+    }
+    gBS->FreePool (Temp);
+  }
+  
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DestroyRootBridgeByHandle (
+  EFI_HANDLE Controller
+  )
+/*++
+
+Routine Description:
+
+  Destroy all device nodes under the root bridge
+  specified by Controller. 
+  The root bridge itself is also included.
+
+Arguments:
+
+  Controller   - An efi handle.
+
+Returns:
+
+  None
+
+--*/
+{
+
+  LIST_ENTRY  *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+
+  CurrentLink = gPciDevicePool.ForwardLink;
+
+  while (CurrentLink && CurrentLink != &gPciDevicePool) {
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (Temp->Handle == Controller) {
+
+      RemoveEntryList (CurrentLink);
+
+      DestroyPciDeviceTree (Temp);
+
+      gBS->FreePool(Temp);
+
+      return EFI_SUCCESS;
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+RegisterPciDevice (
+  IN  EFI_HANDLE                     Controller,
+  IN  PCI_IO_DEVICE                  *PciIoDevice,
+  OUT EFI_HANDLE                     *Handle OPTIONAL
+  )
+/*++
+
+Routine Description:
+
+  This function registers the PCI IO device. It creates a handle for this PCI IO device 
+  (if the handle does not exist), attaches appropriate protocols onto the handle, does
+  necessary initialization, and sets up parent/child relationship with its bus controller.
+
+Arguments:
+
+  Controller    - An EFI handle for the PCI bus controller.
+  PciIoDevice   - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
+  Handle        - A pointer to hold the EFI handle for the PCI IO device.
+
+Returns:
+
+  EFI_SUCCESS   - The PCI device is successfully registered.
+  Others        - An error occurred when registering the PCI device.
+
+--*/
+{
+  EFI_STATUS          Status;
+  UINT8               PciExpressCapRegOffset;
+
+  //
+  // Install the pciio protocol, device path protocol and 
+  // Bus Specific Driver Override Protocol
+  //
+
+  if (PciIoDevice->BusOverride) {
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                  &PciIoDevice->Handle,             
+                  &gEfiDevicePathProtocolGuid,
+                  PciIoDevice->DevicePath,
+                  &gEfiPciIoProtocolGuid,
+                  &PciIoDevice->PciIo,
+                  &gEfiBusSpecificDriverOverrideProtocolGuid,
+                  &PciIoDevice->PciDriverOverride,
+                  NULL
+                  );
+  } else {
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                  &PciIoDevice->Handle,             
+                  &gEfiDevicePathProtocolGuid,
+                  PciIoDevice->DevicePath,
+                  &gEfiPciIoProtocolGuid,
+                  &PciIoDevice->PciIo,
+                  NULL
+                  );
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  } else {
+    Status = gBS->OpenProtocol (
+                    Controller,           
+                    &gEfiPciRootBridgeIoProtocolGuid, 
+                    (VOID **)&(PciIoDevice->PciRootBridgeIo),
+                    gPciBusDriverBinding.DriverBindingHandle,
+                    PciIoDevice->Handle,   
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                    );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  if (Handle != NULL) {
+    *Handle = PciIoDevice->Handle;
+  }
+
+  //
+  // Detect if PCI Express Device
+  //
+  PciExpressCapRegOffset = 0;
+  Status = LocateCapabilityRegBlock (
+             PciIoDevice,
+             EFI_PCI_CAPABILITY_ID_PCIEXP,
+             &PciExpressCapRegOffset,
+             NULL
+             );
+  if (!EFI_ERROR (Status)) {
+    PciIoDevice->IsPciExp = TRUE;
+    DEBUG ((EFI_D_ERROR, "PciExp - %x (B-%x, D-%x, F-%x)\n", PciIoDevice->IsPciExp, PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber));
+  }
+  
+  //
+  // Indicate the pci device is registered
+  //
+  PciIoDevice->Registered = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+DeRegisterPciDevice (
+  IN  EFI_HANDLE                     Controller,
+  IN  EFI_HANDLE                     Handle
+  )
+/*++
+
+Routine Description:
+
+  This function is used to de-register the PCI device from the EFI,
+  That includes un-installing PciIo protocol from the specified PCI 
+  device handle.
+
+Arguments:
+
+  Controller   - An efi handle.
+  Handle       - An efi handle.
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_PCI_IO_PROTOCOL             *PciIo;
+  EFI_STATUS                      Status;
+  PCI_IO_DEVICE                   *PciIoDevice;
+  PCI_IO_DEVICE                   *Node;
+  LIST_ENTRY                  *CurrentLink;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  Status = gBS->OpenProtocol (
+                  Handle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (!EFI_ERROR (Status)) {
+    PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
+
+    //
+    // If it is already de-registered
+    //
+    if (!PciIoDevice->Registered) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    // If it is PPB, first de-register its children
+    //
+
+    if (IS_PCI_BRIDGE (&(PciIoDevice->Pci))) {
+
+      CurrentLink = PciIoDevice->ChildList.ForwardLink;
+
+      while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
+        Node    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+        Status  = DeRegisterPciDevice (Controller, Node->Handle);
+
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+
+        CurrentLink = CurrentLink->ForwardLink;
+      }
+    }
+
+    //
+    // First disconnect this device
+    //
+//    PciIoDevice->PciIo.Attributes(&(PciIoDevice->PciIo),
+//                                    EfiPciIoAttributeOperationDisable,
+//                                    EFI_PCI_DEVICE_ENABLE,
+//                                    NULL
+//                                    );
+       
+    //
+    // Close the child handle
+    //
+    Status = gBS->CloseProtocol (
+                    Controller,
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    gPciBusDriverBinding.DriverBindingHandle,
+                    Handle
+                    );
+
+    //
+    // Un-install the device path protocol and pci io protocol
+    //
+    if (PciIoDevice->BusOverride) {
+      Status = gBS->UninstallMultipleProtocolInterfaces (
+                      Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      PciIoDevice->DevicePath,
+                      &gEfiPciIoProtocolGuid,
+                      &PciIoDevice->PciIo,
+                      &gEfiBusSpecificDriverOverrideProtocolGuid,
+                      &PciIoDevice->PciDriverOverride,
+                      NULL
+                      );
+    } else {
+      Status = gBS->UninstallMultipleProtocolInterfaces (
+                      Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      PciIoDevice->DevicePath,
+                      &gEfiPciIoProtocolGuid,
+                      &PciIoDevice->PciIo,
+                      NULL
+                      );
+    }
+
+    if (EFI_ERROR (Status)) {
+      gBS->OpenProtocol (
+            Controller,
+            &gEfiPciRootBridgeIoProtocolGuid,
+            (VOID **) &PciRootBridgeIo,
+            gPciBusDriverBinding.DriverBindingHandle,
+            Handle,
+            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+            );
+      return Status;
+    }
+    
+    //
+    // The Device Driver should disable this device after disconnect
+    // so the Pci Bus driver will not touch this device any more.
+    // Restore the register field to the original value
+    //
+    PciIoDevice->Registered = FALSE;
+    PciIoDevice->Handle     = NULL;
+  } else {
+
+    //
+    // Handle may be closed before
+    //
+    return EFI_SUCCESS;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EnableBridgeAttributes (
+  IN PCI_IO_DEVICE                       *PciIoDevice
+  )
+{
+  PCI_TYPE01                PciData;
+
+  //
+  // NOTE: We should not set EFI_PCI_DEVICE_ENABLE for a bridge
+  //       directly, because some legacy BIOS will NOT assign
+  //       IO or Memory resource for a bridge who has no child
+  //       device. So we add check IO or Memory here.
+  //
+
+  PciIoDevice->PciIo.Pci.Read (
+                           &PciIoDevice->PciIo,
+                           EfiPciIoWidthUint8,
+                           0,
+                           sizeof (PciData),
+                           &PciData
+                           );
+
+  if ((((PciData.Bridge.IoBase & 0xF) == 0) &&
+        (PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) ||
+      (((PciData.Bridge.IoBase & 0xF) == 1) &&
+        ((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) {
+    PciIoDevice->PciIo.Attributes(
+                         &(PciIoDevice->PciIo),
+                         EfiPciIoAttributeOperationEnable,
+                         (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
+                         NULL
+                         );
+  }
+  if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) {
+    PciIoDevice->PciIo.Attributes(
+                         &(PciIoDevice->PciIo),
+                         EfiPciIoAttributeOperationEnable,
+                         (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
+                         NULL
+                         );
+  }
+  if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) &&
+        (PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) ||
+      (((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) &&
+        ((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) {
+    PciIoDevice->PciIo.Attributes(
+                         &(PciIoDevice->PciIo),
+                         EfiPciIoAttributeOperationEnable,
+                         (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
+                         NULL
+                         );
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS 
+StartPciDevicesOnBridge (
+  IN EFI_HANDLE                          Controller,
+  IN PCI_IO_DEVICE                       *RootBridge,
+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath 
+  )
+/*++
+
+Routine Description:
+
+  Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
+
+Arguments:
+
+  Controller          - An efi handle.
+  RootBridge          - A pointer to the PCI_IO_DEVICE.
+  RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+  NumberOfChildren    - Children number.
+  ChildHandleBuffer   - A pointer to the child handle buffer.
+
+Returns:
+
+  None
+
+--*/
+{
+  PCI_IO_DEVICE             *Temp;
+  PCI_IO_DEVICE             *PciIoDevice;
+  EFI_DEV_PATH_PTR          Node;
+  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
+  EFI_STATUS                Status;
+  LIST_ENTRY            *CurrentLink;
+
+  CurrentLink = RootBridge->ChildList.ForwardLink;
+
+  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    if (RemainingDevicePath != NULL) {
+
+      Node.DevPath = RemainingDevicePath;
+
+      if (Node.Pci->Device != Temp->DeviceNumber || 
+          Node.Pci->Function != Temp->FunctionNumber) {
+        CurrentLink = CurrentLink->ForwardLink;
+        continue;
+      }
+
+      //
+      // Check if the device has been assigned with required resource
+      //
+      if (!Temp->Allocated) {
+        return EFI_NOT_READY;
+      }
+      
+      //
+      // Check if the current node has been registered before
+      // If it is not, register it
+      //
+      if (!Temp->Registered) {
+        PciIoDevice = Temp;
+
+        Status = RegisterPciDevice (
+                  Controller,
+                  PciIoDevice,
+                  NULL
+                  );
+
+      }
+      
+      //
+      // Get the next device path
+      //
+      CurrentDevicePath = NextDevicePathNode (RemainingDevicePath);
+      if (IsDevicePathEnd (CurrentDevicePath)) {
+        return EFI_SUCCESS;
+      }
+  
+      //
+      // If it is a PPB
+      //
+      if (IS_PCI_BRIDGE (&(Temp->Pci))) {
+        Status = StartPciDevicesOnBridge (
+                  Controller,
+                  Temp,
+                  CurrentDevicePath
+                  );
+        EnableBridgeAttributes (Temp);
+
+        return Status;
+      } else {
+
+        //
+        // Currently, the PCI bus driver only support PCI-PCI bridge
+        //
+        return EFI_UNSUPPORTED;
+      }
+
+    } else {
+
+      //
+      // If remaining device path is NULL,
+      // try to enable all the pci devices under this bridge
+      //
+
+      if (!Temp->Registered && Temp->Allocated) {
+
+        PciIoDevice = Temp;
+
+        Status = RegisterPciDevice (
+                  Controller,
+                  PciIoDevice,
+                  NULL
+                  );
+
+      }
+
+      if (IS_PCI_BRIDGE (&(Temp->Pci))) {
+        Status = StartPciDevicesOnBridge ( 
+                   Controller,
+                   Temp,
+                   RemainingDevicePath
+                   );
+        EnableBridgeAttributes (Temp);
+      }
+
+      CurrentLink = CurrentLink->ForwardLink;
+      continue;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+StartPciDevices (
+  IN EFI_HANDLE                         Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath
+  )
+/*++
+
+Routine Description:
+
+  Start to manage the PCI device according to RemainingDevicePath
+  If RemainingDevicePath == NULL, the PCI bus driver will start 
+  to manage all the PCI devices it found previously
+
+Arguments:
+  Controller          - An efi handle.
+  RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_DEV_PATH_PTR  Node;
+  PCI_IO_DEVICE     *RootBridge;
+  LIST_ENTRY    *CurrentLink;
+
+  if (RemainingDevicePath != NULL) {
+
+    //
+    // Check if the RemainingDevicePath is valid
+    //
+    Node.DevPath = RemainingDevicePath;
+    if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
+        Node.DevPath->SubType != HW_PCI_DP         ||
+        DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)
+        ) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  CurrentLink = gPciDevicePool.ForwardLink;
+
+  while (CurrentLink && CurrentLink != &gPciDevicePool) {
+
+    RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    //
+    // Locate the right root bridge to start
+    //
+    if (RootBridge->Handle == Controller) {
+      StartPciDevicesOnBridge (
+        Controller,
+        RootBridge,
+        RemainingDevicePath
+        );
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+PCI_IO_DEVICE *
+CreateRootBridge (
+  IN EFI_HANDLE RootBridgeHandle
+  )
+/*++
+
+Routine Description:
+
+
+Arguments:
+  RootBridgeHandle   - An efi handle.
+
+Returns:
+
+  None
+
+--*/
+{
+
+  EFI_STATUS                      Status;
+  PCI_IO_DEVICE                   *Dev;
+
+  Dev = NULL;
+  Status = gBS->AllocatePool (
+                  EfiBootServicesData,
+                  sizeof (PCI_IO_DEVICE),
+                  (VOID **) &Dev
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  ZeroMem (Dev, sizeof (PCI_IO_DEVICE));
+  Dev->Signature  = PCI_IO_DEVICE_SIGNATURE;
+  Dev->Handle     = RootBridgeHandle;
+  InitializeListHead (&Dev->ChildList);
+
+  return Dev;
+}
+
+PCI_IO_DEVICE *
+GetRootBridgeByHandle (
+  EFI_HANDLE RootBridgeHandle
+  )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+  RootBridgeHandle    - An efi handle.
+
+Returns:
+
+  None
+
+--*/
+{
+  PCI_IO_DEVICE   *RootBridgeDev;
+  LIST_ENTRY  *CurrentLink;
+
+  CurrentLink = gPciDevicePool.ForwardLink;
+
+  while (CurrentLink && CurrentLink != &gPciDevicePool) {
+
+    RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    if (RootBridgeDev->Handle == RootBridgeHandle) {
+      return RootBridgeDev;
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return NULL;
+}
+
+BOOLEAN
+RootBridgeExisted (
+  IN EFI_HANDLE RootBridgeHandle
+  )
+/*++
+
+Routine Description:
+
+  This function searches if RootBridgeHandle has already existed
+  in current device pool.
+
+  If so, it means the given root bridge has been already enumerated.
+
+Arguments:
+
+  RootBridgeHandle   - An efi handle.
+
+Returns:
+
+  None
+
+--*/
+{
+  PCI_IO_DEVICE *Bridge;
+
+  Bridge = GetRootBridgeByHandle (RootBridgeHandle);
+
+  if (Bridge != NULL) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+BOOLEAN
+PciDeviceExisted (
+  IN PCI_IO_DEVICE    *Bridge,
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+/*++
+
+Routine Description:
+  
+Arguments:
+
+  Bridge       - A pointer to the PCI_IO_DEVICE.
+  PciIoDevice  - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+  None
+
+--*/
+{
+
+  PCI_IO_DEVICE   *Temp;
+  LIST_ENTRY  *CurrentLink;
+
+  CurrentLink = Bridge->ChildList.ForwardLink;
+
+  while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (Temp == PciIoDevice) {
+      return TRUE;
+    }
+
+    if (!IsListEmpty (&Temp->ChildList)) {
+      if (PciDeviceExisted (Temp, PciIoDevice)) {
+        return TRUE;
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return FALSE;
+}
+
+PCI_IO_DEVICE *
+ActiveVGADeviceOnTheSameSegment (
+  IN PCI_IO_DEVICE        *VgaDevice
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+  VgaDevice    - A pointer to the PCI_IO_DEVICE.
+  
+Returns:
+
+  None
+
+--*/
+{
+  LIST_ENTRY  *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+
+  CurrentLink = gPciDevicePool.ForwardLink;
+
+  while (CurrentLink && CurrentLink != &gPciDevicePool) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {
+
+      Temp = ActiveVGADeviceOnTheRootBridge (Temp);
+
+      if (Temp != NULL) {
+        return Temp;
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return NULL;
+}
+
+PCI_IO_DEVICE *
+ActiveVGADeviceOnTheRootBridge (
+  IN PCI_IO_DEVICE        *RootBridge
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+  RootBridge    - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+  None
+
+--*/
+{
+  LIST_ENTRY  *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+
+  CurrentLink = RootBridge->ChildList.ForwardLink;
+
+  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (IS_PCI_VGA(&Temp->Pci) && 
+        (Temp->Attributes &
+         (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |
+          EFI_PCI_IO_ATTRIBUTE_VGA_IO     |
+          EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) {
+      return Temp;
+    }
+
+    if (IS_PCI_BRIDGE (&Temp->Pci)) {
+
+      Temp = ActiveVGADeviceOnTheRootBridge (Temp);
+
+      if (Temp != NULL) {
+        return Temp;
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return NULL;
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciDeviceSupport.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciDeviceSupport.h
new file mode 100644 (file)
index 0000000..07fd54b
--- /dev/null
@@ -0,0 +1,324 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciDeviceSupport.h
+  
+Abstract:
+
+  
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_DEVICE_SUPPORT_H
+#define _EFI_PCI_DEVICE_SUPPORT_H
+
+EFI_STATUS
+InitializePciDevicePool (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  None
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InsertPciDevice (
+  PCI_IO_DEVICE *Bridge,
+  PCI_IO_DEVICE *PciDeviceNode
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Bridge        - TODO: add argument description
+  PciDeviceNode - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DestroyPciDeviceTree (
+  IN PCI_IO_DEVICE *Bridge
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Bridge  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DestroyRootBridgeByHandle (
+  EFI_HANDLE Controller
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Controller  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RegisterPciDevice (
+  IN  EFI_HANDLE                     Controller,
+  IN  PCI_IO_DEVICE                  *PciIoDevice,
+  OUT EFI_HANDLE                     *Handle OPTIONAL
+  )
+/*++
+
+Routine Description:
+
+  This function registers the PCI IO device. It creates a handle for this PCI IO device 
+  (if the handle does not exist), attaches appropriate protocols onto the handle, does
+  necessary initialization, and sets up parent/child relationship with its bus controller.
+
+Arguments:
+
+  Controller    - An EFI handle for the PCI bus controller.
+  PciIoDevice   - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
+  Handle        - A pointer to hold the EFI handle for the PCI IO device.
+
+Returns:
+
+  EFI_SUCCESS   - The PCI device is successfully registered.
+  Others        - An error occurred when registering the PCI device.
+
+--*/
+;
+
+EFI_STATUS
+DeRegisterPciDevice (
+  IN  EFI_HANDLE                     Controller,
+  IN  EFI_HANDLE                     Handle
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Controller  - TODO: add argument description
+  Handle      - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+StartPciDevices (
+  IN EFI_HANDLE                         Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Controller          - TODO: add argument description
+  RemainingDevicePath - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+CreateRootBridge (
+  IN EFI_HANDLE RootBridgeHandle
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  RootBridgeHandle  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+GetRootBridgeByHandle (
+  EFI_HANDLE RootBridgeHandle
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  RootBridgeHandle  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS 
+InsertRootBridge (
+  PCI_IO_DEVICE *RootBridge
+);
+
+EFI_STATUS 
+DestroyRootBridge ( 
+   IN PCI_IO_DEVICE *RootBridge 
+);
+
+BOOLEAN
+RootBridgeExisted (
+  IN EFI_HANDLE RootBridgeHandle
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  RootBridgeHandle  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+PciDeviceExisted (
+  IN PCI_IO_DEVICE    *Bridge,
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Bridge      - TODO: add argument description
+  PciIoDevice - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+ActiveVGADeviceOnTheSameSegment (
+  IN PCI_IO_DEVICE        *VgaDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  VgaDevice - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+ActiveVGADeviceOnTheRootBridge (
+  IN PCI_IO_DEVICE        *RootBridge
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  RootBridge  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+#endif
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciDriverOverride.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciDriverOverride.c
new file mode 100644 (file)
index 0000000..6e936ac
--- /dev/null
@@ -0,0 +1,176 @@
+/*++
+
+Copyright (c) 2005 - 2007, 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.             
+
+Module Name:
+
+  PciDriverOverride.c
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+EFI_STATUS
+EFIAPI
+GetDriver(
+  IN     EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL          *This,
+  IN OUT EFI_HANDLE                                         *DriverImageHandle
+  );
+
+
+
+EFI_STATUS
+InitializePciDriverOverrideInstance (
+  PCI_IO_DEVICE  *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  Initializes a PCI Driver Override Instance
+
+Arguments:
+  
+Returns:
+
+  None
+
+--*/
+
+{
+  PciIoDevice->PciDriverOverride.GetDriver = GetDriver;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetDriver (
+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,
+  IN OUT EFI_HANDLE                                         *DriverImageHandle
+  )
+/*++
+
+Routine Description:
+
+  Get a overriding driver image
+
+Arguments:
+  
+Returns:
+
+  None
+
+--*/
+{
+  PCI_IO_DEVICE             *PciIoDevice;
+  LIST_ENTRY            *CurrentLink;
+  PCI_DRIVER_OVERRIDE_LIST  *Node;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);
+
+  CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;
+
+  while (CurrentLink && CurrentLink != &PciIoDevice->OptionRomDriverList) {
+
+    Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);
+
+    if (*DriverImageHandle == NULL) {
+
+      *DriverImageHandle = Node->DriverImageHandle;
+      return EFI_SUCCESS;
+    }
+
+    if (*DriverImageHandle == Node->DriverImageHandle) {
+
+      if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||
+          CurrentLink->ForwardLink == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      //
+      // Get next node
+      //
+      Node                = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);
+      *DriverImageHandle  = Node->DriverImageHandle;
+      return EFI_SUCCESS;
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+AddDriver (
+  IN PCI_IO_DEVICE     *PciIoDevice,
+  IN EFI_HANDLE        DriverImageHandle
+  )
+/*++
+
+Routine Description:
+
+  Add a overriding driver image
+
+Arguments:
+  
+Returns:
+
+  None
+
+--*/
+
+{
+  EFI_STATUS                    Status;
+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  PCI_DRIVER_OVERRIDE_LIST      *Node;
+
+  Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));
+  if (Node == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Node->Signature         = DRIVER_OVERRIDE_SIGNATURE;
+  Node->DriverImageHandle = DriverImageHandle;
+
+  InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));
+
+  PciIoDevice->BusOverride  = TRUE;
+
+
+  ImageContext.Handle    = LoadedImage->ImageBase;
+  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+
+  //
+  // Get information about the image 
+  //
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  if (EFI_ERROR (Status)) {
+    return EFI_SUCCESS;
+  }
+
+  if (ImageContext.Machine != EFI_IMAGE_MACHINE_EBC) {
+    return EFI_SUCCESS;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciDriverOverride.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciDriverOverride.h
new file mode 100644 (file)
index 0000000..5fbba2e
--- /dev/null
@@ -0,0 +1,110 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciDriverOverride.h
+  
+Abstract:
+
+  
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H
+#define _EFI_PCI_DRIVER_OVERRRIDE_H
+
+#include "PciBus.h"
+
+#define DRIVER_OVERRIDE_SIGNATURE SIGNATURE_32 ('d', 'r', 'o', 'v')
+
+typedef struct {
+  UINT32          Signature;
+  LIST_ENTRY  Link;
+  EFI_HANDLE      DriverImageHandle;
+} PCI_DRIVER_OVERRIDE_LIST;
+
+
+#define DRIVER_OVERRIDE_FROM_LINK(a) \
+  CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE)
+
+
+EFI_STATUS
+InitializePciDriverOverrideInstance (
+  PCI_IO_DEVICE  *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  PciIoDevice - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AddDriver (
+  IN PCI_IO_DEVICE     *PciIoDevice,
+  IN EFI_HANDLE        DriverImageHandle
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  PciIoDevice       - TODO: add argument description
+  DriverImageHandle - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+GetDriver (
+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,
+  IN OUT EFI_HANDLE                                         *DriverImageHandle
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  This              - TODO: add argument description
+  DriverImageHandle - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumerator.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumerator.c
new file mode 100644 (file)
index 0000000..729c567
--- /dev/null
@@ -0,0 +1,57 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciEnumerator.c
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+EFI_STATUS
+PciEnumerator (
+  IN EFI_HANDLE                    Controller
+  )
+/*++
+
+Routine Description:
+
+  This routine is used to enumerate entire pci bus system 
+  in a given platform
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  //
+  // This PCI bus driver depends on the legacy BIOS
+  // to do the resource allocation
+  //
+  gFullEnumeration = FALSE;
+
+  return PciEnumeratorLight (Controller) ;
+  
+}
+
+
+
+
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumerator.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumerator.h
new file mode 100644 (file)
index 0000000..09c9d69
--- /dev/null
@@ -0,0 +1,47 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciEnumerator.h
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ENUMERATOR_H
+#define _EFI_PCI_ENUMERATOR_H
+
+EFI_STATUS
+PciEnumerator (
+  IN EFI_HANDLE                    Controller
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Controller  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+#endif
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
new file mode 100644 (file)
index 0000000..27311fd
--- /dev/null
@@ -0,0 +1,1385 @@
+/*++
+
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<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.             
+
+Module Name:
+
+  PciEnumeratorSupport.c
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+EFI_STATUS 
+InitializePPB (
+  IN PCI_IO_DEVICE *PciIoDevice 
+);
+
+EFI_STATUS 
+InitializeP2C (
+  IN PCI_IO_DEVICE *PciIoDevice 
+);
+
+PCI_IO_DEVICE* 
+CreatePciIoDevice (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_TYPE00                       *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+);
+
+
+PCI_IO_DEVICE*
+GatherP2CInfo (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_TYPE00                       *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+);
+
+UINTN
+PciParseBar (
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  IN UINTN          Offset,
+  IN UINTN          BarIndex
+);
+
+
+EFI_STATUS
+PciSearchDevice (
+  IN PCI_IO_DEVICE                      *Bridge,
+  PCI_TYPE00                            *Pci,
+  UINT8                                 Bus,
+  UINT8                                 Device,
+  UINT8                                 Func,
+  PCI_IO_DEVICE                         **PciDevice
+);
+
+
+EFI_STATUS 
+DetermineDeviceAttribute (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+);
+
+EFI_STATUS 
+BarExisted (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINTN         Offset,
+  OUT UINT32       *BarLengthValue,
+  OUT UINT32       *OriginalBarValue
+  );
+
+
+
+EFI_DEVICE_PATH_PROTOCOL*
+CreatePciDevicePath(
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+  IN  PCI_IO_DEVICE            *PciIoDevice 
+);
+
+PCI_IO_DEVICE* 
+GatherDeviceInfo (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_TYPE00                       *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+);
+
+PCI_IO_DEVICE* 
+GatherPPBInfo (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_TYPE00                       *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+);
+
+EFI_STATUS
+PciDevicePresent (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  PCI_TYPE00                          *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+  )
+/*++
+
+Routine Description:
+
+  This routine is used to check whether the pci device is present
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT64      Address;
+  EFI_STATUS  Status;
+
+  //
+  // Create PCI address map in terms of Bus, Device and Func
+  //
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+  //
+  // Read the Vendor Id register
+  //
+  Status = PciRootBridgeIo->Pci.Read (
+                                  PciRootBridgeIo,
+                                  EfiPciWidthUint32,
+                                  Address,
+                                  1,
+                                  Pci
+                                  );
+
+  if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
+
+    //
+    // Read the entire config header for the device
+    //
+
+    Status = PciRootBridgeIo->Pci.Read (
+                                    PciRootBridgeIo,
+                                    EfiPciWidthUint32,
+                                    Address,
+                                    sizeof (PCI_TYPE00) / sizeof (UINT32),
+                                    Pci
+                                    );
+
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+PciPciDeviceInfoCollector (
+  IN PCI_IO_DEVICE                      *Bridge,
+  UINT8                                 StartBusNumber
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS          Status;
+  PCI_TYPE00          Pci;
+  UINT8               Device;
+  UINT8               Func;
+  UINT8               SecBus;
+  PCI_IO_DEVICE       *PciIoDevice;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  Status      = EFI_SUCCESS;
+  SecBus      = 0;
+  PciIoDevice = NULL;
+
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+      //
+      // Check to see whether PCI device is present
+      //
+
+      Status = PciDevicePresent (
+                Bridge->PciRootBridgeIo,
+                &Pci,
+                (UINT8) StartBusNumber,
+                (UINT8) Device,
+                (UINT8) Func
+                );
+
+      if (EFI_ERROR (Status) && Func == 0) {
+        //
+        // go to next device if there is no Function 0
+        //
+        break;
+      }
+
+      if (!EFI_ERROR (Status)) {
+
+        //
+        // Collect all the information about the PCI device discovered
+        //
+        Status = PciSearchDevice (
+                  Bridge,
+                  &Pci,
+                  (UINT8) StartBusNumber,
+                  Device,
+                  Func,
+                  &PciIoDevice
+                  );
+
+        //
+        // Recursively scan PCI busses on the other side of PCI-PCI bridges
+        //
+        //
+
+        if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
+
+          //
+          // If it is PPB, we need to get the secondary bus to continue the enumeration
+          //
+          PciIo   = &(PciIoDevice->PciIo);
+
+          Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
+
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+              
+          //
+          // If the PCI bridge is initialized then enumerate the next level bus
+          //
+          if (SecBus != 0) {
+            Status = PciPciDeviceInfoCollector (
+                      PciIoDevice,
+                      (UINT8) (SecBus)
+                      );
+          }
+        }
+
+        if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+          //
+          // Skip sub functions, this is not a multi function device
+          //
+          Func = PCI_MAX_FUNC;
+        }
+      }
+
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciSearchDevice (
+  IN  PCI_IO_DEVICE                         *Bridge,
+  IN  PCI_TYPE00                            *Pci,
+  IN  UINT8                                 Bus,
+  IN  UINT8                                 Device,
+  IN  UINT8                                 Func,
+  OUT PCI_IO_DEVICE                         **PciDevice
+  )
+/*++
+
+Routine Description:
+
+  Search required device.
+
+Arguments:
+
+  Bridge     - A pointer to the PCI_IO_DEVICE.
+  Pci        - A pointer to the PCI_TYPE00.
+  Bus        - Bus number.
+  Device     - Device number.
+  Func       - Function number.
+  PciDevice  - The Required pci device.
+
+Returns:
+
+  Status code.
+
+--*/
+{
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = NULL;
+
+  if (!IS_PCI_BRIDGE (Pci)) {
+
+    if (IS_CARDBUS_BRIDGE (Pci)) {
+      PciIoDevice = GatherP2CInfo (
+                      Bridge->PciRootBridgeIo,
+                      Pci,
+                      Bus,
+                      Device,
+                      Func
+                      );
+      if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
+        InitializeP2C (PciIoDevice);
+      }
+    } else {
+
+      //
+      // Create private data for Pci Device
+      //
+      PciIoDevice = GatherDeviceInfo (
+                      Bridge->PciRootBridgeIo,
+                      Pci,
+                      Bus,
+                      Device,
+                      Func
+                      );
+
+    }
+
+  } else {
+
+    //
+    // Create private data for PPB
+    //
+    PciIoDevice = GatherPPBInfo (
+                    Bridge->PciRootBridgeIo,
+                    Pci,
+                    Bus,
+                    Device,
+                    Func
+                    );
+
+    //
+    // Special initialization for PPB including making the PPB quiet
+    //
+    if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
+      InitializePPB (PciIoDevice);
+    }
+  }
+
+  if (!PciIoDevice) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  
+  //
+  // Create a device path for this PCI device and store it into its private data
+  //
+  CreatePciDevicePath(
+    Bridge->DevicePath,
+    PciIoDevice 
+    );
+  
+  //
+  // Detect this function has option rom
+  //
+  if (gFullEnumeration) {
+
+    if (!IS_CARDBUS_BRIDGE (Pci)) {
+
+      GetOpRomInfo (PciIoDevice);
+
+    }
+
+    ResetPowerManagementFeature (PciIoDevice);
+    
+  } 
+  else {
+    PciRomGetRomResourceFromPciOptionRomTable (
+      &gPciBusDriverBinding,
+      PciIoDevice->PciRootBridgeIo,
+      PciIoDevice
+      );
+  }
+
+  //
+  // Insert it into a global tree for future reference
+  //
+  InsertPciDevice (Bridge, PciIoDevice);
+
+  //
+  // Determine PCI device attributes
+  //
+  DetermineDeviceAttribute (PciIoDevice);
+
+  if (PciDevice != NULL) {
+    *PciDevice = PciIoDevice;
+  }
+
+  return EFI_SUCCESS;
+}
+
+PCI_IO_DEVICE *
+GatherDeviceInfo (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_TYPE00                       *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINTN                           Offset;
+  UINTN                           BarIndex;
+  PCI_IO_DEVICE                   *PciIoDevice;
+
+  PciIoDevice = CreatePciIoDevice (
+                  PciRootBridgeIo,
+                  Pci,
+                  Bus,
+                  Device,
+                  Func
+                  );
+
+  if (!PciIoDevice) {
+    return NULL;
+  }
+
+  //
+  // If it is a full enumeration, disconnect the device in advance
+  //
+  if (gFullEnumeration) {
+
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+  }
+
+  //
+  // Start to parse the bars
+  //
+  for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
+    Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
+  }
+
+  return PciIoDevice;
+}
+
+PCI_IO_DEVICE *
+GatherPPBInfo (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_TYPE00                       *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  PCI_IO_DEVICE                   *PciIoDevice;
+  EFI_STATUS                      Status;
+  UINT8                           Value;
+  EFI_PCI_IO_PROTOCOL             *PciIo;
+  UINT8                           Temp;
+
+  PciIoDevice = CreatePciIoDevice (
+                  PciRootBridgeIo,
+                  Pci,
+                  Bus,
+                  Device,
+                  Func
+                  );
+
+  if (!PciIoDevice) {
+    return NULL;
+  }
+  
+  if (gFullEnumeration) {
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+    //
+    // Initalize the bridge control register
+    //
+    PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
+  }
+
+  PciIo = &PciIoDevice->PciIo;
+
+  //
+  // Test whether it support 32 decode or not
+  //
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+
+  if (Value) {
+    if (Value & 0x01) {
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
+    } else {
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
+    }
+  }
+
+  Status = BarExisted (
+            PciIoDevice,
+            0x24,
+            NULL,
+            NULL
+            );
+
+  //
+  // test if it supports 64 memory or not
+  //
+  if (!EFI_ERROR (Status)) {
+
+    Status = BarExisted (
+              PciIoDevice,
+              0x28,
+              NULL,
+              NULL
+              );
+
+    if (!EFI_ERROR (Status)) {
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
+    } else {
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+    }
+  }
+
+  //
+  // Memory 32 code is required for ppb
+  //
+  PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
+
+  return PciIoDevice;
+}
+
+PCI_IO_DEVICE *
+GatherP2CInfo (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_TYPE00                       *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  PCI_IO_DEVICE         *PciIoDevice;
+  
+  PciIoDevice = CreatePciIoDevice (
+                  PciRootBridgeIo,
+                  Pci,
+                  Bus,
+                  Device,
+                  Func
+                  );
+
+  if (!PciIoDevice) {
+    return NULL;
+  }
+
+  if (gFullEnumeration) {
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+    //
+    // Initalize the bridge control register
+    //
+    PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
+
+  }
+  //
+  // P2C only has one bar that is in 0x10
+  //
+  PciParseBar(PciIoDevice, 0x10, 0);
+  
+  PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |
+                         EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
+                         EFI_BRIDGE_IO32_DECODE_SUPPORTED;
+
+  return PciIoDevice;
+}
+
+EFI_DEVICE_PATH_PROTOCOL *
+CreatePciDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+  IN  PCI_IO_DEVICE            *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+
+  PCI_DEVICE_PATH PciNode;
+
+  //
+  // Create PCI device path
+  //
+  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
+  PciNode.Header.SubType  = HW_PCI_DP;
+  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+
+  PciNode.Device          = PciIoDevice->DeviceNumber;
+  PciNode.Function        = PciIoDevice->FunctionNumber;
+  PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
+
+  return PciIoDevice->DevicePath;
+}
+
+EFI_STATUS
+BarExisted (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINTN         Offset,
+  OUT UINT32       *BarLengthValue,
+  OUT UINT32       *OriginalBarValue
+  )
+/*++
+
+Routine Description:
+
+  Check the bar is existed or not.
+
+Arguments:
+
+  PciIoDevice       - A pointer to the PCI_IO_DEVICE.
+  Offset            - The offset.
+  BarLengthValue    - The bar length value.
+  OriginalBarValue  - The original bar value.
+
+Returns:
+
+  EFI_NOT_FOUND     - The bar don't exist.
+  EFI_SUCCESS       - The bar exist.
+
+--*/
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT32              OriginalValue;
+  UINT32              Value;
+  EFI_TPL             OldTpl;
+
+  PciIo = &PciIoDevice->PciIo;
+
+  //
+  // Preserve the original value
+  //
+
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
+
+  //
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed
+  //
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
+
+  //
+  // Write back the original value
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
+
+  //
+  // Restore TPL to its original level
+  //
+  gBS->RestoreTPL (OldTpl);
+
+  if (BarLengthValue != NULL) {
+    *BarLengthValue = Value;
+  }
+
+  if (OriginalBarValue != NULL) {
+    *OriginalBarValue = OriginalValue;
+  }
+
+  if (Value == 0) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+
+EFI_STATUS
+DetermineDeviceAttribute (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+  )
+/*++
+
+Routine Description:
+  Determine the related attributes of all devices under a Root Bridge
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT16          Command;
+  UINT16          BridgeControl;
+
+  Command = 0;
+
+  PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;
+  PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+
+  if (IS_PCI_VGA (&(PciIoDevice->Pci))){
+
+    //
+    // If the device is VGA, VGA related Attributes are supported
+    //
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY   ;
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO    ;
+  }
+
+  if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {
+    //
+    // If the devie is a ISA Bridge, set the two attributes
+    //
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
+  }
+
+  if (IS_PCI_GFX (&(PciIoDevice->Pci))) {
+
+    //
+    // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
+    // attribute
+    //
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO    ;
+  }
+
+
+  //
+  // If the device is IDE, IDE related attributes are supported
+  //
+  if (IS_PCI_IDE (&(PciIoDevice->Pci))) {
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO  ;
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO  ;
+  }
+
+  PciReadCommandRegister(PciIoDevice, &Command);
+
+  
+  if (Command & EFI_PCI_COMMAND_IO_SPACE) {
+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
+  }
+
+  if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
+  }
+
+  if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
+  }
+
+  if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) || 
+      IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){
+
+    //
+    // If it is a PPB, read the Bridge Control Register to determine
+    // the relevant attributes
+    //
+    BridgeControl = 0;
+    PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);
+
+    //
+    // Determine whether the ISA bit is set
+    // If ISA Enable on Bridge is set, the PPB
+    // will block forwarding 0x100-0x3ff for each 1KB in the 
+    // first 64KB I/O range.
+    //
+    if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
+    } 
+
+    //
+    // Determine whether the VGA bit is set
+    // If it is set, the bridge is set to decode VGA memory range
+    // and palette register range
+    //
+    if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+    }
+
+    //
+    // if the palette snoop bit is set, then the brige is set to 
+    // decode palette IO write
+    //
+    if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+    }
+  } 
+
+  return EFI_SUCCESS;
+}
+
+UINTN
+PciParseBar (
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  IN UINTN          Offset,
+  IN UINTN          BarIndex
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT32      Value;
+  UINT32      OriginalValue;
+  UINT32      Mask;
+  EFI_STATUS  Status;
+
+  OriginalValue = 0;
+  Value         = 0;
+
+  Status = BarExisted (
+            PciIoDevice,
+            Offset,
+            &Value,
+            &OriginalValue
+            );
+
+  if (EFI_ERROR (Status)) {
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
+    PciIoDevice->PciBar[BarIndex].Length      = 0;
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;
+
+    //
+    // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
+    //
+    PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
+    return Offset + 4;
+  }
+
+  PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
+  if (Value & 0x01) {
+    //
+    // Device I/Os
+    //
+    Mask = 0xfffffffc;
+
+    if (Value & 0xFFFF0000) {
+      //
+      // It is a IO32 bar
+      //
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;
+      PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+    } else {
+      //
+      // It is a IO16 bar
+      //
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;
+      PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+    }
+    //
+    // Workaround. Some platforms inplement IO bar with 0 length
+    // Need to treat it as no-bar
+    //
+    if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+      PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
+    }
+
+    PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;
+    PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;
+
+  } else {
+
+    Mask  = 0xfffffff0;
+
+    PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
+
+    switch (Value & 0x07) {
+
+    //
+    //memory space; anywhere in 32 bit address space
+    //
+    case 0x00:
+      if (Value & 0x08) {
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
+      } else {
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
+      }
+
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+      break;
+
+    //
+    // memory space; anywhere in 64 bit address space
+    //
+    case 0x04:
+      if (Value & 0x08) {
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
+      } else {
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
+      }
+
+      //
+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
+      // is regarded as an extension for the first bar. As a result
+      // the sizing will be conducted on combined 64 bit value
+      // Here just store the masked first 32bit value for future size
+      // calculation
+      //
+      PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+      //
+      // Increment the offset to point to next DWORD
+      //
+      Offset += 4;
+
+      Status = BarExisted (
+                PciIoDevice,
+                Offset,
+                &Value,
+                &OriginalValue
+                );
+
+      if (EFI_ERROR (Status)) {
+        return Offset + 4;
+      }
+
+      //
+      // Fix the length to support some spefic 64 bit BAR
+      //
+      Value |= ((UINT32)(-1) << HighBitSet32 (Value)); 
+
+      //
+      // Calculate the size of 64bit bar
+      //
+      PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
+
+      PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
+      PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+      break;
+
+    //
+    // reserved
+    //
+    default:
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+      break;
+    }
+  }
+  
+  //
+  // Check the length again so as to keep compatible with some special bars
+  //
+  if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+    PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;
+  }
+  
+  //
+  // Increment number of bar
+  //
+  return Offset + 4;
+}
+
+EFI_STATUS
+InitializePPB (
+  IN PCI_IO_DEVICE *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  PciIo = &(PciIoDevice->PciIo);
+
+  //
+  // Put all the resource apertures including IO16
+  // Io32, pMem32, pMem64 to quiescent state
+  // Resource base all ones, Resource limit all zeros
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
+
+  //
+  // don't support use io32 as for now
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeP2C (
+  IN PCI_IO_DEVICE *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  PciIo = &(PciIoDevice->PciIo);
+
+  //
+  // Put all the resource apertures including IO16
+  // Io32, pMem32, pMem64 to quiescent state(
+  // Resource base all ones, Resource limit all zeros
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
+
+  return EFI_SUCCESS;
+}
+
+PCI_IO_DEVICE *
+CreatePciIoDevice (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_TYPE00                       *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = NULL;
+
+  Status = gBS->AllocatePool (
+                  EfiBootServicesData,
+                  sizeof (PCI_IO_DEVICE),
+                  (VOID **) &PciIoDevice
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));
+
+  PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;
+  PciIoDevice->Handle           = NULL;
+  PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;
+  PciIoDevice->DevicePath       = NULL;
+  PciIoDevice->BusNumber        = Bus;
+  PciIoDevice->DeviceNumber     = Device;
+  PciIoDevice->FunctionNumber   = Func;
+  PciIoDevice->Decodes          = 0;
+  if (gFullEnumeration) {
+    PciIoDevice->Allocated = FALSE;
+  } else {
+    PciIoDevice->Allocated = TRUE;
+  }
+
+  PciIoDevice->Attributes         = 0;
+  PciIoDevice->Supports           = 0;
+  PciIoDevice->BusOverride        = FALSE;
+  PciIoDevice->IsPciExp           = FALSE;
+
+  CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
+
+  //
+  // Initialize the PCI I/O instance structure
+  //
+
+  Status  = InitializePciIoInstance (PciIoDevice);
+  Status  = InitializePciDriverOverrideInstance (PciIoDevice);
+
+  if (EFI_ERROR (Status)) {
+    gBS->FreePool (PciIoDevice);
+    return NULL;
+  }
+
+  //
+  // Initialize the reserved resource list
+  //
+  InitializeListHead (&PciIoDevice->ReservedResourceList);
+
+  //
+  // Initialize the driver list
+  //
+  InitializeListHead (&PciIoDevice->OptionRomDriverList);
+
+  //
+  // Initialize the child list
+  //
+  InitializeListHead (&PciIoDevice->ChildList);
+
+  return PciIoDevice;
+}
+
+EFI_STATUS
+PciEnumeratorLight (
+  IN EFI_HANDLE                    Controller
+  )
+/*++
+
+Routine Description:
+
+  This routine is used to enumerate entire pci bus system 
+  in a given platform
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+
+  EFI_STATUS                        Status;
+  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
+  PCI_IO_DEVICE                     *RootBridgeDev;
+  UINT16                            MinBus;
+  UINT16                            MaxBus;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+  MinBus      = 0;
+  MaxBus      = PCI_MAX_BUS;
+  Descriptors = NULL;
+
+  //
+  // If this host bridge has been already enumerated, then return successfully
+  //
+  if (RootBridgeExisted (Controller)) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Open the IO Abstraction(s) needed to perform the supported test
+  //
+  Status = gBS->OpenProtocol (
+                  Controller      ,   
+                  &gEfiDevicePathProtocolGuid,  
+                  (VOID **)&ParentDevicePath,
+                  gPciBusDriverBinding.DriverBindingHandle,     
+                  Controller,   
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+    return Status;
+  }
+
+  //
+  // Open pci root bridge io protocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **) &PciRootBridgeIo,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+    return Status;
+  }
+
+  //
+  // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge 
+  //
+  Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo);
+
+  Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
+
+    //
+    // Create a device node for root bridge device with a NULL host bridge controller handle
+    //
+    RootBridgeDev = CreateRootBridge (Controller);
+
+    //
+    // Record the root bridge device path
+    //
+    RootBridgeDev->DevicePath = ParentDevicePath;
+
+    //
+    // Record the root bridge io protocol
+    //
+    RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
+
+    Status = PciPciDeviceInfoCollector (
+              RootBridgeDev,
+              (UINT8) MinBus
+              );
+
+    if (!EFI_ERROR (Status)) {
+
+      //
+      // If successfully, insert the node into device pool
+      //
+      InsertRootBridge (RootBridgeDev);
+    } else {
+
+      //
+      // If unsuccessly, destroy the entire node
+      //
+      DestroyRootBridge (RootBridgeDev);
+    }
+
+    Descriptors++;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciGetBusRange (
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
+  OUT    UINT16                             *MinBus,
+  OUT    UINT16                             *MaxBus,
+  OUT    UINT16                             *BusRange
+  )
+/*++
+
+Routine Description:
+
+  Get the bus range.
+
+Arguments:
+
+  Descriptors     - A pointer to the address space descriptor.
+  MinBus          - The min bus.
+  MaxBus          - The max bus.
+  BusRange        - The bus range.
+  
+Returns:
+  
+  Status Code.
+
+--*/
+{
+
+  while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
+    if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+      if (MinBus != NULL) {
+        *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;
+      }
+
+      if (MaxBus != NULL) {
+        *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;
+      }
+
+      if (BusRange != NULL) {
+        *BusRange = (UINT16)(*Descriptors)->AddrLen;
+      }
+      return EFI_SUCCESS;
+    }
+
+    (*Descriptors)++;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h
new file mode 100644 (file)
index 0000000..aa2aba2
--- /dev/null
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciEnumeratorSupport.h
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H
+#define _EFI_PCI_ENUMERATOR_SUPPORT_H
+
+#include "PciBus.h"
+
+EFI_STATUS
+PciPciDeviceInfoCollector (
+  IN PCI_IO_DEVICE                      *Bridge,
+  UINT8                                 StartBusNumber
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Bridge          - TODO: add argument description
+  StartBusNumber  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciDevicePresent(
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  PCI_TYPE00                          *Pci,
+  UINT8                               Bus,
+  UINT8                               Device,
+  UINT8                               Func
+);
+
+EFI_STATUS
+PciEnumeratorLight (
+  IN EFI_HANDLE                    Controller
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Controller  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciGetBusRange (
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
+  OUT    UINT16                             *MinBus,
+  OUT    UINT16                             *MaxBus,
+  OUT    UINT16                             *BusRange
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Descriptors - TODO: add argument description
+  MinBus      - TODO: add argument description
+  MaxBus      - TODO: add argument description
+  BusRange    - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+#endif
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciIo.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciIo.c
new file mode 100644 (file)
index 0000000..bf3c1a6
--- /dev/null
@@ -0,0 +1,1852 @@
+/*++
+
+Copyright (c) 2005 - 2014, 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.             
+
+Module Name:
+
+  PciIo.c
+  
+Abstract:
+
+  PCI I/O Abstraction Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+//
+// PCI I/O Support Function Prototypes
+//
+//
+
+BOOLEAN 
+PciDevicesOnTheSamePath (
+  IN PCI_IO_DEVICE       *PciDevice1,
+  IN PCI_IO_DEVICE       *PciDevice2
+);
+
+
+EFI_STATUS 
+UpStreamBridgesAttributes (
+  IN  PCI_IO_DEVICE                            *PciIoDevice,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
+  IN  UINT64                                   Attributes
+);
+
+
+BOOLEAN 
+CheckBarType ( 
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  UINT8             BarIndex,
+  PCI_BAR_TYPE      BarType
+);
+
+
+EFI_STATUS 
+SetBootVGA ( 
+  IN  PCI_IO_DEVICE                  *PciIoDevice
+);
+
+EFI_STATUS 
+DisableBootVGA ( 
+  IN  PCI_IO_DEVICE                  *PciIoDevice
+);
+
+
+EFI_STATUS
+PciIoVerifyBarAccess (
+  PCI_IO_DEVICE                 *PciIoDevice,
+  UINT8                         BarIndex,
+  PCI_BAR_TYPE                  Type,
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN UINTN                      Count,
+  UINT64                        *Offset
+);
+
+EFI_STATUS
+PciIoVerifyConfigAccess (
+  PCI_IO_DEVICE                 *PciIoDevice,
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN UINTN                      Count,
+  IN UINT64                     *Offset
+);
+
+EFI_STATUS
+EFIAPI
+PciIoPollMem (
+  IN  EFI_PCI_IO_PROTOCOL        *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT8                      BarIndex,
+  IN  UINT64                     Offset,
+  IN  UINT64                     Mask,
+  IN  UINT64                     Value,
+  IN  UINT64                     Delay,
+  OUT UINT64                     *Result
+);
+  
+EFI_STATUS
+EFIAPI
+PciIoPollIo (
+  IN  EFI_PCI_IO_PROTOCOL        *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT8                      BarIndex,
+  IN  UINT64                     Offset,
+  IN  UINT64                     Mask,
+  IN  UINT64                     Value,
+  IN  UINT64                     Delay,
+  OUT UINT64                     *Result
+);    
+
+EFI_STATUS
+EFIAPI
+PciIoMemRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+);
+
+EFI_STATUS
+EFIAPI
+PciIoMemWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+);
+
+EFI_STATUS
+EFIAPI
+PciIoIoRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+);
+
+EFI_STATUS
+EFIAPI
+PciIoIoWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+);
+
+EFI_STATUS
+EFIAPI
+PciIoConfigRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT32                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+);
+
+EFI_STATUS
+EFIAPI
+PciIoConfigWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT32                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+);
+
+EFI_STATUS
+EFIAPI
+PciIoCopyMem (
+  IN     EFI_PCI_IO_PROTOCOL  *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN     UINT8                        DestBarIndex,
+  IN     UINT64                       DestOffset,
+  IN     UINT8                        SrcBarIndex,
+  IN     UINT64                       SrcOffset,
+  IN     UINTN                        Count
+);
+
+EFI_STATUS
+EFIAPI
+PciIoMap (
+  IN     EFI_PCI_IO_PROTOCOL            *This,
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                           *HostAddress,
+  IN OUT UINTN                          *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
+  OUT    VOID                           **Mapping
+);
+
+EFI_STATUS
+EFIAPI
+PciIoUnmap (
+  IN  EFI_PCI_IO_PROTOCOL  *This,
+  IN  VOID                 *Mapping
+);
+
+EFI_STATUS
+EFIAPI
+PciIoAllocateBuffer (
+  IN  EFI_PCI_IO_PROTOCOL    *This,
+  IN  EFI_ALLOCATE_TYPE      Type,
+  IN  EFI_MEMORY_TYPE        MemoryType,
+  IN  UINTN                  Pages,
+  OUT VOID                   **HostAddress,
+  IN  UINT64                 Attributes
+);
+
+EFI_STATUS
+EFIAPI
+PciIoFreeBuffer (
+  IN  EFI_PCI_IO_PROTOCOL   *This,
+  IN  UINTN                 Pages,
+  IN  VOID                  *HostAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PciIoFlush (
+  IN  EFI_PCI_IO_PROTOCOL  *This
+  );
+
+EFI_STATUS
+EFIAPI
+PciIoGetLocation (
+  IN  EFI_PCI_IO_PROTOCOL  *This,
+  OUT UINTN                *Segment,
+  OUT UINTN                *Bus,
+  OUT UINTN                *Device,
+  OUT UINTN                *Function
+  );
+
+EFI_STATUS
+EFIAPI
+PciIoAttributes (
+  IN  EFI_PCI_IO_PROTOCOL              *This,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
+  IN  UINT64                                   Attributes,
+  OUT UINT64                                   *Result   OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+PciIoGetBarAttributes(
+  IN  EFI_PCI_IO_PROTOCOL    *This,
+  IN  UINT8                          BarIndex,
+  OUT UINT64                         *Supports,   OPTIONAL
+  OUT VOID                           **Resources  OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+PciIoSetBarAttributes(
+  IN     EFI_PCI_IO_PROTOCOL  *This,
+  IN     UINT64                       Attributes,
+  IN     UINT8                        BarIndex,
+  IN OUT UINT64                       *Offset,
+  IN OUT UINT64                       *Length
+  );
+
+
+//
+// Pci Io Protocol Interface
+//
+EFI_PCI_IO_PROTOCOL  PciIoInterface = {
+  PciIoPollMem,
+  PciIoPollIo,
+  {
+    PciIoMemRead,
+    PciIoMemWrite
+  },
+  {
+    PciIoIoRead,
+    PciIoIoWrite
+  },
+  {
+    PciIoConfigRead,
+    PciIoConfigWrite
+  },
+  PciIoCopyMem,
+  PciIoMap,
+  PciIoUnmap,
+  PciIoAllocateBuffer,
+  PciIoFreeBuffer,
+  PciIoFlush,
+  PciIoGetLocation,
+  PciIoAttributes,
+  PciIoGetBarAttributes,
+  PciIoSetBarAttributes,
+  0,
+  NULL
+};
+
+
+EFI_STATUS
+InitializePciIoInstance (
+  PCI_IO_DEVICE  *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  Initializes a PCI I/O Instance
+
+Arguments:
+  
+Returns:
+
+  None
+
+--*/
+
+{
+  CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoVerifyBarAccess (
+  PCI_IO_DEVICE                   *PciIoDevice,
+  UINT8                           BarIndex,
+  PCI_BAR_TYPE                    Type,
+  IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN UINTN                        Count,
+  UINT64                          *Offset
+  )
+/*++
+
+Routine Description:
+
+  Verifies access to a PCI Base Address Register (BAR)
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // BarIndex 0-5 is legal
+  //
+  if (BarIndex >= PCI_MAX_BAR) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!CheckBarType (PciIoDevice, BarIndex, Type)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+  //
+  if (Width >= EfiPciIoWidthFifoUint8 && Width <= EfiPciIoWidthFifoUint64) {
+    Count = 1;
+  }
+
+  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+  if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoVerifyConfigAccess (
+  PCI_IO_DEVICE                 *PciIoDevice,
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN UINTN                      Count,
+  IN UINT64                     *Offset
+  )
+/*++
+
+Routine Description:
+
+  Verifies access to a PCI Config Header
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT64  ExtendOffset;
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+  //
+  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+  if (PciIoDevice->IsPciExp) {
+    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
+      return EFI_UNSUPPORTED;
+    }
+
+    ExtendOffset  = LShiftU64 (*Offset, 32);
+    *Offset       = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
+    *Offset       = (*Offset) | ExtendOffset;
+
+  } else {
+    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
+      return EFI_UNSUPPORTED;
+    }
+
+    *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoPollMem (
+  IN  EFI_PCI_IO_PROTOCOL        *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT8                      BarIndex,
+  IN  UINT64                     Offset,
+  IN  UINT64                     Mask,
+  IN  UINT64                     Value,
+  IN  UINT64                     Delay,
+  OUT UINT64                     *Result
+  )
+/*++
+
+Routine Description:
+
+  Poll PCI Memmory
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (Width > EfiPciIoWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->PollMem (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                          Offset,
+                                          Mask,
+                                          Value,
+                                          Delay,
+                                          Result
+                                          );
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoPollIo (
+  IN  EFI_PCI_IO_PROTOCOL        *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT8                      BarIndex,
+  IN  UINT64                     Offset,
+  IN  UINT64                     Mask,
+  IN  UINT64                     Value,
+  IN  UINT64                     Delay,
+  OUT UINT64                     *Result
+  )
+/*++
+
+Routine Description:
+
+  Poll PCI IO
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width > EfiPciIoWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->PollIo (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                          Offset,
+                                          Mask,
+                                          Value,
+                                          Delay,
+                                          Result
+                                          );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMemRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Performs a PCI Memory Read Cycle
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  if (Buffer == NULL){
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Offset,
+                                              Count,
+                                              Buffer
+                                              );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMemWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Performs a PCI Memory Write Cycle
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  if (Buffer == NULL){
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Offset,
+                                              Count,
+                                              Buffer
+                                              );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoIoRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Performs a PCI I/O Read Cycle
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  if (Buffer == NULL){
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Io.Read (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Offset,
+                                              Count,
+                                              Buffer
+                                              );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoIoWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Performs a PCI I/O Write Cycle
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  if (Buffer == NULL){
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Io.Write (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Offset,
+                                              Count,
+                                              Buffer
+                                              );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoConfigRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT32                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Performs a PCI Configuration Read Cycle
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+  UINT64        Address;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  Address     = Offset;
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Address,
+                                              Count,
+                                              Buffer
+                                              );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoConfigWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT32                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Performs a PCI Configuration Write Cycle
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+  UINT64        Address;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  Address     = Offset;
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Address,
+                                              Count,
+                                              Buffer
+                                              );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoCopyMem (
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN     UINT8                        DestBarIndex,
+  IN     UINT64                       DestOffset,
+  IN     UINT8                        SrcBarIndex,
+  IN     UINT64                       SrcOffset,
+  IN     UINTN                        Count
+  )
+/*++
+
+Routine Description:
+
+  Copy PCI Memory
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width == EfiPciIoWidthFifoUint8  ||
+      Width == EfiPciIoWidthFifoUint16 ||
+      Width == EfiPciIoWidthFifoUint32 ||
+      Width == EfiPciIoWidthFifoUint64 ||
+      Width == EfiPciIoWidthFillUint8  ||
+      Width == EfiPciIoWidthFillUint16 ||
+      Width == EfiPciIoWidthFillUint32 ||
+      Width == EfiPciIoWidthFillUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->CopyMem (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                          DestOffset,
+                                          SrcOffset,
+                                          Count
+                                          );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMap (
+  IN     EFI_PCI_IO_PROTOCOL            *This,
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                           *HostAddress,
+  IN OUT UINTN                          *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
+  OUT    VOID                           **Mapping
+  )
+/*++
+
+Routine Description:
+
+  Maps a memory region for DMA
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Operation >= EfiPciIoOperationMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
+    Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Map (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
+                                          HostAddress,
+                                          NumberOfBytes,
+                                          DeviceAddress,
+                                          Mapping
+                                          );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoUnmap (
+  IN  EFI_PCI_IO_PROTOCOL  *This,
+  IN  VOID                 *Mapping
+  )
+/*++
+
+Routine Description:
+
+  Unmaps a memory region for DMA
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  Status = PciIoDevice->PciRootBridgeIo->Unmap (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          Mapping
+                                          );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoAllocateBuffer (
+  IN  EFI_PCI_IO_PROTOCOL   *This,
+  IN  EFI_ALLOCATE_TYPE     Type,
+  IN  EFI_MEMORY_TYPE       MemoryType,
+  IN  UINTN                 Pages,
+  OUT VOID                  **HostAddress,
+  IN  UINT64                Attributes
+  )
+/*++
+
+Routine Description:
+
+  Allocates a common buffer for DMA
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  if (Attributes &
+      (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
+    return EFI_UNSUPPORTED;
+  }
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
+    Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          Type,
+                                          MemoryType,
+                                          Pages,
+                                          HostAddress,
+                                          Attributes
+                                          );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoFreeBuffer (
+  IN  EFI_PCI_IO_PROTOCOL   *This,
+  IN  UINTN                 Pages,
+  IN  VOID                  *HostAddress
+  )
+/*++
+
+Routine Description:
+
+  Frees a common buffer 
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+  
+  if( HostAddress == NULL ){
+     return EFI_INVALID_PARAMETER;
+  } 
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          Pages,
+                                          HostAddress
+                                          );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoFlush (
+  IN  EFI_PCI_IO_PROTOCOL  *This
+  )
+/*++
+
+Routine Description:
+
+  Flushes a DMA buffer
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+
+{
+  EFI_STATUS    Status;
+  UINT32         Register;
+  PCI_IO_DEVICE  *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  //
+  // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to 
+  // flush the posted write cycles through the PCI-PCI bridges
+  //
+  if (PciIoDevice->Parent != NULL) {
+    Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);
+  }
+
+  //
+  // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset
+  //
+  Status = PciIoDevice->PciRootBridgeIo->Flush (
+                                           PciIoDevice->PciRootBridgeIo
+                                           );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoGetLocation (
+  IN  EFI_PCI_IO_PROTOCOL  *This,
+  OUT UINTN                *Segment,
+  OUT UINTN                *Bus,
+  OUT UINTN                *Device,
+  OUT UINTN                *Function
+  )
+/*++
+
+Routine Description:
+
+  Gets a PCI device's current bus number, device number, and function number.
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Segment  = PciIoDevice->PciRootBridgeIo->SegmentNumber;
+  *Bus      = PciIoDevice->BusNumber;
+  *Device   = PciIoDevice->DeviceNumber;
+  *Function = PciIoDevice->FunctionNumber;
+
+  return EFI_SUCCESS;
+}
+
+BOOLEAN
+CheckBarType (
+  IN PCI_IO_DEVICE       *PciIoDevice,
+  UINT8                  BarIndex,
+  PCI_BAR_TYPE           BarType
+  )
+/*++
+
+Routine Description:
+
+  Sets a PCI controllers attributes on a resource range
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  switch (BarType) {
+
+  case PciBarTypeMem:
+
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32  &&
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64    ) {
+      return FALSE;
+    }
+
+    return TRUE;
+
+  case PciBarTypeIo:
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
+      return FALSE;
+    }
+
+    return TRUE;
+
+  default:
+    break;
+  }
+
+  return FALSE;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoAttributes (
+  IN EFI_PCI_IO_PROTOCOL                       * This,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
+  IN  UINT64                                   Attributes,
+  OUT UINT64                                   *Result OPTIONAL
+  )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+
+  PCI_IO_DEVICE *PciIoDevice;
+  PCI_IO_DEVICE *Temp;
+  UINT64         NewAttributes;
+  UINT64         PciRootBridgeSupports;
+  UINT64         PciRootBridgeAttributes;
+  UINT64         NewPciRootBridgeAttributes;
+  UINT64         NewUpStreamBridgeAttributes;
+  UINT64         ModifiedPciRootBridgeAttributes;
+  UINT16         EnableCommand;
+  UINT16         DisableCommand;
+  UINT16         EnableBridge;
+  UINT16         DisableBridge;
+  UINT16         Command;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+  NewUpStreamBridgeAttributes = 0;
+
+  EnableCommand   = 0;
+  DisableCommand  = 0;
+  EnableBridge    = 0;
+  DisableBridge   = 0;
+
+  switch (Operation) {
+  case EfiPciIoAttributeOperationGet:
+    if (Result == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *Result = PciIoDevice->Attributes;
+    return EFI_SUCCESS;
+
+  case EfiPciIoAttributeOperationSupported:
+    if (Result == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *Result = PciIoDevice->Supports;
+    return EFI_SUCCESS;
+
+  case EfiPciIoAttributeOperationEnable:
+    if(Attributes & ~(PciIoDevice->Supports)) {
+      return EFI_UNSUPPORTED;
+    }
+    NewAttributes = PciIoDevice->Attributes | Attributes;
+    break;
+  case EfiPciIoAttributeOperationDisable:
+    if(Attributes & ~(PciIoDevice->Supports)) {
+      return EFI_UNSUPPORTED;
+    }
+    NewAttributes = PciIoDevice->Attributes & (~Attributes);
+    break;
+  case EfiPciIoAttributeOperationSet:
+    if(Attributes & ~(PciIoDevice->Supports)) {
+      return EFI_UNSUPPORTED;
+    }
+    NewAttributes = Attributes;
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If VGA_IO is set, then set VGA_MEMORY too.  This driver can not enable them seperately.
+  //
+  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
+    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
+  }
+
+  //
+  // If VGA_MEMORY is set, then set VGA_IO too.  This driver can not enable them seperately.
+  //
+  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {
+    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
+  }
+
+  //
+  // If the attributes are already set correctly, then just return EFI_SUCCESS;
+  //
+  if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and
+  // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER.  Strip these 3 bits off the new attribute mask so
+  // a call to the PCI Root Bridge I/O Protocol can be made
+  //
+
+  if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
+    NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));
+
+    //  
+    // Get the current attributes of this PCI device's PCI Root Bridge
+    //
+    Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
+                                            PciIoDevice->PciRootBridgeIo,
+                                            &PciRootBridgeSupports,
+                                            &PciRootBridgeAttributes
+                                            );
+
+    //
+    // Check to see if any of the PCI Root Bridge attributes are being modified
+    //
+    ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;
+    if (ModifiedPciRootBridgeAttributes) {
+
+      //
+      // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing
+      //
+      if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {
+  //     return EFI_UNSUPPORTED;
+      }
+      //
+      // Call the PCI Root Bridge to attempt to modify the attributes
+      //
+      Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
+                                             PciIoDevice->PciRootBridgeIo,
+                                             NewPciRootBridgeAttributes,
+                                             NULL,
+                                             NULL
+                                             );
+      if (EFI_ERROR (Status)) {
+      //
+      // The PCI Root Bridge could not modify the attributes, so return the error.
+      //
+        return Status;
+      }
+    }
+  }
+
+
+  if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
+
+
+    //
+    // Check to see if an VGA related attributes are being set.
+    //
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {
+
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
+        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;
+      } else {
+        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;
+      }
+    }
+
+    //
+    // Check to see if an VGA related attributes are being set.
+    // If ISA Enable on the PPB is set, the PPB will block the
+    // 0x100-0x3FF for each 1KB block in the first 64K I/O block
+    //
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {
+
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {
+        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;
+      } else {
+        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;
+      }
+    }
+
+    //
+    // Check to see if an VGA related attributes are being set.
+    //
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {
+
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {
+        EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+      } else {
+        DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+      }
+    }
+
+  } else {
+
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {
+
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
+
+        //
+        //Check if there have been an active VGA device on the same segment
+        //
+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
+
+        if (Temp && Temp != PciIoDevice) {
+          return EFI_UNSUPPORTED;
+        }
+      }
+    }
+
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {
+      if (IS_PCI_GFX(&PciIoDevice->Pci)) {
+
+        //
+        //Get the boot VGA on the same segement
+        //
+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
+
+        if (!Temp) {
+
+          //
+          // If there is no VGA device on the segement, set
+          // this graphics card to decode the palette range
+          //
+          DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+        } else {
+
+          //
+          // Check these two agents are on the same path
+          //
+          if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) {
+
+            //
+            // Check if they are on the same bus
+            //
+            if (Temp->Parent == PciIoDevice->Parent) {
+
+              PciReadCommandRegister (Temp, &Command);
+
+              //
+              // If they are on the same bus, either one can
+              // be set to snoop, the other set to decode
+              //
+              if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
+                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+              } else {
+                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+              }
+            } else {
+
+              //
+              // If they are on  the same path but on the different bus
+              // The first agent is set to snoop, the second one set to
+              // decode
+              //
+              if (Temp->BusNumber > PciIoDevice->BusNumber) {
+                PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+              } else {
+                PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+              }
+            }
+          } else {
+
+            EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+          }
+        }
+      }
+    }
+  }
+
+  //
+  // Check to see of the I/O enable is being modified
+  //
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) {
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) {
+      EnableCommand |= EFI_PCI_COMMAND_IO_SPACE;
+    } else {
+      DisableCommand |= EFI_PCI_COMMAND_IO_SPACE;
+    }
+  }
+
+  //
+  // Check to see of the Memory enable is being modified
+  //
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) {
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {
+      EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;
+    } else {
+      DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;
+    }
+  }
+
+  //
+  // Check to see of the Bus Master enable is being modified
+  //
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) {
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {
+      EnableCommand  |= EFI_PCI_COMMAND_BUS_MASTER;
+    } else {
+      DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER;
+    }
+  }
+
+  Status = EFI_SUCCESS;
+  if (EnableCommand) {
+    Status = PciEnableCommandRegister(PciIoDevice, EnableCommand);
+  } 
+
+  if (DisableCommand) {
+    Status = PciDisableCommandRegister(PciIoDevice, DisableCommand);
+  }
+
+  if (EFI_ERROR(Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (EnableBridge) {
+    Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge);
+  }
+
+  if (DisableBridge) {
+    Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge);
+  }
+   
+  if (EFI_ERROR(Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Set the upstream bridge attributes
+  //
+  if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) {
+
+    //
+    // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
+    // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
+    // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge
+    // 
+    NewUpStreamBridgeAttributes = Attributes & \
+                                (~(EFI_PCI_IO_ATTRIBUTE_IO | \
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY | \
+                                EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \
+                                EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));
+
+    if (NewUpStreamBridgeAttributes){
+      UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes);
+    }
+  }
+  
+  PciIoDevice->Attributes = NewAttributes;
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoGetBarAttributes (
+  IN EFI_PCI_IO_PROTOCOL             * This,
+  IN  UINT8                          BarIndex,
+  OUT UINT64                         *Supports, OPTIONAL
+  OUT VOID                           **Resources OPTIONAL
+  )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT8                             *Configuration;
+  PCI_IO_DEVICE                     *PciIoDevice;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace;
+  EFI_ACPI_END_TAG_DESCRIPTOR       *End;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if (Supports == NULL && Resources == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // This driver does not support modifications to the WRITE_COMBINE or
+  // CACHED attributes for BAR ranges.
+  //
+  if (Supports != NULL) {
+    *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+  }
+
+  if (Resources != NULL) {
+    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+    if (Configuration == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    AddressSpace = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+    AddressSpace->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    AddressSpace->Len          = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
+
+    AddressSpace->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
+    AddressSpace->AddrLen      = PciIoDevice->PciBar[BarIndex].Length;
+    AddressSpace->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
+
+    switch (PciIoDevice->PciBar[BarIndex].BarType) {
+    case PciBarTypeIo16:
+    case PciBarTypeIo32:
+      //
+      // Io
+      //
+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+      break;
+
+    case PciBarTypeMem32:
+      //
+      // Mem
+      //
+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // 32 bit
+      //
+      AddressSpace->AddrSpaceGranularity = 32;
+      break;
+
+    case PciBarTypePMem32:
+      //
+      // Mem
+      //
+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // prefechable
+      //
+      AddressSpace->SpecificFlag = 0x6;
+      //
+      // 32 bit
+      //
+      AddressSpace->AddrSpaceGranularity = 32;
+      break;
+
+    case PciBarTypeMem64:
+      //
+      // Mem
+      //
+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // 64 bit
+      //
+      AddressSpace->AddrSpaceGranularity = 64;
+      break;
+
+    case PciBarTypePMem64:
+      //
+      // Mem
+      //
+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // prefechable
+      //
+      AddressSpace->SpecificFlag = 0x6;
+      //
+      // 64 bit
+      //
+      AddressSpace->AddrSpaceGranularity = 64;
+      break;
+
+    default:
+      break;
+    }
+
+    //
+    // put the checksum
+    //
+    End           = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AddressSpace + 1);
+    End->Desc     = ACPI_END_TAG_DESCRIPTOR;
+    End->Checksum = 0;
+
+    *Resources    = Configuration;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoSetBarAttributes (
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     UINT64                       Attributes,
+  IN     UINT8                        BarIndex,
+  IN OUT UINT64                       *Offset,
+  IN OUT UINT64                       *Length
+  )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+  UINT64        NonRelativeOffset;
+  UINT64        Supports;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  //
+  // Make sure Offset and Length are not NULL
+  //
+  if (Offset == NULL || Length == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
+    return EFI_UNSUPPORTED;
+  }
+  //
+  // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
+  // If Attributes is not 0, then return EFI_UNSUPPORTED.
+  //
+  Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+
+  if (Attributes != (Attributes & Supports)) {
+    return EFI_UNSUPPORTED;
+  }
+  //
+  // Attributes must be supported.  Make sure the BAR range describd by BarIndex, Offset, and
+  // Length are valid for this PCI device.
+  //
+  NonRelativeOffset = *Offset;
+  Status = PciIoVerifyBarAccess (
+            PciIoDevice,
+            BarIndex,
+            PciBarTypeMem,
+            EfiPciIoWidthUint8,
+            (UINT32) *Length,
+            &NonRelativeOffset
+            );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpStreamBridgesAttributes (
+  IN  PCI_IO_DEVICE                            *PciIoDevice,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
+  IN  UINT64                                   Attributes
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  PCI_IO_DEVICE       *Parent;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  Parent = PciIoDevice->Parent;
+
+  while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {
+
+    //
+    // Get the PciIo Protocol
+    //
+    PciIo = &Parent->PciIo;
+
+    PciIo->Attributes (PciIo, Operation, Attributes, NULL);
+
+    Parent = Parent->Parent;
+  }
+
+  return EFI_SUCCESS;
+}
+
+BOOLEAN
+PciDevicesOnTheSamePath (
+  IN PCI_IO_DEVICE        *PciDevice1,
+  IN PCI_IO_DEVICE        *PciDevice2
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+  PciDevice1  -  The pointer to the first PCI_IO_DEVICE.
+  PciDevice2  -  The pointer to the second PCI_IO_DEVICE.
+
+Returns:
+
+  TRUE   -  The two Pci devices are on the same path.
+  FALSE  -  The two Pci devices are not on the same path.
+
+--*/
+{
+
+  if (PciDevice1->Parent == PciDevice2->Parent) {
+    return TRUE;
+  }
+
+  return (BOOLEAN) ((PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1)));
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciIo.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciIo.h
new file mode 100644 (file)
index 0000000..b0d465a
--- /dev/null
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciIo.h
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_IO_PROTOCOL_H
+#define _EFI_PCI_IO_PROTOCOL_H
+
+EFI_STATUS
+InitializePciIoInstance (
+  PCI_IO_DEVICE  *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  PciIoDevice - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c
new file mode 100644 (file)
index 0000000..df0ae4e
--- /dev/null
@@ -0,0 +1,557 @@
+/*++
+
+Copyright (c) 2005 - 2012, 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.             
+
+Module Name:
+
+  PciOptionRomSupport.c
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+
+EFI_STATUS
+RomDecode (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT8           RomBarIndex,
+  IN UINT32          RomBar,
+  IN BOOLEAN         Enable
+);
+
+EFI_STATUS
+GetOpRomInfo (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+  UINT8                           RomBarIndex;
+  UINT32                          AllOnes;
+  UINT64                          Address;
+  EFI_STATUS                      Status;
+  UINT8                           Bus;
+  UINT8                           Device;
+  UINT8                           Function;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  Bus             = PciIoDevice->BusNumber;
+  Device          = PciIoDevice->DeviceNumber;
+  Function        = PciIoDevice->FunctionNumber;
+
+  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
+
+  //
+  // offset is 0x30 if is not ppb
+  //
+
+  //
+  // 0x30
+  //
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;
+
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+    //
+    // if is ppb
+    //
+
+    //
+    // 0x38
+    //
+    RomBarIndex = PCI_BRIDGE_ROMBAR;
+  }
+  //
+  // the bit0 is 0 to prevent the enabling of the Rom address decoder
+  //
+  AllOnes = 0xfffffffe;
+  Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);
+
+  Status = PciRootBridgeIo->Pci.Write (
+                                  PciRootBridgeIo,
+                                  EfiPciWidthUint32,
+                                  Address,
+                                  1,
+                                  &AllOnes
+                                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  //
+  // read back
+  //
+  Status = PciRootBridgeIo->Pci.Read (
+                                  PciRootBridgeIo,
+                                  EfiPciWidthUint32,
+                                  Address,
+                                  1,
+                                  &AllOnes
+                                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Bits [1, 10] are reserved
+  //
+  AllOnes &= 0xFFFFF800;
+  if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {
+    return EFI_NOT_FOUND;
+  }
+  
+  DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: OPROM detected!\n"));
+  DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: B-%x, D-%x, F-%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Function));
+
+  PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LoadOpRomImage (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT64          ReservedMemoryBase
+  )
+/*++
+
+Routine Description:
+    Load option rom image for specified PCI device
+
+Arguments:
+
+Returns:
+
+--*/
+{
+  UINT8                     RomBarIndex;
+  UINT8                     Indicator;
+  UINT16                    OffsetPcir;
+  UINT32                    RomBarOffset;
+  UINT32                    RomBar;
+  EFI_STATUS                retStatus;
+  BOOLEAN                   FirstCheck;
+  UINT8                     *Image;
+  PCI_EXPANSION_ROM_HEADER  *RomHeader;
+  PCI_DATA_STRUCTURE        *RomPcir;
+  UINT64                    RomSize;
+  UINT64                    RomImageSize;
+  UINT32                    LegacyImageLength;
+  UINT8                     *RomInMemory;
+  UINT8                     CodeType;
+
+  RomSize       = PciDevice->RomSize;
+
+  Indicator     = 0;
+  RomImageSize  = 0;
+  RomInMemory   = NULL;
+  CodeType      = 0xFF;
+
+  //
+  // Get the RomBarIndex
+  //
+
+  //
+  // 0x30
+  //
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;
+  if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {
+    //
+    // if is ppb
+    //
+
+    //
+    // 0x38
+    //
+    RomBarIndex = PCI_BRIDGE_ROMBAR;
+  }
+  //
+  // Allocate memory for Rom header and PCIR
+  //
+  RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));
+  if (RomHeader == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));
+  if (RomPcir == NULL) {
+    gBS->FreePool (RomHeader);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  RomBar = (UINT32)ReservedMemoryBase;  
+
+  //
+  // Enable RomBar
+  //
+  RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);
+
+  RomBarOffset  = RomBar;
+  retStatus     = EFI_NOT_FOUND;
+  FirstCheck    = TRUE;
+  LegacyImageLength = 0;
+
+  do {
+    PciDevice->PciRootBridgeIo->Mem.Read (
+                                      PciDevice->PciRootBridgeIo,
+                                      EfiPciWidthUint8,
+                                      RomBarOffset,
+                                      sizeof (PCI_EXPANSION_ROM_HEADER),
+                                      (UINT8 *) RomHeader
+                                      );
+
+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+      RomBarOffset = RomBarOffset + 512;
+      if (FirstCheck) {
+        break;
+      } else {
+        RomImageSize = RomImageSize + 512;
+        continue;
+      }
+    }
+
+    FirstCheck  = FALSE;
+    OffsetPcir  = RomHeader->PcirOffset;
+    //
+    // If the pointer to the PCI Data Structure is invalid, no further images can be located. 
+    // The PCI Data Structure must be DWORD aligned. 
+    //
+    if (OffsetPcir == 0 ||
+       (OffsetPcir & 3) != 0 ||
+       RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
+      break;
+    }
+    PciDevice->PciRootBridgeIo->Mem.Read (
+                                      PciDevice->PciRootBridgeIo,
+                                      EfiPciWidthUint8,
+                                      RomBarOffset + OffsetPcir,
+                                      sizeof (PCI_DATA_STRUCTURE),
+                                      (UINT8 *) RomPcir
+                                      );
+    //
+    // If a valid signature is not present in the PCI Data Structure, no further images can be located.
+    //
+    if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+      break;
+    }
+    if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) {
+      break;
+    }
+    if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
+      CodeType = PCI_CODE_TYPE_PCAT_IMAGE;
+      LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;
+    }
+    Indicator     = RomPcir->Indicator;
+    RomImageSize  = RomImageSize + RomPcir->ImageLength * 512;
+    RomBarOffset  = RomBarOffset + RomPcir->ImageLength * 512;
+  } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));
+
+  //
+  // Some Legacy Cards do not report the correct ImageLength so used the maximum
+  // of the legacy length and the PCIR Image Length
+  //
+  if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
+    RomImageSize = MAX (RomImageSize, LegacyImageLength);
+  }
+
+  if (RomImageSize > 0) {
+    retStatus = EFI_SUCCESS;
+    Image     = AllocatePool ((UINT32) RomImageSize);
+    if (Image == NULL) {
+      RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
+      gBS->FreePool (RomHeader);
+      gBS->FreePool (RomPcir);
+      return EFI_OUT_OF_RESOURCES;
+    }
+    
+    //
+    // Copy Rom image into memory
+    //
+    PciDevice->PciRootBridgeIo->Mem.Read (
+                                      PciDevice->PciRootBridgeIo,
+                                      EfiPciWidthUint8,
+                                      RomBar,
+                                      (UINT32) RomImageSize,
+                                      Image
+                                      );
+    RomInMemory = Image;
+  }
+
+  RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
+
+  PciDevice->PciIo.RomSize  = RomImageSize;
+  PciDevice->PciIo.RomImage = RomInMemory;
+
+  //
+  // Free allocated memory
+  //
+  gBS->FreePool (RomHeader);
+  gBS->FreePool (RomPcir);
+
+  return retStatus;
+}
+
+EFI_STATUS
+RomDecode (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT8           RomBarIndex,
+  IN UINT32          RomBar,
+  IN BOOLEAN         Enable
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+  UINT16                          CommandValue;
+  UINT32                          Value32;
+  UINT64                          Address;
+  //EFI_STATUS                      Status;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+  
+  PciRootBridgeIo = PciDevice->PciRootBridgeIo;
+  if (Enable) {
+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);
+    //
+    // set the Rom base address: now is hardcode
+    //
+    PciRootBridgeIo->Pci.Write(
+                               PciRootBridgeIo, 
+                               EfiPciWidthUint32, 
+                               Address, 
+                               1, 
+                               &RomBar);
+  
+    //
+    // enable its decoder
+    //
+    Value32 = RomBar | 0x1;
+    PciRootBridgeIo->Pci.Write(
+                               PciRootBridgeIo, 
+                               EfiPciWidthUint32, 
+                               Address, 
+                               1, 
+                               &Value32);
+    
+    //
+    //setting the memory space bit in the function's command register
+    //
+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, 0x04);
+    PciRootBridgeIo->Pci.Read(
+                              PciRootBridgeIo, 
+                              EfiPciWidthUint16, 
+                              Address, 
+                              1, 
+                              &CommandValue);
+    
+    CommandValue = (UINT16)(CommandValue | 0x0002); //0x0003
+    PciRootBridgeIo->Pci.Write(
+                               PciRootBridgeIo, 
+                               EfiPciWidthUint16, 
+                               Address, 
+                               1, 
+                               &CommandValue);
+  } else {
+    //
+    // disable rom decode
+    //  
+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);
+    Value32 = 0xfffffffe;
+    PciRootBridgeIo->Pci.Write(
+                               PciRootBridgeIo, 
+                               EfiPciWidthUint32, 
+                               Address, 
+                               1, 
+                               &Value32);
+  }
+
+  return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+ProcessOpRomImage (
+  PCI_IO_DEVICE   *PciDevice
+  )
+/*++
+
+Routine Description:
+
+  Process the oprom image.
+  
+Arguments:
+  PciDevice       A pointer to a pci device.
+
+Returns:
+
+  EFI Status.
+  
+--*/
+{
+  UINT8                         Indicator;
+  UINT32                        ImageSize;
+  UINT16                        ImageOffset;
+  VOID                          *RomBar;
+  UINT8                         *RomBarOffset;
+  EFI_HANDLE                    ImageHandle;
+  EFI_STATUS                    Status;
+  EFI_STATUS                    retStatus;
+  BOOLEAN                       SkipImage;
+  UINT32                        DestinationSize;
+  UINT32                        ScratchSize;
+  UINT8                         *Scratch;
+  VOID                          *ImageBuffer;
+  VOID                          *DecompressedImageBuffer;
+  UINT32                        ImageLength;
+  EFI_DECOMPRESS_PROTOCOL       *Decompress;
+  EFI_PCI_EXPANSION_ROM_HEADER  *EfiRomHeader;
+  PCI_DATA_STRUCTURE            *Pcir;
+  UINT32                        InitializationSize;
+
+  Indicator = 0;
+
+  //
+  // Get the Address of the Rom image
+  //
+  RomBar        = PciDevice->PciIo.RomImage;
+  RomBarOffset  = (UINT8 *) RomBar;
+  retStatus     = EFI_NOT_FOUND;
+
+  if (RomBarOffset == NULL) {
+    return retStatus;
+  }
+  ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE);
+
+  do {
+    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;
+    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+      RomBarOffset = RomBarOffset + 512;
+      continue;
+    }
+
+    Pcir        = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);
+    ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);
+    ImageSize   = (UINT32) (Pcir->ImageLength * 512);
+    Indicator   = Pcir->Indicator;
+
+    if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
+        (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
+        ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+         (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {
+
+      ImageOffset             = EfiRomHeader->EfiImageHeaderOffset;
+      InitializationSize      = EfiRomHeader->InitializationSize * 512;
+
+      if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {
+
+        ImageBuffer             = (VOID *) (RomBarOffset + ImageOffset);
+        ImageLength             =  InitializationSize - (UINT32)ImageOffset;
+        DecompressedImageBuffer = NULL;
+
+        //
+        // decompress here if needed
+        //
+        SkipImage = FALSE;
+        if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+          SkipImage = TRUE;
+        }
+
+        if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+          Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
+          if (EFI_ERROR (Status)) {
+            SkipImage = TRUE;
+          } else {
+            SkipImage = TRUE;
+            Status = Decompress->GetInfo (
+                                  Decompress,
+                                  ImageBuffer,
+                                  ImageLength,
+                                  &DestinationSize,
+                                  &ScratchSize
+                                  );
+            if (!EFI_ERROR (Status)) {
+              DecompressedImageBuffer = NULL;
+              DecompressedImageBuffer = AllocatePool (DestinationSize);
+              if (DecompressedImageBuffer != NULL) {
+                Scratch = AllocatePool (ScratchSize);
+                if (Scratch != NULL) {
+                  Status = Decompress->Decompress (
+                                        Decompress,
+                                        ImageBuffer,
+                                        ImageLength,
+                                        DecompressedImageBuffer,
+                                        DestinationSize,
+                                        Scratch,
+                                        ScratchSize
+                                        );
+                  if (!EFI_ERROR (Status)) {
+                    ImageBuffer = DecompressedImageBuffer;
+                    ImageLength = DestinationSize;
+                    SkipImage   = FALSE;
+                  }
+
+                  gBS->FreePool (Scratch);
+                }
+              }
+            }
+          }
+        }
+
+        if (!SkipImage) {
+          //
+          // load image and start image
+          //
+          Status = gBS->LoadImage (
+                          FALSE,
+                          gPciBusDriverBinding.DriverBindingHandle,
+                          NULL,
+                          ImageBuffer,
+                          ImageLength,
+                          &ImageHandle
+                          );
+          if (!EFI_ERROR (Status)) {
+            Status = gBS->StartImage (ImageHandle, NULL, NULL);
+            if (!EFI_ERROR (Status)) {
+              AddDriver (PciDevice, ImageHandle);
+              retStatus = EFI_SUCCESS;
+            }
+          }
+        }
+
+        RomBarOffset = RomBarOffset + ImageSize;
+      } else {
+        RomBarOffset = RomBarOffset + ImageSize;
+      }
+    } else {
+      RomBarOffset = RomBarOffset + ImageSize;
+    }
+
+  } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));
+
+  return retStatus;
+
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h
new file mode 100644 (file)
index 0000000..60c4989
--- /dev/null
@@ -0,0 +1,92 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciOptionRomSupport.h
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_OP_ROM_SUPPORT_H
+#define _EFI_PCI_OP_ROM_SUPPORT_H
+
+EFI_STATUS
+GetOpRomInfo (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  PciIoDevice - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+LoadOpRomImage (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT64          ReservedMemoryBase
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  PciDevice - TODO: add argument description
+  RomBase   - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProcessOpRomImage (
+  PCI_IO_DEVICE   *PciDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  PciDevice - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciPowerManagement.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciPowerManagement.c
new file mode 100644 (file)
index 0000000..0e239ce
--- /dev/null
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 2005 - 2012, 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.             
+
+Module Name:
+
+  PciPowerManagement.c
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+EFI_STATUS
+EFIAPI
+ResetPowerManagementFeature (
+  IN PCI_IO_DEVICE *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  This function is intended to turn off PWE assertion and
+  put the device to D0 state if the device supports
+  PCI Power Management.
+
+Arguments:
+
+Returns:
+  
+  None
+
+--*/
+{
+  EFI_STATUS  Status;
+  UINT8       PowerManagementRegBlock;
+  UINT16      PowerManagementCSR;
+
+  PowerManagementRegBlock = 0;
+
+  Status = LocateCapabilityRegBlock (
+            PciIoDevice,
+            EFI_PCI_CAPABILITY_ID_PMI,
+            &PowerManagementRegBlock,
+            NULL
+            );
+
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Turn off the PWE assertion and put the device into D0 State
+  //
+
+  //
+  // Read PMCSR
+  //
+  Status = PciIoDevice->PciIo.Pci.Read (
+                                    &PciIoDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    PowerManagementRegBlock + 4,
+                                    1,
+                                    &PowerManagementCSR
+                                    );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Clear PME_Status bit
+    //
+    PowerManagementCSR |= BIT15;
+    //
+    // Clear PME_En bit. PowerState = D0.
+    //
+    PowerManagementCSR &= ~(BIT8 | BIT1 | BIT0);
+
+    //
+    // Write PMCSR
+    //
+    Status = PciIoDevice->PciIo.Pci.Write (
+                                      &PciIoDevice->PciIo,
+                                      EfiPciIoWidthUint16,
+                                      PowerManagementRegBlock + 4,
+                                      1,
+                                      &PowerManagementCSR
+                                      );
+  }
+  return Status;
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciPowerManagement.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciPowerManagement.h
new file mode 100644 (file)
index 0000000..98738b3
--- /dev/null
@@ -0,0 +1,49 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciPowerManagement.h
+  
+Abstract:
+
+  PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_POWER_MANAGEMENT_H
+#define _EFI_PCI_POWER_MANAGEMENT_H
+
+EFI_STATUS
+EFIAPI
+ResetPowerManagementFeature (
+  IN PCI_IO_DEVICE *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  PciIoDevice - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciRomTable.c b/CorebootModulePkg/PciBusNoEnumerationDxe/PciRomTable.c
new file mode 100644 (file)
index 0000000..5123b0f
--- /dev/null
@@ -0,0 +1,393 @@
+/*++
+
+Copyright (c) 2005 - 2012, 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.             
+
+Module Name:
+
+  PciRomTable.c
+  
+Abstract:
+
+  Option Rom Support for PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+typedef struct {
+  EFI_HANDLE  ImageHandle;
+  UINTN       Seg;
+  UINT8       Bus;
+  UINT8       Dev;
+  UINT8       Func;
+} EFI_PCI_ROM_IMAGE_MAPPING;
+
+UINTN                      mNumberOfPciRomImages     = 0;
+UINTN                      mMaxNumberOfPciRomImages  = 0;
+EFI_PCI_ROM_IMAGE_MAPPING  *mRomImageTable           = NULL;
+
+CHAR16 mHexDigit[17] = L"0123456789ABCDEF";
+
+VOID
+PciRomAddImageMapping (
+  IN EFI_HANDLE  ImageHandle,
+  IN UINTN       Seg,
+  IN UINT8       Bus,
+  IN UINT8       Dev,
+  IN UINT8       Func
+  )
+
+{
+  EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;
+
+  if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {
+
+    mMaxNumberOfPciRomImages += 0x20;
+
+    TempMapping = NULL;
+    TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
+    if (TempMapping == NULL) {
+      return ;
+    }
+
+    CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
+
+    if (mRomImageTable != NULL) {
+      gBS->FreePool (mRomImageTable);
+    }
+
+    mRomImageTable = TempMapping;
+  }
+
+  mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;
+  mRomImageTable[mNumberOfPciRomImages].Seg         = Seg;
+  mRomImageTable[mNumberOfPciRomImages].Bus         = Bus;
+  mRomImageTable[mNumberOfPciRomImages].Dev         = Dev;
+  mRomImageTable[mNumberOfPciRomImages].Func        = Func;
+  mNumberOfPciRomImages++;
+}
+
+VOID
+HexToString (
+  CHAR16  *String,
+  UINTN   Value,
+  UINTN   Digits
+  )
+
+{
+  for (; Digits > 0; Digits--, String++) {
+    *String = mHexDigit[((Value >> (4*(Digits-1))) & 0x0f)];
+  }
+}
+
+EFI_STATUS
+PciRomLoadEfiDriversFromRomImage (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_PCI_OPTION_ROM_DESCRIPTOR  *PciOptionRomDescriptor
+  )
+/*++
+
+Routine Description:
+  Command entry point. 
+
+Arguments:
+  ImageHandle     The image handle. 
+  SystemTable     The system table.
+
+Returns:
+  EFI_SUCCESS             - The command completed successfully
+  EFI_INVALID_PARAMETER   - Command usage error
+  EFI_UNSUPPORTED         - Protocols unsupported
+  EFI_OUT_OF_RESOURCES    - Out of memory
+  Other value             - Unknown error
+
+--*/
+{
+  VOID                          *RomBar;
+  UINTN                         RomSize;
+  CHAR16                        *FileName;
+  EFI_PCI_EXPANSION_ROM_HEADER  *EfiRomHeader;
+  PCI_DATA_STRUCTURE            *Pcir;
+  UINTN                         ImageIndex;
+  UINTN                         RomBarOffset;
+  UINT32                        ImageSize;
+  UINT16                        ImageOffset;
+  EFI_HANDLE                    ImageHandle;
+  EFI_STATUS                    Status;
+  EFI_STATUS                    retStatus;
+  EFI_DEVICE_PATH_PROTOCOL      *FilePath;
+  BOOLEAN                       SkipImage;
+  UINT32                        DestinationSize;
+  UINT32                        ScratchSize;
+  UINT8                         *Scratch;
+  VOID                          *ImageBuffer;
+  VOID                          *DecompressedImageBuffer;
+  UINT32                        ImageLength;
+  EFI_DECOMPRESS_PROTOCOL       *Decompress;
+  UINT32                        InitializationSize;
+
+  RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
+  RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
+  FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
+
+  HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8);
+  HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2);
+  HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2);
+  HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2);
+
+  ImageIndex    = 0;
+  retStatus     = EFI_NOT_FOUND;
+  RomBarOffset  = (UINTN) RomBar;
+
+  do {
+
+    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
+
+
+    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+      return retStatus;
+    }
+
+    //
+    // If the pointer to the PCI Data Structure is invalid, no further images can be located. 
+    // The PCI Data Structure must be DWORD aligned. 
+    //
+    if (EfiRomHeader->PcirOffset == 0 ||
+        (EfiRomHeader->PcirOffset & 3) != 0 ||
+        RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
+      break;
+    }
+    Pcir      = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
+    //
+    // If a valid signature is not present in the PCI Data Structure, no further images can be located.
+    //
+    if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+      break;
+    }
+    ImageSize = Pcir->ImageLength * 512;
+    if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) {
+      break;
+    }
+
+    if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
+        (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
+        ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+         (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {
+
+      ImageOffset             = EfiRomHeader->EfiImageHeaderOffset;
+      InitializationSize      = EfiRomHeader->InitializationSize * 512;
+
+      if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {
+
+        ImageBuffer             = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
+        ImageLength             = InitializationSize - ImageOffset;
+        DecompressedImageBuffer = NULL;
+
+        //
+        // decompress here if needed
+        //
+        SkipImage = FALSE;
+        if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+          SkipImage = TRUE;
+        }
+
+        if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+          Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
+          if (EFI_ERROR (Status)) {
+            SkipImage = TRUE;
+          } else {
+            SkipImage = TRUE;
+            Status = Decompress->GetInfo (
+                                  Decompress,
+                                  ImageBuffer,
+                                  ImageLength,
+                                  &DestinationSize,
+                                  &ScratchSize
+                                  );
+            if (!EFI_ERROR (Status)) {
+              DecompressedImageBuffer = NULL;
+              DecompressedImageBuffer = AllocatePool (DestinationSize);
+              if (DecompressedImageBuffer != NULL) {
+                Scratch = AllocatePool (ScratchSize);
+                if (Scratch != NULL) {
+                  Status = Decompress->Decompress (
+                                        Decompress,
+                                        ImageBuffer,
+                                        ImageLength,
+                                        DecompressedImageBuffer,
+                                        DestinationSize,
+                                        Scratch,
+                                        ScratchSize
+                                        );
+                  if (!EFI_ERROR (Status)) {
+                    ImageBuffer = DecompressedImageBuffer;
+                    ImageLength = DestinationSize;
+                    SkipImage   = FALSE;
+                  }
+
+                  gBS->FreePool (Scratch);
+                }
+              }
+            }
+          }
+        }
+
+        if (!SkipImage) {
+
+          //
+          // load image and start image
+          //
+
+          HexToString (&FileName[48], ImageIndex, 4);
+          FilePath = FileDevicePath (NULL, FileName);
+
+          Status = gBS->LoadImage (
+                          FALSE,
+                          This->ImageHandle,
+                          FilePath,
+                          ImageBuffer,
+                          ImageLength,
+                          &ImageHandle
+                          );
+          if (!EFI_ERROR (Status)) {
+            Status = gBS->StartImage (ImageHandle, NULL, NULL);
+            if (!EFI_ERROR (Status)) {
+              PciRomAddImageMapping (
+                ImageHandle,
+                PciOptionRomDescriptor->Seg,
+                PciOptionRomDescriptor->Bus,
+                PciOptionRomDescriptor->Dev,
+                PciOptionRomDescriptor->Func
+                );
+              retStatus = Status;
+            }
+          }
+          if (FilePath != NULL) {
+            gBS->FreePool (FilePath);
+          }
+        }
+
+        if (DecompressedImageBuffer != NULL) {
+          gBS->FreePool (DecompressedImageBuffer);
+        }
+
+      }
+    }
+
+    RomBarOffset = RomBarOffset + ImageSize;
+    ImageIndex++;
+  } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
+
+  return retStatus;
+}
+
+EFI_STATUS
+PciRomLoadEfiDriversFromOptionRomTable (
+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+  EFI_STATUS                        Status;
+  EFI_PCI_OPTION_ROM_TABLE          *PciOptionRomTable;
+  EFI_PCI_OPTION_ROM_DESCRIPTOR     *PciOptionRomDescriptor;
+  UINTN                             Index;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+  UINT16                            MinBus;
+  UINT16                            MaxBus;
+
+  Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  Status = EFI_NOT_FOUND;
+
+  for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
+    PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
+    if (!PciOptionRomDescriptor->DontLoadEfiRom) {
+      if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) {
+        Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+
+        PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL);
+        if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) {
+          Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor);
+          PciOptionRomDescriptor->DontLoadEfiRom |= 2;
+        }
+      }
+    }
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+PciRomGetRomResourceFromPciOptionRomTable (
+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  PCI_IO_DEVICE                       *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+  EFI_STATUS                    Status;
+  EFI_PCI_OPTION_ROM_TABLE      *PciOptionRomTable;
+  EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
+  UINTN                         Index;
+
+  Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
+    PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
+    if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&
+        PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber         &&
+        PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber      &&
+        PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {
+
+      PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
+      PciIoDevice->PciIo.RomSize  = (UINTN) PciOptionRomDescriptor->RomLength;
+    }
+  }
+
+  for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
+    if (mRomImageTable[Index].Seg  == PciRootBridgeIo->SegmentNumber &&
+        mRomImageTable[Index].Bus  == PciIoDevice->BusNumber         &&
+        mRomImageTable[Index].Dev  == PciIoDevice->DeviceNumber      &&
+        mRomImageTable[Index].Func == PciIoDevice->FunctionNumber    ) {
+
+      AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/CorebootModulePkg/PciBusNoEnumerationDxe/PciRomTable.h b/CorebootModulePkg/PciBusNoEnumerationDxe/PciRomTable.h
new file mode 100644 (file)
index 0000000..773fe80
--- /dev/null
@@ -0,0 +1,58 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+
+  PciRomTable.h
+  
+Abstract:
+
+  Option Rom Support for PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ROM_TABLE_H
+#define _EFI_PCI_ROM_TABLE_H
+
+
+EFI_STATUS
+PciRomLoadEfiDriversFromOptionRomTable (
+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo
+  );
+
+EFI_STATUS
+PciRomGetRomResourceFromPciOptionRomTable (
+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  PCI_IO_DEVICE                       *PciIoDevice
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  This            - TODO: add argument description
+  PciRootBridgeIo - TODO: add argument description
+  PciIoDevice     - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+#endif
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c
new file mode 100644 (file)
index 0000000..e924b44
--- /dev/null
@@ -0,0 +1,845 @@
+/*++
+
+Copyright (c) 2006 - 2012, 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.             
+
+Module Name:
+
+    DeviceIo.c
+    
+Abstract:
+
+    EFI PC-AT PCI Device IO driver
+
+--*/
+#include "PcatPciRootBridge.h"
+#include "DeviceIo.h"
+
+EFI_STATUS
+DeviceIoConstructor (
+  IN EFI_HANDLE                      Handle,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+  IN EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
+  IN UINT16                          PrimaryBus,
+  IN UINT16                          SubordinateBus
+  )
+/*++
+
+Routine Description:
+  
+  Initialize and install a Device IO protocol on a empty device path handle.
+
+Arguments:
+  
+  Handle               - Handle of PCI RootBridge IO instance
+  PciRootBridgeIo      - PCI RootBridge IO instance
+  DevicePath           - Device Path of PCI RootBridge IO instance
+  PrimaryBus           - Primary Bus
+  SubordinateBus       - Subordinate Bus
+
+Returns:
+  
+  EFI_SUCCESS          -  This driver is added to ControllerHandle.  
+  EFI_ALREADY_STARTED  -  This driver is already running on ControllerHandle.   
+  Others               -  This driver does not support this device.
+
+--*/
+{
+  EFI_STATUS                      Status;
+  DEVICE_IO_PRIVATE_DATA          *Private;
+
+  //
+  // Initialize the Device IO device instance.
+  //
+  Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));
+  if (Private == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Private->Signature                = DEVICE_IO_PRIVATE_DATA_SIGNATURE;
+  Private->Handle                   = Handle;
+  Private->PciRootBridgeIo          = PciRootBridgeIo;
+  Private->DevicePath               = DevicePath;
+  Private->PrimaryBus               = PrimaryBus;
+  Private->SubordinateBus           = SubordinateBus;
+
+  Private->DeviceIo.Mem.Read        = DeviceIoMemRead;
+  Private->DeviceIo.Mem.Write       = DeviceIoMemWrite;
+  Private->DeviceIo.Io.Read         = DeviceIoIoRead;
+  Private->DeviceIo.Io.Write        = DeviceIoIoWrite;
+  Private->DeviceIo.Pci.Read        = DeviceIoPciRead;
+  Private->DeviceIo.Pci.Write       = DeviceIoPciWrite;
+  Private->DeviceIo.PciDevicePath   = DeviceIoPciDevicePath;
+  Private->DeviceIo.Map             = DeviceIoMap;
+  Private->DeviceIo.Unmap           = DeviceIoUnmap;
+  Private->DeviceIo.AllocateBuffer  = DeviceIoAllocateBuffer;
+  Private->DeviceIo.Flush           = DeviceIoFlush;
+  Private->DeviceIo.FreeBuffer      = DeviceIoFreeBuffer;
+
+  //
+  // Install protocol interfaces for the Device IO device.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->Handle,
+                  &gEfiDeviceIoProtocolGuid,
+                  &Private->DeviceIo,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemRead (
+  IN     EFI_DEVICE_IO_PROTOCOL   *This,
+  IN     EFI_IO_WIDTH             Width,
+  IN     UINT64                   Address,
+  IN     UINTN                    Count,
+  IN OUT VOID                     *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform reading memory mapped I/O space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations.
+  Address  -  The base address of I/O operations.  
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.           
+  Buffer   -  The destination buffer to store results.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was read from the device.  
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  if (Width > MMIO_COPY_UINT64) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Width >= MMIO_COPY_UINT8) {
+    Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
+    Status = Private->PciRootBridgeIo->CopyMem (
+                                         Private->PciRootBridgeIo,
+                                         (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                         (UINT64)(UINTN) Buffer,
+                                         Address,
+                                         Count
+                                         );
+  } else {
+    Status = Private->PciRootBridgeIo->Mem.Read (
+                                             Private->PciRootBridgeIo,
+                                             (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                             Address,
+                                             Count,
+                                             Buffer
+                                             );
+  }
+
+  return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemWrite (
+  IN     EFI_DEVICE_IO_PROTOCOL    *This,
+  IN     EFI_IO_WIDTH              Width,
+  IN     UINT64                    Address,
+  IN     UINTN                     Count,
+  IN OUT VOID                      *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform writing memory mapped I/O space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations.  
+  Address  -  The base address of I/O operations.   
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.            
+  Buffer   -  The source buffer of data to be written.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was written to the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  if (Width > MMIO_COPY_UINT64) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Width >= MMIO_COPY_UINT8) {
+    Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
+    Status = Private->PciRootBridgeIo->CopyMem (
+                                         Private->PciRootBridgeIo,
+                                         (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                         Address,
+                                         (UINT64)(UINTN) Buffer,
+                                         Count
+                                         );
+  } else {
+    Status = Private->PciRootBridgeIo->Mem.Write (
+                                             Private->PciRootBridgeIo,
+                                             (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                             Address,
+                                             Count,
+                                             Buffer
+                                             );
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoRead (
+  IN     EFI_DEVICE_IO_PROTOCOL   *This,
+  IN     EFI_IO_WIDTH             Width,
+  IN     UINT64                   Address,
+  IN     UINTN                    Count,
+  IN OUT VOID                     *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform reading I/O space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations.
+  Address  -  The base address of I/O operations. 
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.          
+  Buffer   -  The destination buffer to store results.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was read from the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  if (Width >= MMIO_COPY_UINT8) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = Private->PciRootBridgeIo->Io.Read (
+                                          Private->PciRootBridgeIo,
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                          Address,
+                                          Count,
+                                          Buffer
+                                          );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoWrite (
+  IN     EFI_DEVICE_IO_PROTOCOL    *This,
+  IN     EFI_IO_WIDTH              Width,
+  IN     UINT64                    Address,
+  IN     UINTN                     Count,
+  IN OUT VOID                      *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform writing I/O space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations.
+  Address  -  The base address of I/O operations.
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.        
+  Buffer   -  The source buffer of data to be written.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was written to the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  if (Width >= MMIO_COPY_UINT8) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = Private->PciRootBridgeIo->Io.Write (
+                                          Private->PciRootBridgeIo,
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                          Address,
+                                          Count,
+                                          Buffer
+                                          );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciRead (
+  IN     EFI_DEVICE_IO_PROTOCOL   *This,
+  IN     EFI_IO_WIDTH             Width,
+  IN     UINT64                   Address,
+  IN     UINTN                    Count,
+  IN OUT VOID                     *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform reading PCI configuration space of device
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations. 
+  Address  -  The base address of I/O operations. 
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.           
+  Buffer   -  The destination buffer to store results.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was read from the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  if ((UINT32)Width >= MMIO_COPY_UINT8) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = Private->PciRootBridgeIo->Pci.Read (
+                                           Private->PciRootBridgeIo,
+                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                           Address,
+                                           Count,
+                                           Buffer
+                                           );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciWrite (
+  IN     EFI_DEVICE_IO_PROTOCOL    *This,
+  IN     EFI_IO_WIDTH              Width,
+  IN     UINT64                    Address,
+  IN     UINTN                     Count,
+  IN OUT VOID                      *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform writing PCI configuration space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.   
+  Width    -  Width of I/O operations. 
+  Address  -  The base address of I/O operations. 
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.         
+  Buffer   -  The source buffer of data to be written.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was written to the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  if ((UINT32)Width >= MMIO_COPY_UINT8) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = Private->PciRootBridgeIo->Pci.Write (
+                                           Private->PciRootBridgeIo,
+                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                           Address,
+                                           Count,
+                                           Buffer
+                                           );
+
+  return Status;
+}
+
+EFI_DEVICE_PATH_PROTOCOL *
+AppendPciDevicePath (
+  IN     DEVICE_IO_PRIVATE_DATA    *Private,
+  IN     UINT8                     Bus,
+  IN     UINT8                     Device,
+  IN     UINT8                     Function,
+  IN     EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+  IN OUT UINT16                    *BridgePrimaryBus,
+  IN OUT UINT16                    *BridgeSubordinateBus
+  )
+/*++
+
+Routine Description:
+  
+  Append a PCI device path node to another device path.
+
+Arguments:
+  
+  Private               -  A pointer to DEVICE_IO_PRIVATE_DATA instance.  
+  Bus                   -  PCI bus number of the device.
+  Device                -  PCI device number of the device.
+  Function              -  PCI function number of the device.
+  DevicePath            -  Original device path which will be appended a PCI device path node.
+  BridgePrimaryBus      -  Primary bus number of the bridge.
+  BridgeSubordinateBus  -  Subordinate bus number of the bridge.
+
+Returns:
+  
+  Pointer to the appended PCI device path.
+
+--*/
+{
+  UINT16                    ThisBus;
+  UINT8                     ThisDevice;
+  UINT8                     ThisFunc;
+  UINT64                    Address;
+  PCI_TYPE01                PciBridge;
+  PCI_TYPE01                *PciPtr;
+  EFI_DEVICE_PATH_PROTOCOL  *ReturnDevicePath;
+  PCI_DEVICE_PATH           PciNode;
+
+  PciPtr = &PciBridge;
+  for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
+    for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
+      for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
+        Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
+        ZeroMem (PciPtr, sizeof (PCI_TYPE01));
+        Private->DeviceIo.Pci.Read (
+                                &Private->DeviceIo,
+                                IO_UINT32,
+                                Address,
+                                1,
+                                &(PciPtr->Hdr.VendorId)
+                                );
+        if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
+          break;
+        }
+        if (PciPtr->Hdr.VendorId == 0xffff) {
+          continue;
+        }
+
+        Private->DeviceIo.Pci.Read (
+                                &Private->DeviceIo,
+                                IO_UINT32,
+                                Address,
+                                sizeof (PCI_TYPE01) / sizeof (UINT32),
+                                PciPtr
+                                );
+        if (IS_PCI_BRIDGE (PciPtr)) {
+          if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
+
+            PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
+            PciNode.Header.SubType  = HW_PCI_DP;
+            SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+
+            PciNode.Device        = ThisDevice;
+            PciNode.Function      = ThisFunc;
+            ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);
+
+            *BridgePrimaryBus     = PciPtr->Bridge.SecondaryBus;
+            *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
+            return ReturnDevicePath;
+          }
+        }
+
+        if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
+          //
+          // Skip sub functions, this is not a multi function device
+          //
+          break;
+        }
+      }
+    }
+  }
+
+  ZeroMem (&PciNode, sizeof (PciNode));
+  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
+  PciNode.Header.SubType  = HW_PCI_DP;
+  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+  PciNode.Device        = Device;
+  PciNode.Function      = Function;
+
+  ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);
+
+  *BridgePrimaryBus     = 0xffff;
+  *BridgeSubordinateBus = 0xffff;
+  return ReturnDevicePath;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciDevicePath (
+  IN     EFI_DEVICE_IO_PROTOCOL        *This,
+  IN     UINT64                        Address,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath
+  )
+/*++
+
+Routine Description:
+  
+  Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
+
+Arguments:
+  
+  This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.  
+  Address        -  The PCI configuration space address of the device whose Device Path
+                    is going to be returned.           
+  PciDevicePath  -  A pointer to the pointer for the EFI Device Path for PciAddress.
+                    Memory for the Device Path is allocated from the pool.
+
+Returns:
+  
+  EFI_SUCCESS           -  The PciDevicePath returns a pointer to a valid EFI Device Path.
+  EFI_UNSUPPORTED       -  The PciAddress does not map to a valid EFI Device Path. 
+  EFI_OUT_OF_RESOURCES  -  The request could not be completed due to a lack of resources.
+
+--*/
+{
+  DEVICE_IO_PRIVATE_DATA  *Private;
+  UINT16                  PrimaryBus;
+  UINT16                  SubordinateBus;
+  UINT8                   Bus;
+  UINT8                   Device;
+  UINT8                   Func;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  Bus     = (UINT8) (((UINT32) Address >> 24) & 0xff);
+  Device  = (UINT8) (((UINT32) Address >> 16) & 0xff);
+  Func    = (UINT8) (((UINT32) Address >> 8) & 0xff);
+
+  if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
+    return EFI_UNSUPPORTED;
+  }
+
+  *PciDevicePath  = Private->DevicePath;
+  PrimaryBus      = Private->PrimaryBus;
+  SubordinateBus  = Private->SubordinateBus;
+  do {
+    *PciDevicePath = AppendPciDevicePath (
+                       Private,
+                       Bus,
+                       Device,
+                       Func,
+                       *PciDevicePath,
+                       &PrimaryBus,
+                       &SubordinateBus
+                       );
+    if (*PciDevicePath == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  } while (PrimaryBus != 0xffff);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoMap (
+  IN     EFI_DEVICE_IO_PROTOCOL   *This,
+  IN     EFI_IO_OPERATION_TYPE    Operation,
+  IN     EFI_PHYSICAL_ADDRESS     *HostAddress,
+  IN OUT UINTN                    *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,
+  OUT    VOID                     **Mapping
+  )
+/*++
+
+Routine Description:
+  
+  Provides the device-specific addresses needed to access system memory.
+
+Arguments:
+  
+  This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance. 
+  Operation      -  Indicates if the bus master is going to read or write to system memory.  
+  HostAddress    -  The system memory address to map to the device.
+  NumberOfBytes  -  On input the number of bytes to map. On output the number of bytes
+                    that were mapped.
+  DeviceAddress  -  The resulting map address for the bus master device to use to access the
+                    hosts HostAddress.
+  Mapping        -  A resulting value to pass to Unmap().
+
+Returns:
+  
+  EFI_SUCCESS            -  The range was mapped for the returned NumberOfBytes. 
+  EFI_INVALID_PARAMETER  -  The Operation or HostAddress is undefined. 
+  EFI_UNSUPPORTED        -  The HostAddress cannot be mapped as a common buffer.
+  EFI_DEVICE_ERROR       -  The system hardware could not map the requested address. 
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of resources.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  if ((UINT32)Operation > EfiBusMasterCommonBuffer) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = Private->PciRootBridgeIo->Map (
+                                       Private->PciRootBridgeIo,
+                                       (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
+                                       (VOID *) (UINTN) (*HostAddress),
+                                       NumberOfBytes,
+                                       DeviceAddress,
+                                       Mapping
+                                       );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoUnmap (
+  IN EFI_DEVICE_IO_PROTOCOL   *This,
+  IN VOID                     *Mapping
+  )
+/*++
+
+Routine Description:
+  
+  Completes the Map() operation and releases any corresponding resources.
+
+Arguments:
+  
+  This     -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+  Mapping  -  The mapping value returned from Map().
+
+Returns:
+  
+  EFI_SUCCESS       -  The range was unmapped.
+  EFI_DEVICE_ERROR  -  The data was not committed to the target system memory.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  Status = Private->PciRootBridgeIo->Unmap (
+                                       Private->PciRootBridgeIo,
+                                       Mapping
+                                       );
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoAllocateBuffer (
+  IN     EFI_DEVICE_IO_PROTOCOL    *This,
+  IN     EFI_ALLOCATE_TYPE         Type,
+  IN     EFI_MEMORY_TYPE           MemoryType,
+  IN     UINTN                     Pages,
+  IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress
+  )
+/*++
+
+Routine Description:
+  
+  Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
+
+Arguments:
+  
+  This             -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+  Type             -  The type allocation to perform.
+  MemoryType       -  The type of memory to allocate, EfiBootServicesData or
+                      EfiRuntimeServicesData.
+  Pages            -  The number of pages to allocate.
+  PhysicalAddress  -  A pointer to store the base address of the allocated range.
+
+Returns:
+  
+  EFI_SUCCESS            -  The requested memory pages were allocated.
+  EFI_OUT_OF_RESOURCES   -  The memory pages could not be allocated.
+  EFI_INVALID_PARAMETER  -  The requested memory type is invalid.
+  EFI_UNSUPPORTED        -  The requested PhysicalAddress is not supported on
+                            this platform.
+
+--*/
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  HostAddress;
+
+  HostAddress = *PhysicalAddress;
+
+  if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UINT32)Type >= MaxAllocateType) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
+    Type        = AllocateMaxAddress;
+    HostAddress = MAX_COMMON_BUFFER;
+  }
+
+  Status = gBS->AllocatePages (
+                  Type,
+                  MemoryType,
+                  Pages,
+                  &HostAddress
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+
+  *PhysicalAddress = HostAddress;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoFlush (
+  IN EFI_DEVICE_IO_PROTOCOL  *This
+  )
+/*++
+
+Routine Description:
+  
+  Flushes any posted write data to the device.
+
+Arguments:
+  
+  This  -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+
+Returns:
+  
+  EFI_SUCCESS       -  The buffers were flushed.
+  EFI_DEVICE_ERROR  -  The buffers were not flushed due to a hardware error.
+
+--*/
+{
+  EFI_STATUS              Status;
+  DEVICE_IO_PRIVATE_DATA  *Private;
+
+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+  Status  = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoFreeBuffer (
+  IN EFI_DEVICE_IO_PROTOCOL   *This,
+  IN UINTN                    Pages,
+  IN EFI_PHYSICAL_ADDRESS     HostAddress
+  )
+/*++
+
+Routine Description:
+  
+  Frees pages that were allocated with AllocateBuffer().
+
+Arguments:
+  
+  This         -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+  Pages        -  The number of pages to free.
+  HostAddress  -  The base address of the range to free.
+
+Returns:
+  
+  EFI_SUCCESS            -  The requested memory pages were freed.
+  EFI_NOT_FOUND          -  The requested memory pages were not allocated with
+                            AllocateBuffer().               
+  EFI_INVALID_PARAMETER  -  HostAddress is not page aligned or Pages is invalid.
+
+--*/
+{
+  if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return gBS->FreePages (HostAddress, Pages);
+}
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h
new file mode 100644 (file)
index 0000000..9b48374
--- /dev/null
@@ -0,0 +1,449 @@
+/*++
+
+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.             
+
+Module Name:
+
+    DeviceIo.h
+    
+Abstract:
+
+    Private Data definition for Device IO driver
+
+--*/
+
+#ifndef _DEVICE_IO_H
+#define _DEVICE_IO_H
+
+
+
+#define DEVICE_IO_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('d', 'e', 'v', 'I')
+
+#define MAX_COMMON_BUFFER                 0x00000000FFFFFFFF
+
+typedef struct {
+  UINTN                           Signature;
+  EFI_HANDLE                      Handle;
+  EFI_DEVICE_IO_PROTOCOL          DeviceIo;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
+  UINT16                          PrimaryBus;
+  UINT16                          SubordinateBus;
+} DEVICE_IO_PRIVATE_DATA;
+
+#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)
+
+EFI_STATUS
+DeviceIoConstructor (
+  IN EFI_HANDLE                      Handle,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+  IN EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
+  IN UINT16                          PrimaryBus,
+  IN UINT16                          SubordinateBus
+  )
+/*++
+
+Routine Description:
+
+  Initialize and install a Device IO protocol on a empty device path handle.
+
+Arguments:
+
+  Handle               - Handle of PCI RootBridge IO instance
+  PciRootBridgeIo      - PCI RootBridge IO instance
+  DevicePath           - Device Path of PCI RootBridge IO instance
+  PrimaryBus           - Primary Bus
+  SubordinateBus       - Subordinate Bus
+
+Returns:
+
+  EFI_SUCCESS          -  This driver is added to ControllerHandle.  
+  EFI_ALREADY_STARTED  -  This driver is already running on ControllerHandle.   
+  Others               -  This driver does not support this device.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemRead (
+  IN     EFI_DEVICE_IO_PROTOCOL *This,
+  IN     EFI_IO_WIDTH           Width,
+  IN     UINT64                 Address,
+  IN     UINTN                  Count,
+  IN OUT VOID                   *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform reading memory mapped I/O space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations.
+  Address  -  The base address of I/O operations.  
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.           
+  Buffer   -  The destination buffer to store results.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was read from the device.  
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemWrite (
+  IN     EFI_DEVICE_IO_PROTOCOL *This,
+  IN     EFI_IO_WIDTH           Width,
+  IN     UINT64                 Address,
+  IN     UINTN                  Count,
+  IN OUT VOID                   *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform writing memory mapped I/O space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations.  
+  Address  -  The base address of I/O operations.   
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.            
+  Buffer   -  The source buffer of data to be written.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was written to the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoRead (
+  IN     EFI_DEVICE_IO_PROTOCOL *This,
+  IN     EFI_IO_WIDTH           Width,
+  IN     UINT64                 Address,
+  IN     UINTN                  Count,
+  IN OUT VOID                   *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform reading I/O space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations.
+  Address  -  The base address of I/O operations. 
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.          
+  Buffer   -  The destination buffer to store results.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was read from the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoWrite (
+  IN     EFI_DEVICE_IO_PROTOCOL *This,
+  IN     EFI_IO_WIDTH           Width,
+  IN     UINT64                 Address,
+  IN     UINTN                  Count,
+  IN OUT VOID                   *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform writing I/O space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations.
+  Address  -  The base address of I/O operations.
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.        
+  Buffer   -  The source buffer of data to be written.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was written to the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciRead (
+  IN     EFI_DEVICE_IO_PROTOCOL *This,
+  IN     EFI_IO_WIDTH           Width,
+  IN     UINT64                 Address,
+  IN     UINTN                  Count,
+  IN OUT VOID                   *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform reading PCI configuration space of device
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  
+  Width    -  Width of I/O operations. 
+  Address  -  The base address of I/O operations. 
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.           
+  Buffer   -  The destination buffer to store results.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was read from the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciWrite (
+  IN     EFI_DEVICE_IO_PROTOCOL *This,
+  IN     EFI_IO_WIDTH           Width,
+  IN     UINT64                 Address,
+  IN     UINTN                  Count,
+  IN OUT VOID                   *Buffer
+  )
+/*++
+
+Routine Description:
+  
+  Perform writing PCI configuration space of device.
+
+Arguments:
+  
+  This     -  A pointer to EFI_DEVICE_IO protocol instance.   
+  Width    -  Width of I/O operations. 
+  Address  -  The base address of I/O operations. 
+  Count    -  The number of I/O operations to perform. 
+              Bytes moves is Width size * Count, starting at Address.         
+  Buffer   -  The source buffer of data to be written.
+
+Returns:
+    
+  EFI_SUCCESS            -  The data was written to the device.
+  EFI_INVALID_PARAMETER  -  Width is invalid.
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciDevicePath (
+  IN     EFI_DEVICE_IO_PROTOCOL        *This,
+  IN     UINT64                        Address,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath
+  )
+/*++
+
+Routine Description:
+  
+  Append a PCI device path node to another device path.
+
+Arguments:
+  
+  This                  -  A pointer to EFI_DEVICE_IO_PROTOCOL.  
+  Address               -  PCI bus,device, function.
+  PciDevicePath         -  PCI device path.
+
+Returns:
+  
+  Pointer to the appended PCI device path.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMap (
+  IN     EFI_DEVICE_IO_PROTOCOL   *This,
+  IN     EFI_IO_OPERATION_TYPE    Operation,
+  IN     EFI_PHYSICAL_ADDRESS     *HostAddress,
+  IN OUT UINTN                    *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,
+  OUT    VOID                     **Mapping
+  )
+/*++
+
+Routine Description:
+  
+  Provides the device-specific addresses needed to access system memory.
+
+Arguments:
+  
+  This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance. 
+  Operation      -  Indicates if the bus master is going to read or write to system memory.  
+  HostAddress    -  The system memory address to map to the device.
+  NumberOfBytes  -  On input the number of bytes to map. On output the number of bytes
+                    that were mapped.
+  DeviceAddress  -  The resulting map address for the bus master device to use to access the
+                    hosts HostAddress.
+  Mapping        -  A resulting value to pass to Unmap().
+
+Returns:
+  
+  EFI_SUCCESS            -  The range was mapped for the returned NumberOfBytes. 
+  EFI_INVALID_PARAMETER  -  The Operation or HostAddress is undefined. 
+  EFI_UNSUPPORTED        -  The HostAddress cannot be mapped as a common buffer.
+  EFI_DEVICE_ERROR       -  The system hardware could not map the requested address. 
+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoUnmap (
+  IN EFI_DEVICE_IO_PROTOCOL   *This,
+  IN VOID                     *Mapping
+  )
+/*++
+
+Routine Description:
+  
+  Completes the Map() operation and releases any corresponding resources.
+
+Arguments:
+  
+  This     -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+  Mapping  -  The mapping value returned from Map().
+
+Returns:
+  
+  EFI_SUCCESS       -  The range was unmapped.
+  EFI_DEVICE_ERROR  -  The data was not committed to the target system memory.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoAllocateBuffer (
+  IN     EFI_DEVICE_IO_PROTOCOL    *This,
+  IN     EFI_ALLOCATE_TYPE         Type,
+  IN     EFI_MEMORY_TYPE           MemoryType,
+  IN     UINTN                     Pages,
+  IN OUT EFI_PHYSICAL_ADDRESS      *HostAddress
+  )
+/*++
+
+Routine Description:
+  
+  Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
+
+Arguments:
+  
+  This             -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+  Type             -  The type allocation to perform.
+  MemoryType       -  The type of memory to allocate, EfiBootServicesData or
+                      EfiRuntimeServicesData.
+  Pages            -  The number of pages to allocate.
+  HostAddress      -  A pointer to store the base address of the allocated range.
+
+Returns:
+  
+  EFI_SUCCESS            -  The requested memory pages were allocated.
+  EFI_OUT_OF_RESOURCES   -  The memory pages could not be allocated.
+  EFI_INVALID_PARAMETER  -  The requested memory type is invalid.
+  EFI_UNSUPPORTED        -  The requested PhysicalAddress is not supported on
+                            this platform.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoFlush (
+  IN EFI_DEVICE_IO_PROTOCOL  *This
+  )
+/*++
+
+Routine Description:
+  
+  Flushes any posted write data to the device.
+
+Arguments:
+  
+  This  -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+
+Returns:
+  
+  EFI_SUCCESS       -  The buffers were flushed.
+  EFI_DEVICE_ERROR  -  The buffers were not flushed due to a hardware error.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoFreeBuffer (
+  IN EFI_DEVICE_IO_PROTOCOL   *This,
+  IN UINTN                    Pages,
+  IN EFI_PHYSICAL_ADDRESS     HostAddress
+  )
+/*++
+
+Routine Description:
+  
+  Frees pages that were allocated with AllocateBuffer().
+
+Arguments:
+  
+  This         -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+  Pages        -  The number of pages to free.
+  HostAddress  -  The base address of the range to free.
+
+Returns:
+  
+  EFI_SUCCESS            -  The requested memory pages were freed.
+  EFI_NOT_FOUND          -  The requested memory pages were not allocated with
+                            AllocateBuffer().               
+  EFI_INVALID_PARAMETER  -  HostAddress is not page aligned or Pages is invalid.
+
+--*/
+;
+
+#endif
+
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c
new file mode 100644 (file)
index 0000000..63ea892
--- /dev/null
@@ -0,0 +1,738 @@
+/*++
+
+Copyright (c) 2005 - 2012, 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.             
+
+Module Name:
+    PcatPciRootBridgeIo.c
+    
+Abstract:
+
+    EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+BOOLEAN                  mPciOptionRomTableInstalled = FALSE;
+EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable          = {0, NULL};
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *UserBuffer
+  )
+{
+  return gCpuIo->Io.Read (
+                      gCpuIo,
+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+                      UserAddress,
+                      Count,
+                      UserBuffer
+                      );
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoWrite (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 UserAddress,
+  IN UINTN                                  Count,
+  IN OUT VOID                               *UserBuffer
+  )
+{
+  return gCpuIo->Io.Write (
+                      gCpuIo,
+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+                      UserAddress,
+                      Count,
+                      UserBuffer
+                      );
+
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+  OUT EFI_PHYSICAL_ADDRESS  *IoPortMapping,
+  OUT EFI_PHYSICAL_ADDRESS  *MemoryPortMapping
+  )
+/*++
+
+  Get the IO Port Mapping.  For IA-32 it is always 0.
+  
+--*/
+{
+  *IoPortMapping = 0;
+  *MemoryPortMapping = 0;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN BOOLEAN                                Write,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 UserAddress,
+  IN UINTN                                  Count,
+  IN OUT VOID                               *UserBuffer
+  )
+{
+  PCI_CONFIG_ACCESS_CF8             Pci;
+  PCI_CONFIG_ACCESS_CF8             PciAligned;
+  UINT32                            InStride;
+  UINT32                            OutStride;
+  UINTN                             PciData;
+  UINTN                             PciDataStride;
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE     *PrivateData;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  PciAddress;
+  UINT64                            PciExpressRegAddr;
+  BOOLEAN                           UsePciExpressAccess;
+
+  if ((UINT32)Width >= EfiPciWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  if ((Width & 0x03) >= EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  InStride    = 1 << (Width & 0x03);
+  OutStride   = InStride;
+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+    InStride = 0;
+  }
+
+  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+    OutStride = 0;
+  }
+
+  UsePciExpressAccess = FALSE;
+
+  CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
+
+  if (PciAddress.ExtendedRegister > 0xFF) {
+    //
+    // Check PciExpressBaseAddress
+    //
+    if ((PrivateData->PciExpressBaseAddress == 0) ||
+        (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {
+      return EFI_UNSUPPORTED;
+    } else {
+      UsePciExpressAccess = TRUE;
+    }
+  } else {
+    if (PciAddress.ExtendedRegister != 0) {
+      Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
+    } else {
+      Pci.Bits.Reg = PciAddress.Register;
+    }
+    //
+    // Note: We can also use PciExpress access here, if wanted.
+    //
+  }
+
+  if (!UsePciExpressAccess) {
+    Pci.Bits.Func     = PciAddress.Function;
+    Pci.Bits.Dev      = PciAddress.Device;
+    Pci.Bits.Bus      = PciAddress.Bus;
+    Pci.Bits.Reserved = 0;
+    Pci.Bits.Enable   = 1;
+
+    //
+    // PCI Config access are all 32-bit alligned, but by accessing the
+    //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+    //  are possible on PCI.
+    //
+    // To read a byte of PCI config space you load 0xcf8 and 
+    //  read 0xcfc, 0xcfd, 0xcfe, 0xcff
+    //
+    PciDataStride = Pci.Bits.Reg & 0x03;
+
+    while (Count) {
+      PciAligned = Pci;
+      PciAligned.Bits.Reg &= 0xfc;
+      PciData = (UINTN)PrivateData->PciData + PciDataStride;
+      EfiAcquireLock(&PrivateData->PciLock);
+      This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
+      if (Write) {
+        This->Io.Write (This, Width, PciData, 1, UserBuffer);
+      } else {
+        This->Io.Read (This, Width, PciData, 1, UserBuffer);
+      }
+      EfiReleaseLock(&PrivateData->PciLock);
+      UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
+      PciDataStride = (PciDataStride + InStride) % 4;
+      Pci.Bits.Reg += InStride;
+      Count -= 1;
+    }
+  } else {
+    //
+    // Access PCI-Express space by using memory mapped method.
+    //
+    PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
+                        (PciAddress.Bus      << 20) |
+                        (PciAddress.Device   << 15) |
+                        (PciAddress.Function << 12);
+    if (PciAddress.ExtendedRegister != 0) {
+      PciExpressRegAddr += PciAddress.ExtendedRegister;
+    } else {
+      PciExpressRegAddr += PciAddress.Register;
+    }
+    while (Count) {
+      if (Write) {
+        This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+      } else {
+        This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+      }
+
+      UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
+      PciExpressRegAddr += InStride;
+      Count -= 1;
+    }
+  }
+  
+  return EFI_SUCCESS;
+}
+
+VOID
+ScanPciBus(
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  EFI_PCI_BUS_SCAN_CALLBACK        Callback,
+  VOID                             *Context
+  )
+  
+{
+  UINT16      Bus;
+  UINT16      Device;
+  UINT16      Func;
+  UINT64      Address;
+  PCI_TYPE00  PciHeader;
+
+  //
+  // Loop through all busses
+  //
+  for (Bus = MinBus; Bus <= MaxBus; Bus++) {
+    //  
+    // Loop 32 devices per bus
+    //
+    for (Device = MinDevice; Device <= MaxDevice; Device++) {
+      //
+      // Loop through 8 functions per device
+      //
+      for (Func = MinFunc; Func <= MaxFunc; Func++) {
+
+        //
+        // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
+        //
+        Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+        //
+        // Read the VendorID from this PCI Device's Confioguration Header
+        //
+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
+    
+        //
+        // If VendorId = 0xffff, there does not exist a device at this 
+        // location. For each device, if there is any function on it, 
+        // there must be 1 function at Function 0. So if Func = 0, there
+        // will be no more functions in the same device, so we can break
+        // loop to deal with the next device.
+        //  
+        if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
+          break;
+        }
+        
+        if (PciHeader.Hdr.VendorId != 0xffff) {
+
+          //
+          // Read the HeaderType to determine if this is a multi-function device
+          //
+          IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
+
+          //
+          // Call the callback function for the device that was found
+          //
+          Callback(
+            IoDev, 
+            MinBus, MaxBus,
+            MinDevice, MaxDevice,
+            MinFunc, MaxFunc,
+            Bus,
+            Device,
+            Func,
+            Context
+            );
+
+          //
+          // If this is not a multi-function device, we can leave the loop 
+          // to deal with the next device.
+          //
+          if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
+            break;
+          }
+        }  
+      }
+    }
+  }
+}
+
+VOID
+CheckForRom (
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  UINT16                           Bus,
+  UINT16                           Device,
+  UINT16                           Func,
+  IN VOID                          *VoidContext
+  )
+{
+  EFI_STATUS                                 Status;
+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
+  UINT64                                     Address;
+  PCI_TYPE00                                 PciHeader;
+  PCI_TYPE01                                 *PciBridgeHeader;
+  UINT32                                     Register;
+  UINT32                                     RomBar;
+  UINT32                                     RomBarSize;
+  EFI_PHYSICAL_ADDRESS                       RomBuffer;
+  UINT32                                     MaxRomSize;
+  EFI_PCI_EXPANSION_ROM_HEADER               EfiRomHeader;
+  PCI_DATA_STRUCTURE                         Pcir;
+  EFI_PCI_OPTION_ROM_DESCRIPTOR              *TempPciOptionRomDescriptors;
+  BOOLEAN                                    LastImage;
+
+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+  //
+  // Save the contents of the PCI Configuration Header
+  //
+  IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+
+  if (IS_PCI_BRIDGE(&PciHeader)) {
+
+    PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
+
+    //
+    // See if the PCI-PCI Bridge has its secondary interface enabled.
+    //
+    if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
+
+      //
+      // Disable the Prefetchable Memory Window
+      //
+      Register = 0x00000000;
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
+      Register = 0xffffffff;
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
+
+      //
+      // Program Memory Window to the PCI Root Bridge Memory Window
+      //
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
+
+      //
+      // Enable the Memory decode for the PCI-PCI Bridge
+      //
+      IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+      Register |= 0x02;
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+      //
+      // Recurse on the Secondary Bus Number
+      //
+      ScanPciBus(
+        IoDev,
+        PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, 
+        0, PCI_MAX_DEVICE, 
+        0, PCI_MAX_FUNC, 
+        CheckForRom, Context
+        );
+    }
+  } else {
+
+    //
+    // Check if an Option ROM Register is present and save the Option ROM Window Register
+    //
+    RomBar = 0xffffffff;
+    IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+    IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+
+    RomBarSize = (~(RomBar & 0xfffff800)) + 1;
+
+    //
+    // Make sure the size of the ROM is between 0 and 16 MB
+    //
+    if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
+
+      //
+      // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
+      //
+      RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
+      RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
+      if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
+        MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
+        RomBar = RomBar + 1;
+        IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+        IoDev->Pci.Read  (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+        RomBar = RomBar - 1;
+
+        //
+        // Enable the Memory decode for the PCI Device
+        //
+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+        Register |= 0x02;
+        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+        //
+        // Follow the chain of images to determine the size of the Option ROM present
+        // Keep going until the last image is found by looking at the Indicator field
+        // or the size of an image is 0, or the size of all the images is bigger than the
+        // size of the window programmed into the PPB.
+        //
+        RomBarSize = 0;
+        do {
+
+          LastImage = TRUE;
+
+          ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
+          IoDev->Mem.Read (
+            IoDev, 
+            EfiPciWidthUint8, 
+            RomBar + RomBarSize, 
+            sizeof(EfiRomHeader),
+            &EfiRomHeader
+            );
+
+          Pcir.ImageLength = 0;
+
+          if (EfiRomHeader.Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&
+              EfiRomHeader.PcirOffset != 0 &&
+              (EfiRomHeader.PcirOffset & 3) == 0 &&
+              RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {
+            ZeroMem (&Pcir, sizeof(Pcir));
+            IoDev->Mem.Read (
+              IoDev, 
+              EfiPciWidthUint8, 
+              RomBar + RomBarSize + EfiRomHeader.PcirOffset, 
+              sizeof(Pcir),
+              &Pcir
+              );
+
+            if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+              break;
+            }
+            if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {
+              break;
+            }
+            if ((Pcir.Indicator & 0x80) == 0x00) {
+              LastImage = FALSE;
+            }
+
+            RomBarSize += Pcir.ImageLength * 512;
+          }
+        } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
+
+        if (RomBarSize > 0) {
+
+          //
+          // Allocate a memory buffer for the Option ROM contents.
+          //
+          Status = gBS->AllocatePages(
+                          AllocateAnyPages,
+                          EfiBootServicesData,
+                          EFI_SIZE_TO_PAGES(RomBarSize),
+                          &RomBuffer
+                          );
+
+          if (!EFI_ERROR (Status)) {
+
+            //
+            // Copy the contents of the Option ROM to the memory buffer
+            //
+            IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
+
+            Status = gBS->AllocatePool(
+                            EfiBootServicesData,
+                            ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
+                            (VOID*)&TempPciOptionRomDescriptors
+                            );
+            if (mPciOptionRomTable.PciOptionRomCount > 0) {
+              CopyMem(
+                TempPciOptionRomDescriptors, 
+                mPciOptionRomTable.PciOptionRomDescriptors, 
+                (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
+                );
+
+              gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
+            }
+
+            mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; 
+
+            TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
+
+            TempPciOptionRomDescriptors->RomAddress              = RomBuffer;
+            TempPciOptionRomDescriptors->MemoryType              = EfiBootServicesData;
+            TempPciOptionRomDescriptors->RomLength               = RomBarSize;
+            TempPciOptionRomDescriptors->Seg                     = (UINT32)IoDev->SegmentNumber;
+            TempPciOptionRomDescriptors->Bus                     = (UINT8)Bus;
+            TempPciOptionRomDescriptors->Dev                     = (UINT8)Device;
+            TempPciOptionRomDescriptors->Func                    = (UINT8)Func;
+            TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
+            TempPciOptionRomDescriptors->DontLoadEfiRom          = FALSE;
+
+            mPciOptionRomTable.PciOptionRomCount++;
+          }
+        }
+
+        //
+        // Disable the Memory decode for the PCI-PCI Bridge
+        //
+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+        Register &= (~0x02);
+        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+      }
+    }
+  }
+
+  //
+  // Restore the PCI Configuration Header 
+  //
+  IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+}
+
+VOID
+SaveCommandRegister (
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  UINT16                           Bus,
+  UINT16                           Device,
+  UINT16                           Func,
+  IN VOID                          *VoidContext
+  )
+
+{
+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
+  UINT64  Address;
+  UINTN   Index;
+  UINT16  Command;
+
+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+  IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+
+  //
+  // Clear the memory enable bit
+  //
+  Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));
+
+  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
+}
+
+VOID
+RestoreCommandRegister (
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  UINT16                           Bus,
+  UINT16                           Device,
+  UINT16                           Func,
+  IN VOID                          *VoidContext
+  )
+
+{
+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
+  UINT64                                     Address;
+  UINTN                                      Index;
+
+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev
+  )
+  
+{
+  EFI_STATUS                                 Status;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR          *Descriptors; 
+  UINT16                                     MinBus;
+  UINT16                                     MaxBus;
+  UINT64                                     RootWindowBase;
+  UINT64                                     RootWindowLimit;
+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  Context;
+
+  if (mPciOptionRomTableInstalled == FALSE) {
+    gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
+    mPciOptionRomTableInstalled = TRUE;
+  }
+
+  Status = IoDev->Configuration(IoDev, (VOID **)&Descriptors);
+  if (EFI_ERROR (Status) || Descriptors == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  MinBus = 0xffff;
+  MaxBus = 0xffff;
+  RootWindowBase  = 0;
+  RootWindowLimit = 0;
+  while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
+    //
+    // Find bus range
+    //
+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+      MinBus = (UINT16)Descriptors->AddrRangeMin;
+      MaxBus = (UINT16)Descriptors->AddrRangeMax;
+    }
+    //
+    // Find memory descriptors that are not prefetchable
+    //
+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
+      //
+      // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
+      //
+      if (Descriptors->AddrRangeMax < 0x100000000ULL) {
+        //
+        // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
+        //
+        if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
+          RootWindowBase  = Descriptors->AddrRangeMin;
+          RootWindowLimit = Descriptors->AddrRangeMax;
+        }
+      }
+    }
+    Descriptors ++;
+  }
+
+  //
+  // Make sure a bus range was found
+  //
+  if (MinBus == 0xffff || MaxBus == 0xffff) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Make sure a non-prefetchable memory region was found
+  //
+  if (RootWindowBase == 0 && RootWindowLimit == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Round the Base and Limit values to 1 MB boudaries
+  //
+  RootWindowBase  = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
+  RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
+
+  //
+  // Make sure that the size of the rounded window is greater than zero
+  //
+  if (RootWindowLimit <= RootWindowBase) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Allocate buffer to save the Command register from all the PCI devices
+  //
+  Context.CommandRegisterBuffer = NULL;
+  Status = gBS->AllocatePool(
+                  EfiBootServicesData,
+                  sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
+                  (VOID **)&Context.CommandRegisterBuffer
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Context.PpbMemoryWindow   = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
+
+  //
+  // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
+  //
+  ScanPciBus(
+    IoDev,
+    MinBus, MaxBus, 
+    0, PCI_MAX_DEVICE, 
+    0, PCI_MAX_FUNC, 
+    SaveCommandRegister, &Context
+    );
+
+  //
+  // Recursively scan all the busses for PCI Option ROMs
+  //
+  ScanPciBus(
+    IoDev,
+    MinBus, MinBus, 
+    0, PCI_MAX_DEVICE, 
+    0, PCI_MAX_FUNC, 
+    CheckForRom, &Context
+    );
+
+  //
+  // Restore the Command register in all the PCI devices
+  //
+  ScanPciBus(
+    IoDev,
+    MinBus, MaxBus, 
+    0, PCI_MAX_DEVICE, 
+    0, PCI_MAX_FUNC, 
+    RestoreCommandRegister, &Context
+    );
+
+  //
+  // Free the buffer used to save all the Command register values
+  //
+  gBS->FreePool(Context.CommandRegisterBuffer);
+
+  return EFI_SUCCESS;
+}
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c
new file mode 100644 (file)
index 0000000..f4a7ffa
--- /dev/null
@@ -0,0 +1,459 @@
+/*++
+
+Copyright (c) 2005 - 2012, 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.             
+
+Module Name:
+    PcatPciRootBridgeIo.c
+    
+Abstract:
+
+    EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+#include <IndustryStandard/Pci.h>
+#include "SalProc.h"
+
+#include EFI_GUID_DEFINITION (SalSystemTable)
+
+//
+// Might be good to put this in an include file, but people may start
+//  using it! They should always access the EFI abstraction that is
+//  contained in this file. Just a little information hiding.
+//
+#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )
+                                                                           
+//                                                                  
+// Macro's with casts make this much easier to use and read.
+//
+#define PORT_TO_MEM8(_Port)     (*(UINT8  *)(PORT_TO_MEM(_Port)))
+#define PORT_TO_MEM16(_Port)    (*(UINT16 *)(PORT_TO_MEM(_Port)))
+#define PORT_TO_MEM32(_Port)    (*(UINT32 *)(PORT_TO_MEM(_Port)))
+
+#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \
+    ( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )
+
+//
+// Local variables for performing SAL Proc calls
+//
+PLABEL         mSalProcPlabel;
+CALL_SAL_PROC  mGlobalSalProc;
+
+EFI_STATUS
+PcatRootBridgeIoIoRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *UserBuffer
+  )
+{
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+  UINTN                         InStride;
+  UINTN                         OutStride;
+  UINTN                         AlignMask;
+  UINTN                         Address;
+  PTR                           Buffer;
+  UINT16                        Data16;
+  UINT32                        Data32;
+  
+  if ( UserBuffer == NULL ) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  Address    = (UINTN)  UserAddress;
+  Buffer.buf = (UINT8 *)UserBuffer;
+
+  if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
+    return EFI_INVALID_PARAMETER;
+  }
+    
+  if ((UINT32)Width >= EfiPciWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Width & 0x03) == EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AlignMask = (1 << (Width & 0x03)) - 1;
+  if ( Address & AlignMask ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InStride  = 1 << (Width & 0x03);
+  OutStride = InStride;
+  if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+    InStride = 0;
+  }
+  if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+    OutStride = 0;
+  }
+  Width = Width & 0x03;
+
+  Address += PrivateData->PhysicalIoBase;
+
+  //
+  // Loop for each iteration and move the data
+  //
+
+  switch (Width) {
+  case EfiPciWidthUint8:
+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+      MEMORY_FENCE();
+      *Buffer.ui8 = PORT_TO_MEM8(Address);
+      MEMORY_FENCE();
+    }
+    break;
+
+  case EfiPciWidthUint16:
+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+      MEMORY_FENCE();
+      if (Buffer.ui & 0x1) {
+        Data16 = PORT_TO_MEM16(Address);
+        *Buffer.ui8     = (UINT8)(Data16 & 0xff);
+        *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);
+      } else {
+        *Buffer.ui16 = PORT_TO_MEM16(Address);
+      }
+      MEMORY_FENCE();
+    }
+    break;
+
+  case EfiPciWidthUint32:
+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+      MEMORY_FENCE();
+      if (Buffer.ui & 0x3) {
+        Data32 = PORT_TO_MEM32(Address);
+        *Buffer.ui8     = (UINT8)(Data32 & 0xff);
+        *(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);
+        *(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);
+        *(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);
+      } else {
+        *Buffer.ui32 = PORT_TO_MEM32(Address);
+      }
+      MEMORY_FENCE();
+    }
+    break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoIoWrite (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 UserAddress,
+  IN UINTN                                  Count,
+  IN OUT VOID                               *UserBuffer
+  )
+{
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+  UINTN                          InStride;
+  UINTN                          OutStride;
+  UINTN                          AlignMask;
+  UINTN                          Address;
+  PTR                            Buffer;
+  UINT16                         Data16;
+  UINT32                         Data32;
+
+  if ( UserBuffer == NULL ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  Address    = (UINTN)  UserAddress;
+  Buffer.buf = (UINT8 *)UserBuffer;
+
+  if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
+    return EFI_INVALID_PARAMETER;
+  }
+    
+  if (Width < 0 || Width >= EfiPciWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Width & 0x03) == EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AlignMask = (1 << (Width & 0x03)) - 1;
+  if ( Address & AlignMask ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InStride  = 1 << (Width & 0x03);
+  OutStride = InStride;
+  if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+    InStride = 0;
+  }
+  if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+    OutStride = 0;
+  }
+  Width = Width & 0x03;
+
+  Address += PrivateData->PhysicalIoBase;
+
+  //
+  // Loop for each iteration and move the data
+  //
+
+  switch (Width) {
+  case EfiPciWidthUint8:
+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+      MEMORY_FENCE();
+      PORT_TO_MEM8(Address) = *Buffer.ui8;
+      MEMORY_FENCE();
+    }
+    break;
+
+  case EfiPciWidthUint16:
+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+      MEMORY_FENCE();
+      if (Buffer.ui & 0x1) {
+        Data16 = *Buffer.ui8;
+        Data16 = Data16 | (*(Buffer.ui8+1) << 8);
+        PORT_TO_MEM16(Address) = Data16;
+      } else {
+        PORT_TO_MEM16(Address) = *Buffer.ui16;
+      }
+      MEMORY_FENCE();
+    }
+    break;
+  case EfiPciWidthUint32:
+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+      MEMORY_FENCE();
+      if (Buffer.ui & 0x3) {
+        Data32 = *Buffer.ui8;
+        Data32 = Data32 | (*(Buffer.ui8+1) << 8);
+        Data32 = Data32 | (*(Buffer.ui8+2) << 16);
+        Data32 = Data32 | (*(Buffer.ui8+3) << 24);
+        PORT_TO_MEM32(Address) = Data32;
+      } else {
+        PORT_TO_MEM32(Address) = *Buffer.ui32;
+      }
+      MEMORY_FENCE();
+    }
+    break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+  OUT EFI_PHYSICAL_ADDRESS  *IoPortMapping,
+  OUT EFI_PHYSICAL_ADDRESS  *MemoryPortMapping
+  )
+/*++
+
+  Get the IO Port Map from the SAL System Table.
+  
+--*/
+{
+  SAL_SYSTEM_TABLE_ASCENDING_ORDER    *SalSystemTable;
+  SAL_ST_MEMORY_DESCRIPTOR_ENTRY      *SalMemDesc;
+  EFI_STATUS                          Status;
+
+  //
+  // On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations
+  //
+  *MemoryPortMapping = 0x8000000000000000;
+
+  Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);
+  if (EFI_ERROR(Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // BugBug: Add code to test checksum on the Sal System Table
+  //
+  if (SalSystemTable->Entry0.Type != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry; 
+  mSalProcPlabel.GP             = SalSystemTable->Entry0.GlobalDataPointer;
+  mGlobalSalProc                = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;
+
+  //
+  // The SalSystemTable pointer includes the Type 0 entry.
+  //  The SalMemDesc is Type 1 so it comes next.
+  //
+  SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);
+  while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {
+    if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {
+      *IoPortMapping = SalMemDesc->PhysicalMemoryAddress;
+      *IoPortMapping |= 0x8000000000000000;
+      return EFI_SUCCESS;
+    }
+    SalMemDesc++;
+  }
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     BOOLEAN                                Write,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN OUT UINT8                                  *UserBuffer
+  )
+{
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+  UINTN                          AlignMask;
+  UINTN                          InStride;
+  UINTN                          OutStride;
+  UINT64                         Address;
+  DEFIO_PCI_ADDR                 *Defio;
+  PTR                            Buffer;
+  UINT32                         Data32;
+  UINT16                         Data16;
+  rArg                           Return;
+
+  if (Width < 0 || Width >= EfiPciWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Width & 0x03) == EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AlignMask = (1 << (Width & 0x03)) - 1;
+  if ( UserAddress & AlignMask ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InStride  = 1 << (Width & 0x03);
+  OutStride = InStride;
+  if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+    InStride = 0;
+  }
+  if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+    OutStride = 0;
+  }
+  Width = Width & 0x03;
+
+  Defio = (DEFIO_PCI_ADDR *)&UserAddress;
+
+  if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {
+    return EFI_UNSUPPORTED;
+  }
+  
+  Buffer.buf = (UINT8 *)UserBuffer;
+  
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  Address = EFI_PCI_ADDRESS_IA64(
+              This->SegmentNumber, 
+              Defio->Bus, 
+              Defio->Device, 
+              Defio->Function, 
+              Defio->Register
+              );
+
+  //
+  // PCI Config access are all 32-bit alligned, but by accessing the
+  //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+  //  are possible on PCI.
+  //
+  // SalProc takes care of reading the proper register depending on stride
+  //
+
+  EfiAcquireLock(&PrivateData->PciLock);
+
+  while (Count) {
+
+    if(Write) {
+
+      if (Buffer.ui & 0x3) {
+        Data32  = (*(Buffer.ui8+0) << 0);
+        Data32 |= (*(Buffer.ui8+1) << 8);
+        Data32 |= (*(Buffer.ui8+2) << 16);
+        Data32 |= (*(Buffer.ui8+3) << 24);
+      } else {
+        Data32 = *Buffer.ui32;
+      }
+
+      Return.p0 = -3;
+      Return    = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,
+                                 Address, 1 << Width, Data32, 0, 0, 0, 0);
+        
+      if(Return.p0) {
+        EfiReleaseLock(&PrivateData->PciLock);
+        return EFI_UNSUPPORTED;
+      }
+
+    } else {
+
+      Return.p0 = -3;
+      Return    = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,
+                                 Address, 1 << Width, 0, 0, 0, 0, 0);
+
+      if(Return.p0) {
+        EfiReleaseLock(&PrivateData->PciLock);
+        return EFI_UNSUPPORTED;
+      }
+
+      switch (Width) {
+      case EfiPciWidthUint8:
+        *Buffer.ui8 = (UINT8)Return.p1;
+        break;
+      case EfiPciWidthUint16:
+        if (Buffer.ui & 0x1) {
+          Data16 = (UINT16)Return.p1;
+          *(Buffer.ui8 + 0) = Data16 & 0xff;
+          *(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;
+        } else {
+          *Buffer.ui16 = (UINT16)Return.p1;
+        }
+        break;
+      case EfiPciWidthUint32:
+        if (Buffer.ui & 0x3) {
+          Data32 = (UINT32)Return.p1;
+          *(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);
+          *(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);
+          *(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);
+          *(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);
+        } else {
+          *Buffer.ui32 = (UINT32)Return.p1;
+        }
+        break;
+      }
+    }
+
+    Address += InStride;
+    Buffer.buf += OutStride;
+    Count -= 1;
+  }
+  
+  EfiReleaseLock(&PrivateData->PciLock);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev
+  )
+  
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
new file mode 100644 (file)
index 0000000..e76db54
--- /dev/null
@@ -0,0 +1,1009 @@
+/*++
+
+Copyright (c) 2005 - 2009, 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.             
+
+Module Name:
+  PcatPciRootBridge.c
+    
+Abstract:
+
+    EFI PC-AT PCI Root Bridge Controller
+
+--*/
+
+#include "PcatPciRootBridge.h"
+#include "DeviceIo.h"
+
+EFI_CPU_IO2_PROTOCOL *gCpuIo;
+
+EFI_STATUS
+EFIAPI
+InitializePcatPciRootBridge (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+/*++
+
+Routine Description:
+  Initializes the PCI Root Bridge Controller
+
+Arguments:
+  ImageHandle -
+  SystemTable -
+    
+Returns:
+    None
+
+--*/
+{
+  EFI_STATUS                     Status;
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+  UINTN                          PciSegmentIndex;
+  UINTN                          PciRootBridgeIndex;
+  UINTN                          PrimaryBusIndex;
+  UINTN                          NumberOfPciRootBridges;
+  UINTN                          NumberOfPciDevices;
+  UINTN                          Device;
+  UINTN                          Function;
+  UINT16                         VendorId;
+  PCI_TYPE01                     PciConfigurationHeader;
+  UINT64                         Address;
+  UINT64                         Value;
+  UINT64                         Base;
+  UINT64                         Limit;
+
+  //
+  // Initialize gCpuIo now since the chipset init code requires it.
+  //
+  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&gCpuIo);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Initialize variables required to search all PCI segments for PCI devices
+  //
+  PciSegmentIndex        = 0;
+  PciRootBridgeIndex     = 0;
+  NumberOfPciRootBridges = 0;
+  PrimaryBusIndex        = 0;
+
+  while (PciSegmentIndex <= PCI_MAX_SEGMENT) {
+
+    PrivateData = NULL;
+    Status = gBS->AllocatePool(
+                    EfiBootServicesData,
+                    sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),
+                    (VOID **)&PrivateData
+                    );
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));
+
+    //
+    // Initialize the signature of the private data structure
+    //
+    PrivateData->Signature  = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;
+    PrivateData->Handle     = NULL;
+    PrivateData->DevicePath = NULL;
+    InitializeListHead (&PrivateData->MapInfo);
+
+    //
+    // Initialize the PCI root bridge number and the bus range for that root bridge
+    //
+    PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;
+    PrivateData->PrimaryBus       = (UINT32)PrimaryBusIndex;
+    PrivateData->SubordinateBus   = (UINT32)PrimaryBusIndex;
+
+    PrivateData->IoBase      = 0xffffffff;
+    PrivateData->MemBase     = 0xffffffff;
+    PrivateData->Mem32Base   = 0xffffffffffffffffULL;
+    PrivateData->Pmem32Base  = 0xffffffffffffffffULL;
+    PrivateData->Mem64Base   = 0xffffffffffffffffULL;
+    PrivateData->Pmem64Base  = 0xffffffffffffffffULL;
+
+    //
+    // The default mechanism for performing PCI Configuration cycles is to 
+    // use the I/O ports at 0xCF8 and 0xCFC.  This is only used for IA-32.
+    // IPF uses SAL calls to perform PCI COnfiguration cycles
+    //
+    PrivateData->PciAddress  = 0xCF8;
+    PrivateData->PciData     = 0xCFC;
+
+    //
+    // Get the physical I/O base for performing PCI I/O cycles
+    // For IA-32, this is always 0, because IA-32 has IN and OUT instructions
+    // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles
+    //
+    Status = PcatRootBridgeIoGetIoPortMapping (
+               &PrivateData->PhysicalIoBase, 
+               &PrivateData->PhysicalMemoryBase
+               );
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    //
+    // Get PCI Express Base Address
+    //
+    PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);
+    if (PrivateData->PciExpressBaseAddress != 0) {
+      DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));
+    }
+
+    //
+    // Create a lock for performing PCI Configuration cycles
+    //
+    EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
+
+    //
+    // Initialize the attributes for this PCI root bridge
+    //
+    PrivateData->Attributes  = 0;
+
+    //
+    // Build the EFI Device Path Protocol instance for this PCI Root Bridge
+    //
+    Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (BOOLEAN)((PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE));
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    //
+    // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge
+    //
+    Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+    
+    //
+    // Scan all the PCI devices on the primary bus of the PCI root bridge
+    //
+    for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
+    
+      for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
+
+        //
+        // Compute the PCI configuration address of the PCI device to probe
+        //
+        Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);
+
+        //
+        // Read the Vendor ID from the PCI Configuration Header
+        //
+        Status = PrivateData->Io.Pci.Read (
+                                       &PrivateData->Io, 
+                                       EfiPciWidthUint16, 
+                                       Address, 
+                                       sizeof (VendorId) / sizeof (UINT16), 
+                                       &VendorId
+                                       );
+        if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {
+          //
+          // If the PCI Configuration Read fails, or a PCI device does not exist, then 
+          // skip this entire PCI device
+          //
+          break;
+        }
+        if (VendorId == 0xffff) {
+          //
+          // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.
+          //
+          continue;
+        }
+
+        //
+        // Read the entire PCI Configuration Header
+        //
+        Status = PrivateData->Io.Pci.Read (
+                                       &PrivateData->Io, 
+                                       EfiPciWidthUint16, 
+                                       Address, 
+                                       sizeof (PciConfigurationHeader) / sizeof (UINT16), 
+                                       &PciConfigurationHeader
+                                       );
+        if (EFI_ERROR (Status)) {
+          //
+          // If the entire PCI Configuration Header can not be read, then skip this entire PCI device
+          //
+          break;
+        }
+
+
+        //
+        // Increment the number of PCI device found on the primary bus of the PCI root bridge
+        //
+        NumberOfPciDevices++;
+
+        //
+        // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
+        //
+        if (PciConfigurationHeader.Hdr.Command & 0x20) {
+          PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+        }
+
+        //
+        // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
+        //
+        if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
+          //
+          // Get the Bus range that the PPB is decoding
+          //
+          if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {
+            //
+            // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
+            // current subordinate bus number, then update the PCI root bridge's subordinate bus number 
+            //
+            PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;
+          }
+
+          //
+          // Get the I/O range that the PPB is decoding
+          //
+          Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;
+          Base  = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;
+          Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
+          if (Value == 0x01) {
+            Base  |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);
+            Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);
+          }
+          if (Base < Limit) {
+            if (PrivateData->IoBase > Base) {
+              PrivateData->IoBase = Base;
+            }
+            if (PrivateData->IoLimit < Limit) {
+              PrivateData->IoLimit = Limit;
+            }
+          }
+
+          //
+          // Get the Memory range that the PPB is decoding
+          //
+          Base  = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;
+          Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
+          if (Base < Limit) {
+            if (PrivateData->MemBase > Base) {
+              PrivateData->MemBase = Base;
+            }
+            if (PrivateData->MemLimit < Limit) {
+              PrivateData->MemLimit = Limit;
+            }
+            if (PrivateData->Mem32Base > Base) {
+              PrivateData->Mem32Base = Base;
+            }
+            if (PrivateData->Mem32Limit < Limit) {
+              PrivateData->Mem32Limit = Limit;
+            }
+          }
+
+          //
+          // Get the Prefetchable Memory range that the PPB is decoding
+          //
+          Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;
+          Base  = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
+          Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;
+          if (Value == 0x01) {
+            Base  |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);
+            Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);
+          }
+          if (Base < Limit) {
+            if (PrivateData->MemBase > Base) {
+              PrivateData->MemBase = Base;
+            }
+            if (PrivateData->MemLimit < Limit) {
+              PrivateData->MemLimit = Limit;
+            }
+            if (Value == 0x00) {
+              if (PrivateData->Pmem32Base > Base) {
+                PrivateData->Pmem32Base = Base;
+              }
+              if (PrivateData->Pmem32Limit < Limit) {
+                PrivateData->Pmem32Limit = Limit;
+              }
+            }
+            if (Value == 0x01) {
+              if (PrivateData->Pmem64Base > Base) {
+                PrivateData->Pmem64Base = Base;
+              }
+              if (PrivateData->Pmem64Limit < Limit) {
+                PrivateData->Pmem64Limit = Limit;
+              }
+            }
+          }
+
+          //
+          // Look at the PPB Configuration for legacy decoding attributes
+          //
+          if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+          }
+          if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+          }
+
+        } else {
+          //
+          // Parse the BARs of the PCI device to determine what I/O Ranges,
+          // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
+          //
+          if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
+            Status = PcatPciRootBridgeParseBars (
+                       PrivateData, 
+                       PciConfigurationHeader.Hdr.Command,
+                       PrimaryBusIndex, 
+                       Device, 
+                       Function
+                       );
+          }
+
+          //
+          // See if the PCI device is an IDE controller
+          //
+          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
+              PciConfigurationHeader.Hdr.ClassCode[1] == 0x01    ) {
+            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
+            }
+            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
+            }
+            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
+            }
+          }
+
+          //
+          // See if the PCI device is a legacy VGA controller
+          //
+          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
+              PciConfigurationHeader.Hdr.ClassCode[1] == 0x01    ) {
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+          }
+
+          //
+          // See if the PCI device is a standard VGA controller
+          //
+          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
+              PciConfigurationHeader.Hdr.ClassCode[1] == 0x00    ) {
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+          }
+
+          //
+          // See if the PCI Device is a PCI - ISA or PCI - EISA 
+          // or ISA_POSITIVIE_DECODE Bridge device
+          //
+          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {
+            if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||
+                PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 || 
+                PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {
+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+
+              if (PrivateData->MemBase > 0xa0000) {
+                PrivateData->MemBase = 0xa0000;
+              }
+              if (PrivateData->MemLimit < 0xbffff) {
+               PrivateData->MemLimit = 0xbffff;
+             }
+            }
+          }
+        }
+
+        //
+        // If this device is not a multi function device, then skip the rest of this PCI device
+        //
+        if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
+          break;
+        }
+      }
+    }
+
+    //
+    // After scanning all the PCI devices on the PCI root bridge's primary bus, update the 
+    // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
+    // bus number + 1.
+    //
+    PrimaryBusIndex = PrivateData->SubordinateBus + 1;
+
+    //
+    // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
+    // exists.
+    //
+    if (NumberOfPciDevices > 0) {
+
+      //
+      // Adjust the I/O range used for bounds checking for the legacy decoding attributed
+      //
+      if (PrivateData->Attributes & 0x7f) {
+        PrivateData->IoBase = 0;
+        if (PrivateData->IoLimit < 0xffff) {
+          PrivateData->IoLimit = 0xffff;
+        }
+      }
+
+      //
+      // Adjust the Memory range used for bounds checking for the legacy decoding attributed
+      //
+      if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {
+        if (PrivateData->MemBase > 0xa0000) {
+          PrivateData->MemBase = 0xa0000;
+        }
+        if (PrivateData->MemLimit < 0xbffff) {
+          PrivateData->MemLimit = 0xbffff;
+        }
+      }
+
+      //
+      // Build ACPI descriptors for the resources on the PCI Root Bridge
+      //
+      Status = ConstructConfiguration(PrivateData);
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // Create the handle for this PCI Root Bridge 
+      //
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                     &PrivateData->Handle,              
+                     &gEfiDevicePathProtocolGuid,
+                     PrivateData->DevicePath,
+                     &gEfiPciRootBridgeIoProtocolGuid,
+                     &PrivateData->Io,
+                     NULL
+                     );
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // Contruct DeviceIoProtocol
+      //
+      Status = DeviceIoConstructor (
+                 PrivateData->Handle,
+                 &PrivateData->Io,
+                 PrivateData->DevicePath,
+                 (UINT16)PrivateData->PrimaryBus,
+                 (UINT16)PrivateData->SubordinateBus
+                 );
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
+      //
+      Status = ScanPciRootBridgeForRoms(&PrivateData->Io);
+
+      //
+      // Increment the index for the next PCI Root Bridge
+      //
+      PciRootBridgeIndex++;
+
+    } else {
+
+      //
+      // If no PCI Root Bridges were found on the current PCI segment, then exit
+      //
+      if (NumberOfPciRootBridges == 0) {
+        Status = EFI_SUCCESS;
+        goto Done;
+      }
+
+    }
+
+    //
+    // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
+    // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
+    // Otherwise, the search is continued on the next PCI Root Bridge
+    //
+    if (PrimaryBusIndex > PCI_MAX_BUS) {
+      PciSegmentIndex++;
+      NumberOfPciRootBridges = 0;
+      PrimaryBusIndex = 0;
+    } else {
+      NumberOfPciRootBridges++;
+    }
+
+  }
+
+  return EFI_SUCCESS;
+
+Done:
+  //
+  // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
+  //
+  if (PrivateData) {
+    if (PrivateData->DevicePath) {
+      gBS->FreePool(PrivateData->DevicePath);
+    }
+    gBS->FreePool (PrivateData);
+  }
+
+  //
+  // If no PCI Root Bridges were discovered, then return the error condition from scanning the
+  // first PCI Root Bridge
+  //
+  if (PciRootBridgeIndex == 0) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS 
+ConstructConfiguration(
+  IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS                         Status;
+  UINT8                              NumConfig;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Configuration;
+  EFI_ACPI_END_TAG_DESCRIPTOR        *ConfigurationEnd;
+
+  NumConfig = 0;
+  PrivateData->Configuration = NULL;
+
+  if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
+    NumConfig++;
+  }
+  if (PrivateData->IoLimit >= PrivateData->IoBase) {
+    NumConfig++;
+  }
+  if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
+    NumConfig++;
+  }
+  if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
+    NumConfig++;
+  }
+  if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
+    NumConfig++;
+  }
+  if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
+    NumConfig++;
+  }
+
+  if ( NumConfig == 0 ) {
+
+    //
+    // If there is no resource request
+    //
+    Status = gBS->AllocatePool (
+                    EfiBootServicesData, 
+                    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+                    (VOID **)&PrivateData->Configuration
+                    );
+    if (EFI_ERROR (Status )) {
+      return Status;
+    }
+
+    Configuration = PrivateData->Configuration;
+    
+    ZeroMem (
+      Configuration, 
+      sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) 
+      );
+    
+    Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Configuration->Len  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+    Configuration++;
+
+    ConfigurationEnd       = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
+    ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+    ConfigurationEnd->Checksum = 0;
+  }
+
+  //
+  // If there is at least one type of resource request,
+  // allocate a acpi resource node 
+  //
+  Status = gBS->AllocatePool (
+                  EfiBootServicesData, 
+                  sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+                  (VOID **)&PrivateData->Configuration
+                  );
+  if (EFI_ERROR (Status )) {
+    return Status;
+  }
+  
+  Configuration = PrivateData->Configuration;
+
+  ZeroMem (
+    Configuration, 
+    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+    );
+
+  if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
+    Configuration->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Configuration->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+    Configuration->ResType      = ACPI_ADDRESS_SPACE_TYPE_BUS;
+    Configuration->SpecificFlag = 0; 
+    Configuration->AddrRangeMin = PrivateData->PrimaryBus;
+    Configuration->AddrRangeMax = PrivateData->SubordinateBus;
+    Configuration->AddrLen      = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+    Configuration++;
+  }
+  //
+  // Deal with io aperture
+  //
+  if (PrivateData->IoLimit >= PrivateData->IoBase) {
+    Configuration->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Configuration->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+    Configuration->ResType      = ACPI_ADDRESS_SPACE_TYPE_IO;
+    Configuration->SpecificFlag = 1; //non ISA range
+    Configuration->AddrRangeMin = PrivateData->IoBase;
+    Configuration->AddrRangeMax = PrivateData->IoLimit;
+    Configuration->AddrLen      = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+    Configuration++;
+  }
+
+  //
+  // Deal with mem32 aperture
+  //
+  if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
+    Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+    Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
+    Configuration->SpecificFlag         = 0; //Nonprefechable
+    Configuration->AddrSpaceGranularity = 32; //32 bit
+    Configuration->AddrRangeMin         = PrivateData->Mem32Base;
+    Configuration->AddrRangeMax         = PrivateData->Mem32Limit;
+    Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+    Configuration++;
+  } 
+
+  //
+  // Deal with Pmem32 aperture
+  //
+  if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
+    Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+    Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
+    Configuration->SpecificFlag         = 0x6; //prefechable
+    Configuration->AddrSpaceGranularity = 32; //32 bit
+    Configuration->AddrRangeMin         = PrivateData->Pmem32Base;
+    Configuration->AddrRangeMax         = PrivateData->Pmem32Limit;
+    Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+    Configuration++;
+  }
+
+  //
+  // Deal with mem64 aperture
+  //
+  if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
+    Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+    Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
+    Configuration->SpecificFlag         = 0; //nonprefechable
+    Configuration->AddrSpaceGranularity = 64; //32 bit
+    Configuration->AddrRangeMin         = PrivateData->Mem64Base;
+    Configuration->AddrRangeMax         = PrivateData->Mem64Limit;
+    Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+    Configuration++;
+  }
+
+  //
+  // Deal with Pmem64 aperture
+  //
+  if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
+    Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+    Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
+    Configuration->SpecificFlag         = 0x06; //prefechable
+    Configuration->AddrSpaceGranularity = 64; //32 bit
+    Configuration->AddrRangeMin         = PrivateData->Pmem64Base;
+    Configuration->AddrRangeMax         = PrivateData->Pmem64Limit;
+    Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+    Configuration++;
+  }
+
+  //
+  // put the checksum
+  //
+  ConfigurationEnd           = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
+  ConfigurationEnd->Desc     = ACPI_END_TAG_DESCRIPTOR;
+  ConfigurationEnd->Checksum = 0;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS 
+PcatPciRootBridgeBarExisted (
+  IN  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,
+  IN  UINT64                         Address,
+  OUT UINT32                         *OriginalValue,
+  OUT UINT32                         *Value
+  ) 
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS  Status;
+  UINT32      AllOnes;
+  EFI_TPL     OldTpl;
+
+  //
+  // Preserve the original value
+  //
+  Status = PrivateData->Io.Pci.Read (
+                                 &PrivateData->Io, 
+                                 EfiPciWidthUint32, 
+                                 Address, 
+                                 1, 
+                                 OriginalValue
+                                 );
+
+  //
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed
+  //
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  AllOnes = 0xffffffff;
+
+  Status = PrivateData->Io.Pci.Write (
+                                 &PrivateData->Io, 
+                                 EfiPciWidthUint32, 
+                                 Address, 
+                                 1, 
+                                 &AllOnes
+                                 );
+  Status = PrivateData->Io.Pci.Read (
+                                 &PrivateData->Io, 
+                                 EfiPciWidthUint32, 
+                                 Address, 
+                                 1, 
+                                 Value
+                                 );
+
+  //
+  //Write back the original value
+  //
+  Status = PrivateData->Io.Pci.Write (
+                                 &PrivateData->Io, 
+                                 EfiPciWidthUint32, 
+                                 Address, 
+                                 1, 
+                                 OriginalValue
+                                 );
+
+  //
+  // Restore TPL to its original level
+  //
+  gBS->RestoreTPL (OldTpl);
+
+  if ( *Value == 0 ) {
+    return EFI_DEVICE_ERROR;
+  }
+  return Status;
+}
+
+EFI_STATUS
+PcatPciRootBridgeParseBars (
+  IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,
+  IN UINT16                         Command,
+  IN UINTN                          Bus,
+  IN UINTN                          Device,
+  IN UINTN                          Function
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS  Status;
+  UINT64      Address;
+  UINT32      OriginalValue;
+  UINT32      Value;
+  UINT32      OriginalUpperValue;
+  UINT32      UpperValue;
+  UINT64      Mask;
+  UINTN       Offset;
+  UINT64      Base;
+  UINT64      Length;
+  UINT64      Limit;
+
+  for (Offset = 0x10; Offset < 0x28; Offset += 4) {
+    Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
+    Status = PcatPciRootBridgeBarExisted (
+               PrivateData,
+               Address,
+               &OriginalValue,
+               &Value
+               );
+
+    if (!EFI_ERROR (Status )) {
+      if ( Value & 0x01 ) { 
+        if (Command & 0x0001) {
+          //
+          //Device I/Os
+          //
+          Mask = 0xfffffffc;
+          Base = OriginalValue & Mask;
+          Length = ((~(Value & Mask)) & Mask) + 0x04;
+          if (!(Value & 0xFFFF0000)){
+            Length &= 0x0000FFFF;
+          }
+          Limit = Base + Length - 1;
+
+          if (Base < Limit) {
+            if (PrivateData->IoBase > Base) {
+              PrivateData->IoBase = (UINT32)Base;
+            }
+            if (PrivateData->IoLimit < Limit) {
+              PrivateData->IoLimit = (UINT32)Limit;
+            }
+          }
+        }
+   
+      } else {
+
+        if (Command & 0x0002) {
+
+          Mask = 0xfffffff0;
+          Base = OriginalValue & Mask;
+          Length = Value & Mask;
+          if ((Value & 0x07) != 0x04) {
+            Length = ((~Length) + 1) & 0xffffffff;
+          } else {
+            Offset += 4; 
+            Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
+
+            Status = PcatPciRootBridgeBarExisted (
+                       PrivateData,
+                       Address,
+                       &OriginalUpperValue,
+                       &UpperValue
+                       );
+
+            Base   = Base | LShiftU64((UINT64)OriginalUpperValue,32);
+            Length = Length | LShiftU64((UINT64)UpperValue,32);
+            Length = (~Length) + 1;
+          }
+
+          Limit = Base + Length - 1;
+
+          if (Base < Limit) {
+            if (PrivateData->MemBase > Base) {
+              PrivateData->MemBase = Base;
+            }
+            if (PrivateData->MemLimit < Limit) {
+              PrivateData->MemLimit = Limit;
+            }
+
+            switch (Value &0x07) {
+            case 0x00: ////memory space; anywhere in 32 bit address space
+              if (Value & 0x08) {
+                if (PrivateData->Pmem32Base > Base) {
+                  PrivateData->Pmem32Base = Base;
+                }
+                if (PrivateData->Pmem32Limit < Limit) {
+                  PrivateData->Pmem32Limit = Limit;
+                }
+              } else {
+                if (PrivateData->Mem32Base > Base) {
+                  PrivateData->Mem32Base = Base;
+                }
+                if (PrivateData->Mem32Limit < Limit) {
+                  PrivateData->Mem32Limit = Limit;
+                }
+              }
+              break;
+            case 0x04: //memory space; anywhere in 64 bit address space
+              if (Value & 0x08) {
+                if (PrivateData->Pmem64Base > Base) {
+                  PrivateData->Pmem64Base = Base;
+                }
+                if (PrivateData->Pmem64Limit < Limit) {
+                  PrivateData->Pmem64Limit = Limit;
+                }
+              } else {
+                if (PrivateData->Mem64Base > Base) {
+                  PrivateData->Mem64Base = Base;
+                }
+                if (PrivateData->Mem64Limit < Limit) {
+                  PrivateData->Mem64Limit = Limit;
+                }
+              }
+              break;
+            }
+          }
+        }
+      }
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+UINT64
+GetPciExpressBaseAddressForRootBridge (
+  IN UINTN    HostBridgeNumber,
+  IN UINTN    RootBridgeNumber
+  )
+/*++
+
+Routine Description:
+  This routine is to get PciExpress Base Address for this RootBridge
+
+Arguments:
+  HostBridgeNumber - The number of HostBridge
+  RootBridgeNumber - The number of RootBridge
+    
+Returns:
+  UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
+
+--*/
+{
+  EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
+  UINTN                                    BufferSize;
+  UINT32                                   Index;
+  UINT32                                   Number;
+  EFI_PEI_HOB_POINTERS                     GuidHob;
+
+  //
+  // Get PciExpressAddressInfo Hob
+  //
+  PciExpressBaseAddressInfo = NULL;
+  BufferSize                = 0;
+  GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid);
+  if (GuidHob.Raw != NULL) {
+    PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
+    BufferSize                = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
+  } else {
+    return 0;
+  }
+
+  //
+  // Search the PciExpress Base Address in the Hob for current RootBridge
+  //
+  Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
+  for (Index = 0; Index < Number; Index++) {
+    if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
+        (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
+      return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
+    }
+  }
+
+  //
+  // Do not find the PciExpress Base Address in the Hob
+  //
+  return 0;
+}
+
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h
new file mode 100644 (file)
index 0000000..6cb86c7
--- /dev/null
@@ -0,0 +1,244 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+  PcatPciRootBridge.h
+
+Abstract:
+
+  The driver for the host to pci bridge (root bridge).
+
+--*/
+
+#ifndef _PCAT_PCI_ROOT_BRIDGE_H_
+#define _PCAT_PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/DeviceIo.h>
+#include <Protocol/CpuIo2.h>
+
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+
+#include <Guid/PciOptionRomTable.h>
+#include <Guid/HobList.h>
+#include <Guid/PciExpressBaseAddress.h>
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+
+#define PCI_MAX_SEGMENT   0
+//
+// Driver Instance Data Prototypes
+//
+#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE  SIGNATURE_32('p', 'c', 'r', 'b')
+
+typedef struct {
+  UINT32                            Signature;
+  EFI_HANDLE                        Handle;
+                                    
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   Io;
+  EFI_CPU_IO2_PROTOCOL              *CpuIo;
+
+  UINT32                            RootBridgeNumber;
+  UINT32                            PrimaryBus;
+  UINT32                            SubordinateBus;
+                                     
+  UINT64                            MemBase;     // Offsets host to bus memory addr.
+  UINT64                            MemLimit;    // Max allowable memory access
+                                    
+  UINT64                            IoBase;      // Offsets host to bus io addr.
+  UINT64                            IoLimit;     // Max allowable io access
+                                    
+  UINT64                            PciAddress;
+  UINT64                            PciData;
+                                    
+  UINT64                            PhysicalMemoryBase;
+  UINT64                            PhysicalIoBase;
+                                     
+  EFI_LOCK                          PciLock;
+                                    
+  UINT64                            Attributes;
+                                    
+  UINT64                            Mem32Base;
+  UINT64                            Mem32Limit;
+  UINT64                            Pmem32Base;
+  UINT64                            Pmem32Limit;
+  UINT64                            Mem64Base;
+  UINT64                            Mem64Limit;
+  UINT64                            Pmem64Base;
+  UINT64                            Pmem64Limit;
+
+  UINT64                            PciExpressBaseAddress;
+
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+
+  LIST_ENTRY                    MapInfo;
+} PCAT_PCI_ROOT_BRIDGE_INSTANCE;
+
+//
+// Driver Instance Data Macros
+//
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
+  CR(a, PCAT_PCI_ROOT_BRIDGE_INSTANCE, Io, PCAT_PCI_ROOT_BRIDGE_SIGNATURE)
+
+//
+// Private data types
+//
+typedef union {
+  UINT8   volatile  *buf;
+  UINT8   volatile  *ui8;
+  UINT16  volatile  *ui16;
+  UINT32  volatile  *ui32;
+  UINT64  volatile  *ui64;
+  UINTN   volatile  ui;
+} PTR;
+
+typedef struct {
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation;
+  UINTN                                      NumberOfBytes;
+  UINTN                                      NumberOfPages;
+  EFI_PHYSICAL_ADDRESS                       HostAddress;
+  EFI_PHYSICAL_ADDRESS                       MappedHostAddress;
+} MAP_INFO;
+
+typedef struct {
+  LIST_ENTRY Link;
+  MAP_INFO * Map;  
+} MAP_INFO_INSTANCE;
+
+typedef
+VOID
+(*EFI_PCI_BUS_SCAN_CALLBACK) (
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  UINT16                           Bus,
+  UINT16                           Device,
+  UINT16                           Func,
+  IN VOID                          *Context
+  );
+
+typedef struct {
+  UINT16                    *CommandRegisterBuffer;
+  UINT32                    PpbMemoryWindow;     
+} PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT;
+
+typedef struct {
+  UINT8 Register;
+  UINT8 Function;
+  UINT8 Device;
+  UINT8 Bus;
+  UINT8 Reserved[4];
+} DEFIO_PCI_ADDR;
+
+//
+// Driver Protocol Constructor Prototypes
+//
+EFI_STATUS 
+ConstructConfiguration(
+  IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData
+  );
+
+EFI_STATUS
+PcatPciRootBridgeParseBars (
+  IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,
+  IN UINT16                         Command,
+  IN UINTN                          Bus,
+  IN UINTN                          Device,
+  IN UINTN                          Function
+  );
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev
+  );
+
+EFI_STATUS
+PcatRootBridgeDevicePathConstructor (
+  IN EFI_DEVICE_PATH_PROTOCOL  **Protocol,
+  IN UINTN                     RootBridgeNumber,
+  IN BOOLEAN                   IsPciExpress
+  );
+
+EFI_STATUS
+PcatRootBridgeIoConstructor (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *Protocol,
+  IN UINTN                            SegmentNumber
+  );
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+  OUT EFI_PHYSICAL_ADDRESS  *IoPortMapping,
+  OUT EFI_PHYSICAL_ADDRESS  *MemoryPortMapping
+  );
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN BOOLEAN                                Write,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 UserAddress,
+  IN UINTN                                  Count,
+  IN OUT VOID                               *UserBuffer
+  );
+
+UINT64
+GetPciExpressBaseAddressForRootBridge (
+  IN UINTN    HostBridgeNumber,
+  IN UINTN    RootBridgeNumber
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *UserBuffer
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *UserBuffer
+  );
+
+//
+// Driver entry point prototype
+//
+EFI_STATUS
+EFIAPI
+InitializePcatPciRootBridge (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  );
+
+extern EFI_CPU_IO2_PROTOCOL  *gCpuIo;
+
+#endif
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c
new file mode 100644 (file)
index 0000000..dafa745
--- /dev/null
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) 2005 - 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.             
+
+Module Name:
+    PcatPciRootBridgeDevicePath.c
+    
+Abstract:
+
+    EFI PCAT PCI Root Bridge Device Path Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+//
+// Static device path declarations for this driver.
+//
+
+typedef struct {
+  ACPI_HID_DEVICE_PATH              AcpiDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL          EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
+  {
+    {
+      ACPI_DEVICE_PATH,
+      ACPI_DP,
+      {
+        (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+        (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),
+      }
+    },
+    EISA_PNP_ID(0x0A03),
+    0
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      END_DEVICE_PATH_LENGTH,
+      0
+    }
+  }
+};
+
+EFI_STATUS
+PcatRootBridgeDevicePathConstructor (
+  IN EFI_DEVICE_PATH_PROTOCOL  **Protocol,
+  IN UINTN                     RootBridgeNumber,
+  IN BOOLEAN                   IsPciExpress
+  )
+/*++
+
+Routine Description:
+
+    Construct the device path protocol
+
+Arguments:
+
+    Protocol - protocol to initialize
+    
+Returns:
+
+    None
+
+--*/
+{
+  ACPI_HID_DEVICE_PATH  *AcpiDevicePath;
+  *Protocol = DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(&mEfiPciRootBridgeDevicePath));
+
+  AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)(*Protocol);
+  AcpiDevicePath->UID = (UINT32)RootBridgeNumber;
+
+  if (IsPciExpress) {
+    AcpiDevicePath->HID = EISA_PNP_ID(0x0A08);
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c
new file mode 100644 (file)
index 0000000..a3ee478
--- /dev/null
@@ -0,0 +1,1036 @@
+/*++
+
+Copyright (c) 2005 - 2012, 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.             
+
+Module Name:
+    PcatPciRootBridgeIo.c
+    
+Abstract:
+
+    EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+//
+// Protocol Member Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollMem ( 
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  );
+  
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollIo ( 
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  );
+  
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoCopyMem (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 DestAddress,
+  IN UINT64                                 SrcAddress,
+  IN UINTN                                  Count
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMap (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoUnmap (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN VOID                             *Mapping
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoAllocateBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  EFI_ALLOCATE_TYPE                Type,
+  IN  EFI_MEMORY_TYPE                  MemoryType,
+  IN  UINTN                            Pages,
+  OUT VOID                             **HostAddress,
+  IN  UINT64                           Attributes
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFreeBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  UINTN                            Pages,
+  OUT VOID                             *HostAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFlush (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoGetAttributes (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT UINT64                           *Supported,
+  OUT UINT64                           *Attributes
+  );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoSetAttributes (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN     UINT64                           Attributes,
+  IN OUT UINT64                           *ResourceBase,
+  IN OUT UINT64                           *ResourceLength 
+  ); 
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoConfiguration (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT VOID                             **Resources
+  );
+
+//
+// Private Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRW (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINTN                                  Count,
+  IN  BOOLEAN                                InStrideFlag,
+  IN  PTR                                    In,
+  IN  BOOLEAN                                OutStrideFlag,
+  OUT PTR                                    Out
+  );
+
+EFI_STATUS
+PcatRootBridgeIoConstructor (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *Protocol,
+  IN UINTN                            SegmentNumber
+  )
+/*++
+
+Routine Description:
+
+    Contruct the Pci Root Bridge Io protocol
+
+Arguments:
+
+    Protocol - protocol to initialize
+    
+Returns:
+
+    None
+
+--*/
+{
+  Protocol->ParentHandle   = NULL;
+
+  Protocol->PollMem        = PcatRootBridgeIoPollMem;
+  Protocol->PollIo         = PcatRootBridgeIoPollIo;
+
+  Protocol->Mem.Read       = PcatRootBridgeIoMemRead;
+  Protocol->Mem.Write      = PcatRootBridgeIoMemWrite;
+
+  Protocol->Io.Read        = PcatRootBridgeIoIoRead;
+  Protocol->Io.Write       = PcatRootBridgeIoIoWrite;
+
+  Protocol->CopyMem        = PcatRootBridgeIoCopyMem;
+
+  Protocol->Pci.Read       = PcatRootBridgeIoPciRead;
+  Protocol->Pci.Write      = PcatRootBridgeIoPciWrite;
+
+  Protocol->Map            = PcatRootBridgeIoMap;
+  Protocol->Unmap          = PcatRootBridgeIoUnmap;
+
+  Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer;
+  Protocol->FreeBuffer     = PcatRootBridgeIoFreeBuffer;
+
+  Protocol->Flush          = PcatRootBridgeIoFlush;
+
+  Protocol->GetAttributes  = PcatRootBridgeIoGetAttributes;
+  Protocol->SetAttributes  = PcatRootBridgeIoSetAttributes;
+
+  Protocol->Configuration  = PcatRootBridgeIoConfiguration;
+
+  Protocol->SegmentNumber  = (UINT32)SegmentNumber;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollMem ( 
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      NumberOfTicks;
+  UINT32      Remainder;
+
+  if (Result == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+
+  if ((UINT32)Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+  //
+  // No matter what, always do a single poll.
+  //
+  Status = This->Mem.Read (This, Width, Address, 1, Result);
+  if ( EFI_ERROR(Status) ) {
+    return Status;
+  }    
+  if ( (*Result & Mask) == Value ) {
+    return EFI_SUCCESS;
+  }
+
+  if (Delay == 0) {
+    return EFI_SUCCESS;
+  } else {
+
+    NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
+    if ( Remainder !=0 ) {
+      NumberOfTicks += 1;
+    }
+    NumberOfTicks += 1;
+  
+    while ( NumberOfTicks ) {
+
+      gBS->Stall (10);
+
+      Status = This->Mem.Read (This, Width, Address, 1, Result);
+      if ( EFI_ERROR(Status) ) {
+        return Status;
+      }
+    
+      if ( (*Result & Mask) == Value ) {
+        return EFI_SUCCESS;
+      }
+
+      NumberOfTicks -= 1;
+    }
+  }
+  return EFI_TIMEOUT;
+}
+  
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollIo ( 
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      NumberOfTicks;
+  UINT32       Remainder;
+
+  if (Result == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UINT32)Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+  //
+  // No matter what, always do a single poll.
+  //
+  Status = This->Io.Read (This, Width, Address, 1, Result);
+  if ( EFI_ERROR(Status) ) {
+    return Status;
+  }    
+  if ( (*Result & Mask) == Value ) {
+    return EFI_SUCCESS;
+  }
+
+  if (Delay == 0) {
+    return EFI_SUCCESS;
+  } else {
+
+    NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
+    if ( Remainder !=0 ) {
+      NumberOfTicks += 1;
+    }
+    NumberOfTicks += 1;
+  
+    while ( NumberOfTicks ) {
+
+      gBS->Stall(10);
+    
+      Status = This->Io.Read (This, Width, Address, 1, Result);
+      if ( EFI_ERROR(Status) ) {
+        return Status;
+      }
+    
+      if ( (*Result & Mask) == Value ) {
+        return EFI_SUCCESS;
+      }
+
+      NumberOfTicks -= 1;
+    }
+  }
+  return EFI_TIMEOUT;
+}
+
+BOOLEAN
+PcatRootBridgeMemAddressValid (
+  IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,
+  IN UINT64                         Address
+  )
+{
+  if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {
+    return TRUE;
+  }
+  if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+{
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+  UINTN                          AlignMask;
+  PTR                            In;
+  PTR                            Out;
+
+  if ( Buffer == NULL ) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AlignMask = (1 << (Width & 0x03)) - 1;
+  if (Address & AlignMask) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Address += PrivateData->PhysicalMemoryBase;
+
+  In.buf  = Buffer;
+  Out.buf = (VOID *)(UINTN) Address;
+  if ((UINT32)Width <= EfiPciWidthUint64) {
+    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+  }
+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+  }
+  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+    return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+{
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+  UINTN  AlignMask;
+  PTR    In;
+  PTR    Out;
+
+  if ( Buffer == NULL ) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AlignMask = (1 << (Width & 0x03)) - 1;
+  if (Address & AlignMask) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Address += PrivateData->PhysicalMemoryBase;
+
+  In.buf  = (VOID *)(UINTN) Address;
+  Out.buf = Buffer;
+  if ((UINT32)Width <= EfiPciWidthUint64) {
+    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+  }
+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+    return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+  }
+  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoCopyMem (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 DestAddress,
+  IN UINT64                                 SrcAddress,
+  IN UINTN                                  Count
+  )
+
+{
+  EFI_STATUS  Status;
+  BOOLEAN     Direction;
+  UINTN       Stride;
+  UINTN       Index;
+  UINT64      Result;
+
+  if ((UINT32)Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }       
+
+  if (DestAddress == SrcAddress) {
+    return EFI_SUCCESS;
+  }
+
+  Stride = (UINTN)1 << Width;
+
+  Direction = TRUE;
+  if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+    Direction   = FALSE;
+    SrcAddress  = SrcAddress  + (Count-1) * Stride;
+    DestAddress = DestAddress + (Count-1) * Stride;
+  }
+
+  for (Index = 0;Index < Count;Index++) {
+    Status = PcatRootBridgeIoMemRead (
+               This,
+               Width,
+               SrcAddress,
+               1,
+               &Result
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    Status = PcatRootBridgeIoMemWrite (
+               This,
+               Width,
+               DestAddress,
+               1,
+               &Result
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    if (Direction) {
+      SrcAddress  += Stride;
+      DestAddress += Stride;
+    } else {
+      SrcAddress  -= Stride;
+      DestAddress -= Stride;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+{
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+{
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMap (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  )
+
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
+  MAP_INFO              *MapInfo;
+  MAP_INFO_INSTANCE    *MapInstance;
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+  if ( HostAddress == NULL || NumberOfBytes == NULL || 
+       DeviceAddress == NULL || Mapping == NULL ) {
+    
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Perform a fence operation to make sure all memory operations are flushed
+  //
+  MemoryFence();
+
+  //
+  // Initialize the return values to their defaults
+  //
+  *Mapping = NULL;
+
+  //
+  // Make sure that Operation is valid
+  //
+  if ((UINT32)Operation >= EfiPciOperationMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Most PCAT like chipsets can not handle performing DMA above 4GB.
+  // If any part of the DMA transfer being mapped is above 4GB, then
+  // map the DMA transfer to a buffer below 4GB.
+  //
+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+  if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {
+
+    //
+    // Common Buffer operations can not be remapped.  If the common buffer
+    // if above 4GB, then it is not possible to generate a mapping, so return 
+    // an error.
+    //
+    if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+      return EFI_UNSUPPORTED;
+    }
+
+    //
+    // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+    // called later.
+    //
+    Status = gBS->AllocatePool (
+                    EfiBootServicesData, 
+                    sizeof(MAP_INFO), 
+                    (VOID **)&MapInfo
+                    );
+    if (EFI_ERROR (Status)) {
+      *NumberOfBytes = 0;
+      return Status;
+    }
+
+    //
+    // Return a pointer to the MAP_INFO structure in Mapping
+    //
+    *Mapping = MapInfo;
+
+    //
+    // Initialize the MAP_INFO structure
+    //
+    MapInfo->Operation         = Operation;
+    MapInfo->NumberOfBytes     = *NumberOfBytes;
+    MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES(*NumberOfBytes);
+    MapInfo->HostAddress       = PhysicalAddress;
+    MapInfo->MappedHostAddress = 0x00000000ffffffff;
+
+    //
+    // Allocate a buffer below 4GB to map the transfer to.
+    //
+    Status = gBS->AllocatePages (
+                    AllocateMaxAddress, 
+                    EfiBootServicesData, 
+                    MapInfo->NumberOfPages,
+                    &MapInfo->MappedHostAddress
+                    );
+    if (EFI_ERROR(Status)) {
+      gBS->FreePool (MapInfo);
+      *NumberOfBytes = 0;
+      return Status;
+    }
+
+    //
+    // If this is a read operation from the Bus Master's point of view,
+    // then copy the contents of the real buffer into the mapped buffer
+    // so the Bus Master can read the contents of the real buffer.
+    //
+    if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
+      CopyMem (
+        (VOID *)(UINTN)MapInfo->MappedHostAddress, 
+        (VOID *)(UINTN)MapInfo->HostAddress,
+        MapInfo->NumberOfBytes
+        );
+    }
+
+
+  Status =gBS->AllocatePool (
+                    EfiBootServicesData, 
+                    sizeof(MAP_INFO_INSTANCE), 
+                    (VOID **)&MapInstance
+                    );                    
+    if (EFI_ERROR(Status)) {
+      gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);
+      gBS->FreePool (MapInfo);
+      *NumberOfBytes = 0;
+      return Status;
+    }
+
+    MapInstance->Map=MapInfo;
+    PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+    InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);
+    
+  //
+    // The DeviceAddress is the address of the maped buffer below 4GB
+    //
+    *DeviceAddress = MapInfo->MappedHostAddress;
+  } else {
+    //
+    // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
+    //
+    *DeviceAddress = PhysicalAddress;
+  }
+
+  //
+  // Perform a fence operation to make sure all memory operations are flushed
+  //
+  MemoryFence();
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoUnmap (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN VOID                             *Mapping
+  )
+
+{
+  MAP_INFO    *MapInfo;
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+  LIST_ENTRY *Link;
+
+  //
+  // Perform a fence operation to make sure all memory operations are flushed
+  //
+  MemoryFence();
+
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+  //
+  // See if the Map() operation associated with this Unmap() required a mapping buffer.
+  // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
+  //
+  if (Mapping != NULL) {
+    //
+    // Get the MAP_INFO structure from Mapping
+    //
+    MapInfo = (MAP_INFO *)Mapping;
+
+  for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {
+      if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)
+        break;
+    }
+
+    if (Link == &PrivateData->MapInfo) {
+      return EFI_INVALID_PARAMETER;
+  }
+
+    RemoveEntryList(Link);
+    ((MAP_INFO_INSTANCE*)Link)->Map = NULL;
+    gBS->FreePool((MAP_INFO_INSTANCE*)Link);
+
+    //
+    // If this is a write operation from the Bus Master's point of view,
+    // then copy the contents of the mapped buffer into the real buffer
+    // so the processor can read the contents of the real buffer.
+    //
+    if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
+      CopyMem (
+        (VOID *)(UINTN)MapInfo->HostAddress, 
+        (VOID *)(UINTN)MapInfo->MappedHostAddress,
+        MapInfo->NumberOfBytes
+        );
+    }
+
+    //
+    // Free the mapped buffer and the MAP_INFO structure.
+    //
+    gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
+    gBS->FreePool (Mapping);
+  }
+
+  //
+  // Perform a fence operation to make sure all memory operations are flushed
+  //
+  MemoryFence();
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoAllocateBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  EFI_ALLOCATE_TYPE                Type,
+  IN  EFI_MEMORY_TYPE                  MemoryType,
+  IN  UINTN                            Pages,
+  OUT VOID                             **HostAddress,
+  IN  UINT64                           Attributes
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
+
+  //
+  // Validate Attributes
+  //
+  if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check for invalid inputs
+  //
+  if (HostAddress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+  //
+  if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Limit allocations to memory below 4GB
+  //
+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
+
+  Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *HostAddress = (VOID *)(UINTN)PhysicalAddress;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFreeBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  UINTN                            Pages,
+  OUT VOID                             *HostAddress
+  )
+
+{
+
+  if( HostAddress == NULL ){
+     return EFI_INVALID_PARAMETER;
+  } 
+  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFlush (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
+  )
+
+{
+  //
+  // Perform a fence operation to make sure all memory operations are flushed
+  //
+  MemoryFence();
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoGetAttributes (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT UINT64                           *Supported,  OPTIONAL
+  OUT UINT64                           *Attributes
+  )
+
+{
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  if (Attributes == NULL && Supported == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Supported is an OPTIONAL parameter.  See if it is NULL
+  //
+  if (Supported) {
+    //
+    // This is a generic driver for a PC-AT class system.  It does not have any
+    // chipset specific knowlegde, so none of the attributes can be set or 
+    // cleared.  Any attempt to set attribute that are already set will succeed, 
+    // and any attempt to set an attribute that is not supported will fail.
+    //
+    *Supported = PrivateData->Attributes;
+  }
+
+  //
+  // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized
+  //
+  
+  if (Attributes) {
+    *Attributes = PrivateData->Attributes;
+  }
+  
+   
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoSetAttributes (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN     UINT64                           Attributes,
+  IN OUT UINT64                           *ResourceBase,
+  IN OUT UINT64                           *ResourceLength 
+  )
+
+{
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE   *PrivateData;
+  
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  //
+  // This is a generic driver for a PC-AT class system.  It does not have any
+  // chipset specific knowlegde, so none of the attributes can be set or 
+  // cleared.  Any attempt to set attribute that are already set will succeed, 
+  // and any attempt to set an attribute that is not supported will fail.
+  //
+  if (Attributes & (~PrivateData->Attributes)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoConfiguration (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT VOID                             **Resources
+  )
+
+{
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE   *PrivateData;
+  
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  *Resources = PrivateData->Configuration;
+
+  return EFI_SUCCESS;
+}
+
+//
+// Internal function
+//
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRW (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINTN                                  Count,
+  IN  BOOLEAN                                InStrideFlag,
+  IN  PTR                                    In,
+  IN  BOOLEAN                                OutStrideFlag,
+  OUT PTR                                    Out
+  )
+/*++
+
+Routine Description:
+
+  Private service to provide the memory read/write
+
+Arguments:
+
+  Width of the Memory Access
+  Count of the number of accesses to perform
+
+Returns:
+
+  Status
+
+  EFI_SUCCESS           - Successful transaction
+  EFI_INVALID_PARAMETER - Unsupported width and address combination
+
+--*/
+{
+  UINTN  Stride;
+  UINTN  InStride;
+  UINTN  OutStride;
+
+
+  Width     = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+  Stride    = (UINTN)1 << Width;
+  InStride  = InStrideFlag  ? Stride : 0;
+  OutStride = OutStrideFlag ? Stride : 0;
+
+  //
+  // Loop for each iteration and move the data
+  //
+  switch (Width) {
+  case EfiPciWidthUint8:
+    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+      MemoryFence();
+      *In.ui8 = *Out.ui8;
+      MemoryFence();
+    }
+    break;
+  case EfiPciWidthUint16:
+    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+      MemoryFence();
+      *In.ui16 = *Out.ui16;
+      MemoryFence();
+    }
+    break;
+  case EfiPciWidthUint32:
+    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+      MemoryFence();
+      *In.ui32 = *Out.ui32;
+      MemoryFence();
+    }
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
new file mode 100644 (file)
index 0000000..33f49b2
--- /dev/null
@@ -0,0 +1,69 @@
+## @file
+# 
+# Copyright (c) 2005 - 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.             
+#
+#  Module Name:
+#
+#  Abstract:
+#
+##
+
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PcatPciRootBridge
+  FILE_GUID                      = 0F7EC77A-1EE1-400f-A99D-7CBD1FEB181E
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = InitializePcatPciRootBridge
+
+[Packages]
+  MdePkg/MdePkg.dec
+  DuetPkg/DuetPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  DebugLib
+  BaseMemoryLib
+  DevicePathLib
+  HobLib
+
+[Sources]
+  PcatPciRootBridge.h
+  PcatPciRootBridge.c
+  PcatPciRootBridgeDevicePath.c
+  PcatPciRootBridgeIo.c
+  DeviceIo.h
+  DeviceIo.c
+
+[Sources.ia32]
+  Ia32/PcatIo.c
+  
+[Sources.x64]
+  X64/PcatIo.c
+
+[Sources.ipf]
+  Ipf/PcatIo.c
+
+[Protocols]
+  gEfiPciRootBridgeIoProtocolGuid
+  gEfiDeviceIoProtocolGuid
+  gEfiCpuIo2ProtocolGuid
+
+[Guids]
+  gEfiPciOptionRomTableGuid
+  gEfiPciExpressBaseAddressGuid
+
+[Depex]
+  gEfiCpuIo2ProtocolGuid
diff --git a/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/X64/PcatIo.c b/CorebootModulePkg/PciRootBridgeNoEnumerationDxe/X64/PcatIo.c
new file mode 100644 (file)
index 0000000..a675b36
--- /dev/null
@@ -0,0 +1,738 @@
+/*++
+
+Copyright (c) 2005 - 2012, 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.             
+
+Module Name:
+    PcatPciRootBridgeIo.c
+    
+Abstract:
+
+    EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+BOOLEAN                  mPciOptionRomTableInstalled = FALSE;
+EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable          = {0, NULL};
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *UserBuffer
+  )
+{
+  return gCpuIo->Io.Read (
+                      gCpuIo,
+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+                      UserAddress,
+                      Count,
+                      UserBuffer
+                      );
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoWrite (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 UserAddress,
+  IN UINTN                                  Count,
+  IN OUT VOID                               *UserBuffer
+  )
+{
+  return gCpuIo->Io.Write (
+                      gCpuIo,
+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+                      UserAddress,
+                      Count,
+                      UserBuffer
+                      );
+
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+  OUT EFI_PHYSICAL_ADDRESS  *IoPortMapping,
+  OUT EFI_PHYSICAL_ADDRESS  *MemoryPortMapping
+  )
+/*++
+
+  Get the IO Port Mapping.  For IA-32 it is always 0.
+  
+--*/
+{
+  *IoPortMapping = 0;
+  *MemoryPortMapping = 0;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN BOOLEAN                                Write,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 UserAddress,
+  IN UINTN                                  Count,
+  IN OUT VOID                               *UserBuffer
+  )
+{
+  PCI_CONFIG_ACCESS_CF8             Pci;
+  PCI_CONFIG_ACCESS_CF8             PciAligned;
+  UINT32                            InStride;
+  UINT32                            OutStride;
+  UINTN                             PciData;
+  UINTN                             PciDataStride;
+  PCAT_PCI_ROOT_BRIDGE_INSTANCE     *PrivateData;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  PciAddress;
+  UINT64                            PciExpressRegAddr;
+  BOOLEAN                           UsePciExpressAccess;
+
+  if ((UINT32)Width >= EfiPciWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  if ((Width & 0x03) >= EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+  InStride    = 1 << (Width & 0x03);
+  OutStride   = InStride;
+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+    InStride = 0;
+  }
+
+  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+    OutStride = 0;
+  }
+
+  UsePciExpressAccess = FALSE;
+
+  CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
+
+  if (PciAddress.ExtendedRegister > 0xFF) {
+    //
+    // Check PciExpressBaseAddress
+    //
+    if ((PrivateData->PciExpressBaseAddress == 0) ||
+        (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {
+      return EFI_UNSUPPORTED;
+    } else {
+      UsePciExpressAccess = TRUE;
+    }
+  } else {
+    if (PciAddress.ExtendedRegister != 0) {
+      Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
+    } else {
+      Pci.Bits.Reg = PciAddress.Register;
+    }
+    //
+    // Note: We can also use PciExpress access here, if wanted.
+    //
+  }
+
+  if (!UsePciExpressAccess) {
+    Pci.Bits.Func     = PciAddress.Function;
+    Pci.Bits.Dev      = PciAddress.Device;
+    Pci.Bits.Bus      = PciAddress.Bus;
+    Pci.Bits.Reserved = 0;
+    Pci.Bits.Enable   = 1;
+
+    //
+    // PCI Config access are all 32-bit alligned, but by accessing the
+    //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+    //  are possible on PCI.
+    //
+    // To read a byte of PCI config space you load 0xcf8 and 
+    //  read 0xcfc, 0xcfd, 0xcfe, 0xcff
+    //
+    PciDataStride = Pci.Bits.Reg & 0x03;
+
+    while (Count) {
+      PciAligned = Pci;
+      PciAligned.Bits.Reg &= 0xfc;
+      PciData = (UINTN)PrivateData->PciData + PciDataStride;
+      EfiAcquireLock(&PrivateData->PciLock);
+      This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
+      if (Write) {
+        This->Io.Write (This, Width, PciData, 1, UserBuffer);
+      } else {
+        This->Io.Read (This, Width, PciData, 1, UserBuffer);
+      }
+      EfiReleaseLock(&PrivateData->PciLock);
+      UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
+      PciDataStride = (PciDataStride + InStride) % 4;
+      Pci.Bits.Reg += InStride;
+      Count -= 1;
+    }
+  } else {
+    //
+    // Access PCI-Express space by using memory mapped method.
+    //
+    PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
+                        (PciAddress.Bus      << 20) |
+                        (PciAddress.Device   << 15) |
+                        (PciAddress.Function << 12);
+    if (PciAddress.ExtendedRegister != 0) {
+      PciExpressRegAddr += PciAddress.ExtendedRegister;
+    } else {
+      PciExpressRegAddr += PciAddress.Register;
+    }
+    while (Count) {
+      if (Write) {
+        This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+      } else {
+        This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+      }
+
+      UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
+      PciExpressRegAddr += InStride;
+      Count -= 1;
+    }
+  }
+  
+  return EFI_SUCCESS;
+}
+
+VOID
+ScanPciBus(
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  EFI_PCI_BUS_SCAN_CALLBACK        Callback,
+  VOID                             *Context
+  )
+  
+{
+  UINT16      Bus;
+  UINT16      Device;
+  UINT16      Func;
+  UINT64      Address;
+  PCI_TYPE00  PciHeader;
+
+  //
+  // Loop through all busses
+  //
+  for (Bus = MinBus; Bus <= MaxBus; Bus++) {
+    //  
+    // Loop 32 devices per bus
+    //
+    for (Device = MinDevice; Device <= MaxDevice; Device++) {
+      //
+      // Loop through 8 functions per device
+      //
+      for (Func = MinFunc; Func <= MaxFunc; Func++) {
+
+        //
+        // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
+        //
+        Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+        //
+        // Read the VendorID from this PCI Device's Confioguration Header
+        //
+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
+    
+        //
+        // If VendorId = 0xffff, there does not exist a device at this 
+        // location. For each device, if there is any function on it, 
+        // there must be 1 function at Function 0. So if Func = 0, there
+        // will be no more functions in the same device, so we can break
+        // loop to deal with the next device.
+        //  
+        if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
+          break;
+        }
+        
+        if (PciHeader.Hdr.VendorId != 0xffff) {
+
+          //
+          // Read the HeaderType to determine if this is a multi-function device
+          //
+          IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
+
+          //
+          // Call the callback function for the device that was found
+          //
+          Callback(
+            IoDev, 
+            MinBus, MaxBus,
+            MinDevice, MaxDevice,
+            MinFunc, MaxFunc,
+            Bus,
+            Device,
+            Func,
+            Context
+            );
+
+          //
+          // If this is not a multi-function device, we can leave the loop 
+          // to deal with the next device.
+          //
+          if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
+            break;
+          }
+        }  
+      }
+    }
+  }
+}
+
+VOID
+CheckForRom (
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  UINT16                           Bus,
+  UINT16                           Device,
+  UINT16                           Func,
+  IN VOID                          *VoidContext
+  )
+{
+  EFI_STATUS                                 Status;
+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
+  UINT64                                     Address;
+  PCI_TYPE00                                 PciHeader;
+  PCI_TYPE01                                 *PciBridgeHeader;
+  UINT32                                     Register;
+  UINT32                                     RomBar;
+  UINT32                                     RomBarSize;
+  EFI_PHYSICAL_ADDRESS                       RomBuffer;
+  UINT32                                     MaxRomSize;
+  EFI_PCI_EXPANSION_ROM_HEADER               EfiRomHeader;
+  PCI_DATA_STRUCTURE                         Pcir;
+  EFI_PCI_OPTION_ROM_DESCRIPTOR              *TempPciOptionRomDescriptors;
+  BOOLEAN                                    LastImage;
+
+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+  //
+  // Save the contents of the PCI Configuration Header
+  //
+  IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+
+  if (IS_PCI_BRIDGE(&PciHeader)) {
+
+    PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
+
+    //
+    // See if the PCI-PCI Bridge has its secondary interface enabled.
+    //
+    if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
+
+      //
+      // Disable the Prefetchable Memory Window
+      //
+      Register = 0x00000000;
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
+      Register = 0xffffffff;
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
+
+      //
+      // Program Memory Window to the PCI Root Bridge Memory Window
+      //
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
+
+      //
+      // Enable the Memory decode for the PCI-PCI Bridge
+      //
+      IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+      Register |= 0x02;
+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+      //
+      // Recurse on the Secondary Bus Number
+      //
+      ScanPciBus(
+        IoDev,
+        PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, 
+        0, PCI_MAX_DEVICE, 
+        0, PCI_MAX_FUNC, 
+        CheckForRom, Context
+        );
+    }
+  } else {
+
+    //
+    // Check if an Option ROM Register is present and save the Option ROM Window Register
+    //
+    RomBar = 0xffffffff;
+    IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+    IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+
+    RomBarSize = (~(RomBar & 0xfffff800)) + 1;
+
+    //
+    // Make sure the size of the ROM is between 0 and 16 MB
+    //
+    if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
+
+      //
+      // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
+      //
+      RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
+      RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
+      if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
+        MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
+        RomBar = RomBar + 1;
+        IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+        IoDev->Pci.Read  (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+        RomBar = RomBar - 1;
+
+        //
+        // Enable the Memory decode for the PCI Device
+        //
+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+        Register |= 0x02;
+        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+        //
+        // Follow the chain of images to determine the size of the Option ROM present
+        // Keep going until the last image is found by looking at the Indicator field
+        // or the size of an image is 0, or the size of all the images is bigger than the
+        // size of the window programmed into the PPB.
+        //
+        RomBarSize = 0;
+        do {
+
+          LastImage = TRUE;
+
+          ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
+          IoDev->Mem.Read (
+            IoDev, 
+            EfiPciWidthUint8, 
+            RomBar + RomBarSize, 
+            sizeof(EfiRomHeader),
+            &EfiRomHeader
+            );
+
+          Pcir.ImageLength = 0;
+
+          if (EfiRomHeader.Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&
+              EfiRomHeader.PcirOffset != 0 &&
+              (EfiRomHeader.PcirOffset & 3) == 0 &&
+              RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {
+            ZeroMem (&Pcir, sizeof(Pcir));
+            IoDev->Mem.Read (
+              IoDev, 
+              EfiPciWidthUint8, 
+              RomBar + RomBarSize + EfiRomHeader.PcirOffset, 
+              sizeof(Pcir),
+              &Pcir
+              );
+
+            if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+              break;
+            }
+            if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {
+              break;
+            }
+            if ((Pcir.Indicator & 0x80) == 0x00) {
+              LastImage = FALSE;
+            }
+
+            RomBarSize += Pcir.ImageLength * 512;
+          }
+        } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
+
+        if (RomBarSize > 0) {
+
+          //
+          // Allocate a memory buffer for the Option ROM contents.
+          //
+          Status = gBS->AllocatePages(
+                          AllocateAnyPages,
+                          EfiBootServicesData,
+                          EFI_SIZE_TO_PAGES(RomBarSize),
+                          &RomBuffer
+                          );
+
+          if (!EFI_ERROR (Status)) {
+
+            //
+            // Copy the contents of the Option ROM to the memory buffer
+            //
+            IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
+
+            Status = gBS->AllocatePool(
+                            EfiBootServicesData,
+                            ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
+                            (VOID **) &TempPciOptionRomDescriptors
+                            );
+            if (mPciOptionRomTable.PciOptionRomCount > 0) {
+              CopyMem(
+                TempPciOptionRomDescriptors, 
+                mPciOptionRomTable.PciOptionRomDescriptors, 
+                (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
+                );
+
+              gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
+            }
+
+            mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; 
+
+            TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
+
+            TempPciOptionRomDescriptors->RomAddress              = RomBuffer;
+            TempPciOptionRomDescriptors->MemoryType              = EfiBootServicesData;
+            TempPciOptionRomDescriptors->RomLength               = RomBarSize;
+            TempPciOptionRomDescriptors->Seg                     = (UINT32)IoDev->SegmentNumber;
+            TempPciOptionRomDescriptors->Bus                     = (UINT8)Bus;
+            TempPciOptionRomDescriptors->Dev                     = (UINT8)Device;
+            TempPciOptionRomDescriptors->Func                    = (UINT8)Func;
+            TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
+            TempPciOptionRomDescriptors->DontLoadEfiRom          = FALSE;
+
+            mPciOptionRomTable.PciOptionRomCount++;
+          }
+        }
+
+        //
+        // Disable the Memory decode for the PCI-PCI Bridge
+        //
+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+        Register &= (~0x02);
+        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+      }
+    }
+  }
+
+  //
+  // Restore the PCI Configuration Header 
+  //
+  IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+}
+
+VOID
+SaveCommandRegister (
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  UINT16                           Bus,
+  UINT16                           Device,
+  UINT16                           Func,
+  IN VOID                          *VoidContext
+  )
+
+{
+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
+  UINT64  Address;
+  UINTN   Index;
+  UINT16  Command;
+
+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+  IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+
+  //
+  // Clear the memory enable bit
+  //
+  Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));
+
+  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
+}
+
+VOID
+RestoreCommandRegister (
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
+  UINT16                           MinBus,
+  UINT16                           MaxBus,
+  UINT16                           MinDevice,
+  UINT16                           MaxDevice,
+  UINT16                           MinFunc,
+  UINT16                           MaxFunc,
+  UINT16                           Bus,
+  UINT16                           Device,
+  UINT16                           Func,
+  IN VOID                          *VoidContext
+  )
+
+{
+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
+  UINT64                                     Address;
+  UINTN                                      Index;
+
+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev
+  )
+  
+{
+  EFI_STATUS                                 Status;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR          *Descriptors; 
+  UINT16                                     MinBus;
+  UINT16                                     MaxBus;
+  UINT64                                     RootWindowBase;
+  UINT64                                     RootWindowLimit;
+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  Context;
+
+  if (mPciOptionRomTableInstalled == FALSE) {
+    gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
+    mPciOptionRomTableInstalled = TRUE;
+  }
+
+  Status = IoDev->Configuration(IoDev, (VOID **) &Descriptors);
+  if (EFI_ERROR (Status) || Descriptors == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  MinBus = 0xffff;
+  MaxBus = 0xffff;
+  RootWindowBase  = 0;
+  RootWindowLimit = 0;
+  while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
+    //
+    // Find bus range
+    //
+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+      MinBus = (UINT16)Descriptors->AddrRangeMin;
+      MaxBus = (UINT16)Descriptors->AddrRangeMax;
+    }
+    //
+    // Find memory descriptors that are not prefetchable
+    //
+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
+      //
+      // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
+      //
+      if (Descriptors->AddrRangeMax < 0x100000000ULL) {
+        //
+        // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
+        //
+        if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
+          RootWindowBase  = Descriptors->AddrRangeMin;
+          RootWindowLimit = Descriptors->AddrRangeMax;
+        }
+      }
+    }
+    Descriptors ++;
+  }
+
+  //
+  // Make sure a bus range was found
+  //
+  if (MinBus == 0xffff || MaxBus == 0xffff) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Make sure a non-prefetchable memory region was found
+  //
+  if (RootWindowBase == 0 && RootWindowLimit == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Round the Base and Limit values to 1 MB boudaries
+  //
+  RootWindowBase  = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
+  RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
+
+  //
+  // Make sure that the size of the rounded window is greater than zero
+  //
+  if (RootWindowLimit <= RootWindowBase) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Allocate buffer to save the Command register from all the PCI devices
+  //
+  Context.CommandRegisterBuffer = NULL;
+  Status = gBS->AllocatePool(
+                  EfiBootServicesData,
+                  sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
+                  (VOID **) &Context.CommandRegisterBuffer
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Context.PpbMemoryWindow   = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
+
+  //
+  // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
+  //
+  ScanPciBus(
+    IoDev,
+    MinBus, MaxBus, 
+    0, PCI_MAX_DEVICE, 
+    0, PCI_MAX_FUNC, 
+    SaveCommandRegister, &Context
+    );
+
+  //
+  // Recursively scan all the busses for PCI Option ROMs
+  //
+  ScanPciBus(
+    IoDev,
+    MinBus, MinBus, 
+    0, PCI_MAX_DEVICE, 
+    0, PCI_MAX_FUNC, 
+    CheckForRom, &Context
+    );
+
+  //
+  // Restore the Command register in all the PCI devices
+  //
+  ScanPciBus(
+    IoDev,
+    MinBus, MaxBus, 
+    0, PCI_MAX_DEVICE, 
+    0, PCI_MAX_FUNC, 
+    RestoreCommandRegister, &Context
+    );
+
+  //
+  // Free the buffer used to save all the Command register values
+  //
+  gBS->FreePool(Context.CommandRegisterBuffer);
+
+  return EFI_SUCCESS;
+}
diff --git a/CorebootModulePkg/SataControllerDxe/ComponentName.c b/CorebootModulePkg/SataControllerDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..c470cd4
--- /dev/null
@@ -0,0 +1,176 @@
+/** @file
+  UEFI Component Name(2) protocol implementation for Sata Controller driver.
+
+  Copyright (c) 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 "SataController.h"
+
+//
+/// EFI Component Name Protocol
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gSataControllerComponentName = {
+  SataControllerComponentNameGetDriverName,
+  SataControllerComponentNameGetControllerName,
+  "eng"
+};
+
+//
+/// EFI Component Name 2 Protocol
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SataControllerComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SataControllerComponentNameGetControllerName,
+  "en"
+};
+
+//
+/// Driver Name Strings
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSataControllerDriverNameTable[] = {
+  {
+    "eng;en",
+    (CHAR16 *)L"Sata Controller Init Driver"
+  },
+  {
+    NULL,
+    NULL
+  }
+};
+
+///
+/// Controller Name Strings
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSataControllerControllerNameTable[] = {
+  {
+    "eng;en",
+    (CHAR16 *)L"Sata Controller"
+  },
+  {
+    NULL,
+    NULL
+  }
+};
+
+/**
+  Retrieves a Unicode string that is the user readable name of the UEFI Driver.
+
+  @param This           A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param Language       A pointer to a three character ISO 639-2 language identifier.
+                        This is the language of the driver name that that the caller
+                        is requesting, and it must match one of the languages specified
+                        in SupportedLanguages.  The number of languages supported by a
+                        driver is up to the driver writer.
+  @param DriverName     A pointer to the Unicode string to return.  This Unicode string
+                        is the name of the driver specified by This in the language
+                        specified by Language.
+  
+  @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
+SataControllerComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME_PROTOCOL    *This,
+  IN CHAR8                          *Language,
+  OUT CHAR16                        **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mSataControllerDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gSataControllerComponentName)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an UEFI Driver.  
+
+  @param This                   A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param ControllerHandle       The handle of a controller that the driver specified by
+                                This is managing.  This handle specifies the controller
+                                whose name is to be returned.
+  @param ChildHandle OPTIONAL   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               A pointer to a three character ISO 639-2 language
+                                identifier.  This is the language of the controller name
+                                that that the caller is requesting, and it must match one
+                                of the languages specified in SupportedLanguages.  The
+                                number of languages supported by a driver is up to the
+                                driver writer.
+  @param ControllerName         A pointer to the Unicode string to return.  This Unicode
+                                string is the name of the controller specified by
+                                ControllerHandle and ChildHandle in the language
+                                specified by Language from the point of view of the
+                                driver specified by This.
+  
+  @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
+SataControllerComponentNameGetControllerName (
+  IN EFI_COMPONENT_NAME_PROTOCOL    *This,
+  IN EFI_HANDLE                     ControllerHandle,
+  IN EFI_HANDLE                     ChildHandle OPTIONAL,
+  IN CHAR8                          *Language,
+  OUT CHAR16                        **ControllerName
+  )
+{
+  EFI_STATUS    Status;
+
+  //
+  // Make sure this driver is currently managing ControllHandle
+  //
+  Status = EfiTestManagedDevice (
+             ControllerHandle,
+             gSataControllerDriverBinding.DriverBindingHandle,
+             &gEfiPciIoProtocolGuid
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return LookupUnicodeString2 (
+          Language,
+          This->SupportedLanguages,
+          mSataControllerControllerNameTable,
+          ControllerName,
+          (BOOLEAN)(This == &gSataControllerComponentName)
+          );
+}
diff --git a/CorebootModulePkg/SataControllerDxe/SataController.c b/CorebootModulePkg/SataControllerDxe/SataController.c
new file mode 100644 (file)
index 0000000..d35c6c3
--- /dev/null
@@ -0,0 +1,1049 @@
+/** @file
+  This driver module produces IDE_CONTROLLER_INIT protocol for Sata Controllers.
+
+  Copyright (c) 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 "SataController.h"
+
+///
+/// EFI_DRIVER_BINDING_PROTOCOL instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding = {
+  SataControllerSupported,
+  SataControllerStart,
+  SataControllerStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+/**
+  Read AHCI Operation register.
+
+  @param PciIo      The PCI IO protocol instance.
+  @param Offset     The operation register offset.
+
+  @return The register content read.
+
+**/
+UINT32
+EFIAPI
+AhciReadReg (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT32                 Offset
+  )
+{
+  UINT32    Data;
+
+  ASSERT (PciIo != NULL);
+  
+  Data = 0;
+
+  PciIo->Mem.Read (
+               PciIo,
+               EfiPciIoWidthUint32,
+               AHCI_BAR_INDEX,
+               (UINT64) Offset,
+               1,
+               &Data
+               );
+
+  return Data;
+}
+
+/**
+  Write AHCI Operation register.
+
+  @param PciIo      The PCI IO protocol instance.
+  @param Offset     The operation register offset.
+  @param Data       The data used to write down.
+
+**/
+VOID
+EFIAPI
+AhciWriteReg (
+  IN EFI_PCI_IO_PROTOCOL    *PciIo,
+  IN UINT32                 Offset,
+  IN UINT32                 Data
+  )
+{
+  ASSERT (PciIo != NULL);
+
+  PciIo->Mem.Write (
+               PciIo,
+               EfiPciIoWidthUint32,
+               AHCI_BAR_INDEX,
+               (UINT64) Offset,
+               1,
+               &Data
+               );
+
+  return;
+}
+
+/**
+  This function is used to calculate the best PIO mode supported by specific IDE device
+
+  @param IdentifyData   The identify data of specific IDE device.
+  @param DisPioMode     Disqualified PIO modes collection.
+  @param SelectedMode   Available PIO modes collection.
+
+  @retval EFI_SUCCESS       Best PIO modes are returned.
+  @retval EFI_UNSUPPORTED   The device doesn't support PIO mode,
+                            or all supported modes have been disqualified.
+**/
+EFI_STATUS
+CalculateBestPioMode (
+  IN EFI_IDENTIFY_DATA  *IdentifyData,
+  IN UINT16             *DisPioMode OPTIONAL,
+  OUT UINT16            *SelectedMode
+  )
+{
+  UINT16    PioMode;
+  UINT16    AdvancedPioMode;
+  UINT16    Temp;
+  UINT16    Index;
+  UINT16    MinimumPioCycleTime;
+
+  Temp = 0xff;
+
+  PioMode = (UINT8) (((ATA5_IDENTIFY_DATA *) (&(IdentifyData->AtaData)))->pio_cycle_timing >> 8);
+
+  //
+  // See whether Identify Data word 64 - 70 are valid
+  //
+  if ((IdentifyData->AtaData.field_validity & 0x02) == 0x02) {
+
+    AdvancedPioMode = IdentifyData->AtaData.advanced_pio_modes;
+    DEBUG ((EFI_D_INFO, "CalculateBestPioMode: AdvancedPioMode = %x\n", AdvancedPioMode));
+
+    for (Index = 0; Index < 8; Index++) {
+      if ((AdvancedPioMode & 0x01) != 0) {
+        Temp = Index;
+      }
+
+      AdvancedPioMode >>= 1;
+    }
+
+    //
+    // If Temp is modified, mean the advanced_pio_modes is not zero;
+    // if Temp is not modified, mean there is no advanced PIO mode supported,
+    // the best PIO Mode is the value in pio_cycle_timing.
+    //
+    if (Temp != 0xff) {
+      AdvancedPioMode = (UINT16) (Temp + 3);
+    } else {
+      AdvancedPioMode = PioMode;
+    }
+
+    //
+    // Limit the PIO mode to at most PIO4.
+    //
+    PioMode = (UINT16) MIN (AdvancedPioMode, 4);
+
+    MinimumPioCycleTime = IdentifyData->AtaData.min_pio_cycle_time_with_flow_control;
+
+    if (MinimumPioCycleTime <= 120) {
+      PioMode = (UINT16) MIN (4, PioMode);
+    } else if (MinimumPioCycleTime <= 180) {
+      PioMode = (UINT16) MIN (3, PioMode);
+    } else if (MinimumPioCycleTime <= 240) {
+      PioMode = (UINT16) MIN (2, PioMode);
+    } else {
+      PioMode = 0;
+    }
+
+    //
+    // Degrade the PIO mode if the mode has been disqualified
+    //
+    if (DisPioMode != NULL) {
+      if (*DisPioMode < 2) {
+        return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2
+      }
+
+      if (PioMode >= *DisPioMode) {
+        PioMode = (UINT16) (*DisPioMode - 1);
+      }
+    }
+
+    if (PioMode < 2) {
+      *SelectedMode = 1;        // ATA_PIO_MODE_BELOW_2;
+    } else {
+      *SelectedMode = PioMode;  // ATA_PIO_MODE_2 to ATA_PIO_MODE_4;
+    }
+
+  } else {
+    //
+    // Identify Data word 64 - 70 are not valid
+    // Degrade the PIO mode if the mode has been disqualified
+    //
+    if (DisPioMode != NULL) {
+      if (*DisPioMode < 2) {
+        return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2
+      }
+
+      if (PioMode == *DisPioMode) {
+        PioMode--;
+      }
+    }
+
+    if (PioMode < 2) {
+      *SelectedMode = 1;        // ATA_PIO_MODE_BELOW_2;
+    } else {
+      *SelectedMode = 2;        // ATA_PIO_MODE_2;
+    }
+
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is used to calculate the best UDMA mode supported by specific IDE device
+
+  @param IdentifyData   The identify data of specific IDE device.
+  @param DisUDmaMode     Disqualified UDMA modes collection.
+  @param SelectedMode   Available UDMA modes collection.
+
+  @retval EFI_SUCCESS       Best UDMA modes are returned.
+  @retval EFI_UNSUPPORTED   The device doesn't support UDMA mode,
+                            or all supported modes have been disqualified.
+**/
+EFI_STATUS
+CalculateBestUdmaMode (
+  IN EFI_IDENTIFY_DATA  *IdentifyData,
+  IN UINT16             *DisUDmaMode OPTIONAL,
+  OUT UINT16            *SelectedMode
+  )
+{
+  UINT16    TempMode;
+  UINT16    DeviceUDmaMode;
+
+  DeviceUDmaMode = 0;
+
+  //
+  // Check whether the WORD 88 (supported UltraDMA by drive) is valid
+  //
+  if ((IdentifyData->AtaData.field_validity & 0x04) == 0x00) {
+    return EFI_UNSUPPORTED;
+  }
+
+  DeviceUDmaMode = IdentifyData->AtaData.ultra_dma_mode;
+  DEBUG ((EFI_D_INFO, "CalculateBestUdmaMode: DeviceUDmaMode = %x\n", DeviceUDmaMode));
+  DeviceUDmaMode &= 0x3f;
+  TempMode = 0;                 // initialize it to UDMA-0
+
+  while ((DeviceUDmaMode >>= 1) != 0) {
+    TempMode++;
+  }
+
+  //
+  // Degrade the UDMA mode if the mode has been disqualified
+  //
+  if (DisUDmaMode != NULL) {
+    if (*DisUDmaMode == 0) {
+      *SelectedMode = 0;
+      return EFI_UNSUPPORTED;   // no mode below ATA_UDMA_MODE_0
+    }
+
+    if (TempMode >= *DisUDmaMode) {
+      TempMode = (UINT16) (*DisUDmaMode - 1);
+    }
+  }
+
+  //
+  // Possible returned mode is between ATA_UDMA_MODE_0 and ATA_UDMA_MODE_5
+  //
+  *SelectedMode = TempMode;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The Entry Point of module. It follows the standard UEFI driver model.
+
+  @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
+InitializeSataControllerDriver (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+
+  //
+  // Install driver model protocol(s).
+  //
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gSataControllerDriverBinding,
+             ImageHandle,
+             &gSataControllerComponentName,
+             &gSataControllerComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Supported function of Driver Binding protocol for this driver.
+  Test to see if this driver supports ControllerHandle.
+
+  @param This                   Protocol instance pointer.
+  @param Controller             Handle of device to test.
+  @param RemainingDevicePath    A pointer to the device path.
+                                it should be ignored by device driver.
+
+  @retval EFI_SUCCESS           This driver supports this device.
+  @retval EFI_ALREADY_STARTED   This driver is already running on this device.
+  @retval other                 This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+  PCI_TYPE00            PciData;
+
+  //
+  // Attempt to open PCI I/O Protocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Now further check the PCI header: Base Class (offset 0x0B) and
+  // Sub Class (offset 0x0A). This controller should be an SATA controller
+  //
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint8,
+                        PCI_CLASSCODE_OFFSET,
+                        sizeof (PciData.Hdr.ClassCode),
+                        PciData.Hdr.ClassCode
+                        );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (IS_PCI_IDE (&PciData) || IS_PCI_SATADPA (&PciData)) {
+    return EFI_SUCCESS;
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  This routine is called right after the .Supported() called and 
+  Start this driver on ControllerHandle.
+
+  @param This                   Protocol instance pointer.
+  @param Controller             Handle of device to bind driver to.
+  @param RemainingDevicePath    A pointer to the device path.
+                                it should be ignored by device driver.
+
+  @retval EFI_SUCCESS           This driver is added to this device.
+  @retval EFI_ALREADY_STARTED   This driver is already running on this device.
+  @retval other                 Some error occurs when binding this driver to this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  PCI_TYPE00                        PciData;
+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
+  UINT32                            Data32;
+  UINTN                             ChannelDeviceCount;
+
+  DEBUG ((EFI_D_INFO, "SataControllerStart START\n"));
+
+  SataPrivateData = NULL;
+
+  //
+  // Now test and open PCI I/O Protocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "SataControllerStart error return status = %r\n", Status));
+    return Status;
+  }
+
+  //
+  // Allocate Sata Private Data structure
+  //
+  SataPrivateData = AllocateZeroPool (sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA));
+  if (SataPrivateData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // Initialize Sata Private Data
+  //
+  SataPrivateData->Signature = SATA_CONTROLLER_SIGNATURE;
+  SataPrivateData->PciIo = PciIo;
+  SataPrivateData->IdeInit.GetChannelInfo = IdeInitGetChannelInfo;
+  SataPrivateData->IdeInit.NotifyPhase = IdeInitNotifyPhase;
+  SataPrivateData->IdeInit.SubmitData = IdeInitSubmitData;
+  SataPrivateData->IdeInit.DisqualifyMode = IdeInitDisqualifyMode;
+  SataPrivateData->IdeInit.CalculateMode = IdeInitCalculateMode;
+  SataPrivateData->IdeInit.SetTiming = IdeInitSetTiming;
+  SataPrivateData->IdeInit.EnumAll = SATA_ENUMER_ALL;
+
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint8,
+                        PCI_CLASSCODE_OFFSET,
+                        sizeof (PciData.Hdr.ClassCode),
+                        PciData.Hdr.ClassCode
+                        );
+  ASSERT_EFI_ERROR (Status);
+
+  if (IS_PCI_IDE (&PciData)) {
+    SataPrivateData->IdeInit.ChannelCount = IDE_MAX_CHANNEL;
+    SataPrivateData->DeviceCount = IDE_MAX_DEVICES;
+  } else if (IS_PCI_SATADPA (&PciData)) {
+    //
+    // Read Host Capability Register(CAP) to get Number of Ports(NPS) and Supports Port Multiplier(SPM)
+    //   NPS is 0's based value indicating the maximum number of ports supported by the HBA silicon.
+    //   A maximum of 32 ports can be supported. A value of '0h', indicating one port, is the minimum requirement.
+    //
+    Data32 = AhciReadReg (PciIo, R_AHCI_CAP);
+    SataPrivateData->IdeInit.ChannelCount = (UINT8) ((Data32 & B_AHCI_CAP_NPS) + 1);
+    SataPrivateData->DeviceCount = AHCI_MAX_DEVICES;
+    if ((Data32 & B_AHCI_CAP_SPM) == B_AHCI_CAP_SPM) {
+      SataPrivateData->DeviceCount = AHCI_MULTI_MAX_DEVICES;
+    }
+  }
+
+  ChannelDeviceCount = (UINTN) (SataPrivateData->IdeInit.ChannelCount) * (UINTN) (SataPrivateData->DeviceCount);
+  SataPrivateData->DisqualifiedModes = AllocateZeroPool ((sizeof (EFI_ATA_COLLECTIVE_MODE)) * ChannelDeviceCount);
+  if (SataPrivateData->DisqualifiedModes == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  SataPrivateData->IdentifyData = AllocateZeroPool ((sizeof (EFI_IDENTIFY_DATA)) * ChannelDeviceCount);
+  if (SataPrivateData->IdentifyData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  SataPrivateData->IdentifyValid = AllocateZeroPool ((sizeof (BOOLEAN)) * ChannelDeviceCount);
+  if (SataPrivateData->IdentifyValid == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // Install IDE Controller Init Protocol to this instance
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Controller,
+                  &gEfiIdeControllerInitProtocolGuid,
+                  &(SataPrivateData->IdeInit),
+                  NULL
+                  );
+
+Done:
+  if (EFI_ERROR (Status)) {
+
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiPciIoProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+    if (SataPrivateData != NULL) {
+      if (SataPrivateData->DisqualifiedModes != NULL) {
+        FreePool (SataPrivateData->DisqualifiedModes);
+      }
+      if (SataPrivateData->IdentifyData != NULL) {
+        FreePool (SataPrivateData->IdentifyData);
+      }
+      if (SataPrivateData->IdentifyValid != NULL) {
+        FreePool (SataPrivateData->IdentifyValid);
+      }
+      FreePool (SataPrivateData);
+    }
+  }
+
+  DEBUG ((EFI_D_INFO, "SataControllerStart END status = %r\n", Status));
+
+  return Status;
+}
+
+/**
+  Stop this driver on ControllerHandle.
+
+  @param This               Protocol instance pointer.
+  @param Controller         Handle of device to stop driver on.
+  @param NumberOfChildren   Not used.
+  @param ChildHandleBuffer  Not used.
+
+  @retval EFI_SUCCESS   This driver is removed from this device.
+  @retval other         Some error occurs when removing this driver from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN UINTN                          NumberOfChildren,
+  IN EFI_HANDLE                     *ChildHandleBuffer
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;
+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
+
+  //
+  // Open the produced protocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiIdeControllerInitProtocolGuid,
+                  (VOID **) &IdeInit,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (IdeInit);
+  ASSERT (SataPrivateData != NULL);
+
+  //
+  // Uninstall the IDE Controller Init Protocol from this instance
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  Controller,
+                  &gEfiIdeControllerInitProtocolGuid,
+                  &(SataPrivateData->IdeInit),
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (SataPrivateData != NULL) {
+    if (SataPrivateData->DisqualifiedModes != NULL) {
+      FreePool (SataPrivateData->DisqualifiedModes);
+    }
+    if (SataPrivateData->IdentifyData != NULL) {
+      FreePool (SataPrivateData->IdentifyData);
+    }
+    if (SataPrivateData->IdentifyValid != NULL) {
+      FreePool (SataPrivateData->IdentifyValid);
+    }
+    FreePool (SataPrivateData);
+  }
+
+  //
+  // Close protocols opened by Sata Controller driver
+  //
+  return gBS->CloseProtocol (
+                Controller,
+                &gEfiPciIoProtocolGuid,
+                This->DriverBindingHandle,
+                Controller
+                );
+}
+
+/**
+  Calculate the flat array subscript of a (Channel, Device) pair.
+
+  @param[in] SataPrivateData  The private data structure corresponding to the
+                              SATA controller that attaches the device for
+                              which the flat array subscript is being
+                              calculated.
+
+  @param[in] Channel          The channel (ie. port) number on the SATA
+                              controller that the device is attached to.
+
+  @param[in] Device           The device number on the channel.
+
+  @return  The flat array subscript suitable for indexing DisqualifiedModes,
+           IdentifyData, and IdentifyValid.
+**/
+STATIC
+UINTN
+FlatDeviceIndex (
+  IN CONST EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData,
+  IN UINTN                                   Channel,
+  IN UINTN                                   Device
+  )
+{
+  ASSERT (SataPrivateData != NULL);
+  ASSERT (Channel < SataPrivateData->IdeInit.ChannelCount);
+  ASSERT (Device < SataPrivateData->DeviceCount);
+
+  return Channel * SataPrivateData->DeviceCount + Device;
+}
+
+//
+// Interface functions of IDE_CONTROLLER_INIT protocol
+//
+/**
+  Returns the information about the specified IDE channel.
+  
+  This function can be used to obtain information about a particular IDE channel.
+  The driver entity uses this information during the enumeration process. 
+  
+  If Enabled is set to FALSE, the driver entity will not scan the channel. Note 
+  that it will not prevent an operating system driver from scanning the channel.
+  
+  For most of today's controllers, MaxDevices will either be 1 or 2. For SATA 
+  controllers, this value will always be 1. SATA configurations can contain SATA 
+  port multipliers. SATA port multipliers behave like SATA bridges and can support
+  up to 16 devices on the other side. If a SATA port out of the IDE controller 
+  is connected to a port multiplier, MaxDevices will be set to the number of SATA 
+  devices that the port multiplier supports. Because today's port multipliers 
+  support up to fifteen SATA devices, this number can be as large as fifteen. The IDE  
+  bus driver is required to scan for the presence of port multipliers behind an SATA 
+  controller and enumerate up to MaxDevices number of devices behind the port 
+  multiplier.    
+  
+  In this context, the devices behind a port multiplier constitute a channel.  
+  
+  @param[in]  This         The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in]  Channel      Zero-based channel number.
+  @param[out] Enabled      TRUE if this channel is enabled.  Disabled channels 
+                           are not scanned to see if any devices are present.
+  @param[out] MaxDevices   The maximum number of IDE devices that the bus driver
+                           can expect on this channel.  For the ATA/ATAPI 
+                           specification, version 6, this number will either be 
+                           one or two. For Serial ATA (SATA) configurations with a 
+                           port multiplier, this number can be as large as fifteen.
+
+  @retval EFI_SUCCESS             Information was returned without any errors.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitGetChannelInfo (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  OUT BOOLEAN                           *Enabled,
+  OUT UINT8                             *MaxDevices
+  )
+{
+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
+  ASSERT (SataPrivateData != NULL);
+
+  if (Channel < This->ChannelCount) {
+    *Enabled = TRUE;
+    *MaxDevices = SataPrivateData->DeviceCount;
+    return EFI_SUCCESS;
+  }
+
+  *Enabled = FALSE;
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  The notifications from the driver entity that it is about to enter a certain
+  phase of the IDE channel enumeration process.
+  
+  This function can be used to notify the IDE controller driver to perform 
+  specific actions, including any chipset-specific initialization, so that the 
+  chipset is ready to enter the next phase. Seven notification points are defined 
+  at this time. 
+  
+  More synchronization points may be added as required in the future.  
+
+  @param[in] This      The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in] Phase     The phase during enumeration.
+  @param[in] Channel   Zero-based channel number.
+
+  @retval EFI_SUCCESS             The notification was accepted without any errors.
+  @retval EFI_UNSUPPORTED         Phase is not supported.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_NOT_READY           This phase cannot be entered at this time; for 
+                                  example, an attempt was made to enter a Phase 
+                                  without having entered one or more previous 
+                                  Phase.
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitNotifyPhase (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN EFI_IDE_CONTROLLER_ENUM_PHASE      Phase,
+  IN UINT8                              Channel
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Submits the device information to the IDE controller driver.
+
+  This function is used by the driver entity to pass detailed information about 
+  a particular device to the IDE controller driver. The driver entity obtains 
+  this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData
+  is the pointer to the response data buffer. The IdentifyData buffer is owned 
+  by the driver entity, and the IDE controller driver must make a local copy 
+  of the entire buffer or parts of the buffer as needed. The original IdentifyData 
+  buffer pointer may not be valid when
+  
+    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or
+    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.
+    
+  The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to 
+  compute the optimum mode for the device. These fields are not limited to the 
+  timing information. For example, an implementation of the IDE controller driver 
+  may examine the vendor and type/mode field to match known bad drives.  
+  
+  The driver entity may submit drive information in any order, as long as it 
+  submits information for all the devices belonging to the enumeration group 
+  before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device
+  in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
+  should be called with IdentifyData set to NULL.  The IDE controller driver may 
+  not have any other mechanism to know whether a device is present or not. Therefore, 
+  setting IdentifyData to NULL does not constitute an error condition. 
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a 
+  given (Channel, Device) pair.  
+    
+  @param[in] This           A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in] Channel        Zero-based channel number.
+  @param[in] Device         Zero-based device number on the Channel.
+  @param[in] IdentifyData   The device's response to the ATA IDENTIFY_DEVICE command.
+
+  @retval EFI_SUCCESS             The information was accepted without any errors.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_INVALID_PARAMETER   Device is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitSubmitData (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  IN UINT8                              Device,
+  IN EFI_IDENTIFY_DATA                  *IdentifyData
+  )
+{
+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
+  UINTN                             DeviceIndex;
+
+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
+  ASSERT (SataPrivateData != NULL);
+
+  if ((Channel >= This->ChannelCount) || (Device >= SataPrivateData->DeviceCount)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DeviceIndex = FlatDeviceIndex (SataPrivateData, Channel, Device);
+
+  //
+  // Make a local copy of device's IdentifyData and mark the valid flag
+  //
+  if (IdentifyData != NULL) {
+    CopyMem (
+      &(SataPrivateData->IdentifyData[DeviceIndex]),
+      IdentifyData,
+      sizeof (EFI_IDENTIFY_DATA)
+      );
+
+    SataPrivateData->IdentifyValid[DeviceIndex] = TRUE;
+  } else {
+    SataPrivateData->IdentifyValid[DeviceIndex] = FALSE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Disqualifies specific modes for an IDE device.
+
+  This function allows the driver entity or other drivers (such as platform 
+  drivers) to reject certain timing modes and request the IDE controller driver
+  to recalculate modes. This function allows the driver entity and the IDE 
+  controller driver to negotiate the timings on a per-device basis. This function 
+  is useful in the case of drives that lie about their capabilities. An example 
+  is when the IDE device fails to accept the timing modes that are calculated 
+  by the IDE controller driver based on the response to the Identify Drive command.
+
+  If the driver entity does not want to limit the ATA timing modes and leave that 
+  decision to the IDE controller driver, it can either not call this function for 
+  the given device or call this function and set the Valid flag to FALSE for all 
+  modes that are listed in EFI_ATA_COLLECTIVE_MODE.
+  
+  The driver entity may disqualify modes for a device in any order and any number 
+  of times.
+  
+  This function can be called multiple times to invalidate multiple modes of the 
+  same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI 
+  specification for more information on PIO modes.  
+  
+  For Serial ATA (SATA) controllers, this member function can be used to disqualify
+  a higher transfer rate mode on a given channel. For example, a platform driver
+  may inform the IDE controller driver to not use second-generation (Gen2) speeds 
+  for a certain SATA drive.
+  
+  @param[in] This       The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in] Channel    The zero-based channel number.
+  @param[in] Device     The zero-based device number on the Channel.
+  @param[in] BadModes   The modes that the device does not support and that
+                        should be disqualified.
+
+  @retval EFI_SUCCESS             The modes were accepted without any errors.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_INVALID_PARAMETER   Device is invalid.
+  @retval EFI_INVALID_PARAMETER   IdentifyData is NULL.
+                                
+**/
+EFI_STATUS
+EFIAPI
+IdeInitDisqualifyMode (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  IN UINT8                              Device,
+  IN EFI_ATA_COLLECTIVE_MODE            *BadModes
+  )
+{
+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
+  UINTN                             DeviceIndex;
+
+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
+  ASSERT (SataPrivateData != NULL);
+
+  if ((Channel >= This->ChannelCount) || (BadModes == NULL) || (Device >= SataPrivateData->DeviceCount)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DeviceIndex = FlatDeviceIndex (SataPrivateData, Channel, Device);
+
+  //
+  // Record the disqualified modes per channel per device. From ATA/ATAPI spec,
+  // if a mode is not supported, the modes higher than it is also not supported.
+  //
+  CopyMem (
+    &(SataPrivateData->DisqualifiedModes[DeviceIndex]),
+    BadModes,
+    sizeof (EFI_ATA_COLLECTIVE_MODE)
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Returns the information about the optimum modes for the specified IDE device.
+
+  This function is used by the driver entity to obtain the optimum ATA modes for
+  a specific device.  The IDE controller driver takes into account the following 
+  while calculating the mode:
+    - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
+    - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()
+
+  The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() 
+  for all the devices that belong to an enumeration group before calling 
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.  
+  
+  The IDE controller driver will use controller- and possibly platform-specific 
+  algorithms to arrive at SupportedModes.  The IDE controller may base its 
+  decision on user preferences and other considerations as well. This function 
+  may be called multiple times because the driver entity may renegotiate the mode 
+  with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().
+    
+  The driver entity may collect timing information for various devices in any 
+  order. The driver entity is responsible for making sure that all the dependencies
+  are satisfied. For example, the SupportedModes information for device A that 
+  was previously returned may become stale after a call to 
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.
+  
+  The buffer SupportedModes is allocated by the callee because the caller does 
+  not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE 
+  is defined in a way that allows for future extensibility and can be of variable 
+  length. This memory pool should be deallocated by the caller when it is no 
+  longer necessary.  
+  
+  The IDE controller driver for a Serial ATA (SATA) controller can use this 
+  member function to force a lower speed (first-generation [Gen1] speeds on a 
+  second-generation [Gen2]-capable hardware).  The IDE controller driver can 
+  also allow the driver entity to stay with the speed that has been negotiated 
+  by the physical layer.
+  
+  @param[in]  This             The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in]  Channel          A zero-based channel number.
+  @param[in]  Device           A zero-based device number on the Channel.
+  @param[out] SupportedModes   The optimum modes for the device.
+
+  @retval EFI_SUCCESS             SupportedModes was returned.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_INVALID_PARAMETER   Device is invalid. 
+  @retval EFI_INVALID_PARAMETER   SupportedModes is NULL.
+  @retval EFI_NOT_READY           Modes cannot be calculated due to a lack of 
+                                  data.  This error may happen if 
+                                  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() 
+                                  and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData() 
+                                  were not called for at least one drive in the 
+                                  same enumeration group.
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitCalculateMode (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  IN UINT8                              Device,
+  OUT EFI_ATA_COLLECTIVE_MODE           **SupportedModes
+  )
+{
+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
+  EFI_IDENTIFY_DATA                 *IdentifyData;
+  BOOLEAN                           IdentifyValid;
+  EFI_ATA_COLLECTIVE_MODE           *DisqualifiedModes;
+  UINT16                            SelectedMode;
+  EFI_STATUS                        Status;
+  UINTN                             DeviceIndex;
+
+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
+  ASSERT (SataPrivateData != NULL);
+
+  if ((Channel >= This->ChannelCount) || (SupportedModes == NULL) || (Device >= SataPrivateData->DeviceCount)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *SupportedModes = AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE));
+  if (*SupportedModes == NULL) {
+    ASSERT (*SupportedModes != NULL);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DeviceIndex = FlatDeviceIndex (SataPrivateData, Channel, Device);
+
+  IdentifyData = &(SataPrivateData->IdentifyData[DeviceIndex]);
+  IdentifyValid = SataPrivateData->IdentifyValid[DeviceIndex];
+  DisqualifiedModes = &(SataPrivateData->DisqualifiedModes[DeviceIndex]);
+
+  //
+  // Make sure we've got the valid identify data of the device from SubmitData()
+  //
+  if (!IdentifyValid) {
+    FreePool (*SupportedModes);
+    return EFI_NOT_READY;
+  }
+
+  Status = CalculateBestPioMode (
+            IdentifyData,
+            (DisqualifiedModes->PioMode.Valid ? ((UINT16 *) &(DisqualifiedModes->PioMode.Mode)) : NULL),
+            &SelectedMode
+            );
+  if (!EFI_ERROR (Status)) {
+    (*SupportedModes)->PioMode.Valid = TRUE;
+    (*SupportedModes)->PioMode.Mode = SelectedMode;
+
+  } else {
+    (*SupportedModes)->PioMode.Valid = FALSE;
+  }
+  DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: PioMode = %x\n", (*SupportedModes)->PioMode.Mode));
+
+  Status = CalculateBestUdmaMode (
+            IdentifyData,
+            (DisqualifiedModes->UdmaMode.Valid ? ((UINT16 *) &(DisqualifiedModes->UdmaMode.Mode)) : NULL),
+            &SelectedMode
+            );
+
+  if (!EFI_ERROR (Status)) {
+    (*SupportedModes)->UdmaMode.Valid = TRUE;
+    (*SupportedModes)->UdmaMode.Mode  = SelectedMode;
+
+  } else {
+    (*SupportedModes)->UdmaMode.Valid = FALSE;
+  }
+  DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: UdmaMode = %x\n", (*SupportedModes)->UdmaMode.Mode));
+
+  //
+  // The modes other than PIO and UDMA are not supported
+  //
+  return EFI_SUCCESS;
+}
+
+/**
+  Commands the IDE controller driver to program the IDE controller hardware
+  so that the specified device can operate at the specified mode.
+
+  This function is used by the driver entity to instruct the IDE controller 
+  driver to program the IDE controller hardware to the specified modes. This 
+  function can be called only once for a particular device. For a Serial ATA 
+  (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-
+  specific programming may be required.
+
+  @param[in] This      Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in] Channel   Zero-based channel number.
+  @param[in] Device    Zero-based device number on the Channel.
+  @param[in] Modes     The modes to set.
+
+  @retval EFI_SUCCESS             The command was accepted without any errors.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_INVALID_PARAMETER   Device is invalid.
+  @retval EFI_NOT_READY           Modes cannot be set at this time due to lack of data.
+  @retval EFI_DEVICE_ERROR        Modes cannot be set due to hardware failure.
+                                  The driver entity should not use this device.
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitSetTiming (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  IN UINT8                              Device,
+  IN EFI_ATA_COLLECTIVE_MODE            *Modes
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/CorebootModulePkg/SataControllerDxe/SataController.h b/CorebootModulePkg/SataControllerDxe/SataController.h
new file mode 100644 (file)
index 0000000..e76df74
--- /dev/null
@@ -0,0 +1,542 @@
+/** @file
+  Header file for Sata Controller driver.
+
+  Copyright (c) 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 _SATA_CONTROLLER_H_
+#define _SATA_CONTROLLER_H_
+
+#include <Uefi.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/IdeControllerInit.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <IndustryStandard/Pci.h>
+
+//
+// Global Variables definitions
+//
+extern EFI_DRIVER_BINDING_PROTOCOL  gSataControllerDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL  gSataControllerComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2;
+
+#define AHCI_BAR_INDEX 0x05
+#define R_AHCI_CAP 0x0
+#define   B_AHCI_CAP_NPS (BIT4 | BIT3 | BIT2 | BIT1 | BIT0) // Number of Ports
+#define   B_AHCI_CAP_SPM BIT17 // Supports Port Multiplier
+
+///
+/// AHCI each channel can have up to 1 device
+///
+#define AHCI_MAX_DEVICES 0x01
+
+///
+/// AHCI each channel can have 15 devices in the presence of a multiplier
+///
+#define AHCI_MULTI_MAX_DEVICES 0x0F
+
+///
+/// IDE supports 2 channel max
+///
+#define IDE_MAX_CHANNEL 0x02
+
+///
+/// IDE supports 2 devices max
+///
+#define IDE_MAX_DEVICES 0x02
+
+#define SATA_ENUMER_ALL FALSE
+
+//
+// Sata Controller driver private data structure
+//
+
+#define SATA_CONTROLLER_SIGNATURE SIGNATURE_32('S','A','T','A')
+
+typedef struct _EFI_SATA_CONTROLLER_PRIVATE_DATA {
+  //
+  // Standard signature used to identify Sata Controller private data
+  //
+  UINT32                            Signature;
+
+  //
+  // Protocol instance of IDE_CONTROLLER_INIT produced by this driver
+  //
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL  IdeInit;
+
+  //
+  // Copy of protocol pointers used by this driver
+  //
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+
+  //
+  // The number of devices that are supported by this channel
+  //
+  UINT8                             DeviceCount;
+
+  //
+  // The highest disqulified mode for each attached device,
+  // From ATA/ATAPI spec, if a mode is not supported,
+  // the modes higher than it is also not supported
+  //
+  EFI_ATA_COLLECTIVE_MODE           *DisqualifiedModes;
+
+  //
+  // A copy of EFI_IDENTIFY_DATA data for each attached SATA device and its flag
+  //
+  EFI_IDENTIFY_DATA                 *IdentifyData;
+  BOOLEAN                           *IdentifyValid;
+} EFI_SATA_CONTROLLER_PRIVATE_DATA;
+
+#define SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_SATA_CONTROLLER_PRIVATE_DATA, IdeInit, SATA_CONTROLLER_SIGNATURE)
+
+//
+// Driver binding functions declaration
+//
+/**
+  Supported function of Driver Binding protocol for this driver.
+  Test to see if this driver supports ControllerHandle.
+
+  @param This                   Protocol instance pointer.
+  @param Controller             Handle of device to test.
+  @param RemainingDevicePath    A pointer to the device path. Should be ignored by
+                                device driver.
+
+  @retval EFI_SUCCESS           This driver supports this device.
+  @retval EFI_ALREADY_STARTED   This driver is already running on this device.
+  @retval other                 This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+;
+
+/**
+  This routine is called right after the .Supported() called and 
+  Start this driver on ControllerHandle.
+
+  @param This                   Protocol instance pointer.
+  @param Controller             Handle of device to bind driver to.
+  @param RemainingDevicePath    A pointer to the device path. Should be ignored by
+                                device driver.
+
+  @retval EFI_SUCCESS           This driver is added to this device.
+  @retval EFI_ALREADY_STARTED   This driver is already running on this device.
+  @retval other                 Some error occurs when binding this driver to this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+;
+
+/**
+  Stop this driver on ControllerHandle.
+
+  @param This               Protocol instance pointer.
+  @param Controller         Handle of device to stop driver on.
+  @param NumberOfChildren   Not used.
+  @param ChildHandleBuffer  Not used.
+
+  @retval EFI_SUCCESS   This driver is removed from this device.
+  @retval other         Some error occurs when removing this driver from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN UINTN                          NumberOfChildren,
+  IN EFI_HANDLE                     *ChildHandleBuffer
+  )
+;
+
+//
+// IDE controller init functions declaration
+//
+/**
+  Returns the information about the specified IDE channel.
+  
+  This function can be used to obtain information about a particular IDE channel.
+  The driver entity uses this information during the enumeration process. 
+  
+  If Enabled is set to FALSE, the driver entity will not scan the channel. Note 
+  that it will not prevent an operating system driver from scanning the channel.
+  
+  For most of today's controllers, MaxDevices will either be 1 or 2. For SATA 
+  controllers, this value will always be 1. SATA configurations can contain SATA 
+  port multipliers. SATA port multipliers behave like SATA bridges and can support
+  up to 16 devices on the other side. If a SATA port out of the IDE controller 
+  is connected to a port multiplier, MaxDevices will be set to the number of SATA 
+  devices that the port multiplier supports. Because today's port multipliers 
+  support up to fifteen SATA devices, this number can be as large as fifteen. The IDE  
+  bus driver is required to scan for the presence of port multipliers behind an SATA 
+  controller and enumerate up to MaxDevices number of devices behind the port 
+  multiplier.    
+  
+  In this context, the devices behind a port multiplier constitute a channel.  
+  
+  @param[in]  This         The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in]  Channel      Zero-based channel number.
+  @param[out] Enabled      TRUE if this channel is enabled.  Disabled channels 
+                           are not scanned to see if any devices are present.
+  @param[out] MaxDevices   The maximum number of IDE devices that the bus driver
+                           can expect on this channel.  For the ATA/ATAPI 
+                           specification, version 6, this number will either be 
+                           one or two. For Serial ATA (SATA) configurations with a 
+                           port multiplier, this number can be as large as fifteen.
+
+  @retval EFI_SUCCESS             Information was returned without any errors.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitGetChannelInfo (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  OUT BOOLEAN                           *Enabled,
+  OUT UINT8                             *MaxDevices
+  )
+;
+
+/**
+  The notifications from the driver entity that it is about to enter a certain
+  phase of the IDE channel enumeration process.
+  
+  This function can be used to notify the IDE controller driver to perform 
+  specific actions, including any chipset-specific initialization, so that the 
+  chipset is ready to enter the next phase. Seven notification points are defined 
+  at this time. 
+  
+  More synchronization points may be added as required in the future.  
+
+  @param[in] This      The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in] Phase     The phase during enumeration.
+  @param[in] Channel   Zero-based channel number.
+
+  @retval EFI_SUCCESS             The notification was accepted without any errors.
+  @retval EFI_UNSUPPORTED         Phase is not supported.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_NOT_READY           This phase cannot be entered at this time; for 
+                                  example, an attempt was made to enter a Phase 
+                                  without having entered one or more previous 
+                                  Phase.
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitNotifyPhase (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN EFI_IDE_CONTROLLER_ENUM_PHASE      Phase,
+  IN UINT8                              Channel
+  )
+;
+
+/**
+  Submits the device information to the IDE controller driver.
+
+  This function is used by the driver entity to pass detailed information about 
+  a particular device to the IDE controller driver. The driver entity obtains 
+  this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData
+  is the pointer to the response data buffer. The IdentifyData buffer is owned 
+  by the driver entity, and the IDE controller driver must make a local copy 
+  of the entire buffer or parts of the buffer as needed. The original IdentifyData 
+  buffer pointer may not be valid when
+  
+    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or
+    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.
+    
+  The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to 
+  compute the optimum mode for the device. These fields are not limited to the 
+  timing information. For example, an implementation of the IDE controller driver 
+  may examine the vendor and type/mode field to match known bad drives.  
+  
+  The driver entity may submit drive information in any order, as long as it 
+  submits information for all the devices belonging to the enumeration group 
+  before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device
+  in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
+  should be called with IdentifyData set to NULL.  The IDE controller driver may 
+  not have any other mechanism to know whether a device is present or not. Therefore, 
+  setting IdentifyData to NULL does not constitute an error condition. 
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a 
+  given (Channel, Device) pair.  
+    
+  @param[in] This           A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in] Channel        Zero-based channel number.
+  @param[in] Device         Zero-based device number on the Channel.
+  @param[in] IdentifyData   The device's response to the ATA IDENTIFY_DEVICE command.
+
+  @retval EFI_SUCCESS             The information was accepted without any errors.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_INVALID_PARAMETER   Device is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitSubmitData (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  IN UINT8                              Device,
+  IN EFI_IDENTIFY_DATA                  *IdentifyData
+  )
+;
+
+/**
+  Disqualifies specific modes for an IDE device.
+
+  This function allows the driver entity or other drivers (such as platform 
+  drivers) to reject certain timing modes and request the IDE controller driver
+  to recalculate modes. This function allows the driver entity and the IDE 
+  controller driver to negotiate the timings on a per-device basis. This function 
+  is useful in the case of drives that lie about their capabilities. An example 
+  is when the IDE device fails to accept the timing modes that are calculated 
+  by the IDE controller driver based on the response to the Identify Drive command.
+
+  If the driver entity does not want to limit the ATA timing modes and leave that 
+  decision to the IDE controller driver, it can either not call this function for 
+  the given device or call this function and set the Valid flag to FALSE for all 
+  modes that are listed in EFI_ATA_COLLECTIVE_MODE.
+  
+  The driver entity may disqualify modes for a device in any order and any number 
+  of times.
+  
+  This function can be called multiple times to invalidate multiple modes of the 
+  same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI 
+  specification for more information on PIO modes.  
+  
+  For Serial ATA (SATA) controllers, this member function can be used to disqualify
+  a higher transfer rate mode on a given channel. For example, a platform driver
+  may inform the IDE controller driver to not use second-generation (Gen2) speeds 
+  for a certain SATA drive.
+  
+  @param[in] This       The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in] Channel    The zero-based channel number.
+  @param[in] Device     The zero-based device number on the Channel.
+  @param[in] BadModes   The modes that the device does not support and that
+                        should be disqualified.
+
+  @retval EFI_SUCCESS             The modes were accepted without any errors.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_INVALID_PARAMETER   Device is invalid.
+  @retval EFI_INVALID_PARAMETER   IdentifyData is NULL.
+                                
+**/
+EFI_STATUS
+EFIAPI
+IdeInitDisqualifyMode (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  IN UINT8                              Device,
+  IN EFI_ATA_COLLECTIVE_MODE            *BadModes
+  )
+;
+
+/**
+  Returns the information about the optimum modes for the specified IDE device.
+
+  This function is used by the driver entity to obtain the optimum ATA modes for
+  a specific device.  The IDE controller driver takes into account the following 
+  while calculating the mode:
+    - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
+    - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()
+
+  The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() 
+  for all the devices that belong to an enumeration group before calling 
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.  
+  
+  The IDE controller driver will use controller- and possibly platform-specific 
+  algorithms to arrive at SupportedModes.  The IDE controller may base its 
+  decision on user preferences and other considerations as well. This function 
+  may be called multiple times because the driver entity may renegotiate the mode 
+  with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().
+    
+  The driver entity may collect timing information for various devices in any 
+  order. The driver entity is responsible for making sure that all the dependencies
+  are satisfied. For example, the SupportedModes information for device A that 
+  was previously returned may become stale after a call to 
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.
+  
+  The buffer SupportedModes is allocated by the callee because the caller does 
+  not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE 
+  is defined in a way that allows for future extensibility and can be of variable 
+  length. This memory pool should be deallocated by the caller when it is no 
+  longer necessary.  
+  
+  The IDE controller driver for a Serial ATA (SATA) controller can use this 
+  member function to force a lower speed (first-generation [Gen1] speeds on a 
+  second-generation [Gen2]-capable hardware).  The IDE controller driver can 
+  also allow the driver entity to stay with the speed that has been negotiated 
+  by the physical layer.
+  
+  @param[in]  This             The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in]  Channel          A zero-based channel number.
+  @param[in]  Device           A zero-based device number on the Channel.
+  @param[out] SupportedModes   The optimum modes for the device.
+
+  @retval EFI_SUCCESS             SupportedModes was returned.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_INVALID_PARAMETER   Device is invalid. 
+  @retval EFI_INVALID_PARAMETER   SupportedModes is NULL.
+  @retval EFI_NOT_READY           Modes cannot be calculated due to a lack of 
+                                  data.  This error may happen if 
+                                  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() 
+                                  and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData() 
+                                  were not called for at least one drive in the 
+                                  same enumeration group.
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitCalculateMode (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  IN UINT8                              Device,
+  OUT EFI_ATA_COLLECTIVE_MODE           **SupportedModes
+  )
+;
+
+/**
+  Commands the IDE controller driver to program the IDE controller hardware
+  so that the specified device can operate at the specified mode.
+
+  This function is used by the driver entity to instruct the IDE controller 
+  driver to program the IDE controller hardware to the specified modes. This 
+  function can be called only once for a particular device. For a Serial ATA 
+  (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-
+  specific programming may be required.
+
+  @param[in] This      Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+  @param[in] Channel   Zero-based channel number.
+  @param[in] Device    Zero-based device number on the Channel.
+  @param[in] Modes     The modes to set.
+
+  @retval EFI_SUCCESS             The command was accepted without any errors.
+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
+  @retval EFI_INVALID_PARAMETER   Device is invalid.
+  @retval EFI_NOT_READY           Modes cannot be set at this time due to lack of data.
+  @retval EFI_DEVICE_ERROR        Modes cannot be set due to hardware failure.
+                                  The driver entity should not use this device.
+
+**/
+EFI_STATUS
+EFIAPI
+IdeInitSetTiming (
+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
+  IN UINT8                              Channel,
+  IN UINT8                              Device,
+  IN EFI_ATA_COLLECTIVE_MODE            *Modes
+  )
+;
+
+//
+// Forward reference declaration
+//
+/**
+  Retrieves a Unicode string that is the user readable name of the UEFI Driver.
+
+  @param This           A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param Language       A pointer to a three character ISO 639-2 language identifier.
+                        This is the language of the driver name that that the caller
+                        is requesting, and it must match one of the languages specified
+                        in SupportedLanguages.  The number of languages supported by a
+                        driver is up to the driver writer.
+  @param DriverName     A pointer to the Unicode string to return.  This Unicode string
+                        is the name of the driver specified by This in the language
+                        specified by Language.
+
+  @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
+SataControllerComponentNameGetDriverName (
+  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 an UEFI Driver.
+
+  @param This                   A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param ControllerHandle       The handle of a controller that the driver specified by
+                                This is managing.  This handle specifies the controller
+                                whose name is to be returned.
+  @param OPTIONAL   ChildHandle The handle of the child controller to retrieve the name
+                                of.  This is an optional parameter that may be NULL.  It
+                                will be NULL for device drivers.  It will also be NULL
+                                for a bus drivers that wish to retrieve the name of the
+                                bus controller.  It will not be NULL for a bus driver
+                                that wishes to retrieve the name of a child controller.
+  @param Language               A pointer to a three character ISO 639-2 language
+                                identifier.  This is the language of the controller name
+                                that that the caller is requesting, and it must match one
+                                of the languages specified in SupportedLanguages.  The
+                                number of languages supported by a driver is up to the
+                                driver writer.
+  @param ControllerName         A pointer to the Unicode string to return.  This Unicode
+                                string is the name of the controller specified by
+                                ControllerHandle and ChildHandle in the language
+                                specified by Language from the point of view of the
+                                driver specified by This.
+
+  @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
+SataControllerComponentNameGetControllerName (
+  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/CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf b/CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf
new file mode 100644 (file)
index 0000000..b0ed2f4
--- /dev/null
@@ -0,0 +1,49 @@
+## @file
+#  
+#    Component description file for the Sata Controller driver.
+#
+#  Copyright (c) 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                      = SataController
+  FILE_GUID                      = 8F4CD826-A5A0-4e93-9522-CFB0AB72926C
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializeSataControllerDriver
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  ComponentName.c
+  SataController.c
+  SataController.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  DebugLib
+  UefiLib
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+
+[Protocols]
+  gEfiPciIoProtocolGuid  
+  gEfiIdeControllerInitProtocolGuid
index a8ddb9ba10ede1c4d1c79e2d0f09cec6ab1750d0..3cc5a4d7bfbc2198b2de20cd59ac47a523f564ae 100644 (file)
@@ -110,8 +110,8 @@ INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
 #\r
 # PCI Support\r
 #\r
 #\r
 # PCI Support\r
 #\r
-INF DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf\r
-INF DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
+INF CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
+INF CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
 \r
 #\r
 # ISA Support\r
 \r
 #\r
 # ISA Support\r
@@ -132,7 +132,7 @@ INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
 INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf\r
 INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
 INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
 INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf\r
 INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
 INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
-INF DuetPkg/SataControllerDxe/SataControllerDxe.inf
+INF CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf
 INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf\r
 INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf\r
 INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf\r
 INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf\r
 INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf\r
 INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf\r
index 0306d97afc4f898681571759c552860924dd9a76..49afa731b4ffc973ef17a50b6c9006fa42bcde86 100644 (file)
   #\r
   # PCI Support\r
   #\r
   #\r
   # PCI Support\r
   #\r
-  DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf\r
-  DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
+  CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
+  CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
 
   #\r
   # SCSI/ATA/IDE/DISK Support\r
 
   #\r
   # SCSI/ATA/IDE/DISK Support\r
   MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
   MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
   FatPkg/EnhancedFatDxe/Fat.inf
   MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
   MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
   FatPkg/EnhancedFatDxe/Fat.inf
-  DuetPkg/SataControllerDxe/SataControllerDxe.inf
+  CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf
   MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf\r
   MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
   MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf\r
   MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf\r
   MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
   MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf\r
index fdd092a56b77cc19923e62461f8e90eea26850db..b5b0635c9650fcc86ae54b79ec5e7a1e3a694f6d 100644 (file)
   #\r
   # PCI Support\r
   #
   #\r
   # PCI Support\r
   #
-  DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf\r
-  DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
+  CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
+  CorebootModulePkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
 
   #\r
   # SCSI/ATA/IDE/DISK Support\r
 
   #\r
   # SCSI/ATA/IDE/DISK Support\r
   MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
   MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
   FatPkg/EnhancedFatDxe/Fat.inf
   MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
   MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
   FatPkg/EnhancedFatDxe/Fat.inf
-  DuetPkg/SataControllerDxe/SataControllerDxe.inf
+  CorebootModulePkg/SataControllerDxe/SataControllerDxe.inf
   MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf\r
   MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
   MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf\r
   MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf\r
   MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
   MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf\r