summaryrefslogtreecommitdiff
path: root/ArmVirtPkg/PciHostBridgeDxe
diff options
context:
space:
mode:
authorOlivier Martin <olivier.martin@arm.com>2015-05-29 13:50:43 +0000
committeroliviermartin <oliviermartin@Edk2>2015-05-29 13:50:43 +0000
commit7fbd1eb2312d3dfab2ac8cdfcefc234c73d8aeeb (patch)
tree0062d16f930c05cb0fe7e7eececca5f8fb91b18e /ArmVirtPkg/PciHostBridgeDxe
parent4c31caef17170dfd5bd7fe82b890078547750370 (diff)
downloadedk2-platforms-7fbd1eb2312d3dfab2ac8cdfcefc234c73d8aeeb.tar.xz
Renamed ArmPlatformPkg/ArmVirtualizationPkg into ArmVirtPkg
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Laszlo Ersek <lersek@redhat.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17537 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmVirtPkg/PciHostBridgeDxe')
-rw-r--r--ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c1266
-rw-r--r--ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h498
-rw-r--r--ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf69
-rw-r--r--ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c2144
4 files changed, 3977 insertions, 0 deletions
diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
new file mode 100644
index 0000000000..735c7f2163
--- /dev/null
+++ b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -0,0 +1,1266 @@
+/** @file
+ Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation
+
+Copyright (c) 2008 - 2013, 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 "PciHostBridge.h"
+
+//
+// Hard code: Root Bridge Number within the host bridge
+// Root Bridge's attribute
+// Root Bridge's device path
+// Root Bridge's resource aperture
+//
+UINTN RootBridgeNumber[1] = { 1 };
+
+UINT64 RootBridgeAttribute[1][1] = { { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM } };
+
+EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
+ {
+ {
+ {
+ {
+ 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
+ }
+ }
+ }
+ }
+};
+
+STATIC PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1][1];
+
+EFI_HANDLE mDriverImageHandle;
+
+PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
+ PCI_HOST_BRIDGE_SIGNATURE, // Signature
+ NULL, // HostBridgeHandle
+ 0, // RootBridgeNumber
+ {NULL, NULL}, // Head
+ FALSE, // ResourceSubiteed
+ TRUE, // CanRestarted
+ {
+ NotifyPhase,
+ GetNextRootBridge,
+ GetAttributes,
+ StartBusEnumeration,
+ SetBusNumbers,
+ SubmitResources,
+ GetProposedResources,
+ PreprocessController
+ }
+};
+
+//
+// Implementation
+//
+
+/**
+ Entry point of this driver
+
+ @param ImageHandle Handle of driver image
+ @param SystemTable Point to EFI_SYSTEM_TABLE
+
+ @retval EFI_ABORTED PCI host bridge not present
+ @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
+ @retval EFI_DEVICE_ERROR Can not install the protocol instance
+ @retval EFI_SUCCESS Success to initialize the Pci host bridge.
+**/
+EFI_STATUS
+EFIAPI
+InitializePciHostBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINT64 MmioAttributes;
+ EFI_STATUS Status;
+ UINTN Loop1;
+ UINTN Loop2;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ if (PcdGet64 (PcdPciExpressBaseAddress) == 0) {
+ DEBUG ((EFI_D_INFO, "%a: PCI host bridge not present\n", __FUNCTION__));
+ return EFI_ABORTED;
+ }
+
+ mDriverImageHandle = ImageHandle;
+
+ mResAperture[0][0].BusBase = PcdGet32 (PcdPciBusMin);
+ mResAperture[0][0].BusLimit = PcdGet32 (PcdPciBusMax);
+
+ mResAperture[0][0].MemBase = PcdGet32 (PcdPciMmio32Base);
+ mResAperture[0][0].MemLimit = (UINT64)PcdGet32 (PcdPciMmio32Base) +
+ PcdGet32 (PcdPciMmio32Size) - 1;
+
+ mResAperture[0][0].IoBase = PcdGet64 (PcdPciIoBase);
+ mResAperture[0][0].IoLimit = PcdGet64 (PcdPciIoBase) +
+ PcdGet64 (PcdPciIoSize) - 1;
+ mResAperture[0][0].IoTranslation = PcdGet64 (PcdPciIoTranslation);
+
+ //
+ // Add IO and MMIO memory space, so that resources can be allocated in the
+ // EfiPciHostBridgeAllocateResources phase.
+ //
+ Status = gDS->AddIoSpace (
+ EfiGcdIoTypeIo,
+ PcdGet64 (PcdPciIoBase),
+ PcdGet64 (PcdPciIoSize)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ MmioAttributes = FeaturePcdGet (PcdKludgeMapPciMmioAsCached) ?
+ EFI_MEMORY_WB : EFI_MEMORY_UC;
+
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ PcdGet32 (PcdPciMmio32Base),
+ PcdGet32 (PcdPciMmio32Size),
+ MmioAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: AddMemorySpace: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ Status = gDS->SetMemorySpaceAttributes (
+ PcdGet32 (PcdPciMmio32Base),
+ PcdGet32 (PcdPciMmio32Size),
+ MmioAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: SetMemorySpaceAttributes: %r\n", __FUNCTION__,
+ Status));
+ return Status;
+ }
+
+ //
+ // Create Host Bridge Device Handle
+ //
+ for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
+ HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate);
+ if (HostBridge == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
+ InitializeListHead (&HostBridge->Head);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &HostBridge->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (HostBridge);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Create Root Bridge Device Handle in this Host Bridge
+ //
+
+ for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
+ PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
+ if (PrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
+ PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
+
+ RootBridgeConstructor (
+ &PrivateData->Io,
+ HostBridge->HostBridgeHandle,
+ RootBridgeAttribute[Loop1][Loop2],
+ &mResAperture[Loop1][Loop2]
+ );
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid, PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool(PrivateData);
+ return EFI_DEVICE_ERROR;
+ }
+
+ InsertTailList (&HostBridge->Head, &PrivateData->Link);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ These are the notifications from the PCI bus driver that it is about to enter a certain
+ phase of the PCI enumeration process.
+
+ This member function can be used to notify the host bridge driver to perform specific actions,
+ including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
+ Eight notification points are defined at this time. See belows:
+ EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
+ structures. The PCI enumerator should issue this notification
+ before starting a fresh enumeration process. Enumeration cannot
+ be restarted after sending any other notification such as
+ EfiPciHostBridgeBeginBusAllocation.
+ EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
+ required here. This notification can be used to perform any
+ chipset-specific programming.
+ EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
+ specific action is required here. This notification can be used to
+ perform any chipset-specific programming.
+ EfiPciHostBridgeBeginResourceAllocation
+ The resource allocation phase is about to begin. No specific
+ action is required here. This notification can be used to perform
+ any chipset-specific programming.
+ EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
+ root bridges. These resource settings are returned on the next call to
+ GetProposedResources(). Before calling NotifyPhase() with a Phase of
+ EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
+ for gathering I/O and memory requests for
+ all the PCI root bridges and submitting these requests using
+ SubmitResources(). This function pads the resource amount
+ to suit the root bridge hardware, takes care of dependencies between
+ the PCI root bridges, and calls the Global Coherency Domain (GCD)
+ with the allocation request. In the case of padding, the allocated range
+ could be bigger than what was requested.
+ EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
+ resources (proposed resources) for all the PCI root bridges. After the
+ hardware is programmed, reassigning resources will not be supported.
+ The bus settings are not affected.
+ EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
+ root bridges and resets the I/O and memory apertures to their initial
+ state. The bus settings are not affected. If the request to allocate
+ resources fails, the PCI enumerator can use this notification to
+ deallocate previous resources, adjust the requests, and retry
+ allocation.
+ EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
+ required here. This notification can be used to perform any chipsetspecific
+ programming.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] Phase The phase during enumeration
+
+ @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
+ is valid for a Phase of EfiPciHostBridgeAllocateResources if
+ SubmitResources() has not been called for one or more
+ PCI root bridges before this call
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
+ for a Phase of EfiPciHostBridgeSetResources.
+ @retval EFI_INVALID_PARAMETER Invalid phase parameter
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
+ previously submitted resource requests cannot be fulfilled or
+ were only partially fulfilled.
+ @retval EFI_SUCCESS The notification was accepted without any errors.
+
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ PCI_RESOURCE_TYPE Index;
+ LIST_ENTRY *List;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 AddrLen;
+ UINTN BitsOfAlignment;
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ switch (Phase) {
+
+ case EfiPciHostBridgeBeginEnumeration:
+ if (HostBridgeInstance->CanRestarted) {
+ //
+ // Reset the Each Root Bridge
+ //
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeMax; Index++) {
+ RootBridgeInstance->ResAllocNode[Index].Type = Index;
+ RootBridgeInstance->ResAllocNode[Index].Base = 0;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ HostBridgeInstance->ResourceSubmited = FALSE;
+ HostBridgeInstance->CanRestarted = TRUE;
+ } else {
+ //
+ // Can not restart
+ //
+ return EFI_NOT_READY;
+ }
+ break;
+
+ case EfiPciHostBridgeEndEnumeration:
+ break;
+
+ case EfiPciHostBridgeBeginBusAllocation:
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+ HostBridgeInstance->CanRestarted = FALSE;
+ break;
+
+ case EfiPciHostBridgeEndBusAllocation:
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+ //HostBridgeInstance->CanRestarted = FALSE;
+ break;
+
+ case EfiPciHostBridgeBeginResourceAllocation:
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+ //HostBridgeInstance->CanRestarted = FALSE;
+ break;
+
+ case EfiPciHostBridgeAllocateResources:
+ ReturnStatus = EFI_SUCCESS;
+ if (HostBridgeInstance->ResourceSubmited) {
+ //
+ // Take care of the resource dependencies between the root bridges
+ //
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+
+ AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+
+ //
+ // Get the number of '1' in Alignment.
+ //
+ BitsOfAlignment = (UINTN) (HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1);
+
+ switch (Index) {
+
+ case TypeIo:
+ //
+ // It is impossible for this chipset to align 0xFFFF for IO16
+ // So clear it
+ //
+ if (BitsOfAlignment >= 16) {
+ BitsOfAlignment = 0;
+ }
+
+ BaseAddress = mResAperture[0][0].IoLimit;
+ Status = gDS->AllocateIoSpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdIoTypeIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ mDriverImageHandle,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ } else {
+ ReturnStatus = Status;
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ }
+ }
+
+ break;
+
+
+ case TypeMem32:
+ //
+ // It is impossible for this chipset to align 0xFFFFFFFF for Mem32
+ // So clear it
+ //
+
+ if (BitsOfAlignment >= 32) {
+ BitsOfAlignment = 0;
+ }
+
+ BaseAddress = mResAperture[0][0].MemLimit;
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ mDriverImageHandle,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ // We were able to allocate the PCI memory
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+
+ } else {
+ // Not able to allocate enough PCI memory
+ ReturnStatus = Status;
+
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ }
+ ASSERT (FALSE);
+ }
+ break;
+
+ case TypePMem32:
+ case TypeMem64:
+ case TypePMem64:
+ ReturnStatus = EFI_ABORTED;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }; //end switch
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return ReturnStatus;
+ } else {
+ return EFI_NOT_READY;
+ }
+
+ case EfiPciHostBridgeSetResources:
+ break;
+
+ case EfiPciHostBridgeFreeResources:
+ ReturnStatus = EFI_SUCCESS;
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
+ AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
+ switch (Index) {
+
+ case TypeIo:
+ Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+ break;
+
+ case TypeMem32:
+ Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+ break;
+
+ case TypePMem32:
+ break;
+
+ case TypeMem64:
+ break;
+
+ case TypePMem64:
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+
+ }; //end switch
+ RootBridgeInstance->ResAllocNode[Index].Type = Index;
+ RootBridgeInstance->ResAllocNode[Index].Base = 0;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+
+ HostBridgeInstance->ResourceSubmited = FALSE;
+ HostBridgeInstance->CanRestarted = TRUE;
+ return ReturnStatus;
+
+ case EfiPciHostBridgeEndResourceAllocation:
+ HostBridgeInstance->CanRestarted = FALSE;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
+
+ This function is called multiple times to retrieve the device handles of all the PCI root bridges that
+ are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
+ root bridges. On each call, the handle that was returned by the previous call is passed into the
+ interface, and on output the interface returns the device handle of the next PCI root bridge. The
+ caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ for that root bridge. When there are no more PCI root bridges to report, the interface returns
+ EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
+ are returned by this function.
+ For D945 implementation, there is only one root bridge in PCI host bridge.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge.
+
+ @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
+ specific Host bridge and return EFI_SUCCESS.
+ @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
+ returned on a previous call to GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ )
+{
+ BOOLEAN NoRootBridge;
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ NoRootBridge = TRUE;
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+
+ while (List != &HostBridgeInstance->Head) {
+ NoRootBridge = FALSE;
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (*RootBridgeHandle == NULL) {
+ //
+ // Return the first Root Bridge Handle of the Host Bridge
+ //
+ *RootBridgeHandle = RootBridgeInstance->Handle;
+ return EFI_SUCCESS;
+ } else {
+ if (*RootBridgeHandle == RootBridgeInstance->Handle) {
+ //
+ // Get next if have
+ //
+ List = List->ForwardLink;
+ if (List!=&HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ *RootBridgeHandle = RootBridgeInstance->Handle;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ List = List->ForwardLink;
+ } //end while
+
+ if (NoRootBridge) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/**
+ Returns the allocation attributes of a PCI root bridge.
+
+ The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
+ from one PCI root bridge to another. These attributes are different from the decode-related
+ attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+ RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
+ handles of all the root bridges that are associated with this host bridge must be obtained by calling
+ GetNextRootBridge(). The attributes are static in the sense that they do not change during or
+ after the enumeration process. The hardware may provide mechanisms to change the attributes on
+ the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
+ installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+ "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
+ For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
+ include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
+ prefetchable memory.
+ Attribute Description
+ ------------------------------------ ----------------------------------------------------------------------
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate
+ windows for nonprefetchable and prefetchable memory. A PCI bus
+ driver needs to include requests for prefetchable memory in the
+ nonprefetchable memory pool.
+
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory
+ windows. If this bit is not set, the PCI bus driver needs to include
+ requests for a 64-bit memory address in the corresponding 32-bit
+ memory pool.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type
+ EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Attributes The pointer to attribte of root bridge, it is output parameter
+
+ @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
+ @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
+ @retval EFI_SUCCESS Success to get attribute of interested root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ if (Attributes == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ *Attributes = RootBridgeInstance->RootBridgeAttrib;
+ return EFI_SUCCESS;
+ }
+ List = List->ForwardLink;
+ }
+
+ //
+ // RootBridgeHandle is not an EFI_HANDLE
+ // that was returned on a previous call to GetNextRootBridge()
+ //
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Sets up the specified PCI root bridge for the bus enumeration process.
+
+ This member function sets up the root bridge for bus enumeration and returns the PCI bus range
+ over which the search should be performed in ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
+ @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
+ @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
+
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ VOID *Buffer;
+ UINT8 *Temp;
+ UINT64 BusStart;
+ UINT64 BusEnd;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ //
+ // Set up the Root Bridge for Bus Enumeration
+ //
+ BusStart = RootBridgeInstance->BusBase;
+ BusEnd = RootBridgeInstance->BusLimit;
+ //
+ // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
+ //
+
+ Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Temp = (UINT8 *)Buffer;
+
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1;
+
+ Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+ return EFI_SUCCESS;
+ }
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
+
+ This member function programs the specified PCI root bridge to decode the bus range that is
+ specified by the input parameter Configuration.
+ The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed
+ @param[in] Configuration The pointer to the PCI bus resource descriptor
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than
+ bus descriptors.
+ @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.
+ @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Ptr;
+ UINTN BusStart;
+ UINTN BusEnd;
+ UINTN BusLen;
+
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr = Configuration;
+
+ //
+ // Check the Configuration is valid
+ //
+ if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ Ptr = Configuration;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
+ BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
+ BusEnd = BusStart + BusLen - 1;
+
+ if (BusStart > BusEnd) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Update the Bus Range
+ //
+ RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
+ RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
+ RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
+
+ //
+ // Program the Root Bridge Hardware
+ //
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+
+/**
+ Submits the I/O and memory resource requirements for the specified PCI root bridge.
+
+ This function is used to submit all the I/O and memory resources that are required by the specified
+ PCI root bridge. The input parameter Configuration is used to specify the following:
+ - The various types of resources that are required
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.
+ @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
+
+ @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are
+ not supported by this PCI root bridge. This error will happen if the caller
+ did not combine resources according to Attributes that were returned by
+ GetAllocAttributes().
+ @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ UINT64 AddrLen;
+ UINT64 Alignment;
+
+ //
+ // Check the input parameter: Configuration
+ //
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ Temp = (UINT8 *)Configuration;
+ while ( *Temp == 0x8A) {
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
+ }
+ if (*Temp != 0x79) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Temp = (UINT8 *)Configuration;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ for (;
+ *Temp == 0x8A;
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)
+ ) {
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
+
+ //
+ // Check Address Length
+ //
+ if (Ptr->AddrLen == 0) {
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ continue;
+ }
+ if (Ptr->AddrLen > 0xffffffff) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check address range alignment
+ //
+ if (Ptr->AddrRangeMax >= 0xffffffff || Ptr->AddrRangeMax != (GetPowerOfTwo64 (Ptr->AddrRangeMax + 1) - 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Ptr->ResType) {
+
+ case 0:
+
+ //
+ // Check invalid Address Sapce Granularity
+ //
+ if (Ptr->AddrSpaceGranularity != 32) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // check the memory resource request is supported by PCI root bridge
+ //
+ if (RootBridgeInstance->RootBridgeAttrib == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
+ Ptr->SpecificFlag == 0x06) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AddrLen = Ptr->AddrLen;
+ Alignment = Ptr->AddrRangeMax;
+ if (Ptr->AddrSpaceGranularity == 32) {
+ if (Ptr->SpecificFlag == 0x06) {
+ //
+ // Apply from GCD
+ //
+ RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
+ } else {
+ RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ }
+ }
+
+ if (Ptr->AddrSpaceGranularity == 64) {
+ if (Ptr->SpecificFlag == 0x06) {
+ RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
+ } else {
+ RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
+ }
+ }
+ break;
+
+ case 1:
+ AddrLen = (UINTN) Ptr->AddrLen;
+ Alignment = (UINTN) Ptr->AddrRangeMax;
+ RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ break;
+
+ default:
+ break;
+ };
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Returns the proposed resource settings for the specified PCI root bridge.
+
+ This member function returns the proposed resource settings for the specified PCI root bridge. The
+ proposed resource settings are prepared when NotifyPhase() is called with a Phase of
+ EfiPciHostBridgeAllocateResources. The output parameter Configuration
+ specifies the following:
+ - The various types of resources, excluding bus resources, that are allocated
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINTN Index;
+ UINTN Number;
+ VOID *Buffer;
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ UINT64 ResStatus;
+
+ Buffer = NULL;
+ Number = 0;
+ //
+ // Get the Host Bridge Instance from the resource allocation protocol
+ //
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ //
+ // Enumerate the root bridges in this host bridge
+ //
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ for (Index = 0; Index < TypeBus; Index ++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ Number ++;
+ }
+ }
+
+ if (Number == 0) {
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;
+
+ End = AllocateZeroPool (sizeof *End);
+ if (End == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;
+ *Configuration = End;
+ return EFI_SUCCESS;
+ }
+
+ Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Temp = Buffer;
+ for (Index = 0; Index < TypeBus; Index ++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
+ ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
+
+ switch (Index) {
+
+ case TypeIo:
+ //
+ // Io
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 1;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 0;
+ Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = \
+ (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypeMem32:
+ //
+ // Memory 32
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 0;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 0;
+ Ptr->AddrSpaceGranularity = 32;
+ Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = \
+ (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypePMem32:
+ //
+ // Prefetch memory 32
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 0;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 6;
+ Ptr->AddrSpaceGranularity = 32;
+ Ptr->AddrRangeMin = 0;
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ Ptr->AddrLen = 0;
+ break;
+
+ case TypeMem64:
+ //
+ // Memory 64
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 0;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 0;
+ Ptr->AddrSpaceGranularity = 64;
+ Ptr->AddrRangeMin = 0;
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ Ptr->AddrLen = 0;
+ break;
+
+ case TypePMem64:
+ //
+ // Prefetch memory 64
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 0;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 6;
+ Ptr->AddrSpaceGranularity = 64;
+ Ptr->AddrRangeMin = 0;
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ Ptr->AddrLen = 0;
+ break;
+ };
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+ }
+
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+ stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+ PCI controllers before enumeration.
+
+ This function is called during the PCI enumeration process. No specific action is expected from this
+ member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+ enumeration.
+
+ @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in
+ InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
+ configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
+ the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+ @param Phase The phase of the PCI device enumeration.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
+ EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
+ not enumerate this device, including its child devices if it is a PCI-to-PCI
+ bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ LIST_ENTRY *List;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ //
+ // Enumerate the root bridges in this host bridge
+ //
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ break;
+ }
+ List = List->ForwardLink;
+ }
+ if (List == &HostBridgeInstance->Head) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h
new file mode 100644
index 0000000000..8161b546ff
--- /dev/null
+++ b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h
@@ -0,0 +1,498 @@
+/** @file
+ The Header file of the Pci Host Bridge Driver
+
+ Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCI_HOST_BRIDGE_H_
+#define _PCI_HOST_BRIDGE_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/Metronome.h>
+#include <Protocol/DevicePath.h>
+
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+
+//
+// Hard code the host bridge number in the platform.
+// In this chipset, there is only one host bridge.
+//
+#define HOST_BRIDGE_NUMBER 1
+
+#define MAX_PCI_DEVICE_NUMBER 31
+#define MAX_PCI_FUNCTION_NUMBER 7
+#define MAX_PCI_REG_ADDRESS (SIZE_4KB - 1)
+
+typedef enum {
+ IoOperation,
+ MemOperation,
+ PciOperation
+} OPERATION_TYPE;
+
+#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32('e', 'h', 's', 't')
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE HostBridgeHandle;
+ UINTN RootBridgeNumber;
+ LIST_ENTRY Head;
+ BOOLEAN ResourceSubmited;
+ BOOLEAN CanRestarted;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;
+} PCI_HOST_BRIDGE_INSTANCE;
+
+#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) \
+ CR(a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
+
+//
+// HostBridge Resource Allocation interface
+//
+
+/**
+ These are the notifications from the PCI bus driver that it is about to enter a certain
+ phase of the PCI enumeration process.
+
+ This member function can be used to notify the host bridge driver to perform specific actions,
+ including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
+ Eight notification points are defined at this time. See belows:
+ EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
+ structures. The PCI enumerator should issue this notification
+ before starting a fresh enumeration process. Enumeration cannot
+ be restarted after sending any other notification such as
+ EfiPciHostBridgeBeginBusAllocation.
+ EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
+ required here. This notification can be used to perform any
+ chipset-specific programming.
+ EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
+ specific action is required here. This notification can be used to
+ perform any chipset-specific programming.
+ EfiPciHostBridgeBeginResourceAllocation
+ The resource allocation phase is about to begin. No specific
+ action is required here. This notification can be used to perform
+ any chipset-specific programming.
+ EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
+ root bridges. These resource settings are returned on the next call to
+ GetProposedResources(). Before calling NotifyPhase() with a Phase of
+ EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
+ for gathering I/O and memory requests for
+ all the PCI root bridges and submitting these requests using
+ SubmitResources(). This function pads the resource amount
+ to suit the root bridge hardware, takes care of dependencies between
+ the PCI root bridges, and calls the Global Coherency Domain (GCD)
+ with the allocation request. In the case of padding, the allocated range
+ could be bigger than what was requested.
+ EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
+ resources (proposed resources) for all the PCI root bridges. After the
+ hardware is programmed, reassigning resources will not be supported.
+ The bus settings are not affected.
+ EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
+ root bridges and resets the I/O and memory apertures to their initial
+ state. The bus settings are not affected. If the request to allocate
+ resources fails, the PCI enumerator can use this notification to
+ deallocate previous resources, adjust the requests, and retry
+ allocation.
+ EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
+ required here. This notification can be used to perform any chipsetspecific
+ programming.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] Phase The phase during enumeration
+
+ @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
+ is valid for a Phase of EfiPciHostBridgeAllocateResources if
+ SubmitResources() has not been called for one or more
+ PCI root bridges before this call
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
+ for a Phase of EfiPciHostBridgeSetResources.
+ @retval EFI_INVALID_PARAMETER Invalid phase parameter
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
+ previously submitted resource requests cannot be fulfilled or
+ were only partially fulfilled.
+ @retval EFI_SUCCESS The notification was accepted without any errors.
+
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ );
+
+/**
+ Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
+
+ This function is called multiple times to retrieve the device handles of all the PCI root bridges that
+ are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
+ root bridges. On each call, the handle that was returned by the previous call is passed into the
+ interface, and on output the interface returns the device handle of the next PCI root bridge. The
+ caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ for that root bridge. When there are no more PCI root bridges to report, the interface returns
+ EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
+ are returned by this function.
+ For D945 implementation, there is only one root bridge in PCI host bridge.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge.
+
+ @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
+ specific Host bridge and return EFI_SUCCESS.
+ @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
+ returned on a previous call to GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ );
+
+/**
+ Returns the allocation attributes of a PCI root bridge.
+
+ The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
+ from one PCI root bridge to another. These attributes are different from the decode-related
+ attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+ RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
+ handles of all the root bridges that are associated with this host bridge must be obtained by calling
+ GetNextRootBridge(). The attributes are static in the sense that they do not change during or
+ after the enumeration process. The hardware may provide mechanisms to change the attributes on
+ the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
+ installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+ "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
+ For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
+ include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
+ prefetchable memory.
+ Attribute Description
+ ------------------------------------ ----------------------------------------------------------------------
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate
+ windows for nonprefetchable and prefetchable memory. A PCI bus
+ driver needs to include requests for prefetchable memory in the
+ nonprefetchable memory pool.
+
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory
+ windows. If this bit is not set, the PCI bus driver needs to include
+ requests for a 64-bit memory address in the corresponding 32-bit
+ memory pool.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type
+ EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Attributes The pointer to attribte of root bridge, it is output parameter
+
+ @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
+ @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
+ @retval EFI_SUCCESS Success to get attribute of interested root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ );
+
+/**
+ Sets up the specified PCI root bridge for the bus enumeration process.
+
+ This member function sets up the root bridge for bus enumeration and returns the PCI bus range
+ over which the search should be performed in ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
+ @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
+ @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
+
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ );
+
+/**
+ Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
+
+ This member function programs the specified PCI root bridge to decode the bus range that is
+ specified by the input parameter Configuration.
+ The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed
+ @param[in] Configuration The pointer to the PCI bus resource descriptor
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than
+ bus descriptors.
+ @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.
+ @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ );
+
+/**
+ Submits the I/O and memory resource requirements for the specified PCI root bridge.
+
+ This function is used to submit all the I/O and memory resources that are required by the specified
+ PCI root bridge. The input parameter Configuration is used to specify the following:
+ - The various types of resources that are required
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.
+ @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
+
+ @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are
+ not supported by this PCI root bridge. This error will happen if the caller
+ did not combine resources according to Attributes that were returned by
+ GetAllocAttributes().
+ @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ );
+
+/**
+ Returns the proposed resource settings for the specified PCI root bridge.
+
+ This member function returns the proposed resource settings for the specified PCI root bridge. The
+ proposed resource settings are prepared when NotifyPhase() is called with a Phase of
+ EfiPciHostBridgeAllocateResources. The output parameter Configuration
+ specifies the following:
+ - The various types of resources, excluding bus resources, that are allocated
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ );
+
+/**
+ Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+ stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+ PCI controllers before enumeration.
+
+ This function is called during the PCI enumeration process. No specific action is expected from this
+ member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+ enumeration.
+
+ @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in
+ InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
+ configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
+ the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+ @param Phase The phase of the PCI device enumeration.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
+ EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
+ not enumerate this device, including its child devices if it is a PCI-to-PCI
+ bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ );
+
+
+//
+// Define resource status constant
+//
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+
+
+//
+// Driver Instance Data Prototypes
+//
+
+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 {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef struct {
+ UINT64 BusBase;
+ UINT64 BusLimit;
+
+ UINT64 MemBase;
+ UINT64 MemLimit;
+
+ UINT64 IoBase;
+ UINT64 IoLimit;
+ UINT64 IoTranslation;
+} PCI_ROOT_BRIDGE_RESOURCE_APERTURE;
+
+typedef enum {
+ TypeIo = 0,
+ TypeMem32,
+ TypePMem32,
+ TypeMem64,
+ TypePMem64,
+ TypeBus,
+ TypeMax
+} PCI_RESOURCE_TYPE;
+
+typedef enum {
+ ResNone = 0,
+ ResSubmitted,
+ ResRequested,
+ ResAllocated,
+ ResStatusMax
+} RES_STATUS;
+
+typedef struct {
+ PCI_RESOURCE_TYPE Type;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Alignment;
+ RES_STATUS Status;
+} PCI_RES_NODE;
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32('e', '2', 'p', 'b')
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ EFI_HANDLE Handle;
+ UINT64 RootBridgeAttrib;
+ UINT64 Attributes;
+ UINT64 Supports;
+
+ //
+ // Specific for this memory controller: Bus, I/O, Mem
+ //
+ PCI_RES_NODE ResAllocNode[6];
+
+ //
+ // Addressing for Memory and I/O and Bus arrange
+ //
+ UINT64 BusBase;
+ UINT64 MemBase;
+ UINT64 IoBase;
+ UINT64 BusLimit;
+ UINT64 MemLimit;
+ UINT64 IoLimit;
+ UINT64 IoTranslation;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+
+} PCI_ROOT_BRIDGE_INSTANCE;
+
+
+//
+// Driver Instance Data Macros
+//
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
+ CR(a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+
+#define DRIVER_INSTANCE_FROM_LIST_ENTRY(a) \
+ CR(a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)
+
+/**
+
+ Construct the Pci Root Bridge Io protocol
+
+ @param Protocol Point to protocol instance
+ @param HostBridgeHandle Handle of host bridge
+ @param Attri Attribute of host bridge
+ @param ResAperture ResourceAperture for host bridge
+
+ @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
+
+**/
+EFI_STATUS
+RootBridgeConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN UINT64 Attri,
+ IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture
+ );
+
+#endif
diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
new file mode 100644
index 0000000000..6d782582e0
--- /dev/null
+++ b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -0,0 +1,69 @@
+## @file
+# The basic interfaces implementation to a single segment PCI Host Bridge driver.
+#
+# Copyright (c) 2008 - 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PciHostBridge
+ FILE_GUID = 9f609346-37cb-4eb7-801f-f55099373998
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializePciHostBridge
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+ UefiLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ DevicePathLib
+ IoLib
+ PciLib
+ PcdLib
+
+[Sources]
+ PciHostBridge.c
+ PciRootBridgeIo.c
+ PciHostBridge.h
+
+[Protocols]
+ gEfiPciHostBridgeResourceAllocationProtocolGuid ## PRODUCES
+ gEfiPciRootBridgeIoProtocolGuid ## PRODUCES
+ gEfiMetronomeArchProtocolGuid ## CONSUMES
+ gEfiDevicePathProtocolGuid ## PRODUCES
+
+[Pcd]
+ gArmPlatformTokenSpaceGuid.PcdPciBusMin
+ gArmPlatformTokenSpaceGuid.PcdPciBusMax
+ gArmPlatformTokenSpaceGuid.PcdPciIoBase
+ gArmPlatformTokenSpaceGuid.PcdPciIoSize
+ gArmPlatformTokenSpaceGuid.PcdPciIoTranslation
+ gArmPlatformTokenSpaceGuid.PcdPciMmio32Base
+ gArmPlatformTokenSpaceGuid.PcdPciMmio32Size
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[FeaturePcd]
+ gArmVirtTokenSpaceGuid.PcdKludgeMapPciMmioAsCached
+
+[depex]
+ gEfiMetronomeArchProtocolGuid AND
+ gEfiCpuArchProtocolGuid
diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c b/ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c
new file mode 100644
index 0000000000..c867887950
--- /dev/null
+++ b/ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -0,0 +1,2144 @@
+/** @file
+ PCI Root Bridge Io Protocol implementation
+
+Copyright (c) 2008 - 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.
+
+**/
+
+#include "PciHostBridge.h"
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[TypeMax];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
+} RESOURCE_CONFIGURATION;
+
+RESOURCE_CONFIGURATION Configuration = {
+ {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
+ {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},
+ {0x79, 0}
+};
+
+//
+// Protocol Member Function Prototypes
+//
+
+/**
+ Polls an address in memory mapped I/O space until an exit condition is met, or
+ a timeout occurs.
+
+ This function provides a standard way to poll a PCI memory location. A PCI memory read
+ operation is performed at the PCI memory address specified by Address for the width specified
+ by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
+ read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
+ Mask) is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the memory operations. The caller is
+ responsible for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the memory address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ 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
+ );
+
+/**
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
+ satisfied or after a defined duration.
+
+ This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
+ performed at the PCI I/O address specified by Address for the width specified by Width.
+ The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
+ repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
+ to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is responsible
+ for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the I/O address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ 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
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ OUT VOID *UserBuffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[in] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN VOID *UserBuffer
+ );
+
+/**
+ Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
+ root bridge memory space.
+
+ The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
+ space to another region of PCI root bridge memory space. This is especially useful for video scroll
+ operation on a memory mapped video buffer.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI root bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] DestAddress The destination address of the memory operation. The caller is
+ responsible for aligning the DestAddress if required.
+ @param[in] SrcAddress The source address of the memory operation. The caller is
+ responsible for aligning the SrcAddress if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at DestAddress and SrcAddress.
+
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ 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
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Provides the PCI controller-specific addresses required to access system memory from a
+ DMA bus master.
+
+ The Map() function provides the PCI controller specific addresses needed to access system
+ memory. This function is used to map system memory for PCI bus master DMA accesses.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Operation Indicates if the bus master is going to read or write to system memory.
+ @param[in] HostAddress The system memory address to map to the PCI controller.
+ @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped.
+ @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use
+ to access the system memory's HostAddress.
+ @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete.
+
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
+ @retval EFI_INVALID_PARAMETER Operation is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
+ @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
+ @retval EFI_INVALID_PARAMETER Mapping is NULL.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ 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
+ );
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ The Unmap() function completes the Map() operation and releases any corresponding resources.
+ If the operation was an EfiPciOperationBusMasterWrite or
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
+ Any resources used for the mapping are freed.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+/**
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
+ EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory address of the allocated range.
+ @param Attributes The requested bit mask of attributes for the allocated range. Only
+ the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
+ and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ 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
+ );
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
+ memory. Posted write transactions are generated by PCI bus masters when they perform write
+ transactions to target addresses in system memory.
+ This function does not flush posted write transactions from any PCI bridges. A PCI controller
+ specific action must be taken to guarantee that the posted write transactions have been flushed from
+ the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
+ a PCI read transaction from the PCI controller prior to calling Flush().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
+ host bridge due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+/**
+ Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
+ attributes that a PCI root bridge is currently using.
+
+ The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
+ and the mask of attributes that the PCI root bridge is currently using.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Supported A pointer to the mask of attributes that this PCI root bridge
+ supports setting with SetAttributes().
+ @param Attributes A pointer to the mask of attributes that this PCI root bridge is
+ currently using.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
+ bridge supports is returned in Supports. If Attributes is
+ not NULL, then the attributes that the PCI root bridge is currently
+ using is returned in Attributes.
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+/**
+ Sets attributes for a resource range on a PCI root bridge.
+
+ The SetAttributes() function sets the attributes specified in Attributes for the PCI root
+ bridge on the resource range specified by ResourceBase and ResourceLength. Since the
+ granularity of setting these attributes may vary from resource type to resource type, and from
+ platform to platform, the actual resource range and the one passed in by the caller may differ. As a
+ result, this function may set the attributes specified by Attributes on a larger resource range
+ than the caller requested. The actual range is returned in ResourceBase and
+ ResourceLength. The caller is responsible for verifying that the actual range for which the
+ attributes were set is acceptable.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Attributes The mask of attributes to set. If the attribute bit
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
+ MEMORY_DISABLE is set, then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then ResourceBase and
+ ResourceLength are ignored, and may be NULL.
+ @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified
+ by the attributes specified by Attributes.
+ @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+/**
+ Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
+ resource descriptors.
+
+ There are only two resource descriptor types from the ACPI Specification that may be used to
+ describe the current resources allocated to a PCI root bridge. These are the QWORD Address
+ Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
+ QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
+ or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
+ Address Space Descriptors followed by an End Tag.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the
+ current configuration of this PCI root bridge. The storage for the
+ ACPI 2.0 resource descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only data, and the buffer
+ must not be freed by the caller.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+//
+// Memory Controller Pci Root Bridge Io Module Variables
+//
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mInStride[] = {
+ 1, // EfiPciWidthUint8
+ 2, // EfiPciWidthUint16
+ 4, // EfiPciWidthUint32
+ 8, // EfiPciWidthUint64
+ 0, // EfiPciWidthFifoUint8
+ 0, // EfiPciWidthFifoUint16
+ 0, // EfiPciWidthFifoUint32
+ 0, // EfiPciWidthFifoUint64
+ 1, // EfiPciWidthFillUint8
+ 2, // EfiPciWidthFillUint16
+ 4, // EfiPciWidthFillUint32
+ 8 // EfiPciWidthFillUint64
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mOutStride[] = {
+ 1, // EfiPciWidthUint8
+ 2, // EfiPciWidthUint16
+ 4, // EfiPciWidthUint32
+ 8, // EfiPciWidthUint64
+ 1, // EfiPciWidthFifoUint8
+ 2, // EfiPciWidthFifoUint16
+ 4, // EfiPciWidthFifoUint32
+ 8, // EfiPciWidthFifoUint64
+ 0, // EfiPciWidthFillUint8
+ 0, // EfiPciWidthFillUint16
+ 0, // EfiPciWidthFillUint32
+ 0 // EfiPciWidthFillUint64
+};
+
+/**
+
+ Construct the Pci Root Bridge Io protocol
+
+ @param Protocol Point to protocol instance
+ @param HostBridgeHandle Handle of host bridge
+ @param Attri Attribute of host bridge
+ @param ResAperture ResourceAperture for host bridge
+
+ @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
+
+**/
+EFI_STATUS
+RootBridgeConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN UINT64 Attri,
+ IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture
+ )
+{
+ EFI_STATUS Status;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ PCI_RESOURCE_TYPE Index;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
+
+ //
+ // The host to PCI bridge. The host memory addresses are direct mapped to PCI
+ // addresses, so there's no need to translate them. IO addresses need
+ // translation however.
+ //
+ PrivateData->MemBase = ResAperture->MemBase;
+ PrivateData->IoBase = ResAperture->IoBase;
+ PrivateData->IoTranslation = ResAperture->IoTranslation;
+
+ //
+ // The host bridge only supports 32bit addressing for memory
+ // and standard IA32 16bit io
+ //
+ PrivateData->MemLimit = ResAperture->MemLimit;
+ PrivateData->IoLimit = ResAperture->IoLimit;
+
+ //
+ // Bus Aperture for this Root Bridge (Possible Range)
+ //
+ PrivateData->BusBase = ResAperture->BusBase;
+ PrivateData->BusLimit = ResAperture->BusLimit;
+
+ //
+ // Specific for this chipset
+ //
+ for (Index = TypeIo; Index < TypeMax; Index++) {
+ PrivateData->ResAllocNode[Index].Type = Index;
+ PrivateData->ResAllocNode[Index].Base = 0;
+ PrivateData->ResAllocNode[Index].Length = 0;
+ PrivateData->ResAllocNode[Index].Status = ResNone;
+ }
+
+ PrivateData->RootBridgeAttrib = Attri;
+
+ PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | \
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
+ EFI_PCI_ATTRIBUTE_VGA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
+ PrivateData->Attributes = PrivateData->Supports;
+
+ Protocol->ParentHandle = HostBridgeHandle;
+
+ Protocol->PollMem = RootBridgeIoPollMem;
+ Protocol->PollIo = RootBridgeIoPollIo;
+
+ Protocol->Mem.Read = RootBridgeIoMemRead;
+ Protocol->Mem.Write = RootBridgeIoMemWrite;
+
+ Protocol->Io.Read = RootBridgeIoIoRead;
+ Protocol->Io.Write = RootBridgeIoIoWrite;
+
+ Protocol->CopyMem = RootBridgeIoCopyMem;
+
+ Protocol->Pci.Read = RootBridgeIoPciRead;
+ Protocol->Pci.Write = RootBridgeIoPciWrite;
+
+ Protocol->Map = RootBridgeIoMap;
+ Protocol->Unmap = RootBridgeIoUnmap;
+
+ Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
+ Protocol->FreeBuffer = RootBridgeIoFreeBuffer;
+
+ Protocol->Flush = RootBridgeIoFlush;
+
+ Protocol->GetAttributes = RootBridgeIoGetAttributes;
+ Protocol->SetAttributes = RootBridgeIoSetAttributes;
+
+ Protocol->Configuration = RootBridgeIoConfiguration;
+
+ Protocol->SegmentNumber = 0;
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] OperationType I/O operation type: IO/MMIO/PCI.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The parameters for this request pass the checks.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+RootBridgeIoCheckParameter (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN OPERATION_TYPE OperationType,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;
+ UINT32 Stride;
+ UINT64 Base;
+ UINT64 Limit;
+
+ //
+ // Check to see if Buffer is NULL
+ //
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Width is in the valid range
+ //
+ if ((UINT32)Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For FIFO type, the target address won't increase during the access,
+ // so treat Count as 1
+ //
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ Count = 1;
+ }
+
+ //
+ // Check to see if Width is in the valid range for I/O Port operations
+ //
+ Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ if ((OperationType != MemOperation) && (Width == EfiPciWidthUint64)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Address is aligned
+ //
+ Stride = mInStride[Width];
+ if ((Address & (UINT64)(Stride - 1)) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ //
+ // Check to see if any address associated with this transfer exceeds the maximum
+ // allowed address. The maximum address implied by the parameters passed in is
+ // Address + Size * Count. If the following condition is met, then the transfer
+ // is not supported.
+ //
+ // Address + Size * Count > Limit + 1
+ //
+ // Since Limit can be the maximum integer value supported by the CPU and Count
+ // can also be the maximum integer value supported by the CPU, this range
+ // check must be adjusted to avoid all oveflow conditions.
+ //
+ if (OperationType == IoOperation) {
+ Base = PrivateData->IoBase;
+ Limit = PrivateData->IoLimit;
+ } else if (OperationType == MemOperation) {
+ Base = PrivateData->MemBase;
+ Limit = PrivateData->MemLimit;
+ } else {
+ PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
+ if (PciRbAddr->Bus < PrivateData->BusBase || PciRbAddr->Bus > PrivateData->BusLimit) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER || PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PciRbAddr->ExtendedRegister != 0) {
+ Address = PciRbAddr->ExtendedRegister;
+ } else {
+ Address = PciRbAddr->Register;
+ }
+ Base = 0;
+ Limit = MAX_PCI_REG_ADDRESS;
+ }
+
+ if (Limit < Address) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Address < Base) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Base <= Address <= Limit
+ //
+ if (Address == 0 && Limit == MAX_UINT64) {
+ //
+ // 2^64 bytes are valid to transfer. With Stride == 1, that's simply
+ // impossible to reach in Count; with Stride in {2, 4, 8}, we can divide
+ // both 2^64 and Stride with 2.
+ //
+ if (Stride > 1 && Count > DivU64x32 (BIT63, Stride / 2)) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ //
+ // (Limit - Address) does not wrap, and it is smaller than MAX_UINT64.
+ //
+ if (Count > DivU64x32 (Limit - Address + 1, Stride)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write memory space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write Switch value for Read or Write.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+RootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+
+ Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (Write) {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ break;
+ case EfiPciWidthUint16:
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint32:
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint64:
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ } else {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint16:
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint32:
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint64:
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write IO space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write Switch value for Read or Write.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+RootBridgeIoIoRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+
+ Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ //
+ // The addition below is performed in UINT64 modular arithmetic, in
+ // accordance with the definition of PcdPciIoTranslation in
+ // "ArmPlatformPkg.dec". Meaning, the addition below may in fact *decrease*
+ // Address, implementing a negative offset translation.
+ //
+ Address += PrivateData->IoTranslation;
+
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (Write) {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ break;
+ case EfiPciWidthUint16:
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint32:
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ } else {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint16:
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint32:
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write PCI configuration space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write Switch value for Read or Write.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+RootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;
+ UINTN PcieRegAddr;
+
+ Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
+
+ PcieRegAddr = (UINTN) PCI_LIB_ADDRESS (
+ PciRbAddr->Bus,
+ PciRbAddr->Device,
+ PciRbAddr->Function,
+ (PciRbAddr->ExtendedRegister != 0) ? \
+ PciRbAddr->ExtendedRegister :
+ PciRbAddr->Register
+ );
+
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = Buffer; Count > 0; PcieRegAddr += InStride, Uint8Buffer += OutStride, Count--) {
+ if (Write) {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ PciWrite8 (PcieRegAddr, *Uint8Buffer);
+ break;
+ case EfiPciWidthUint16:
+ PciWrite16 (PcieRegAddr, *((UINT16 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint32:
+ PciWrite32 (PcieRegAddr, *((UINT32 *)Uint8Buffer));
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ } else {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ *Uint8Buffer = PciRead8 (PcieRegAddr);
+ break;
+ case EfiPciWidthUint16:
+ *((UINT16 *)Uint8Buffer) = PciRead16 (PcieRegAddr);
+ break;
+ case EfiPciWidthUint32:
+ *((UINT32 *)Uint8Buffer) = PciRead32 (PcieRegAddr);
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Polls an address in memory mapped I/O space until an exit condition is met, or
+ a timeout occurs.
+
+ This function provides a standard way to poll a PCI memory location. A PCI memory read
+ operation is performed at the PCI memory address specified by Address for the width specified
+ by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
+ read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
+ Mask) is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the memory operations. The caller is
+ responsible for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the memory address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ 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 {
+
+ //
+ // Determine the proper # of metronome ticks to wait for polling the
+ // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ // The "+1" to account for the possibility of the first tick being short
+ // because we started in the middle of a tick.
+ //
+ // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
+ // protocol definition is updated.
+ //
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks != 0) {
+
+ mMetronome->WaitForTick (mMetronome, 1);
+
+ 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;
+}
+
+/**
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
+ satisfied or after a defined duration.
+
+ This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
+ performed at the PCI I/O address specified by Address for the width specified by Width.
+ The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
+ repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
+ to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is responsible
+ for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the I/O address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ 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;
+
+ //
+ // No matter what, always do a single poll.
+ //
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((UINT32)Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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 {
+
+ //
+ // Determine the proper # of metronome ticks to wait for polling the
+ // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ // The "+1" to account for the possibility of the first tick being short
+ // because we started in the middle of a tick.
+ //
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks != 0) {
+
+ mMetronome->WaitForTick (mMetronome, 1);
+
+ 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;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
+ root bridge memory space.
+
+ The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
+ space to another region of PCI root bridge memory space. This is especially useful for video scroll
+ operation on a memory mapped video buffer.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI root bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] DestAddress The destination address of the memory operation. The caller is
+ responsible for aligning the DestAddress if required.
+ @param[in] SrcAddress The source address of the memory operation. The caller is
+ responsible for aligning the SrcAddress if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at DestAddress and SrcAddress.
+
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ 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 = RootBridgeIoMemRead (
+ This,
+ Width,
+ SrcAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RootBridgeIoMemWrite (
+ 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;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Provides the PCI controller-specific addresses required to access system memory from a
+ DMA bus master.
+
+ The Map() function provides the PCI controller specific addresses needed to access system
+ memory. This function is used to map system memory for PCI bus master DMA accesses.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Operation Indicates if the bus master is going to read or write to system memory.
+ @param[in] HostAddress The system memory address to map to the PCI controller.
+ @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped.
+ @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use
+ to access the system memory's HostAddress.
+ @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete.
+
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
+ @retval EFI_INVALID_PARAMETER Operation is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
+ @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
+ @retval EFI_INVALID_PARAMETER Mapping is NULL.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ 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;
+
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // 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
+ );
+ }
+
+ //
+ // 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;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ The Unmap() function completes the Map() operation and releases any corresponding resources.
+ If the operation was an EfiPciOperationBusMasterWrite or
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
+ Any resources used for the mapping are freed.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ MAP_INFO *MapInfo;
+
+ //
+ // 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;
+
+ //
+ // 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);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
+ EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory address of the allocated range.
+ @param Attributes The requested bit mask of attributes for the allocated range. Only
+ the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
+ and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ 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) != 0) {
+ 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;
+}
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ )
+{
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
+}
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
+ memory. Posted write transactions are generated by PCI bus masters when they perform write
+ transactions to target addresses in system memory.
+ This function does not flush posted write transactions from any PCI bridges. A PCI controller
+ specific action must be taken to guarantee that the posted write transactions have been flushed from
+ the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
+ a PCI read transaction from the PCI controller prior to calling Flush().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
+ host bridge due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+{
+ //
+ // not supported yet
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
+ attributes that a PCI root bridge is currently using.
+
+ The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
+ and the mask of attributes that the PCI root bridge is currently using.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Supported A pointer to the mask of attributes that this PCI root bridge
+ supports setting with SetAttributes().
+ @param Attributes A pointer to the mask of attributes that this PCI root bridge is
+ currently using.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
+ bridge supports is returned in Supports. If Attributes is
+ not NULL, then the attributes that the PCI root bridge is currently
+ using is returned in Attributes.
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (Attributes == NULL && Supported == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set the return value for Supported and Attributes
+ //
+ if (Supported != NULL) {
+ *Supported = PrivateData->Supports;
+ }
+
+ if (Attributes != NULL) {
+ *Attributes = PrivateData->Attributes;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets attributes for a resource range on a PCI root bridge.
+
+ The SetAttributes() function sets the attributes specified in Attributes for the PCI root
+ bridge on the resource range specified by ResourceBase and ResourceLength. Since the
+ granularity of setting these attributes may vary from resource type to resource type, and from
+ platform to platform, the actual resource range and the one passed in by the caller may differ. As a
+ result, this function may set the attributes specified by Attributes on a larger resource range
+ than the caller requested. The actual range is returned in ResourceBase and
+ ResourceLength. The caller is responsible for verifying that the actual range for which the
+ attributes were set is acceptable.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Attributes The mask of attributes to set. If the attribute bit
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
+ MEMORY_DISABLE is set, then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then ResourceBase and
+ ResourceLength are ignored, and may be NULL.
+ @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified
+ by the attributes specified by Attributes.
+ @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (Attributes != 0) {
+ if ((Attributes & (~(PrivateData->Supports))) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // 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;
+}
+
+/**
+ Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
+ resource descriptors.
+
+ There are only two resource descriptor types from the ACPI Specification that may be used to
+ describe the current resources allocated to a PCI root bridge. These are the QWORD Address
+ Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
+ QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
+ or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
+ Address Space Descriptors followed by an End Tag.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the
+ current configuration of this PCI root bridge. The storage for the
+ ACPI 2.0 resource descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only data, and the buffer
+ must not be freed by the caller.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN Index;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ for (Index = 0; Index < TypeMax; Index++) {
+ if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
+ Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
+ Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
+ Configuration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length;
+ }
+ }
+
+ *Resources = &Configuration;
+ return EFI_SUCCESS;
+}
+