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