]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add PciBusNoEnumeration module
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 5 May 2008 01:28:34 +0000 (01:28 +0000)
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 5 May 2008 01:28:34 +0000 (01:28 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5157 6f19259b-4bc3-4df7-8a09-765794883524

22 files changed:
DuetPkg/PciBusNoEnumerationDxe/ComponentName.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciBus.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciBus.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciCommand.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciCommand.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciIo.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciIo.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.h [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciRomTable.c [new file with mode: 0644]
DuetPkg/PciBusNoEnumerationDxe/PciRomTable.h [new file with mode: 0644]

diff --git a/DuetPkg/PciBusNoEnumerationDxe/ComponentName.c b/DuetPkg/PciBusNoEnumerationDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..48b0dce
--- /dev/null
@@ -0,0 +1,161 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  ComponentName.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **ControllerName\r
+  );\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName = {\r
+  PciBusComponentNameGetDriverName,\r
+  PciBusComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControllerName,\r
+  "en"\r
+};\r
+\r
+\r
+STATIC EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {\r
+  { "eng;en", L"PCI Bus Driver" },\r
+  { NULL, NULL }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves a Unicode string that is the user readable name of the EFI Driver.\r
+\r
+  Arguments:\r
+    This       - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+    Language   - A pointer to a three character ISO 639-2 language identifier.\r
+                 This is the language of the driver name that that the caller \r
+                 is requesting, and it must match one of the languages specified\r
+                 in SupportedLanguages.  The number of languages supported by a \r
+                 driver is up to the driver writer.\r
+    DriverName - A pointer to the Unicode string to return.  This Unicode string\r
+                 is the name of the driver specified by This in the language \r
+                 specified by Language.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Unicode string for the Driver specified by This\r
+                            and the language specified by Language was returned \r
+                            in DriverName.\r
+    EFI_INVALID_PARAMETER - Language is NULL.\r
+    EFI_INVALID_PARAMETER - DriverName is NULL.\r
+    EFI_UNSUPPORTED       - The driver specified by This does not support the \r
+                            language specified by Language.\r
+\r
+--*/\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mPciBusDriverNameTable, \r
+           DriverName,\r
+           (BOOLEAN)(This == &gPciBusComponentName)\r
+           );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **ControllerName\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves a Unicode string that is the user readable name of the controller\r
+    that is being managed by an EFI Driver.\r
+\r
+  Arguments:\r
+    This             - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+    ControllerHandle - The handle of a controller that the driver specified by \r
+                       This is managing.  This handle specifies the controller \r
+                       whose name is to be returned.\r
+    ChildHandle      - The handle of the child controller to retrieve the name \r
+                       of.  This is an optional parameter that may be NULL.  It \r
+                       will be NULL for device drivers.  It will also be NULL \r
+                       for a bus drivers that wish to retrieve the name of the \r
+                       bus controller.  It will not be NULL for a bus driver \r
+                       that wishes to retrieve the name of a child controller.\r
+    Language         - A pointer to a three character ISO 639-2 language \r
+                       identifier.  This is the language of the controller name \r
+                       that that the caller is requesting, and it must match one\r
+                       of the languages specified in SupportedLanguages.  The \r
+                       number of languages supported by a driver is up to the \r
+                       driver writer.\r
+    ControllerName   - A pointer to the Unicode string to return.  This Unicode\r
+                       string is the name of the controller specified by \r
+                       ControllerHandle and ChildHandle in the language specified\r
+                       by Language from the point of view of the driver specified\r
+                       by This. \r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Unicode string for the user readable name in the \r
+                            language specified by Language for the driver \r
+                            specified by This was returned in DriverName.\r
+    EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.\r
+    EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.\r
+    EFI_INVALID_PARAMETER - Language is NULL.\r
+    EFI_INVALID_PARAMETER - ControllerName is NULL.\r
+    EFI_UNSUPPORTED       - The driver specified by This is not currently managing \r
+                            the controller specified by ControllerHandle and \r
+                            ChildHandle.\r
+    EFI_UNSUPPORTED       - The driver specified by This does not support the \r
+                            language specified by Language.\r
+\r
+--*/\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciBus.c b/DuetPkg/PciBusNoEnumerationDxe/PciBus.c
new file mode 100644 (file)
index 0000000..d50becd
--- /dev/null
@@ -0,0 +1,343 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciBus.c\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
\r
+--*/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// PCI Bus Support Function Prototypes\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
+  IN  EFI_HANDLE                    Controller,\r
+  IN  UINTN                         NumberOfChildren,\r
+  IN  EFI_HANDLE                    *ChildHandleBuffer\r
+  );\r
+\r
+\r
+//\r
+// PCI Bus Driver Global Variables\r
+//\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {\r
+  PciBusDriverBindingSupported,\r
+  PciBusDriverBindingStart,\r
+  PciBusDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+BOOLEAN gFullEnumeration;\r
\r
+//\r
+// PCI Bus Driver Support Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize the global variables\r
+  publish the driver binding protocol\r
+\r
+Arguments:\r
+\r
+  IN EFI_HANDLE     ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS \r
+  EFI_DEVICE_ERROR \r
+\r
+--*/\r
+{\r
+  EFI_STATUS         Status;\r
+\r
+  //\r
+  // Initialize the EFI Driver Library\r
+  //\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gPciBusDriverBinding,\r
+             ImageHandle,\r
+             &gPciBusComponentName,\r
+             &gPciBusComponentName2\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  InitializePciDevicePool ();\r
+\r
+  gFullEnumeration = TRUE;\r
+  \r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check to see if pci bus driver supports the given controller\r
+\r
+Arguments:\r
+  \r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  EFI_DEV_PATH_PTR                Node;\r
+\r
+  if (RemainingDevicePath != NULL) {\r
+    Node.DevPath = RemainingDevicePath;\r
+    if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
+        Node.DevPath->SubType != HW_PCI_DP         ||\r
+        DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+  //\r
+  // Open the IO Abstraction(s) needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+        Controller,\r
+        &gEfiDevicePathProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        Controller\r
+        );\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiPciRootBridgeIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Start to management the controller passed in\r
+\r
+Arguments:\r
+  \r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+\r
+Returns:\r
\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                          Status;\r
+\r
+  //\r
+  // Enumerate the entire host bridge\r
+  // After enumeration, a database that records all the device information will be created\r
+  //\r
+  //\r
+  Status = PciEnumerator (Controller);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Enable PCI device specified by remaining device path. BDS or other driver can call the\r
+  // start more than once.\r
+  //\r
+  \r
+  StartPciDevices (Controller, RemainingDevicePath);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
+  IN  EFI_HANDLE                    Controller,\r
+  IN  UINTN                         NumberOfChildren,\r
+  IN  EFI_HANDLE                    *ChildHandleBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Stop one or more children created at start of pci bus driver\r
+  if all the the children get closed, close the protocol\r
+\r
+Arguments:\r
+  \r
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
+  IN  EFI_HANDLE                    Controller,\r
+  IN  UINTN                         NumberOfChildren,\r
+  IN  EFI_HANDLE                    *ChildHandleBuffer\r
+\r
+Returns:\r
+\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Index;\r
+  BOOLEAN     AllChildrenStopped;\r
+\r
+  if (NumberOfChildren == 0) {\r
+    //\r
+    // Close the bus driver\r
+    //\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiDevicePathProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiPciRootBridgeIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+\r
+    DestroyRootBridgeByHandle (\r
+      Controller\r
+      );\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Stop all the children\r
+  //\r
+\r
+  AllChildrenStopped = TRUE;\r
+\r
+  for (Index = 0; Index < NumberOfChildren; Index++) {\r
+\r
+    //\r
+    // De register all the pci device\r
+    //\r
+    Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      AllChildrenStopped = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!AllChildrenStopped) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciBus.h b/DuetPkg/PciBusNoEnumerationDxe/PciBus.h
new file mode 100644 (file)
index 0000000..edc479b
--- /dev/null
@@ -0,0 +1,224 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciBus.h\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_BUS_H\r
+#define _EFI_PCI_BUS_H\r
+\r
+#include <FrameworkDxe.h>\r
+\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/Decompress.h>\r
+#include <Protocol/UgaIo.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/BusSpecificDriverOverride.h>\r
+\r
+#include <Guid/PciOptionRomTable.h>\r
+\r
+#include <IndustryStandard/Pci23.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/PeImage.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+\r
+//\r
+// Driver Produced Protocol Prototypes\r
+//\r
+\r
+#define VGABASE1  0x3B0\r
+#define VGALIMIT1 0x3BB\r
+\r
+#define VGABASE2  0x3C0\r
+#define VGALIMIT2 0x3DF\r
+\r
+#define ISABASE   0x100\r
+#define ISALIMIT  0x3FF\r
+\r
+typedef enum {\r
+  PciBarTypeUnknown = 0,\r
+  PciBarTypeIo16,\r
+  PciBarTypeIo32,\r
+  PciBarTypeMem32,\r
+  PciBarTypePMem32,\r
+  PciBarTypeMem64,\r
+  PciBarTypePMem64,\r
+  PciBarTypeIo,\r
+  PciBarTypeMem,\r
+  PciBarTypeMaxType\r
+} PCI_BAR_TYPE;\r
+\r
+typedef struct {\r
+  UINT64        BaseAddress;\r
+  UINT64        Length;\r
+  UINT64        Alignment;\r
+  PCI_BAR_TYPE  BarType;\r
+  BOOLEAN       Prefetchable;\r
+  UINT8         MemType;\r
+  UINT8         Offset;\r
+} PCI_BAR;\r
+\r
+#define PCI_IO_DEVICE_SIGNATURE   EFI_SIGNATURE_32 ('p','c','i','o')\r
+\r
+#define EFI_BRIDGE_IO32_DECODE_SUPPORTED        0x0001 \r
+#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED      0x0002 \r
+#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED      0x0004 \r
+#define EFI_BRIDGE_IO16_DECODE_SUPPORTED        0x0008  \r
+#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED   0x0010  \r
+#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED       0x0020\r
+#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED       0x0040\r
+\r
+\r
+typedef struct _PCI_IO_DEVICE {\r
+  UINT32                                    Signature;\r
+  EFI_HANDLE                                Handle;\r
+  EFI_PCI_IO_PROTOCOL                       PciIo;\r
+  LIST_ENTRY                            Link;\r
+\r
+  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;\r
+  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *PciRootBridgeIo;\r
+\r
+  //\r
+  // PCI configuration space header type\r
+  //\r
+  PCI_TYPE00                                Pci;\r
+\r
+  //\r
+  // Bus number, Device number, Function number\r
+  //\r
+  UINT8                                     BusNumber;\r
+  UINT8                                     DeviceNumber;\r
+  UINT8                                     FunctionNumber;\r
+\r
+  //\r
+  // BAR for this PCI Device\r
+  //\r
+  PCI_BAR                                   PciBar[PCI_MAX_BAR];\r
+\r
+  //\r
+  // The bridge device this pci device is subject to\r
+  //\r
+  struct _PCI_IO_DEVICE                     *Parent;\r
+\r
+  //\r
+  // A linked list for children Pci Device if it is bridge device\r
+  //\r
+  LIST_ENTRY                            ChildList;\r
+\r
+  //\r
+  // TURE if the PCI bus driver creates the handle for this PCI device\r
+  //\r
+  BOOLEAN                                   Registered;\r
+\r
+  //\r
+  // TRUE if the PCI bus driver successfully allocates the resource required by\r
+  // this PCI device\r
+  //\r
+  BOOLEAN                                   Allocated;\r
+\r
+  //\r
+  // The attribute this PCI device currently set\r
+  //\r
+  UINT64                                    Attributes;\r
+\r
+  //\r
+  // The attributes this PCI device actually supports\r
+  //\r
+  UINT64                                    Supports;\r
+\r
+  //\r
+  // The resource decode the bridge supports\r
+  //\r
+  UINT32                                    Decodes;\r
+\r
+  //\r
+  // The OptionRom Size\r
+  //\r
+  UINT64                                    RomSize;\r
+\r
+  //\r
+  // TRUE if there is any EFI driver in the OptionRom\r
+  //\r
+  BOOLEAN                                   BusOverride;\r
+\r
+  //\r
+  //  A list tracking reserved resource on a bridge device\r
+  //\r
+  LIST_ENTRY                            ReservedResourceList;\r
+\r
+  //\r
+  // A list tracking image handle of platform specific overriding driver\r
+  //\r
+  LIST_ENTRY                            OptionRomDriverList;\r
+\r
+  BOOLEAN                                   IsPciExp;\r
+\r
+} PCI_IO_DEVICE;\r
+\r
+\r
+#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \\r
+  CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \\r
+  CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+#define PCI_IO_DEVICE_FROM_LINK(a) \\r
+  CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;\r
+extern GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL  gPciBusComponentName2;\r
+extern EFI_DRIVER_BINDING_PROTOCOL  gPciBusDriverBinding;\r
+\r
+extern BOOLEAN                     gFullEnumeration;\r
+static UINT64                      gAllOne = 0xFFFFFFFFFFFFFFFF;\r
+static UINT64                      gAllZero   = 0;\r
+\r
+#include "PciIo.h"\r
+#include "PciCommand.h"\r
+#include "PciDeviceSupport.h"\r
+#include "PciEnumerator.h"\r
+#include "PciEnumeratorSupport.h"\r
+#include "PciDriverOverride.h"\r
+#include "PciRomTable.h"\r
+#include "PciOptionRomSupport.h"\r
+#include "PciPowerManagement.h"\r
+\r
+\r
+#define IS_ISA_BRIDGE(_p)       IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_ISA)  \r
+#define IS_INTEL_ISA_BRIDGE(_p) (IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_ISA_POSITIVE_DECODE) && ((_p)->Hdr.VendorId == 0x8086) && ((_p)->Hdr.DeviceId == 0x7110))\r
+\r
+#endif\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf b/DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
new file mode 100644 (file)
index 0000000..65adec9
--- /dev/null
@@ -0,0 +1,72 @@
+#/*++\r
+# \r
+# Copyright (c) 2005, Intel Corporation                                                         \r
+# All rights reserved. This program and the accompanying materials                          \r
+# are licensed and made available under the terms and conditions of the BSD License         \r
+# which accompanies this distribution.  The full text of the license may be found at        \r
+# http://opensource.org/licenses/bsd-license.php                                            \r
+#                                                                                           \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#\r
+#  Module Name:\r
+#\r
+#  Abstract:\r
+#\r
+#--*/\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PciBusNoEnumerationDxe\r
+  FILE_GUID                      = 35C0C168-2607-4e51-BB53-448E3ED1A87F\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+\r
+  ENTRY_POINT                    = PciBusEntryPoint\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  DebugLib\r
+  BaseLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  BaseMemoryLib\r
+  ReportStatusCodeLib\r
+  DevicePathLib\r
+\r
+[Sources]\r
+  PciBus.h\r
+  PciIo.h\r
+  PciCommand.h\r
+  PciDeviceSupport.h\r
+  PciEnumerator.h\r
+  PciEnumeratorSupport.h\r
+  PciOptionRomSupport.h\r
+  PciRomTable.h\r
+  PciPowerManagement.h\r
+  PciPowerManagement.c\r
+  PciRomTable.c\r
+  PciDriverOverride.h\r
+  PciDriverOverride.c\r
+  PciOptionRomSupport.c\r
+  PciEnumerator.c\r
+  PciEnumeratorSupport.c\r
+  PciCommand.c\r
+  ComponentName.c\r
+  PciDeviceSupport.c\r
+  PciBus.c\r
+  PciIo.c\r
+\r
+[Protocols]\r
+  gEfiPciRootBridgeIoProtocolGuid\r
+  gEfiPciIoProtocolGuid\r
+  gEfiDevicePathProtocolGuid\r
+  gEfiBusSpecificDriverOverrideProtocolGuid\r
+  gEfiPciOptionRomTableGuid\r
+  gEfiDecompressProtocolGuid\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciCommand.c b/DuetPkg/PciBusNoEnumerationDxe/PciCommand.c
new file mode 100644 (file)
index 0000000..8614ee2
--- /dev/null
@@ -0,0 +1,464 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciCommand.c\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Pcibus.h"\r
+\r
+\r
+EFI_STATUS \r
+PciReadCommandRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  OUT UINT16       *Command\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+\r
+  *Command = 0;\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  return PciIo->Pci.Read (\r
+                PciIo, \r
+                EfiPciIoWidthUint16, \r
+                PCI_COMMAND_OFFSET, \r
+                1, \r
+                Command\r
+                );\r
+}\r
+  \r
+EFI_STATUS \r
+PciSetCommandRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT16                Temp;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+  \r
+  Temp = Command;\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  return PciIo->Pci.Write (\r
+              PciIo, \r
+              EfiPciIoWidthUint16, \r
+              PCI_COMMAND_OFFSET, \r
+              1, \r
+              &Temp\r
+              );\r
+  \r
+}\r
+\r
+\r
+EFI_STATUS \r
+PciEnableCommandRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT16  OldCommand;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+\r
+  OldCommand = 0;\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  PciIo->Pci.Read (\r
+          PciIo, \r
+          EfiPciIoWidthUint16, \r
+          PCI_COMMAND_OFFSET, \r
+          1, \r
+          &OldCommand\r
+          );\r
+\r
+  OldCommand |= Command;\r
+\r
+  return PciIo->Pci.Write (\r
+              PciIo, \r
+              EfiPciIoWidthUint16, \r
+              PCI_COMMAND_OFFSET, \r
+              1, \r
+              &OldCommand\r
+              );\r
+  \r
+}\r
+\r
+\r
+EFI_STATUS \r
+PciDisableCommandRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT16  OldCommand;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+\r
+  OldCommand = 0;\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  PciIo->Pci.Read (\r
+          PciIo, \r
+          EfiPciIoWidthUint16, \r
+          PCI_COMMAND_OFFSET, \r
+          1, \r
+          &OldCommand\r
+          );\r
+\r
+  OldCommand &= ~(Command);\r
+\r
+  return PciIo->Pci.Write (\r
+            PciIo, \r
+            EfiPciIoWidthUint16, \r
+            PCI_COMMAND_OFFSET, \r
+            1, \r
+            &OldCommand\r
+           );\r
+  \r
+}\r
+\r
+\r
+\r
+EFI_STATUS \r
+PciSetBridgeControlRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT16                Temp;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+\r
+  Temp = Command;\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  return PciIo->Pci.Write (\r
+                PciIo, \r
+                EfiPciIoWidthUint16, \r
+                PCI_BRIDGE_CONTROL_REGISTER_OFFSET, \r
+                1, \r
+                &Temp\r
+               );\r
\r
+}\r
+\r
+\r
+EFI_STATUS \r
+PciEnableBridgeControlRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT16  OldCommand;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+\r
+  OldCommand = 0;\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  PciIo->Pci.Read (\r
+          PciIo, \r
+          EfiPciIoWidthUint16, \r
+          PCI_BRIDGE_CONTROL_REGISTER_OFFSET, \r
+          1, \r
+          &OldCommand\r
+          );\r
+\r
+  OldCommand |= Command;\r
+\r
+  return PciIo->Pci.Write (\r
+              PciIo, \r
+              EfiPciIoWidthUint16, \r
+              PCI_BRIDGE_CONTROL_REGISTER_OFFSET, \r
+              1, \r
+              &OldCommand\r
+             );\r
+  \r
+}\r
+\r
+EFI_STATUS \r
+PciDisableBridgeControlRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT16  OldCommand;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+\r
+  OldCommand = 0;\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  PciIo->Pci.Read (\r
+          PciIo, \r
+          EfiPciIoWidthUint16, \r
+          PCI_BRIDGE_CONTROL_REGISTER_OFFSET, \r
+          1, \r
+          &OldCommand\r
+          );\r
+\r
+  OldCommand &= ~(Command);\r
+\r
+  return PciIo->Pci.Write (\r
+              PciIo, \r
+              EfiPciIoWidthUint16, \r
+              PCI_BRIDGE_CONTROL_REGISTER_OFFSET, \r
+              1, \r
+              &OldCommand\r
+              );\r
\r
+}\r
+\r
+\r
+\r
+EFI_STATUS \r
+PciReadBridgeControlRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  OUT UINT16       *Command\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+\r
+  *Command = 0;\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  return PciIo->Pci.Read (\r
+                PciIo, \r
+                EfiPciIoWidthUint16, \r
+                PCI_BRIDGE_CONTROL_REGISTER_OFFSET, \r
+                1, \r
+                Command\r
+                );\r
\r
+}\r
+\r
+BOOLEAN\r
+PciCapabilitySupport (\r
+  IN PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  \r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+{\r
+\r
+  if (PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+LocateCapabilityRegBlock (\r
+  IN     PCI_IO_DEVICE *PciIoDevice,\r
+  IN     UINT8         CapId,\r
+  IN OUT UINT8         *Offset,\r
+     OUT UINT8         *NextRegBlock OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Locate Capability register.\r
+\r
+Arguments:\r
+\r
+  PciIoDevice         - A pointer to the PCI_IO_DEVICE.\r
+  CapId               - The capability ID.\r
+  Offset              - A pointer to the offset. \r
+                        As input: the default offset; \r
+                        As output: the offset of the found block.\r
+  NextRegBlock        - An optional pointer to return the value of next block.\r
+\r
+Returns:\r
+  \r
+  EFI_UNSUPPORTED     - The Pci Io device is not supported.\r
+  EFI_NOT_FOUND       - The Pci Io device cannot be found.\r
+  EFI_SUCCESS         - The Pci Io device is successfully located.\r
+\r
+--*/\r
+{\r
+  UINT8   CapabilityPtr;\r
+  UINT16  CapabilityEntry;\r
+  UINT8   CapabilityID;\r
+  UINT32  Temp;\r
+\r
+  //\r
+  // To check the capability of this device supports\r
+  //\r
+  if (!PciCapabilitySupport (PciIoDevice)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (*Offset != 0) {\r
+    CapabilityPtr = *Offset;\r
+  } else {\r
+\r
+    CapabilityPtr = 0;\r
+    if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+      PciIoDevice->PciIo.Pci.Read (\r
+                               &PciIoDevice->PciIo,\r
+                               EfiPciIoWidthUint8,\r
+                               EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,\r
+                               1,\r
+                               &CapabilityPtr\r
+                               );\r
+    } else {\r
+\r
+      PciIoDevice->PciIo.Pci.Read (\r
+                               &PciIoDevice->PciIo,\r
+                               EfiPciIoWidthUint32,\r
+                               EFI_PCI_CAPABILITY_PTR,\r
+                               1,\r
+                               &Temp\r
+                               );\r
+      //\r
+      // Do not get byte read directly, because some PCI card will return 0xFF\r
+      // when perform PCI-Express byte read, while return correct 0x00 \r
+      // when perform PCI-Express dword read, or PCI dword read.\r
+      //\r
+      CapabilityPtr = (UINT8)Temp;\r
+    }\r
+  }\r
+\r
+  while (CapabilityPtr > 0x3F) {\r
+    //\r
+    // Mask it to DWORD alignment per PCI spec\r
+    //\r
+    CapabilityPtr &= 0xFC;\r
+    PciIoDevice->PciIo.Pci.Read (\r
+                             &PciIoDevice->PciIo,\r
+                             EfiPciIoWidthUint16,\r
+                             CapabilityPtr,\r
+                             1,\r
+                             &CapabilityEntry\r
+                             );\r
+\r
+    CapabilityID = (UINT8) CapabilityEntry;\r
+\r
+    if (CapabilityID == CapId) {\r
+      *Offset = CapabilityPtr;\r
+      if (NextRegBlock != NULL) {\r
+        *NextRegBlock = (UINT8) (CapabilityEntry >> 8);\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CapabilityPtr = (UINT8) (CapabilityEntry >> 8);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciCommand.h b/DuetPkg/PciBusNoEnumerationDxe/PciCommand.h
new file mode 100644 (file)
index 0000000..3e948fd
--- /dev/null
@@ -0,0 +1,167 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  \r
+    PciCommand.h\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_COMMAND_H\r
+#define _EFI_PCI_COMMAND_H\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// The PCI Command register bits owned by PCI Bus driver.\r
+//\r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCI_COMMAND_BITS_OWNED                          ( \\r
+                EFI_PCI_COMMAND_IO_SPACE                    | \\r
+                EFI_PCI_COMMAND_MEMORY_SPACE                | \\r
+                EFI_PCI_COMMAND_BUS_MASTER                  | \\r
+                EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \\r
+                EFI_PCI_COMMAND_VGA_PALETTE_SNOOP           | \\r
+                EFI_PCI_COMMAND_FAST_BACK_TO_BACK             \\r
+                )\r
+\r
+//\r
+// The PCI Bridge Control register bits owned by PCI Bus driver.\r
+// \r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED                   ( \\r
+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \\r
+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \\r
+                EFI_PCI_BRIDGE_CONTROL_VGA_16               | \\r
+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \\r
+                )\r
+\r
+//\r
+// The PCCard Bridge Control register bits owned by PCI Bus driver.\r
+// \r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED                ( \\r
+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \\r
+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \\r
+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \\r
+                )\r
+\r
+EFI_STATUS \r
+PciReadCommandRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  OUT UINT16       *Command\r
+);\r
+\r
+  \r
+EFI_STATUS \r
+PciSetCommandRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+);\r
+\r
+EFI_STATUS \r
+PciEnableCommandRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+);\r
+\r
+EFI_STATUS \r
+PciDisableCommandRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+);\r
+\r
+EFI_STATUS \r
+PciDisableBridgeControlRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+);\r
+\r
+\r
+EFI_STATUS \r
+PciEnableBridgeControlRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINT16        Command\r
+);\r
+\r
+EFI_STATUS \r
+PciReadBridgeControlRegister (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  OUT UINT16       *Command\r
+);\r
+\r
+BOOLEAN\r
+PciCapabilitySupport (\r
+  IN PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PciIoDevice - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+LocateCapabilityRegBlock (\r
+  IN     PCI_IO_DEVICE *PciIoDevice,\r
+  IN     UINT8         CapId,\r
+  IN OUT UINT8         *Offset,\r
+     OUT UINT8         *NextRegBlock OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Locate Capability register.\r
+\r
+Arguments:\r
+\r
+  PciIoDevice         - A pointer to the PCI_IO_DEVICE.\r
+  CapId               - The capability ID.\r
+  Offset              - A pointer to the offset. \r
+                        As input: the default offset; \r
+                        As output: the offset of the found block.\r
+  NextRegBlock        - An optional pointer to return the value of next block.\r
+\r
+Returns:\r
+  \r
+  EFI_UNSUPPORTED     - The Pci Io device is not supported.\r
+  EFI_NOT_FOUND       - The Pci Io device cannot be found.\r
+  EFI_SUCCESS         - The Pci Io device is successfully located.\r
+\r
+--*/\r
+;\r
+\r
+\r
+#endif\r
+\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.c b/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.c
new file mode 100644 (file)
index 0000000..822f41a
--- /dev/null
@@ -0,0 +1,973 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciDeviceSupport.c\r
+  \r
+Abstract:\r
+\r
+  This file provides routine to support Pci device node manipulation\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Pcibus.h"\r
+\r
+//\r
+// This device structure is serviced as a header.\r
+// Its Next field points to the first root bridge device node\r
+//\r
+LIST_ENTRY  gPciDevicePool;\r
+\r
+EFI_STATUS\r
+InitializePciDevicePool (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize the gPciDevicePool\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  InitializeListHead (&gPciDevicePool);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InsertRootBridge (\r
+  IN PCI_IO_DEVICE *RootBridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Insert a root bridge into PCI device pool\r
+\r
+Arguments:\r
+\r
+  RootBridge    - A pointer to the PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  InsertTailList (&gPciDevicePool, &(RootBridge->Link));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InsertPciDevice (\r
+  PCI_IO_DEVICE *Bridge,\r
+  PCI_IO_DEVICE *PciDeviceNode\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to insert a PCI device node under\r
+  a bridge\r
+\r
+Arguments:\r
+  Bridge        - A pointer to the PCI_IO_DEVICE.\r
+  PciDeviceNode - A pointer to the PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+{\r
+\r
+  InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));\r
+  PciDeviceNode->Parent = Bridge;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DestroyRootBridge (\r
+  IN PCI_IO_DEVICE *RootBridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  \r
+Arguments:\r
+\r
+  RootBridge   - A pointer to the PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  DestroyPciDeviceTree (RootBridge);\r
+\r
+  gBS->FreePool (RootBridge);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DestroyPciDeviceTree (\r
+  IN PCI_IO_DEVICE *Bridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Destroy all the pci device node under the bridge.\r
+  Bridge itself is not included.\r
+\r
+Arguments:\r
+\r
+  Bridge   - A pointer to the PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  LIST_ENTRY  *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+    CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+    //\r
+    // Remove this node from the linked list\r
+    //\r
+    RemoveEntryList (CurrentLink);\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (IS_PCI_BRIDGE (&(Temp->Pci))) {\r
+      DestroyPciDeviceTree (Temp);\r
+    }\r
+    gBS->FreePool (Temp);\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DestroyRootBridgeByHandle (\r
+  EFI_HANDLE Controller\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Destroy all device nodes under the root bridge\r
+  specified by Controller. \r
+  The root bridge itself is also included.\r
+\r
+Arguments:\r
+\r
+  Controller   - An efi handle.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  LIST_ENTRY  *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  CurrentLink = gPciDevicePool.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &gPciDevicePool) {\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->Handle == Controller) {\r
+\r
+      RemoveEntryList (CurrentLink);\r
+\r
+      DestroyPciDeviceTree (Temp);\r
+\r
+      gBS->FreePool(Temp);\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+RegisterPciDevice (\r
+  IN  EFI_HANDLE                     Controller,\r
+  IN  PCI_IO_DEVICE                  *PciIoDevice,\r
+  OUT EFI_HANDLE                     *Handle OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function registers the PCI IO device. It creates a handle for this PCI IO device \r
+  (if the handle does not exist), attaches appropriate protocols onto the handle, does\r
+  necessary initialization, and sets up parent/child relationship with its bus controller.\r
+\r
+Arguments:\r
+\r
+  Controller    - An EFI handle for the PCI bus controller.\r
+  PciIoDevice   - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.\r
+  Handle        - A pointer to hold the EFI handle for the PCI IO device.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS   - The PCI device is successfully registered.\r
+  Others        - An error occurred when registering the PCI device.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS          Status;\r
+  UINT8               PciExpressCapRegOffset;\r
+\r
+  //\r
+  // Install the pciio protocol, device path protocol and \r
+  // Bus Specific Driver Override Protocol\r
+  //\r
+\r
+  if (PciIoDevice->BusOverride) {\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &PciIoDevice->Handle,             \r
+                  &gEfiDevicePathProtocolGuid,\r
+                  PciIoDevice->DevicePath,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  &PciIoDevice->PciIo,\r
+                  &gEfiBusSpecificDriverOverrideProtocolGuid,\r
+                  &PciIoDevice->PciDriverOverride,\r
+                  NULL\r
+                  );\r
+  } else {\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &PciIoDevice->Handle,             \r
+                  &gEfiDevicePathProtocolGuid,\r
+                  PciIoDevice->DevicePath,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  &PciIoDevice->PciIo,\r
+                  NULL\r
+                  );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  } else {\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,           \r
+                    &gEfiPciRootBridgeIoProtocolGuid, \r
+                    (VOID **)&(PciIoDevice->PciRootBridgeIo),\r
+                    gPciBusDriverBinding.DriverBindingHandle,\r
+                    PciIoDevice->Handle,   \r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  if (Handle != NULL) {\r
+    *Handle = PciIoDevice->Handle;\r
+  }\r
+\r
+  //\r
+  // Detect if PCI Express Device\r
+  //\r
+  PciExpressCapRegOffset = 0;\r
+  Status = LocateCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCI_CAPABILITY_ID_PCIEXP,\r
+             &PciExpressCapRegOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    PciIoDevice->IsPciExp = TRUE;\r
+    DEBUG ((EFI_D_ERROR, "PciExp - %x (B-%x, D-%x, F-%x)\n", PciIoDevice->IsPciExp, PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber));\r
+  }\r
+  \r
+  //\r
+  // Indicate the pci device is registered\r
+  //\r
+  PciIoDevice->Registered = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+DeRegisterPciDevice (\r
+  IN  EFI_HANDLE                     Controller,\r
+  IN  EFI_HANDLE                     Handle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to de-register the PCI device from the EFI,\r
+  That includes un-installing PciIo protocol from the specified PCI \r
+  device handle.\r
+\r
+Arguments:\r
+\r
+  Controller   - An efi handle.\r
+  Handle       - An efi handle.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_PCI_IO_PROTOCOL             *PciIo;\r
+  EFI_STATUS                      Status;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+  PCI_IO_DEVICE                   *Node;\r
+  LIST_ENTRY                  *CurrentLink;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &PciIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
+\r
+    //\r
+    // If it is already de-registered\r
+    //\r
+    if (!PciIoDevice->Registered) {\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    //\r
+    // If it is PPB, first de-register its children\r
+    //\r
+\r
+    if (IS_PCI_BRIDGE (&(PciIoDevice->Pci))) {\r
+\r
+      CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+\r
+      while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
+        Node    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+        Status  = DeRegisterPciDevice (Controller, Node->Handle);\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        CurrentLink = CurrentLink->ForwardLink;\r
+      }\r
+    }\r
+\r
+    //\r
+    // First disconnect this device\r
+    //\r
+//    PciIoDevice->PciIo.Attributes(&(PciIoDevice->PciIo),\r
+//                                    EfiPciIoAttributeOperationDisable,\r
+//                                    EFI_PCI_DEVICE_ENABLE,\r
+//                                    NULL\r
+//                                    );\r
+       \r
+    //\r
+    // Close the child handle\r
+    //\r
+    Status = gBS->CloseProtocol (\r
+                    Controller,\r
+                    &gEfiPciRootBridgeIoProtocolGuid,\r
+                    gPciBusDriverBinding.DriverBindingHandle,\r
+                    Handle\r
+                    );\r
+\r
+    //\r
+    // Un-install the device path protocol and pci io protocol\r
+    //\r
+    if (PciIoDevice->BusOverride) {\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      Handle,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      PciIoDevice->DevicePath,\r
+                      &gEfiPciIoProtocolGuid,\r
+                      &PciIoDevice->PciIo,\r
+                      &gEfiBusSpecificDriverOverrideProtocolGuid,\r
+                      &PciIoDevice->PciDriverOverride,\r
+                      NULL\r
+                      );\r
+    } else {\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      Handle,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      PciIoDevice->DevicePath,\r
+                      &gEfiPciIoProtocolGuid,\r
+                      &PciIoDevice->PciIo,\r
+                      NULL\r
+                      );\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->OpenProtocol (\r
+            Controller,\r
+            &gEfiPciRootBridgeIoProtocolGuid,\r
+            (VOID **) &PciRootBridgeIo,\r
+            gPciBusDriverBinding.DriverBindingHandle,\r
+            Handle,\r
+            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+            );\r
+      return Status;\r
+    }\r
+    \r
+    //\r
+    // The Device Driver should disable this device after disconnect\r
+    // so the Pci Bus driver will not touch this device any more.\r
+    // Restore the register field to the original value\r
+    //\r
+    PciIoDevice->Registered = FALSE;\r
+    PciIoDevice->Handle     = NULL;\r
+  } else {\r
+\r
+    //\r
+    // Handle may be closed before\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EnableBridgeAttributes (\r
+  IN PCI_IO_DEVICE                       *PciIoDevice\r
+  )\r
+{\r
+  PCI_TYPE01                PciData;\r
+\r
+  //\r
+  // NOTE: We should not set EFI_PCI_DEVICE_ENABLE for a bridge\r
+  //       directly, because some legacy BIOS will NOT assign\r
+  //       IO or Memory resource for a bridge who has no child\r
+  //       device. So we add check IO or Memory here.\r
+  //\r
+\r
+  PciIoDevice->PciIo.Pci.Read (\r
+                           &PciIoDevice->PciIo,\r
+                           EfiPciIoWidthUint8,\r
+                           0,\r
+                           sizeof (PciData),\r
+                           &PciData\r
+                           );\r
+\r
+  if ((((PciData.Bridge.IoBase & 0xF) == 0) &&\r
+        (PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) ||\r
+      (((PciData.Bridge.IoBase & 0xF) == 1) &&\r
+        ((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) {\r
+    PciIoDevice->PciIo.Attributes(\r
+                         &(PciIoDevice->PciIo),\r
+                         EfiPciIoAttributeOperationEnable,\r
+                         (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),\r
+                         NULL\r
+                         );\r
+  }\r
+  if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) {\r
+    PciIoDevice->PciIo.Attributes(\r
+                         &(PciIoDevice->PciIo),\r
+                         EfiPciIoAttributeOperationEnable,\r
+                         (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),\r
+                         NULL\r
+                         );\r
+  }\r
+  if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) &&\r
+        (PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) ||\r
+      (((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) &&\r
+        ((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) {\r
+    PciIoDevice->PciIo.Attributes(\r
+                         &(PciIoDevice->PciIo),\r
+                         EfiPciIoAttributeOperationEnable,\r
+                         (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),\r
+                         NULL\r
+                         );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS \r
+StartPciDevicesOnBridge (\r
+  IN EFI_HANDLE                          Controller,\r
+  IN PCI_IO_DEVICE                       *RootBridge,\r
+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath \r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge\r
+\r
+Arguments:\r
+\r
+  Controller          - An efi handle.\r
+  RootBridge          - A pointer to the PCI_IO_DEVICE.\r
+  RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.\r
+  NumberOfChildren    - Children number.\r
+  ChildHandleBuffer   - A pointer to the child handle buffer.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE             *Temp;\r
+  PCI_IO_DEVICE             *PciIoDevice;\r
+  EFI_DEV_PATH_PTR          Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;\r
+  EFI_STATUS                Status;\r
+  LIST_ENTRY            *CurrentLink;\r
+\r
+  CurrentLink = RootBridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    if (RemainingDevicePath != NULL) {\r
+\r
+      Node.DevPath = RemainingDevicePath;\r
+\r
+      if (Node.Pci->Device != Temp->DeviceNumber || \r
+          Node.Pci->Function != Temp->FunctionNumber) {\r
+        CurrentLink = CurrentLink->ForwardLink;\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Check if the device has been assigned with required resource\r
+      //\r
+      if (!Temp->Allocated) {\r
+        return EFI_NOT_READY;\r
+      }\r
+      \r
+      //\r
+      // Check if the current node has been registered before\r
+      // If it is not, register it\r
+      //\r
+      if (!Temp->Registered) {\r
+        PciIoDevice = Temp;\r
+\r
+        Status = RegisterPciDevice (\r
+                  Controller,\r
+                  PciIoDevice,\r
+                  NULL\r
+                  );\r
+\r
+      }\r
+      \r
+      //\r
+      // Get the next device path\r
+      //\r
+      CurrentDevicePath = EfiNextDevicePathNode (RemainingDevicePath);\r
+      if (EfiIsDevicePathEnd (CurrentDevicePath)) {\r
+        return EFI_SUCCESS;\r
+      }\r
+  \r
+      //\r
+      // If it is a PPB\r
+      //\r
+      if (IS_PCI_BRIDGE (&(Temp->Pci))) {\r
+        Status = StartPciDevicesOnBridge (\r
+                  Controller,\r
+                  Temp,\r
+                  CurrentDevicePath\r
+                  );\r
+        EnableBridgeAttributes (Temp);\r
+\r
+        return Status;\r
+      } else {\r
+\r
+        //\r
+        // Currently, the PCI bus driver only support PCI-PCI bridge\r
+        //\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+\r
+    } else {\r
+\r
+      //\r
+      // If remaining device path is NULL,\r
+      // try to enable all the pci devices under this bridge\r
+      //\r
+\r
+      if (!Temp->Registered && Temp->Allocated) {\r
+\r
+        PciIoDevice = Temp;\r
+\r
+        Status = RegisterPciDevice (\r
+                  Controller,\r
+                  PciIoDevice,\r
+                  NULL\r
+                  );\r
+\r
+      }\r
+\r
+      if (IS_PCI_BRIDGE (&(Temp->Pci))) {\r
+        Status = StartPciDevicesOnBridge ( \r
+                   Controller,\r
+                   Temp,\r
+                   RemainingDevicePath\r
+                   );\r
+        EnableBridgeAttributes (Temp);\r
+      }\r
+\r
+      CurrentLink = CurrentLink->ForwardLink;\r
+      continue;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+StartPciDevices (\r
+  IN EFI_HANDLE                         Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Start to manage the PCI device according to RemainingDevicePath\r
+  If RemainingDevicePath == NULL, the PCI bus driver will start \r
+  to manage all the PCI devices it found previously\r
+\r
+Arguments:\r
+  Controller          - An efi handle.\r
+  RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_DEV_PATH_PTR  Node;\r
+  PCI_IO_DEVICE     *RootBridge;\r
+  LIST_ENTRY    *CurrentLink;\r
+\r
+  if (RemainingDevicePath != NULL) {\r
+\r
+    //\r
+    // Check if the RemainingDevicePath is valid\r
+    //\r
+    Node.DevPath = RemainingDevicePath;\r
+    if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
+        Node.DevPath->SubType != HW_PCI_DP         &&\r
+        DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)\r
+        ) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  CurrentLink = gPciDevicePool.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &gPciDevicePool) {\r
+\r
+    RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    //\r
+    // Locate the right root bridge to start\r
+    //\r
+    if (RootBridge->Handle == Controller) {\r
+      StartPciDevicesOnBridge (\r
+        Controller,\r
+        RootBridge,\r
+        RemainingDevicePath\r
+        );\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+CreateRootBridge (\r
+  IN EFI_HANDLE RootBridgeHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+  RootBridgeHandle   - An efi handle.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  EFI_STATUS                      Status;\r
+  PCI_IO_DEVICE                   *Dev;\r
+\r
+  Dev = NULL;\r
+  Status = gBS->AllocatePool (\r
+                  EfiBootServicesData,\r
+                  sizeof (PCI_IO_DEVICE),\r
+                  (VOID **) &Dev\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  ZeroMem (Dev, sizeof (PCI_IO_DEVICE));\r
+  Dev->Signature  = PCI_IO_DEVICE_SIGNATURE;\r
+  Dev->Handle     = RootBridgeHandle;\r
+  InitializeListHead (&Dev->ChildList);\r
+\r
+  return Dev;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+GetRootBridgeByHandle (\r
+  EFI_HANDLE RootBridgeHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+  RootBridgeHandle    - An efi handle.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE   *RootBridgeDev;\r
+  LIST_ENTRY  *CurrentLink;\r
+\r
+  CurrentLink = gPciDevicePool.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &gPciDevicePool) {\r
+\r
+    RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    if (RootBridgeDev->Handle == RootBridgeHandle) {\r
+      return RootBridgeDev;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+BOOLEAN\r
+RootBridgeExisted (\r
+  IN EFI_HANDLE RootBridgeHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function searches if RootBridgeHandle has already existed\r
+  in current device pool.\r
+\r
+  If so, it means the given root bridge has been already enumerated.\r
+\r
+Arguments:\r
+\r
+  RootBridgeHandle   - An efi handle.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE *Bridge;\r
+\r
+  Bridge = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+  if (Bridge != NULL) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+PciDeviceExisted (\r
+  IN PCI_IO_DEVICE    *Bridge,\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+Arguments:\r
+\r
+  Bridge       - A pointer to the PCI_IO_DEVICE.\r
+  PciIoDevice  - A pointer to the PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  PCI_IO_DEVICE   *Temp;\r
+  LIST_ENTRY  *CurrentLink;\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp == PciIoDevice) {\r
+      return TRUE;\r
+    }\r
+\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+      if (PciDeviceExisted (Temp, PciIoDevice)) {\r
+        return TRUE;\r
+      }\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheSameSegment (\r
+  IN PCI_IO_DEVICE        *VgaDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  VgaDevice    - A pointer to the PCI_IO_DEVICE.\r
+  \r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  LIST_ENTRY  *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  CurrentLink = gPciDevicePool.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &gPciDevicePool) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {\r
+\r
+      Temp = ActiveVGADeviceOnTheRootBridge (Temp);\r
+\r
+      if (Temp != NULL) {\r
+        return Temp;\r
+      }\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheRootBridge (\r
+  IN PCI_IO_DEVICE        *RootBridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  RootBridge    - A pointer to the PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  LIST_ENTRY  *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  CurrentLink = RootBridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (IS_PCI_VGA(&Temp->Pci) && \r
+        (Temp->Attributes &\r
+         (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |\r
+          EFI_PCI_IO_ATTRIBUTE_VGA_IO     |\r
+          EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) {\r
+      return Temp;\r
+    }\r
+\r
+    if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+\r
+      Temp = ActiveVGADeviceOnTheRootBridge (Temp);\r
+\r
+      if (Temp != NULL) {\r
+        return Temp;\r
+      }\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.h b/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.h
new file mode 100644 (file)
index 0000000..610d949
--- /dev/null
@@ -0,0 +1,324 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciDeviceSupport.h\r
+  \r
+Abstract:\r
+\r
+  \r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_DEVICE_SUPPORT_H\r
+#define _EFI_PCI_DEVICE_SUPPORT_H\r
+\r
+EFI_STATUS\r
+InitializePciDevicePool (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+InsertPciDevice (\r
+  PCI_IO_DEVICE *Bridge,\r
+  PCI_IO_DEVICE *PciDeviceNode\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Bridge        - TODO: add argument description\r
+  PciDeviceNode - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+DestroyPciDeviceTree (\r
+  IN PCI_IO_DEVICE *Bridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Bridge  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+DestroyRootBridgeByHandle (\r
+  EFI_HANDLE Controller\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Controller  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+RegisterPciDevice (\r
+  IN  EFI_HANDLE                     Controller,\r
+  IN  PCI_IO_DEVICE                  *PciIoDevice,\r
+  OUT EFI_HANDLE                     *Handle OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function registers the PCI IO device. It creates a handle for this PCI IO device \r
+  (if the handle does not exist), attaches appropriate protocols onto the handle, does\r
+  necessary initialization, and sets up parent/child relationship with its bus controller.\r
+\r
+Arguments:\r
+\r
+  Controller    - An EFI handle for the PCI bus controller.\r
+  PciIoDevice   - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.\r
+  Handle        - A pointer to hold the EFI handle for the PCI IO device.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS   - The PCI device is successfully registered.\r
+  Others        - An error occurred when registering the PCI device.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+DeRegisterPciDevice (\r
+  IN  EFI_HANDLE                     Controller,\r
+  IN  EFI_HANDLE                     Handle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Controller  - TODO: add argument description\r
+  Handle      - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+StartPciDevices (\r
+  IN EFI_HANDLE                         Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Controller          - TODO: add argument description\r
+  RemainingDevicePath - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+PCI_IO_DEVICE *\r
+CreateRootBridge (\r
+  IN EFI_HANDLE RootBridgeHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  RootBridgeHandle  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+PCI_IO_DEVICE *\r
+GetRootBridgeByHandle (\r
+  EFI_HANDLE RootBridgeHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  RootBridgeHandle  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS \r
+InsertRootBridge (\r
+  PCI_IO_DEVICE *RootBridge\r
+);\r
+\r
+EFI_STATUS \r
+DestroyRootBridge ( \r
+   IN PCI_IO_DEVICE *RootBridge \r
+);\r
+\r
+BOOLEAN\r
+RootBridgeExisted (\r
+  IN EFI_HANDLE RootBridgeHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  RootBridgeHandle  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+PciDeviceExisted (\r
+  IN PCI_IO_DEVICE    *Bridge,\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Bridge      - TODO: add argument description\r
+  PciIoDevice - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheSameSegment (\r
+  IN PCI_IO_DEVICE        *VgaDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  VgaDevice - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheRootBridge (\r
+  IN PCI_IO_DEVICE        *RootBridge\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  RootBridge  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+#endif\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.c b/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.c
new file mode 100644 (file)
index 0000000..888f379
--- /dev/null
@@ -0,0 +1,290 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciDriverOverride.c\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "pcibus.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriver(\r
+  IN     struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *This,\r
+  IN OUT EFI_HANDLE                                         *DriverImageHandle\r
+  );\r
+\r
+\r
+\r
+EFI_STATUS\r
+InitializePciDriverOverrideInstance (\r
+  PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initializes a PCI Driver Override Instance\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+{\r
+  PciIoDevice->PciDriverOverride.GetDriver = GetDriver;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriver (\r
+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,\r
+  IN OUT EFI_HANDLE                                         *DriverImageHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get a overriding driver image\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE             *PciIoDevice;\r
+  LIST_ENTRY            *CurrentLink;\r
+  PCI_DRIVER_OVERRIDE_LIST  *Node;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);\r
+\r
+  CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;\r
+\r
+  while (CurrentLink && CurrentLink != &PciIoDevice->OptionRomDriverList) {\r
+\r
+    Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);\r
+\r
+    if (*DriverImageHandle == NULL) {\r
+\r
+      *DriverImageHandle = Node->DriverImageHandle;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    if (*DriverImageHandle == Node->DriverImageHandle) {\r
+\r
+      if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||\r
+          CurrentLink->ForwardLink == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      //\r
+      // Get next node\r
+      //\r
+      Node                = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);\r
+      *DriverImageHandle  = Node->DriverImageHandle;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+AddDriver (\r
+  IN PCI_IO_DEVICE     *PciIoDevice,\r
+  IN EFI_HANDLE        DriverImageHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add a overriding driver image\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_IMAGE_DOS_HEADER          *DosHdr;\r
+  EFI_IMAGE_NT_HEADERS          *PeHdr;\r
+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;\r
+  PCI_DRIVER_OVERRIDE_LIST      *Node;\r
+#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
+  EFI_DRIVER_OS_HANDOFF_HEADER  *DriverOsHandoffHeader;\r
+  EFI_DRIVER_OS_HANDOFF_HEADER  *NewDriverOsHandoffHeader;\r
+  EFI_DRIVER_OS_HANDOFF         *DriverOsHandoff;\r
+  EFI_DEVICE_PATH_PROTOCOL      *DevicePath;\r
+  EFI_HANDLE                    DeviceHandle;\r
+  UINTN                         NumberOfEntries;\r
+  UINTN                         Size;\r
+  UINTN                         Index;\r
+#endif\r
+\r
+  Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));\r
+  if (Node == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Node->Signature         = DRIVER_OVERRIDE_SIGNATURE;\r
+  Node->DriverImageHandle = DriverImageHandle;\r
+\r
+  InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));\r
+\r
+  PciIoDevice->BusOverride  = TRUE;\r
+\r
+  DosHdr                    = (EFI_IMAGE_DOS_HEADER *) LoadedImage->ImageBase;\r
+  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) LoadedImage->ImageBase + DosHdr->e_lfanew);\r
+\r
+  if (PeHdr->FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+#if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
+  DriverOsHandoffHeader = NULL;\r
+  Status                = EfiLibGetSystemConfigurationTable (&gEfiUgaIoProtocolGuid, (VOID **) &DriverOsHandoffHeader);\r
+  if (!EFI_ERROR (Status) && DriverOsHandoffHeader != NULL) {\r
+    for (Index = 0; Index < DriverOsHandoffHeader->NumberOfEntries; Index++) {\r
+      DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)(DriverOsHandoffHeader)    + \r
+                                                  DriverOsHandoffHeader->HeaderSize + \r
+                                                  Index * DriverOsHandoffHeader->SizeOfEntries);\r
+      DevicePath  = DriverOsHandoff->DevicePath;\r
+      Status      = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
+      if (!EFI_ERROR (Status) && DeviceHandle != NULL && IsDevicePathEnd (DevicePath)) {\r
+        if (DeviceHandle == PciIoDevice->Handle) {\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+\r
+    NumberOfEntries = DriverOsHandoffHeader->NumberOfEntries + 1;\r
+  } else {\r
+    NumberOfEntries = 1;\r
+  }\r
+\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  sizeof (EFI_DRIVER_OS_HANDOFF_HEADER) + NumberOfEntries * sizeof (EFI_DRIVER_OS_HANDOFF),\r
+                  (VOID **) &NewDriverOsHandoffHeader\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (DriverOsHandoffHeader == NULL) {\r
+    NewDriverOsHandoffHeader->Version         = 0;\r
+    NewDriverOsHandoffHeader->HeaderSize      = sizeof (EFI_DRIVER_OS_HANDOFF_HEADER);\r
+    NewDriverOsHandoffHeader->SizeOfEntries   = sizeof (EFI_DRIVER_OS_HANDOFF);\r
+    NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;\r
+  } else {\r
+    gBS->CopyMem (\r
+          NewDriverOsHandoffHeader,\r
+          DriverOsHandoffHeader,\r
+          DriverOsHandoffHeader->HeaderSize + (NumberOfEntries - 1) * DriverOsHandoffHeader->SizeOfEntries\r
+          );\r
+    NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;\r
+  }\r
+\r
+  DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)NewDriverOsHandoffHeader      + \r
+                                              NewDriverOsHandoffHeader->HeaderSize + \r
+                                              (NumberOfEntries - 1) * NewDriverOsHandoffHeader->SizeOfEntries);\r
+\r
+  //\r
+  // Fill in the EFI_DRIVER_OS_HANDOFF structure\r
+  //\r
+  DriverOsHandoff->Type = EfiUgaDriverFromPciRom;\r
+\r
+  //\r
+  // Compute the size of the device path\r
+  //\r
+  Size = EfiDevicePathSize (PciIoDevice->DevicePath);\r
+  if (Size == 0) {\r
+    DriverOsHandoff->DevicePath = NULL;\r
+  } else {\r
+\r
+    //\r
+    // Allocate space for duplicate device path\r
+    //\r
+    Status = gBS->AllocatePool (\r
+                    EfiRuntimeServicesData,\r
+                    Size,\r
+                    (VOID **) &DriverOsHandoff->DevicePath\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->FreePool (NewDriverOsHandoffHeader);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Make copy of device path\r
+    //\r
+    CopyMem (DriverOsHandoff->DevicePath, PciIoDevice->DevicePath, Size);\r
+  }\r
+\r
+  DriverOsHandoff->PciRomSize = (UINT64) PciIoDevice->PciIo.RomSize;\r
+  Status = gBS->AllocatePool (\r
+                  EfiRuntimeServicesData,\r
+                  (UINTN) DriverOsHandoff->PciRomSize,\r
+                  (VOID **) &DriverOsHandoff->PciRomImage\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (NewDriverOsHandoffHeader);\r
+    return Status;\r
+  }\r
+\r
+  gBS->CopyMem (\r
+        DriverOsHandoff->PciRomImage,\r
+        PciIoDevice->PciIo.RomImage,\r
+        (UINTN) DriverOsHandoff->PciRomSize\r
+        );\r
+\r
+  Status = gBS->InstallConfigurationTable (&gEfiUgaIoProtocolGuid, NewDriverOsHandoffHeader);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (DriverOsHandoffHeader != NULL) {\r
+    gBS->FreePool (DriverOsHandoffHeader);\r
+  }\r
+#endif\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.h b/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.h
new file mode 100644 (file)
index 0000000..e6fbe92
--- /dev/null
@@ -0,0 +1,110 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciDriverOverride.h\r
+  \r
+Abstract:\r
+\r
+  \r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H\r
+#define _EFI_PCI_DRIVER_OVERRRIDE_H\r
+\r
+#include "PciBus.h"\r
+\r
+#define DRIVER_OVERRIDE_SIGNATURE EFI_SIGNATURE_32 ('d', 'r', 'o', 'v')\r
+\r
+typedef struct {\r
+  UINT32          Signature;\r
+  LIST_ENTRY  Link;\r
+  EFI_HANDLE      DriverImageHandle;\r
+} PCI_DRIVER_OVERRIDE_LIST;\r
+\r
+\r
+#define DRIVER_OVERRIDE_FROM_LINK(a) \\r
+  CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE)\r
+\r
+\r
+EFI_STATUS\r
+InitializePciDriverOverrideInstance (\r
+  PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PciIoDevice - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+AddDriver (\r
+  IN PCI_IO_DEVICE     *PciIoDevice,\r
+  IN EFI_HANDLE        DriverImageHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PciIoDevice       - TODO: add argument description\r
+  DriverImageHandle - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriver (\r
+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,\r
+  IN OUT EFI_HANDLE                                         *DriverImageHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  This              - TODO: add argument description\r
+  DriverImageHandle - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.c b/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.c
new file mode 100644 (file)
index 0000000..b7af4ed
--- /dev/null
@@ -0,0 +1,57 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciEnumerator.c\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Pcibus.h"\r
+\r
+EFI_STATUS\r
+PciEnumerator (\r
+  IN EFI_HANDLE                    Controller\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to enumerate entire pci bus system \r
+  in a given platform\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  //\r
+  // This PCI bus driver depends on the legacy BIOS\r
+  // to do the resource allocation\r
+  //\r
+  gFullEnumeration = FALSE;\r
+\r
+  return PciEnumeratorLight (Controller) ;\r
+  \r
+}\r
+\r
+\r
+\r
+\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.h b/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.h
new file mode 100644 (file)
index 0000000..23d4083
--- /dev/null
@@ -0,0 +1,47 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciEnumerator.h\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_ENUMERATOR_H\r
+#define _EFI_PCI_ENUMERATOR_H\r
+\r
+EFI_STATUS\r
+PciEnumerator (\r
+  IN EFI_HANDLE                    Controller\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Controller  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+#endif
\ No newline at end of file
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c b/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
new file mode 100644 (file)
index 0000000..01d991d
--- /dev/null
@@ -0,0 +1,1384 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciEnumeratorSupport.c\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Pcibus.h"\r
+\r
+EFI_STATUS \r
+InitializePPB (\r
+  IN PCI_IO_DEVICE *PciIoDevice \r
+);\r
+\r
+EFI_STATUS \r
+InitializeP2C (\r
+  IN PCI_IO_DEVICE *PciIoDevice \r
+);\r
+\r
+PCI_IO_DEVICE* \r
+CreatePciIoDevice (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+);\r
+\r
+\r
+PCI_IO_DEVICE*\r
+GatherP2CInfo (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+);\r
+\r
+UINTN\r
+PciParseBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+);\r
+\r
+\r
+EFI_STATUS\r
+PciSearchDevice (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  PCI_TYPE00                            *Pci,\r
+  UINT8                                 Bus,\r
+  UINT8                                 Device,\r
+  UINT8                                 Func,\r
+  PCI_IO_DEVICE                         **PciDevice\r
+);\r
+\r
+\r
+EFI_STATUS \r
+DetermineDeviceAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+);\r
+\r
+EFI_STATUS \r
+BarExisted (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINTN         Offset,\r
+  OUT UINT32       *BarLengthValue,\r
+  OUT UINT32       *OriginalBarValue\r
+  );\r
+\r
+\r
+\r
+EFI_DEVICE_PATH_PROTOCOL*\r
+CreatePciDevicePath(\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+  IN  PCI_IO_DEVICE            *PciIoDevice \r
+);\r
+\r
+PCI_IO_DEVICE* \r
+GatherDeviceInfo (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+);\r
+\r
+PCI_IO_DEVICE* \r
+GatherPPBInfo (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+);\r
+\r
+EFI_STATUS\r
+PciDevicePresent (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  PCI_TYPE00                          *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to check whether the pci device is present\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT64      Address;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Create PCI address map in terms of Bus, Device and Func\r
+  //\r
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
+\r
+  //\r
+  // Read the Vendor Id register\r
+  //\r
+  Status = PciRootBridgeIo->Pci.Read (\r
+                                  PciRootBridgeIo,\r
+                                  EfiPciWidthUint32,\r
+                                  Address,\r
+                                  1,\r
+                                  Pci\r
+                                  );\r
+\r
+  if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {\r
+\r
+    //\r
+    // Read the entire config header for the device\r
+    //\r
+\r
+    Status = PciRootBridgeIo->Pci.Read (\r
+                                    PciRootBridgeIo,\r
+                                    EfiPciWidthUint32,\r
+                                    Address,\r
+                                    sizeof (PCI_TYPE00) / sizeof (UINT32),\r
+                                    Pci\r
+                                    );\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+PciPciDeviceInfoCollector (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  UINT8                                 StartBusNumber\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS          Status;\r
+  PCI_TYPE00          Pci;\r
+  UINT8               Device;\r
+  UINT8               Func;\r
+  UINT8               SecBus;\r
+  PCI_IO_DEVICE       *PciIoDevice;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  SecBus  = 0;\r
+\r
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+\r
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+      //\r
+      // Check to see whether PCI device is present\r
+      //\r
+\r
+      Status = PciDevicePresent (\r
+                Bridge->PciRootBridgeIo,\r
+                &Pci,\r
+                (UINT8) StartBusNumber,\r
+                (UINT8) Device,\r
+                (UINT8) Func\r
+                );\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+\r
+        //\r
+        // Collect all the information about the PCI device discovered\r
+        //\r
+        Status = PciSearchDevice (\r
+                  Bridge,\r
+                  &Pci,\r
+                  (UINT8) StartBusNumber,\r
+                  Device,\r
+                  Func,\r
+                  &PciIoDevice\r
+                  );\r
+\r
+        //\r
+        // Recursively scan PCI busses on the other side of PCI-PCI bridges\r
+        //\r
+        //\r
+\r
+        if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
+\r
+          //\r
+          // If it is PPB, we need to get the secondary bus to continue the enumeration\r
+          //\r
+          PciIo   = &(PciIoDevice->PciIo);\r
+\r
+          Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);\r
+\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+              \r
+          //\r
+          // Deep enumerate the next level bus\r
+          //\r
+          Status = PciPciDeviceInfoCollector (\r
+                    PciIoDevice,\r
+                    (UINT8) (SecBus)\r
+                    );\r
+\r
+        }\r
+\r
+        if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+\r
+          //\r
+          // Skip sub functions, this is not a multi function device\r
+          //\r
+          Func = PCI_MAX_FUNC;\r
+        }\r
+      }\r
+\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciSearchDevice (\r
+  IN  PCI_IO_DEVICE                         *Bridge,\r
+  IN  PCI_TYPE00                            *Pci,\r
+  IN  UINT8                                 Bus,\r
+  IN  UINT8                                 Device,\r
+  IN  UINT8                                 Func,\r
+  OUT PCI_IO_DEVICE                         **PciDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Search required device.\r
+\r
+Arguments:\r
+\r
+  Bridge     - A pointer to the PCI_IO_DEVICE.\r
+  Pci        - A pointer to the PCI_TYPE00.\r
+  Bus        - Bus number.\r
+  Device     - Device number.\r
+  Func       - Function number.\r
+  PciDevice  - The Required pci device.\r
+\r
+Returns:\r
+\r
+  Status code.\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = NULL;\r
+\r
+  if (!IS_PCI_BRIDGE (Pci)) {\r
+\r
+    if (IS_CARDBUS_BRIDGE (Pci)) {\r
+      PciIoDevice = GatherP2CInfo (\r
+                      Bridge->PciRootBridgeIo,\r
+                      Pci,\r
+                      Bus,\r
+                      Device,\r
+                      Func\r
+                      );\r
+      if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {\r
+        InitializeP2C (PciIoDevice);\r
+      }\r
+    } else {\r
+\r
+      //\r
+      // Create private data for Pci Device\r
+      //\r
+      PciIoDevice = GatherDeviceInfo (\r
+                      Bridge->PciRootBridgeIo,\r
+                      Pci,\r
+                      Bus,\r
+                      Device,\r
+                      Func\r
+                      );\r
+\r
+    }\r
+\r
+  } else {\r
+\r
+    //\r
+    // Create private data for PPB\r
+    //\r
+    PciIoDevice = GatherPPBInfo (\r
+                    Bridge->PciRootBridgeIo,\r
+                    Pci,\r
+                    Bus,\r
+                    Device,\r
+                    Func\r
+                    );\r
+\r
+    //\r
+    // Special initialization for PPB including making the PPB quiet\r
+    //\r
+    if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {\r
+      InitializePPB (PciIoDevice);\r
+    }\r
+  }\r
+\r
+  if (!PciIoDevice) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  //\r
+  // Create a device path for this PCI device and store it into its private data\r
+  //\r
+  CreatePciDevicePath(\r
+    Bridge->DevicePath,\r
+    PciIoDevice \r
+    );\r
+  \r
+  //\r
+  // Detect this function has option rom\r
+  //\r
+  if (gFullEnumeration) {\r
+\r
+    if (!IS_CARDBUS_BRIDGE (Pci)) {\r
+\r
+      GetOpRomInfo (PciIoDevice);\r
+\r
+    }\r
+\r
+    ResetPowerManagementFeature (PciIoDevice);\r
+    \r
+  } \r
+  else {\r
+    PciRomGetRomResourceFromPciOptionRomTable (\r
+      &gPciBusDriverBinding,\r
+      PciIoDevice->PciRootBridgeIo,\r
+      PciIoDevice\r
+      );\r
+  }\r
+\r
\r
+  //\r
+  // Insert it into a global tree for future reference\r
+  //\r
+  InsertPciDevice (Bridge, PciIoDevice);\r
+\r
+  //\r
+  // Determine PCI device attributes\r
+  //\r
+  DetermineDeviceAttribute (PciIoDevice);\r
+\r
+  if (PciDevice != NULL) {\r
+    *PciDevice = PciIoDevice;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+GatherDeviceInfo (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN                           Offset;\r
+  UINTN                           BarIndex;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+\r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (!PciIoDevice) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // If it is a full enumeration, disconnect the device in advance\r
+  //\r
+  if (gFullEnumeration) {\r
+\r
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+  }\r
+\r
+  //\r
+  // Start to parse the bars\r
+  //\r
+  for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {\r
+    Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
+  }\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+GatherPPBInfo (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+  EFI_STATUS                      Status;\r
+  UINT32                          Value;\r
+  EFI_PCI_IO_PROTOCOL             *PciIo;\r
+  UINT8                           Temp;\r
+\r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (!PciIoDevice) {\r
+    return NULL;\r
+  }\r
+  \r
+  if (gFullEnumeration) {\r
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+    //\r
+    // Initalize the bridge control register\r
+    //\r
+    PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);\r
+  }\r
+\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Test whether it support 32 decode or not\r
+  //\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
+\r
+  if (Value) {\r
+    if (Value & 0x01) {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
+    } else {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
+    }\r
+  }\r
+\r
+  Status = BarExisted (\r
+            PciIoDevice,\r
+            0x24,\r
+            NULL,\r
+            NULL\r
+            );\r
+\r
+  //\r
+  // test if it supports 64 memory or not\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    Status = BarExisted (\r
+              PciIoDevice,\r
+              0x28,\r
+              NULL,\r
+              NULL\r
+              );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
+    } else {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Memory 32 code is required for ppb\r
+  //\r
+  PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+GatherP2CInfo (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE         *PciIoDevice;\r
+  \r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (!PciIoDevice) {\r
+    return NULL;\r
+  }\r
+\r
+  if (gFullEnumeration) {\r
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+    //\r
+    // Initalize the bridge control register\r
+    //\r
+    PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);\r
+\r
+  }\r
+  //\r
+  // P2C only has one bar that is in 0x10\r
+  //\r
+  PciParseBar(PciIoDevice, 0x10, 0);\r
+  \r
+  PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |\r
+                         EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
+                         EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+CreatePciDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+  IN  PCI_IO_DEVICE            *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  PCI_DEVICE_PATH PciNode;\r
+\r
+  //\r
+  // Create PCI device path\r
+  //\r
+  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;\r
+  PciNode.Header.SubType  = HW_PCI_DP;\r
+  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
+\r
+  PciNode.Device          = PciIoDevice->DeviceNumber;\r
+  PciNode.Function        = PciIoDevice->FunctionNumber;\r
+  PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);\r
+\r
+  return PciIoDevice->DevicePath;\r
+}\r
+\r
+EFI_STATUS\r
+BarExisted (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINTN         Offset,\r
+  OUT UINT32       *BarLengthValue,\r
+  OUT UINT32       *OriginalBarValue\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check the bar is existed or not.\r
+\r
+Arguments:\r
+\r
+  PciIoDevice       - A pointer to the PCI_IO_DEVICE.\r
+  Offset            - The offset.\r
+  BarLengthValue    - The bar length value.\r
+  OriginalBarValue  - The original bar value.\r
+\r
+Returns:\r
+\r
+  EFI_NOT_FOUND     - The bar don't exist.\r
+  EFI_SUCCESS       - The bar exist.\r
+\r
+--*/\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT32              OriginalValue;\r
+  UINT32              Value;\r
+  EFI_TPL             OldTpl;\r
+\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Preserve the original value\r
+  //\r
+\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);\r
+\r
+  //\r
+  // Write back the original value\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Restore TPL to its original level\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  if (BarLengthValue != NULL) {\r
+    *BarLengthValue = Value;\r
+  }\r
+\r
+  if (OriginalBarValue != NULL) {\r
+    *OriginalBarValue = OriginalValue;\r
+  }\r
+\r
+  if (Value == 0) {\r
+    return EFI_NOT_FOUND;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
+\r
+EFI_STATUS\r
+DetermineDeviceAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
\r
+  Determine the related attributes of all devices under a Root Bridge\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT16          Command;\r
+  UINT16          BridgeControl;\r
+\r
+  Command = 0;\r
+\r
+  PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;\r
+  PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+\r
+  if (IS_PCI_VGA (&(PciIoDevice->Pci))){\r
+\r
+    //\r
+    // If the device is VGA, VGA related Attributes are supported\r
+    //\r
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;\r
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY   ;\r
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO    ;\r
+  }\r
+\r
+  if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {\r
+    //\r
+    // If the devie is a ISA Bridge, set the two attributes\r
+    //\r
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+  }\r
+\r
+  if (IS_PCI_GFX (&(PciIoDevice->Pci))) {\r
+\r
+    //\r
+    // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO\r
+    // attribute\r
+    //\r
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO    ;\r
+  }\r
+\r
+\r
+  //\r
+  // If the device is IDE, IDE related attributes are supported\r
+  //\r
+  if (IS_PCI_IDE (&(PciIoDevice->Pci))) {\r
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO  ;\r
+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO  ;\r
+  }\r
+\r
+  PciReadCommandRegister(PciIoDevice, &Command);\r
+\r
+  \r
+  if (Command & EFI_PCI_COMMAND_IO_SPACE) {\r
+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;\r
+  }\r
+\r
+  if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {\r
+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;\r
+  }\r
+\r
+  if (Command & EFI_PCI_COMMAND_BUS_MASTER) {\r
+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;\r
+  }\r
+\r
+  if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) || \r
+      IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){\r
+\r
+    //\r
+    // If it is a PPB, read the Bridge Control Register to determine\r
+    // the relevant attributes\r
+    //\r
+    BridgeControl = 0;\r
+    PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);\r
+\r
+    //\r
+    // Determine whether the ISA bit is set\r
+    // If ISA Enable on Bridge is set, the PPB\r
+    // will block forwarding 0x100-0x3ff for each 1KB in the \r
+    // first 64KB I/O range.\r
+    //\r
+    if (!BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) {\r
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+    } \r
+\r
+    //\r
+    // Determine whether the VGA bit is set\r
+    // If it is set, the bridge is set to decode VGA memory range\r
+    // and palette register range\r
+    //\r
+    if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {\r
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+    }\r
+\r
+    //\r
+    // if the palette snoop bit is set, then the brige is set to \r
+    // decode palette IO write\r
+    //\r
+    if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {\r
+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+    }\r
+  } \r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+UINTN\r
+PciParseBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT32      Value;\r
+  UINT64      BarValue64;\r
+  UINT32      OriginalValue;\r
+  UINT32      Mask;\r
+  UINT32      Data;\r
+  UINT8       Index;\r
+  EFI_STATUS  Status;\r
+\r
+  OriginalValue = 0;\r
+  Value         = 0;\r
+  BarValue64    = 0;\r
+\r
+  Status = BarExisted (\r
+            PciIoDevice,\r
+            Offset,\r
+            &Value,\r
+            &OriginalValue\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->PciBar[BarIndex].Length      = 0;\r
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
+\r
+    //\r
+    // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
+    //\r
+    PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
+    return Offset + 4;\r
+  }\r
+\r
+  PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
+  if (Value & 0x01) {\r
+    //\r
+    // Device I/Os\r
+    //\r
+    Mask = 0xfffffffc;\r
+\r
+    if (Value & 0xFFFF0000) {\r
+      //\r
+      // It is a IO32 bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;\r
+      PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+    } else {\r
+      //\r
+      // It is a IO16 bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;\r
+      PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+    }\r
+    //\r
+    // Workaround. Some platforms inplement IO bar with 0 length\r
+    // Need to treat it as no-bar\r
+    //\r
+    if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+      PciIoDevice->PciBar[BarIndex].BarType = 0;\r
+    }\r
+\r
+    PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;\r
+\r
+  } else {\r
+\r
+    Mask  = 0xfffffff0;\r
+\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
+\r
+    switch (Value & 0x07) {\r
+\r
+    //\r
+    //memory space; anywhere in 32 bit address space\r
+    //\r
+    case 0x00:\r
+      if (Value & 0x08) {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
+      }\r
+\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      break;\r
+\r
+    //\r
+    // memory space; anywhere in 64 bit address space\r
+    //\r
+    case 0x04:\r
+      if (Value & 0x08) {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
+      }\r
+\r
+      //\r
+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
+      // is regarded as an extension for the first bar. As a result\r
+      // the sizing will be conducted on combined 64 bit value\r
+      // Here just store the masked first 32bit value for future size\r
+      // calculation\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      //\r
+      // Increment the offset to point to next DWORD\r
+      //\r
+      Offset += 4;\r
+\r
+      Status = BarExisted (\r
+                PciIoDevice,\r
+                Offset,\r
+                &Value,\r
+                &OriginalValue\r
+                );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Offset + 4;\r
+      }\r
+\r
+      //\r
+      // Fix the length to support some spefic 64 bit BAR\r
+      //\r
+      Data  = Value;\r
+      Index = 0;\r
+      for (Data = Value; Data != 0; Data >>= 1) {\r
+       Index ++;\r
+      }\r
+      Value |= ((UINT32)(-1) << Index); \r
+\r
+      //\r
+      // Calculate the size of 64bit bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
+\r
+      PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      break;\r
+\r
+    //\r
+    // reserved\r
+    //\r
+    default:\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      break;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Check the length again so as to keep compatible with some special bars\r
+  //\r
+  if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+    PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
+  }\r
+  \r
+  //\r
+  // Increment number of bar\r
+  //\r
+  return Offset + 4;\r
+}\r
+\r
+EFI_STATUS\r
+InitializePPB (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  PciIo = &(PciIoDevice->PciIo);\r
+\r
+  //\r
+  // Put all the resource apertures including IO16\r
+  // Io32, pMem32, pMem64 to quiescent state\r
+  // Resource base all ones, Resource limit all zeros\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
+\r
+  //\r
+  // don't support use io32 as for now\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeP2C (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  PciIo = &(PciIoDevice->PciIo);\r
+\r
+  //\r
+  // Put all the resource apertures including IO16\r
+  // Io32, pMem32, pMem64 to quiescent state(\r
+  // Resource base all ones, Resource limit all zeros\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+CreatePciIoDevice (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = NULL;\r
+\r
+  Status = gBS->AllocatePool (\r
+                  EfiBootServicesData,\r
+                  sizeof (PCI_IO_DEVICE),\r
+                  (VOID **) &PciIoDevice\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));\r
+\r
+  PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;\r
+  PciIoDevice->Handle           = NULL;\r
+  PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;\r
+  PciIoDevice->DevicePath       = NULL;\r
+  PciIoDevice->BusNumber        = Bus;\r
+  PciIoDevice->DeviceNumber     = Device;\r
+  PciIoDevice->FunctionNumber   = Func;\r
+  PciIoDevice->Decodes          = 0;\r
+  if (gFullEnumeration) {\r
+    PciIoDevice->Allocated = FALSE;\r
+  } else {\r
+    PciIoDevice->Allocated = TRUE;\r
+  }\r
+\r
+  PciIoDevice->Attributes         = 0;\r
+  PciIoDevice->Supports           = 0;\r
+  PciIoDevice->BusOverride        = FALSE;\r
+  PciIoDevice->IsPciExp           = FALSE;\r
+\r
+  CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
+\r
+  //\r
+  // Initialize the PCI I/O instance structure\r
+  //\r
+\r
+  Status  = InitializePciIoInstance (PciIoDevice);\r
+  Status  = InitializePciDriverOverrideInstance (PciIoDevice);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (PciIoDevice);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Initialize the reserved resource list\r
+  //\r
+  InitializeListHead (&PciIoDevice->ReservedResourceList);\r
+\r
+  //\r
+  // Initialize the driver list\r
+  //\r
+  InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
+\r
+  //\r
+  // Initialize the child list\r
+  //\r
+  InitializeListHead (&PciIoDevice->ChildList);\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+EFI_STATUS\r
+PciEnumeratorLight (\r
+  IN EFI_HANDLE                    Controller\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to enumerate entire pci bus system \r
+  in a given platform\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  EFI_STATUS                        Status;\r
+  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;\r
+  PCI_IO_DEVICE                     *RootBridgeDev;\r
+  UINT16                            MinBus;\r
+  UINT16                            MaxBus;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+\r
+  MinBus      = 0;\r
+  MaxBus      = PCI_MAX_BUS;\r
+  Descriptors = NULL;\r
+\r
+  //\r
+  // If this host bridge has been already enumerated, then return successfully\r
+  //\r
+  if (RootBridgeExisted (Controller)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Open the IO Abstraction(s) needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller      ,   \r
+                  &gEfiDevicePathProtocolGuid,  \r
+                  (VOID **)&ParentDevicePath,\r
+                  gPciBusDriverBinding.DriverBindingHandle,     \r
+                  Controller,   \r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Open pci root bridge io protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge \r
+  //\r
+  Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo);\r
+\r
+  Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  while (PciGetBusRange (Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
+\r
+    //\r
+    // Create a device node for root bridge device with a NULL host bridge controller handle\r
+    //\r
+    RootBridgeDev = CreateRootBridge (Controller);\r
+\r
+    //\r
+    // Record the root bridge device path\r
+    //\r
+    RootBridgeDev->DevicePath = ParentDevicePath;\r
+\r
+    //\r
+    // Record the root bridge io protocol\r
+    //\r
+    RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+    Status = PciPciDeviceInfoCollector (\r
+              RootBridgeDev,\r
+              (UINT8) MinBus\r
+              );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+\r
+      //\r
+      // If successfully, insert the node into device pool\r
+      //\r
+      InsertRootBridge (RootBridgeDev);\r
+    } else {\r
+\r
+      //\r
+      // If unsuccessly, destroy the entire node\r
+      //\r
+      DestroyRootBridge (RootBridgeDev);\r
+    }\r
+\r
+    Descriptors++;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciGetBusRange (\r
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Descriptors,\r
+  OUT    UINT16                             *MinBus,\r
+  OUT    UINT16                             *MaxBus,\r
+  OUT    UINT16                             *BusRange\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get the bus range.\r
+\r
+Arguments:\r
+\r
+  Descriptors     - A pointer to the address space descriptor.\r
+  MinBus          - The min bus.\r
+  MaxBus          - The max bus.\r
+  BusRange        - The bus range.\r
+  \r
+Returns:\r
+  \r
+  Status Code.\r
+\r
+--*/\r
+{\r
+\r
+  while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+      if (MinBus != NULL) {\r
+        *MinBus = (UINT16)Descriptors->AddrRangeMin;\r
+      }\r
+\r
+      if (MaxBus != NULL) {\r
+        *MaxBus = (UINT16)Descriptors->AddrRangeMax;\r
+      }\r
+\r
+      if (BusRange != NULL) {\r
+        *BusRange = (UINT16)Descriptors->AddrLen;\r
+      }\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Descriptors ++;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h b/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h
new file mode 100644 (file)
index 0000000..420ee6b
--- /dev/null
@@ -0,0 +1,108 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciEnumeratorSupport.h\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H\r
+#define _EFI_PCI_ENUMERATOR_SUPPORT_H\r
+\r
+#include "PciBus.h"\r
+\r
+EFI_STATUS\r
+PciPciDeviceInfoCollector (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  UINT8                                 StartBusNumber\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Bridge          - TODO: add argument description\r
+  StartBusNumber  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+PciDevicePresent(\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  PCI_TYPE00                          *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+);\r
+\r
+EFI_STATUS\r
+PciEnumeratorLight (\r
+  IN EFI_HANDLE                    Controller\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Controller  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+PciGetBusRange (\r
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Descriptors,\r
+  OUT    UINT16                             *MinBus,\r
+  OUT    UINT16                             *MaxBus,\r
+  OUT    UINT16                             *BusRange\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Descriptors - TODO: add argument description\r
+  MinBus      - TODO: add argument description\r
+  MaxBus      - TODO: add argument description\r
+  BusRange    - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+#endif\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciIo.c b/DuetPkg/PciBusNoEnumerationDxe/PciIo.c
new file mode 100644 (file)
index 0000000..e5485dc
--- /dev/null
@@ -0,0 +1,1867 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciIo.c\r
+  \r
+Abstract:\r
+\r
+  PCI I/O Abstraction Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Pcibus.h"\r
+\r
+//\r
+// PCI I/O Support Function Prototypes\r
+//\r
+//\r
+\r
+BOOLEAN \r
+PciDevicesOnTheSamePath (\r
+  IN PCI_IO_DEVICE       *PciDevice1,\r
+  IN PCI_IO_DEVICE       *PciDevice2\r
+);\r
+\r
+\r
+EFI_STATUS \r
+UpStreamBridgesAttributes (\r
+  IN  PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes\r
+);\r
+\r
+\r
+BOOLEAN \r
+CheckBarType ( \r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  UINT8             BarIndex,\r
+  PCI_BAR_TYPE      BarType\r
+);\r
+\r
+\r
+EFI_STATUS \r
+SetBootVGA ( \r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+);\r
+\r
+EFI_STATUS \r
+DisableBootVGA ( \r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+);\r
+\r
+\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+  PCI_IO_DEVICE                 *PciIoDevice,\r
+  UINT8                         BarIndex,\r
+  PCI_BAR_TYPE                  Type,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINTN                      Count,\r
+  UINT64                        *Offset\r
+);\r
+\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+  PCI_IO_DEVICE                 *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINTN                      Count,\r
+  IN UINT64                     *Offset\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+);\r
+  \r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+);    \r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+  IN     EFI_PCI_IO_PROTOCOL  *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        DestBarIndex,\r
+  IN     UINT64                       DestOffset,\r
+  IN     UINT8                        SrcBarIndex,\r
+  IN     UINT64                       SrcOffset,\r
+  IN     UINTN                        Count\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+  IN     EFI_PCI_IO_PROTOCOL            *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,\r
+  IN     VOID                           *HostAddress,\r
+  IN OUT UINTN                          *NumberOfBytes,\r
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,\r
+  OUT    VOID                           **Mapping\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  IN  VOID                 *Mapping\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL    *This,\r
+  IN  EFI_ALLOCATE_TYPE      Type,\r
+  IN  EFI_MEMORY_TYPE        MemoryType,\r
+  IN  UINTN                  Pages,\r
+  OUT VOID                   **HostAddress,\r
+  IN  UINT64                 Attributes\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  UINTN                 Pages,\r
+  IN  VOID                  *HostAddress\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  OUT UINTN                *Segment,\r
+  OUT UINTN                *Bus,\r
+  OUT UINTN                *Device,\r
+  OUT UINTN                *Function\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+  IN  EFI_PCI_IO_PROTOCOL              *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes,\r
+  OUT UINT64                                   *Result   OPTIONAL\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes(\r
+  IN  EFI_PCI_IO_PROTOCOL    *This,\r
+  IN  UINT8                          BarIndex,\r
+  OUT UINT64                         *Supports,   OPTIONAL\r
+  OUT VOID                           **Resources  OPTIONAL\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes(\r
+  IN     EFI_PCI_IO_PROTOCOL  *This,\r
+  IN     UINT64                       Attributes,\r
+  IN     UINT8                        BarIndex,\r
+  IN OUT UINT64                       *Offset,\r
+  IN OUT UINT64                       *Length\r
+  );\r
+\r
+\r
+//\r
+// Pci Io Protocol Interface\r
+//\r
+static EFI_PCI_IO_PROTOCOL  PciIoInterface = {\r
+  PciIoPollMem,\r
+  PciIoPollIo,\r
+  {\r
+    PciIoMemRead,\r
+    PciIoMemWrite\r
+  },\r
+  {\r
+    PciIoIoRead,\r
+    PciIoIoWrite\r
+  },\r
+  {\r
+    PciIoConfigRead,\r
+    PciIoConfigWrite\r
+  },\r
+  PciIoCopyMem,\r
+  PciIoMap,\r
+  PciIoUnmap,\r
+  PciIoAllocateBuffer,\r
+  PciIoFreeBuffer,\r
+  PciIoFlush,\r
+  PciIoGetLocation,\r
+  PciIoAttributes,\r
+  PciIoGetBarAttributes,\r
+  PciIoSetBarAttributes,\r
+  0,\r
+  NULL\r
+};\r
+\r
+\r
+EFI_STATUS\r
+InitializePciIoInstance (\r
+  PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initializes a PCI I/O Instance\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+{\r
+  CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+  PCI_IO_DEVICE                   *PciIoDevice,\r
+  UINT8                           BarIndex,\r
+  PCI_BAR_TYPE                    Type,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN UINTN                        Count,\r
+  UINT64                          *Offset\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Verifies access to a PCI Base Address Register (BAR)\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // BarIndex 0-5 is legal\r
+  //\r
+  if (BarIndex >= PCI_MAX_BAR) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!CheckBarType (PciIoDevice, BarIndex, Type)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+  //\r
+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+    Count = 1;\r
+  }\r
+\r
+  Width &= 0x03;\r
+\r
+  if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+  PCI_IO_DEVICE                 *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINTN                      Count,\r
+  IN UINT64                     *Offset\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Verifies access to a PCI Config Header\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT64  ExtendOffset;\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+  //\r
+  Width &= 0x03;\r
+\r
+  if (PciIoDevice->IsPciExp) {\r
+    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    ExtendOffset  = LShiftU64 (*Offset, 32);\r
+    *Offset       = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
+    *Offset       = (*Offset) | ExtendOffset;\r
+\r
+  } else {\r
+    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Poll PCI Memmory\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (Width > EfiPciIoWidthUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->PollMem (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                          Offset,\r
+                                          Mask,\r
+                                          Value,\r
+                                          Delay,\r
+                                          Result\r
+                                          );\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Poll PCI IO\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width > EfiPciIoWidthUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->PollIo (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                          Offset,\r
+                                          Mask,\r
+                                          Value,\r
+                                          Delay,\r
+                                          Result\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI Memory Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Buffer == NULL){\r
+         return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Read (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI Memory Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Buffer == NULL){\r
+         return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI I/O Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Buffer == NULL){\r
+         return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Io.Read (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI I/O Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Buffer == NULL){\r
+         return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Io.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI Configuration Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        Address;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Address     = Offset;\r
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Read (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Address,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI Configuration Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        Address;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Address     = Offset;\r
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Address,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        DestBarIndex,\r
+  IN     UINT64                       DestOffset,\r
+  IN     UINT8                        SrcBarIndex,\r
+  IN     UINT64                       SrcOffset,\r
+  IN     UINTN                        Count\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Copy PCI Memory\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Width == EfiPciIoWidthFifoUint8  ||\r
+      Width == EfiPciIoWidthFifoUint16 ||\r
+      Width == EfiPciIoWidthFifoUint32 ||\r
+      Width == EfiPciIoWidthFifoUint64 ||\r
+      Width == EfiPciIoWidthFillUint8  ||\r
+      Width == EfiPciIoWidthFillUint16 ||\r
+      Width == EfiPciIoWidthFillUint32 ||\r
+      Width == EfiPciIoWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->CopyMem (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                          DestOffset,\r
+                                          SrcOffset,\r
+                                          Count\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+  IN     EFI_PCI_IO_PROTOCOL            *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,\r
+  IN     VOID                           *HostAddress,\r
+  IN OUT UINTN                          *NumberOfBytes,\r
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,\r
+  OUT    VOID                           **Mapping\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Maps a memory region for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {\r
+    Operation = Operation + EfiPciOperationBusMasterRead64;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Map (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
+                                          HostAddress,\r
+                                          NumberOfBytes,\r
+                                          DeviceAddress,\r
+                                          Mapping\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  IN  VOID                 *Mapping\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Unmaps a memory region for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Mapping\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  EFI_ALLOCATE_TYPE     Type,\r
+  IN  EFI_MEMORY_TYPE       MemoryType,\r
+  IN  UINTN                 Pages,\r
+  OUT VOID                  **HostAddress,\r
+  IN  UINT64                Attributes\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Allocates a common buffer for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Attributes &\r
+      (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {\r
+    Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Type,\r
+                                          MemoryType,\r
+                                          Pages,\r
+                                          HostAddress,\r
+                                          Attributes\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  UINTN                 Pages,\r
+  IN  VOID                  *HostAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Frees a common buffer \r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  \r
+  if( HostAddress == NULL ){\r
+        return EFI_INVALID_PARAMETER;\r
+  } \r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Pages,\r
+                                          HostAddress\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Flushes a DMA buffer\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+{\r
+  EFI_STATUS    Status;\r
+  UINT32         Register;\r
+  PCI_IO_DEVICE  *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  //\r
+  // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to \r
+  // flush the posted write cycles through the PCI-PCI bridges\r
+  //\r
+  if (PciIoDevice->Parent != NULL) {\r
+    Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);\r
+  }\r
+\r
+  //\r
+  // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset\r
+  //\r
+  Status = PciIoDevice->PciRootBridgeIo->Flush (\r
+                                           PciIoDevice->PciRootBridgeIo\r
+                                           );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  OUT UINTN                *Segment,\r
+  OUT UINTN                *Bus,\r
+  OUT UINTN                *Device,\r
+  OUT UINTN                *Function\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Gets a PCI device's current bus number, device number, and function number.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Segment  = PciIoDevice->PciRootBridgeIo->SegmentNumber;\r
+  *Bus      = PciIoDevice->BusNumber;\r
+  *Device   = PciIoDevice->DeviceNumber;\r
+  *Function = PciIoDevice->FunctionNumber;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+CheckBarType (\r
+  IN PCI_IO_DEVICE       *PciIoDevice,\r
+  UINT8                  BarIndex,\r
+  PCI_BAR_TYPE           BarType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Sets a PCI controllers attributes on a resource range\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  switch (BarType) {\r
+\r
+  case PciBarTypeMem:\r
+\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32  &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64    ) {\r
+      return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+\r
+  case PciBarTypeIo:\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){\r
+      return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL                       * This,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes,\r
+  OUT UINT64                                   *Result OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  PCI_IO_DEVICE *Temp;\r
+  UINT64         NewAttributes;\r
+  UINT64         PciRootBridgeSupports;\r
+  UINT64         PciRootBridgeAttributes;\r
+  UINT64         NewPciRootBridgeAttributes;\r
+  UINT64         NewUpStreamBridgeAttributes;\r
+  UINT64         ModifiedPciRootBridgeAttributes;\r
+  UINT16         EnableCommand;\r
+  UINT16         DisableCommand;\r
+  UINT16         EnableBridge;\r
+  UINT16         DisableBridge;\r
+  UINT16         Command;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+  NewUpStreamBridgeAttributes = 0;\r
+\r
+  EnableCommand   = 0;\r
+  DisableCommand  = 0;\r
+  EnableBridge    = 0;\r
+  DisableBridge   = 0;\r
+\r
+  switch (Operation) {\r
+  case EfiPciIoAttributeOperationGet:\r
+    if (Result == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    *Result = PciIoDevice->Attributes;\r
+    return EFI_SUCCESS;\r
+\r
+  case EfiPciIoAttributeOperationSupported:\r
+    if (Result == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    *Result = PciIoDevice->Supports;\r
+    return EFI_SUCCESS;\r
+\r
+  case EfiPciIoAttributeOperationEnable:\r
+         if(Attributes & ~(PciIoDevice->Supports)) {\r
+                 return EFI_UNSUPPORTED;\r
+         }\r
+         NewAttributes = PciIoDevice->Attributes | Attributes;\r
+    break;\r
+  case EfiPciIoAttributeOperationDisable:\r
+         if(Attributes & ~(PciIoDevice->Supports)) {\r
+                 return EFI_UNSUPPORTED;\r
+         }\r
+    NewAttributes = PciIoDevice->Attributes & (~Attributes);\r
+    break;\r
+  case EfiPciIoAttributeOperationSet:\r
+         if(Attributes & ~(PciIoDevice->Supports)) {\r
+                 return EFI_UNSUPPORTED;\r
+         }\r
+    NewAttributes = Attributes;\r
+    break;\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // If VGA_IO is set, then set VGA_MEMORY too.  This driver can not enable them seperately.\r
+  //\r
+  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+  }\r
+\r
+  //\r
+  // If VGA_MEMORY is set, then set VGA_IO too.  This driver can not enable them seperately.\r
+  //\r
+  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {\r
+    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+  }\r
+\r
+  //\r
+  // If the attributes are already set correctly, then just return EFI_SUCCESS;\r
+  //\r
+  if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and\r
+  // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER.  Strip these 3 bits off the new attribute mask so\r
+  // a call to the PCI Root Bridge I/O Protocol can be made\r
+  //\r
+\r
+  if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {\r
+    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));\r
+\r
+    //  \r
+    // Get the current attributes of this PCI device's PCI Root Bridge\r
+    //\r
+    Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
+                                            PciIoDevice->PciRootBridgeIo,\r
+                                            &PciRootBridgeSupports,\r
+                                            &PciRootBridgeAttributes\r
+                                            );\r
+\r
+    //\r
+    // Check to see if any of the PCI Root Bridge attributes are being modified\r
+    //\r
+    ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;\r
+    if (ModifiedPciRootBridgeAttributes) {\r
+\r
+      //\r
+      // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing\r
+      //\r
+      if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {\r
+  //     return EFI_UNSUPPORTED;\r
+      }\r
+      //\r
+      // Call the PCI Root Bridge to attempt to modify the attributes\r
+      //\r
+      Status = PciIoDevice->PciRootBridgeIo->SetAttributes (\r
+                                             PciIoDevice->PciRootBridgeIo,\r
+                                             NewPciRootBridgeAttributes,\r
+                                             NULL,\r
+                                             NULL\r
+                                             );\r
+      if (EFI_ERROR (Status)) {\r
+      //\r
+      // The PCI Root Bridge could not modify the attributes, so return the error.\r
+      //\r
+        return Status;\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {\r
+\r
+\r
+    //\r
+    // Check to see if an VGA related attributes are being set.\r
+    //\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {\r
+\r
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
+      } else {\r
+        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Check to see if an VGA related attributes are being set.\r
+    // If ISA Enable on the PPB is set, the PPB will block the\r
+    // 0x100-0x3FF for each 1KB block in the first 64K I/O block\r
+    //\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {\r
+\r
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {\r
+        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
+      } else {\r
+        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Check to see if an VGA related attributes are being set.\r
+    //\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {\r
+\r
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {\r
+        EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+      } else {\r
+        DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+      }\r
+    }\r
+\r
+  } else {\r
+\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {\r
+\r
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+\r
+        //\r
+        //Check if there have been an active VGA device on the same segment\r
+        //\r
+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+\r
+        if (Temp && Temp != PciIoDevice) {\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+      }\r
+    }\r
+\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {\r
+      if (IS_PCI_GFX(&PciIoDevice->Pci)) {\r
+\r
+        //\r
+        //Get the boot VGA on the same segement\r
+        //\r
+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+\r
+        if (!Temp) {\r
+\r
+          //\r
+          // If there is no VGA device on the segement, set\r
+          // this graphics card to decode the palette range\r
+          //\r
+          DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+        } else {\r
+\r
+          //\r
+          // Check these two agents are on the same path\r
+          //\r
+          if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) {\r
+\r
+            //\r
+            // Check if they are on the same bus\r
+            //\r
+            if (Temp->Parent == PciIoDevice->Parent) {\r
+\r
+              PciReadCommandRegister (Temp, &Command);\r
+\r
+              //\r
+              // If they are on the same bus, either one can\r
+              // be set to snoop, the other set to decode\r
+              //\r
+              if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {\r
+                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+              } else {\r
+                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+              }\r
+            } else {\r
+\r
+              //\r
+              // If they are on  the same path but on the different bus\r
+              // The first agent is set to snoop, the second one set to\r
+              // decode\r
+              //\r
+              if (Temp->BusNumber > PciIoDevice->BusNumber) {\r
+                PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+              } else {\r
+                PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+              }\r
+            }\r
+          } else {\r
+\r
+            EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check to see of the I/O enable is being modified\r
+  //\r
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) {\r
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) {\r
+      EnableCommand |= EFI_PCI_COMMAND_IO_SPACE;\r
+    } else {\r
+      DisableCommand |= EFI_PCI_COMMAND_IO_SPACE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check to see of the Memory enable is being modified\r
+  //\r
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) {\r
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {\r
+      EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
+    } else {\r
+      DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check to see of the Bus Master enable is being modified\r
+  //\r
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) {\r
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {\r
+      EnableCommand  |= EFI_PCI_COMMAND_BUS_MASTER;\r
+    } else {\r
+      DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER;\r
+    }\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (EnableCommand) {\r
+    Status = PciEnableCommandRegister(PciIoDevice, EnableCommand);\r
+  } \r
+\r
+  if (DisableCommand) {\r
+    Status = PciDisableCommandRegister(PciIoDevice, DisableCommand);\r
+  }\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (EnableBridge) {\r
+    Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge);\r
+  }\r
+\r
+  if (DisableBridge) {\r
+    Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge);\r
+  }\r
+   \r
+  if (EFI_ERROR(Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Set the upstream bridge attributes\r
+  //\r
+  if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) {\r
+\r
+    //\r
+    // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER\r
+    // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED\r
+    // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge\r
+    // \r
+    NewUpStreamBridgeAttributes = Attributes & \\r
+                                (~(EFI_PCI_IO_ATTRIBUTE_IO | \\r
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY | \\r
+                                EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \\r
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \\r
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \\r
+                                EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));\r
+\r
+    if (NewUpStreamBridgeAttributes){\r
+      UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes);\r
+    }\r
+  }\r
+  \r
+  PciIoDevice->Attributes = NewAttributes;\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL             * This,\r
+  IN  UINT8                          BarIndex,\r
+  OUT UINT64                         *Supports, OPTIONAL\r
+  OUT VOID                           **Resources OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  UINT8                             *Configuration;\r
+  UINT8                             NumConfig;\r
+  PCI_IO_DEVICE                     *PciIoDevice;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;\r
+\r
+  NumConfig   = 0;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Supports == NULL && Resources == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BarIndex >= PCI_MAX_BAR) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // This driver does not support modifications to the WRITE_COMBINE or\r
+  // CACHED attributes for BAR ranges.\r
+  //\r
+  if (Supports != NULL) {\r
+    *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+  }\r
+\r
+  if (Resources != NULL) {\r
+\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {\r
+      NumConfig = 1;\r
+    }\r
+\r
+    Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+    if (Configuration == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    ZeroMem (\r
+      Configuration,\r
+      sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+      );\r
+\r
+    Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+\r
+    if (NumConfig == 1) {\r
+      Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Ptr->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+\r
+      Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+      Ptr->AddrLen      = PciIoDevice->PciBar[BarIndex].Length;\r
+      Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;\r
+\r
+      switch (PciIoDevice->PciBar[BarIndex].BarType) {\r
+      case PciBarTypeIo16:\r
+      case PciBarTypeIo32:\r
+        //\r
+        // Io\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+        break;\r
+\r
+      case PciBarTypeMem32:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // 32 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 32;\r
+        break;\r
+\r
+      case PciBarTypePMem32:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // prefechable\r
+        //\r
+        Ptr->SpecificFlag = 0x6;\r
+        //\r
+        // 32 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 32;\r
+        break;\r
+\r
+      case PciBarTypeMem64:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // 64 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 64;\r
+        break;\r
+\r
+      case PciBarTypePMem64:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // prefechable\r
+        //\r
+        Ptr->SpecificFlag = 0x6;\r
+        //\r
+        // 64 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 64;\r
+        break;\r
+      }\r
+\r
+      Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
+    }\r
+    \r
+    //\r
+    // put the checksum\r
+    //\r
+    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
+    PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
+    PtrEnd->Checksum  = 0;\r
+\r
+    *Resources        = Configuration;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     UINT64                       Attributes,\r
+  IN     UINT8                        BarIndex,\r
+  IN OUT UINT64                       *Offset,\r
+  IN OUT UINT64                       *Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        NonRelativeOffset;\r
+  UINT64        Supports;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  //\r
+  // Make sure Offset and Length are not NULL\r
+  //\r
+  if (Offset == NULL || Length == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.\r
+  // If Attributes is not 0, then return EFI_UNSUPPORTED.\r
+  //\r
+  Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+\r
+  if (Attributes != (Attributes & Supports)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Attributes must be supported.  Make sure the BAR range describd by BarIndex, Offset, and\r
+  // Length are valid for this PCI device.\r
+  //\r
+  NonRelativeOffset = *Offset;\r
+  Status = PciIoVerifyBarAccess (\r
+            PciIoDevice,\r
+            BarIndex,\r
+            PciBarTypeMem,\r
+            EfiPciIoWidthUint8,\r
+            (UINT32) *Length,\r
+            &NonRelativeOffset\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpStreamBridgesAttributes (\r
+  IN  PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE       *Parent;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  Parent = PciIoDevice->Parent;\r
+\r
+  while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {\r
+\r
+    //\r
+    // Get the PciIo Protocol\r
+    //\r
+    PciIo = &Parent->PciIo;\r
+\r
+    PciIo->Attributes (PciIo, Operation, Attributes, NULL);\r
+\r
+    Parent = Parent->Parent;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+PciDevicesOnTheSamePath (\r
+  IN PCI_IO_DEVICE        *PciDevice1,\r
+  IN PCI_IO_DEVICE        *PciDevice2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  PciDevice1  -  The pointer to the first PCI_IO_DEVICE.\r
+  PciDevice2  -  The pointer to the second PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+  TRUE   -  The two Pci devices are on the same path.\r
+  FALSE  -  The two Pci devices are not on the same path.\r
+\r
+--*/\r
+{\r
+\r
+  if (PciDevice1->Parent == PciDevice2->Parent) {\r
+    return TRUE;\r
+  }\r
+\r
+  return (PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1));\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciIo.h b/DuetPkg/PciBusNoEnumerationDxe/PciIo.h
new file mode 100644 (file)
index 0000000..08064fa
--- /dev/null
@@ -0,0 +1,48 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciIo.h\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_IO_PROTOCOL_H\r
+#define _EFI_PCI_IO_PROTOCOL_H\r
+\r
+EFI_STATUS\r
+InitializePciIoInstance (\r
+  PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PciIoDevice - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif
\ No newline at end of file
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c b/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c
new file mode 100644 (file)
index 0000000..02815c7
--- /dev/null
@@ -0,0 +1,537 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciOptionRomSupport.c\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PciBus.h"\r
+\r
+\r
+EFI_STATUS\r
+RomDecode (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT8           RomBarIndex,\r
+  IN UINT32          RomBar,\r
+  IN BOOLEAN         Enable\r
+);\r
+\r
+EFI_STATUS\r
+GetOpRomInfo (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  UINT8                           RomBarIndex;\r
+  UINT32                          AllOnes;\r
+  UINT64                          Address;\r
+  EFI_STATUS                      Status;\r
+  UINT8                           Bus;\r
+  UINT8                           Device;\r
+  UINT8                           Function;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  Bus             = PciIoDevice->BusNumber;\r
+  Device          = PciIoDevice->DeviceNumber;\r
+  Function        = PciIoDevice->FunctionNumber;\r
+\r
+  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
+\r
+  //\r
+  // offset is 0x30 if is not ppb\r
+  //\r
+\r
+  //\r
+  // 0x30\r
+  //\r
+  RomBarIndex = PCI_DEVICE_ROMBAR;\r
+\r
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+    //\r
+    // if is ppb\r
+    //\r
+\r
+    //\r
+    // 0x38\r
+    //\r
+    RomBarIndex = PCI_BRIDGE_ROMBAR;\r
+  }\r
+  //\r
+  // the bit0 is 0 to prevent the enabling of the Rom address decoder\r
+  //\r
+  AllOnes = 0xfffffffe;\r
+  Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);\r
+\r
+  Status = PciRootBridgeIo->Pci.Write (\r
+                                  PciRootBridgeIo,\r
+                                  EfiPciWidthUint32,\r
+                                  Address,\r
+                                  1,\r
+                                  &AllOnes\r
+                                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // read back\r
+  //\r
+  Status = PciRootBridgeIo->Pci.Read (\r
+                                  PciRootBridgeIo,\r
+                                  EfiPciWidthUint32,\r
+                                  Address,\r
+                                  1,\r
+                                  &AllOnes\r
+                                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Bits [1, 10] are reserved\r
+  //\r
+  AllOnes &= 0xFFFFF800;\r
+  if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  \r
+  DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: OPROM detected!\n"));\r
+  DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: B-%x, D-%x, F-%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Function));\r
+\r
+  PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LoadOpRomImage (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT64          ReservedMemoryBase\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
\r
+    Load option rom image for specified PCI device\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  UINT8                     RomBarIndex;\r
+  UINT8                     Indicator;\r
+  UINT16                    OffsetPcir;\r
+  UINT32                    RomBarOffset;\r
+  UINT32                    RomBar;\r
+  UINT64                    Temp;\r
+  EFI_STATUS                retStatus;\r
+  BOOLEAN                   FirstCheck;\r
+  UINT8                     *Image;\r
+  PCI_EXPANSION_ROM_HEADER  *RomHeader;\r
+  PCI_DATA_STRUCTURE        *RomPcir;\r
+  UINT64                    RomSize;\r
+  UINT64                    RomImageSize;\r
+  UINT8                     *RomInMemory;\r
+  UINT8                     CodeType;\r
+\r
+  RomSize       = PciDevice->RomSize;\r
+\r
+  Indicator     = 0;\r
+  RomImageSize  = 0;\r
+  RomInMemory   = NULL;\r
+  Temp          = 0;\r
+  CodeType      = 0xFF;\r
+\r
+  //\r
+  // Get the RomBarIndex\r
+  //\r
+\r
+  //\r
+  // 0x30\r
+  //\r
+  RomBarIndex = PCI_DEVICE_ROMBAR;\r
+  if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
+    //\r
+    // if is ppb\r
+    //\r
+\r
+    //\r
+    // 0x38\r
+    //\r
+    RomBarIndex = PCI_BRIDGE_ROMBAR;\r
+  }\r
+  //\r
+  // Allocate memory for Rom header and PCIR\r
+  //\r
+  RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
+  if (RomHeader == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
+  if (RomPcir == NULL) {\r
+    gBS->FreePool (RomHeader);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  RomBar = (UINT32)ReservedMemoryBase;  \r
+\r
+  //\r
+  // Enable RomBar\r
+  //\r
+  RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
+\r
+  RomBarOffset  = RomBar;\r
+  retStatus     = EFI_NOT_FOUND;\r
+  FirstCheck    = TRUE;\r
+\r
+  do {\r
+    PciDevice->PciRootBridgeIo->Mem.Read (\r
+                                      PciDevice->PciRootBridgeIo,\r
+                                      EfiPciWidthUint8,\r
+                                      RomBarOffset,\r
+                                      sizeof (PCI_EXPANSION_ROM_HEADER),\r
+                                      (UINT8 *) RomHeader\r
+                                      );\r
+\r
+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+      RomBarOffset = RomBarOffset + 512;\r
+      if (FirstCheck) {\r
+        break;\r
+      } else {\r
+        RomImageSize = RomImageSize + 512;\r
+        continue;\r
+      }\r
+    }\r
+\r
+    FirstCheck  = FALSE;\r
+    OffsetPcir  = RomHeader->PcirOffset;\r
+    PciDevice->PciRootBridgeIo->Mem.Read (\r
+                                      PciDevice->PciRootBridgeIo,\r
+                                      EfiPciWidthUint8,\r
+                                      RomBarOffset + OffsetPcir,\r
+                                      sizeof (PCI_DATA_STRUCTURE),\r
+                                      (UINT8 *) RomPcir\r
+                                      );\r
+    if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
+      CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
+    }\r
+    Indicator     = RomPcir->Indicator;\r
+    RomImageSize  = RomImageSize + RomPcir->ImageLength * 512;\r
+    RomBarOffset  = RomBarOffset + RomPcir->ImageLength * 512;\r
+  } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
+\r
+  //\r
+  // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
+  // of the legacy length and the PCIR Image Length\r
+  //\r
+  if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
+    RomImageSize = MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));\r
+  }\r
+\r
+  if (RomImageSize > 0) {\r
+    retStatus = EFI_SUCCESS;\r
+    Image     = AllocatePool ((UINT32) RomImageSize);\r
+    if (Image == NULL) {\r
+      RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
+      gBS->FreePool (RomHeader);\r
+      gBS->FreePool (RomPcir);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    \r
+    //\r
+    // Copy Rom image into memory\r
+    //\r
+    PciDevice->PciRootBridgeIo->Mem.Read (\r
+                                      PciDevice->PciRootBridgeIo,\r
+                                      EfiPciWidthUint8,\r
+                                      RomBar,\r
+                                      (UINT32) RomImageSize,\r
+                                      Image\r
+                                      );\r
+    RomInMemory = Image;\r
+  }\r
+\r
+  RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
+\r
+  PciDevice->PciIo.RomSize  = RomImageSize;\r
+  PciDevice->PciIo.RomImage = RomInMemory;\r
+\r
+  //\r
+  // Free allocated memory\r
+  //\r
+  gBS->FreePool (RomHeader);\r
+  gBS->FreePool (RomPcir);\r
+\r
+  return retStatus;\r
+}\r
+\r
+EFI_STATUS\r
+RomDecode (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT8           RomBarIndex,\r
+  IN UINT32          RomBar,\r
+  IN BOOLEAN         Enable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  UINT16                          CommandValue;\r
+  UINT32                          Value32;\r
+  UINT64                          Address;\r
+  //EFI_STATUS                      Status;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  \r
+  PciRootBridgeIo = PciDevice->PciRootBridgeIo;\r
+  if (Enable) {\r
+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);\r
+    //\r
+    // set the Rom base address: now is hardcode\r
+    //\r
+    PciRootBridgeIo->Pci.Write(\r
+                               PciRootBridgeIo, \r
+                               EfiPciWidthUint32, \r
+                               Address, \r
+                               1, \r
+                               &RomBar);\r
+  \r
+    //\r
+    // enable its decoder\r
+    //\r
+    Value32 = RomBar | 0x1;\r
+    PciRootBridgeIo->Pci.Write(\r
+                               PciRootBridgeIo, \r
+                               EfiPciWidthUint32, \r
+                               Address, \r
+                               1, \r
+                               &Value32);\r
+    \r
+    //\r
+    //setting the memory space bit in the function's command register\r
+    //\r
+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, 0x04);\r
+    PciRootBridgeIo->Pci.Read(\r
+                              PciRootBridgeIo, \r
+                              EfiPciWidthUint16, \r
+                              Address, \r
+                              1, \r
+                              &CommandValue);\r
+    \r
+    CommandValue = (UINT16)(CommandValue | 0x0002); //0x0003\r
+    PciRootBridgeIo->Pci.Write(\r
+                               PciRootBridgeIo, \r
+                               EfiPciWidthUint16, \r
+                               Address, \r
+                               1, \r
+                               &CommandValue);\r
+  } else {\r
+    //\r
+    // disable rom decode\r
+    //  \r
+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);\r
+    Value32 = 0xfffffffe;\r
+    PciRootBridgeIo->Pci.Write(\r
+                               PciRootBridgeIo, \r
+                               EfiPciWidthUint32, \r
+                               Address, \r
+                               1, \r
+                               &Value32);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+ProcessOpRomImage (\r
+  PCI_IO_DEVICE   *PciDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Process the oprom image.\r
+  \r
+Arguments:\r
+  PciDevice       A pointer to a pci device.\r
+\r
+Returns:\r
+\r
+  EFI Status.\r
+  \r
+--*/\r
+{\r
+  UINT8                         Indicator;\r
+  UINT32                        ImageSize;\r
+  UINT16                        ImageOffset;\r
+  VOID                          *RomBar;\r
+  UINT8                         *RomBarOffset;\r
+  EFI_HANDLE                    ImageHandle;\r
+  EFI_STATUS                    Status;\r
+  EFI_STATUS                    retStatus;\r
+  BOOLEAN                       FirstCheck;\r
+  BOOLEAN                       SkipImage;\r
+  UINT32                        DestinationSize;\r
+  UINT32                        ScratchSize;\r
+  UINT8                         *Scratch;\r
+  VOID                          *ImageBuffer;\r
+  VOID                          *DecompressedImageBuffer;\r
+  UINT32                        ImageLength;\r
+  EFI_DECOMPRESS_PROTOCOL       *Decompress;\r
+  EFI_PCI_EXPANSION_ROM_HEADER  *EfiRomHeader;\r
+  PCI_DATA_STRUCTURE            *Pcir;\r
+\r
+  Indicator = 0;\r
+\r
+  //\r
+  // Get the Address of the Rom image\r
+  //\r
+  RomBar        = PciDevice->PciIo.RomImage;\r
+  RomBarOffset  = (UINT8 *) RomBar;\r
+  retStatus     = EFI_NOT_FOUND;\r
+  FirstCheck    = TRUE;\r
+\r
+  do {\r
+    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
+    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+      RomBarOffset = RomBarOffset + 512;\r
+      if (FirstCheck) {\r
+        break;\r
+      } else {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    FirstCheck  = FALSE;\r
+    Pcir        = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
+    ImageSize   = (UINT32) (Pcir->ImageLength * 512);\r
+    Indicator   = Pcir->Indicator;\r
+\r
+    if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && \r
+        (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) {\r
+\r
+      if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)  ||\r
+          (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {\r
+\r
+        ImageOffset             = EfiRomHeader->EfiImageHeaderOffset;\r
+        ImageSize               = (UINT32) (EfiRomHeader->InitializationSize * 512);\r
+\r
+        ImageBuffer             = (VOID *) (RomBarOffset + ImageOffset);\r
+        ImageLength             = ImageSize - (UINT32)ImageOffset;\r
+        DecompressedImageBuffer = NULL;\r
+\r
+        //\r
+        // decompress here if needed\r
+        //\r
+        SkipImage = FALSE;\r
+        if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+          SkipImage = TRUE;\r
+        }\r
+\r
+        if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+          Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
+          if (EFI_ERROR (Status)) {\r
+            SkipImage = TRUE;\r
+          } else {\r
+            SkipImage = TRUE;\r
+            Status = Decompress->GetInfo (\r
+                                  Decompress,\r
+                                  ImageBuffer,\r
+                                  ImageLength,\r
+                                  &DestinationSize,\r
+                                  &ScratchSize\r
+                                  );\r
+            if (!EFI_ERROR (Status)) {\r
+              DecompressedImageBuffer = NULL;\r
+              DecompressedImageBuffer = AllocatePool (DestinationSize);\r
+              if (DecompressedImageBuffer != NULL) {\r
+                Scratch = AllocatePool (ScratchSize);\r
+                if (Scratch != NULL) {\r
+                  Status = Decompress->Decompress (\r
+                                        Decompress,\r
+                                        ImageBuffer,\r
+                                        ImageLength,\r
+                                        DecompressedImageBuffer,\r
+                                        DestinationSize,\r
+                                        Scratch,\r
+                                        ScratchSize\r
+                                        );\r
+                  if (!EFI_ERROR (Status)) {\r
+                    ImageBuffer = DecompressedImageBuffer;\r
+                    ImageLength = DestinationSize;\r
+                    SkipImage   = FALSE;\r
+                  }\r
+\r
+                  gBS->FreePool (Scratch);\r
+                }\r
+              }\r
+            }\r
+          }\r
+        }\r
+\r
+        if (!SkipImage) {\r
+          //\r
+          // load image and start image\r
+          //\r
+          Status = gBS->LoadImage (\r
+                          FALSE,\r
+                          gPciBusDriverBinding.DriverBindingHandle,\r
+                          NULL,\r
+                          ImageBuffer,\r
+                          ImageLength,\r
+                          &ImageHandle\r
+                          );\r
+          if (!EFI_ERROR (Status)) {\r
+            Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
+            if (!EFI_ERROR (Status)) {\r
+              AddDriver (PciDevice, ImageHandle);\r
+              retStatus = EFI_SUCCESS;\r
+            }\r
+          }\r
+        }\r
+\r
+        RomBarOffset = RomBarOffset + ImageSize;\r
+      } else {\r
+        RomBarOffset = RomBarOffset + ImageSize;\r
+      }\r
+    } else {\r
+      RomBarOffset = RomBarOffset + ImageSize;\r
+    }\r
+\r
+  } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
+\r
+  return retStatus;\r
+\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h b/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h
new file mode 100644 (file)
index 0000000..a82c4ce
--- /dev/null
@@ -0,0 +1,92 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciOptionRomSupport.h\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_OP_ROM_SUPPORT_H\r
+#define _EFI_PCI_OP_ROM_SUPPORT_H\r
+\r
+EFI_STATUS\r
+GetOpRomInfo (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PciIoDevice - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+LoadOpRomImage (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT64          ReservedMemoryBase\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PciDevice - TODO: add argument description\r
+  RomBase   - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+ProcessOpRomImage (\r
+  PCI_IO_DEVICE   *PciDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PciDevice - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif
\ No newline at end of file
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.c b/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.c
new file mode 100644 (file)
index 0000000..5c2386c
--- /dev/null
@@ -0,0 +1,80 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciPowerManagement.c\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Pcibus.h"\r
+\r
+EFI_STATUS\r
+ResetPowerManagementFeature (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is intended to turn off PWE assertion and\r
+  put the device to D0 state if the device supports\r
+  PCI Power Management.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+  \r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       PowerManagementRegBlock;\r
+  UINT16      PMCSR;\r
+\r
+  PowerManagementRegBlock = 0;\r
+\r
+  Status = LocateCapabilityRegBlock (\r
+            PciIoDevice,\r
+            EFI_PCI_CAPABILITY_ID_PMI,\r
+            &PowerManagementRegBlock,\r
+            NULL\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Turn off the PWE assertion and put the device into D0 State\r
+  //\r
+  PMCSR = 0x8000;\r
+\r
+  //\r
+  // Write PMCSR\r
+  //\r
+  PciIoDevice->PciIo.Pci.Write (\r
+                          &PciIoDevice->PciIo,\r
+                          EfiPciIoWidthUint16,\r
+                          PowerManagementRegBlock + 4,\r
+                          1,\r
+                          &PMCSR\r
+                          );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.h b/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.h
new file mode 100644 (file)
index 0000000..3b16fe8
--- /dev/null
@@ -0,0 +1,48 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciPowerManagement.h\r
+  \r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_POWER_MANAGEMENT_H\r
+#define _EFI_PCI_POWER_MANAGEMENT_H\r
+\r
+EFI_STATUS\r
+ResetPowerManagementFeature (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PciIoDevice - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif
\ No newline at end of file
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.c b/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.c
new file mode 100644 (file)
index 0000000..ce72176
--- /dev/null
@@ -0,0 +1,374 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciRomTable.c\r
+  \r
+Abstract:\r
+\r
+  Option Rom Support for PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "pcibus.h"\r
+\r
+typedef struct {\r
+  EFI_HANDLE  ImageHandle;\r
+  UINTN       Seg;\r
+  UINT8       Bus;\r
+  UINT8       Dev;\r
+  UINT8       Func;\r
+} EFI_PCI_ROM_IMAGE_MAPPING;\r
+\r
+static UINTN                      mNumberOfPciRomImages     = 0;\r
+static UINTN                      mMaxNumberOfPciRomImages  = 0;\r
+static EFI_PCI_ROM_IMAGE_MAPPING  *mRomImageTable           = NULL;\r
+\r
+static CHAR16 mHexDigit[17] = L"0123456789ABCDEF";\r
+\r
+static\r
+VOID\r
+PciRomAddImageMapping (\r
+  IN EFI_HANDLE  ImageHandle,\r
+  IN UINTN       Seg,\r
+  IN UINT8       Bus,\r
+  IN UINT8       Dev,\r
+  IN UINT8       Func\r
+  )\r
+\r
+{\r
+  EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;\r
+\r
+  if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {\r
+\r
+    mMaxNumberOfPciRomImages += 0x20;\r
+\r
+    TempMapping = NULL;\r
+    TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));\r
+    if (TempMapping == NULL) {\r
+      return ;\r
+    }\r
+\r
+    CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));\r
+\r
+    if (mRomImageTable != NULL) {\r
+      gBS->FreePool (mRomImageTable);\r
+    }\r
+\r
+    mRomImageTable = TempMapping;\r
+  }\r
+\r
+  mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;\r
+  mRomImageTable[mNumberOfPciRomImages].Seg         = Seg;\r
+  mRomImageTable[mNumberOfPciRomImages].Bus         = Bus;\r
+  mRomImageTable[mNumberOfPciRomImages].Dev         = Dev;\r
+  mRomImageTable[mNumberOfPciRomImages].Func        = Func;\r
+  mNumberOfPciRomImages++;\r
+}\r
+\r
+static\r
+VOID\r
+HexToString (\r
+  CHAR16  *String,\r
+  UINTN   Value,\r
+  UINTN   Digits\r
+  )\r
+\r
+{\r
+  for (; Digits > 0; Digits--, String++) {\r
+    *String = mHexDigit[((Value >> (4*(Digits-1))) & 0x0f)];\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+PciRomLoadEfiDriversFromRomImage (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_PCI_OPTION_ROM_DESCRIPTOR  *PciOptionRomDescriptor\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Command entry point. \r
+\r
+Arguments:\r
+  ImageHandle     The image handle. \r
+  SystemTable     The system table.\r
+\r
+Returns:\r
+  EFI_SUCCESS             - The command completed successfully\r
+  EFI_INVALID_PARAMETER   - Command usage error\r
+  EFI_UNSUPPORTED         - Protocols unsupported\r
+  EFI_OUT_OF_RESOURCES    - Out of memory\r
+  Other value             - Unknown error\r
+\r
+--*/\r
+{\r
+  VOID                          *RomBar;\r
+  UINTN                         RomSize;\r
+  CHAR16                        *FileName;\r
+  EFI_PCI_EXPANSION_ROM_HEADER  *EfiRomHeader;\r
+  PCI_DATA_STRUCTURE            *Pcir;\r
+  UINTN                         ImageIndex;\r
+  UINTN                         RomBarOffset;\r
+  UINT32                        ImageSize;\r
+  UINT16                        ImageOffset;\r
+  EFI_HANDLE                    ImageHandle;\r
+  EFI_STATUS                    Status;\r
+  EFI_STATUS                    retStatus;\r
+  EFI_DEVICE_PATH_PROTOCOL      *FilePath;\r
+  BOOLEAN                       SkipImage;\r
+  UINT32                        DestinationSize;\r
+  UINT32                        ScratchSize;\r
+  UINT8                         *Scratch;\r
+  VOID                          *ImageBuffer;\r
+  VOID                          *DecompressedImageBuffer;\r
+  UINT32                        ImageLength;\r
+  EFI_DECOMPRESS_PROTOCOL       *Decompress;\r
+\r
+  RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;\r
+  RomSize = (UINTN) PciOptionRomDescriptor->RomLength;\r
+  FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";\r
+\r
+  HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8);\r
+  HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2);\r
+  HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2);\r
+  HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2);\r
+\r
+  ImageIndex    = 0;\r
+  retStatus     = EFI_NOT_FOUND;\r
+  RomBarOffset  = (UINTN) RomBar;\r
+\r
+  do {\r
+\r
+    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;\r
+\r
+    if (EfiRomHeader->Signature != 0xaa55) {\r
+      return retStatus;\r
+    }\r
+\r
+    Pcir      = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);\r
+    ImageSize = Pcir->ImageLength * 512;\r
+\r
+    if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
+        (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {\r
+\r
+      if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
+          (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {\r
+\r
+        ImageOffset             = EfiRomHeader->EfiImageHeaderOffset;\r
+        ImageSize               = EfiRomHeader->InitializationSize * 512;\r
+\r
+        ImageBuffer             = (VOID *) (UINTN) (RomBarOffset + ImageOffset);\r
+        ImageLength             = ImageSize - ImageOffset;\r
+        DecompressedImageBuffer = NULL;\r
+\r
+        //\r
+        // decompress here if needed\r
+        //\r
+        SkipImage = FALSE;\r
+        if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+          SkipImage = TRUE;\r
+        }\r
+\r
+        if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+          Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
+          if (EFI_ERROR (Status)) {\r
+            SkipImage = TRUE;\r
+          } else {\r
+            SkipImage = TRUE;\r
+            Status = Decompress->GetInfo (\r
+                                  Decompress,\r
+                                  ImageBuffer,\r
+                                  ImageLength,\r
+                                  &DestinationSize,\r
+                                  &ScratchSize\r
+                                  );\r
+            if (!EFI_ERROR (Status)) {\r
+              DecompressedImageBuffer = NULL;\r
+              DecompressedImageBuffer = AllocatePool (DestinationSize);\r
+              if (DecompressedImageBuffer != NULL) {\r
+                Scratch = AllocatePool (ScratchSize);\r
+                if (Scratch != NULL) {\r
+                  Status = Decompress->Decompress (\r
+                                        Decompress,\r
+                                        ImageBuffer,\r
+                                        ImageLength,\r
+                                        DecompressedImageBuffer,\r
+                                        DestinationSize,\r
+                                        Scratch,\r
+                                        ScratchSize\r
+                                        );\r
+                  if (!EFI_ERROR (Status)) {\r
+                    ImageBuffer = DecompressedImageBuffer;\r
+                    ImageLength = DestinationSize;\r
+                    SkipImage   = FALSE;\r
+                  }\r
+\r
+                  gBS->FreePool (Scratch);\r
+                }\r
+              }\r
+            }\r
+          }\r
+        }\r
+\r
+        if (!SkipImage) {\r
+\r
+          //\r
+          // load image and start image\r
+          //\r
+\r
+          HexToString (&FileName[48], ImageIndex, 4);\r
+          FilePath = FileDevicePath (NULL, FileName);\r
+\r
+          Status = gBS->LoadImage (\r
+                          FALSE,\r
+                          This->ImageHandle,\r
+                          FilePath,\r
+                          ImageBuffer,\r
+                          ImageLength,\r
+                          &ImageHandle\r
+                          );\r
+          if (!EFI_ERROR (Status)) {\r
+            Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
+            if (!EFI_ERROR (Status)) {\r
+              PciRomAddImageMapping (\r
+                ImageHandle,\r
+                PciOptionRomDescriptor->Seg,\r
+                PciOptionRomDescriptor->Bus,\r
+                PciOptionRomDescriptor->Dev,\r
+                PciOptionRomDescriptor->Func\r
+                );\r
+              retStatus = Status;\r
+            }\r
+          }\r
+          if (FilePath != NULL) {\r
+            gBS->FreePool (FilePath);\r
+          }\r
+        }\r
+\r
+        if (DecompressedImageBuffer != NULL) {\r
+          gBS->FreePool (DecompressedImageBuffer);\r
+        }\r
+\r
+      }\r
+    }\r
+\r
+    RomBarOffset = RomBarOffset + ImageSize;\r
+    ImageIndex++;\r
+  } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));\r
+\r
+  return retStatus;\r
+}\r
+\r
+EFI_STATUS\r
+PciRomLoadEfiDriversFromOptionRomTable (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_PCI_OPTION_ROM_TABLE          *PciOptionRomTable;\r
+  EFI_PCI_OPTION_ROM_DESCRIPTOR     *PciOptionRomDescriptor;\r
+  UINTN                             Index;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+  UINT16                            MinBus;\r
+  UINT16                            MaxBus;\r
+\r
+  Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Status = EFI_NOT_FOUND;\r
+\r
+  for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {\r
+    PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];\r
+    if (!PciOptionRomDescriptor->DontLoadEfiRom) {\r
+      if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) {\r
+        Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        PciGetBusRange (Descriptors, &MinBus, &MaxBus, NULL);\r
+        if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) {\r
+          Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor);\r
+          PciOptionRomDescriptor->DontLoadEfiRom |= 2;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+PciRomGetRomResourceFromPciOptionRomTable (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  PCI_IO_DEVICE                       *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_PCI_OPTION_ROM_TABLE      *PciOptionRomTable;\r
+  EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;\r
+  UINTN                         Index;\r
+\r
+  Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {\r
+    PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];\r
+    if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&\r
+        PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber         &&\r
+        PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber      &&\r
+        PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {\r
+\r
+      PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;\r
+      PciIoDevice->PciIo.RomSize  = (UINTN) PciOptionRomDescriptor->RomLength;\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < mNumberOfPciRomImages; Index++) {\r
+    if (mRomImageTable[Index].Seg  == PciRootBridgeIo->SegmentNumber &&\r
+        mRomImageTable[Index].Bus  == PciIoDevice->BusNumber         &&\r
+        mRomImageTable[Index].Dev  == PciIoDevice->DeviceNumber      &&\r
+        mRomImageTable[Index].Func == PciIoDevice->FunctionNumber    ) {\r
+\r
+      AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.h b/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.h
new file mode 100644 (file)
index 0000000..db4dc1c
--- /dev/null
@@ -0,0 +1,58 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciRomTable.h\r
+  \r
+Abstract:\r
+\r
+  Option Rom Support for PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PCI_ROM_TABLE_H\r
+#define _EFI_PCI_ROM_TABLE_H\r
+\r
+\r
+EFI_STATUS\r
+PciRomLoadEfiDriversFromOptionRomTable (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo\r
+  );\r
+\r
+EFI_STATUS\r
+PciRomGetRomResourceFromPciOptionRomTable (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  PCI_IO_DEVICE                       *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  This            - TODO: add argument description\r
+  PciRootBridgeIo - TODO: add argument description\r
+  PciIoDevice     - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+#endif\r