--- /dev/null
+/** @file\r
+\r
+ Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.\r
+\r
+Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciHostBridge.h"\r
+#include "PciRootBridge.h"\r
+#include "PciHostResource.h"\r
+\r
+\r
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
+EFI_CPU_IO2_PROTOCOL *mCpuIo;\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {\r
+ L"Mem", L"I/O", L"Bus"\r
+};\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {\r
+ L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"\r
+};\r
+\r
+/**\r
+\r
+ Entry point of this driver.\r
+\r
+ @param ImageHandle Image handle of this driver.\r
+ @param SystemTable Pointer to standard EFI system table.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePciHostBridge (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ PCI_ROOT_BRIDGE *RootBridges;\r
+ UINTN RootBridgeCount;\r
+ UINTN Index;\r
+ PCI_ROOT_BRIDGE_APERTURE *MemApertures[4];\r
+ UINTN MemApertureIndex;\r
+\r
+ RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);\r
+ if ((RootBridges == NULL) || (RootBridgeCount == 0)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Most systems in the world including complex servers have only one Host Bridge.\r
+ //\r
+ HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));\r
+ ASSERT (HostBridge != NULL);\r
+\r
+ HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;\r
+ HostBridge->CanRestarted = TRUE;\r
+ InitializeListHead (&HostBridge->RootBridges);\r
+\r
+ HostBridge->ResAlloc.NotifyPhase = NotifyPhase;\r
+ HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;\r
+ HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;\r
+ HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;\r
+ HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;\r
+ HostBridge->ResAlloc.SubmitResources = SubmitResources;\r
+ HostBridge->ResAlloc.GetProposedResources = GetProposedResources;\r
+ HostBridge->ResAlloc.PreprocessController = PreprocessController;\r
+\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &HostBridge->Handle,\r
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (HostBridge);\r
+ PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create Root Bridge Device Handle in this Host Bridge\r
+ //\r
+ for (Index = 0; Index < RootBridgeCount; Index++) {\r
+ //\r
+ // Create Root Bridge Handle Instance\r
+ //\r
+ RootBridge = CreateRootBridge (&RootBridges[Index], HostBridge->Handle);\r
+ ASSERT (RootBridge != NULL);\r
+ if (RootBridge == NULL) {\r
+ continue;\r
+ }\r
+\r
+ if (RootBridges[Index].Io.Limit > RootBridges[Index].Io.Base) {\r
+ Status = gDS->AddIoSpace (\r
+ EfiGcdIoTypeIo,\r
+ RootBridges[Index].Io.Base,\r
+ RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ //\r
+ // Add all the Mem/PMem aperture to GCD\r
+ // Mem/PMem shouldn't overlap with each other\r
+ // Root bridge which needs to combine MEM and PMEM should only report\r
+ // the MEM aperture in Mem\r
+ //\r
+ MemApertures[0] = &RootBridges[Index].Mem;\r
+ MemApertures[1] = &RootBridges[Index].MemAbove4G;\r
+ MemApertures[2] = &RootBridges[Index].PMem;\r
+ MemApertures[3] = &RootBridges[Index].PMemAbove4G;\r
+\r
+ for (MemApertureIndex = 0; MemApertureIndex < sizeof (MemApertures) / sizeof (MemApertures[0]); MemApertureIndex++) {\r
+ if (MemApertures[MemApertureIndex]->Limit > MemApertures[MemApertureIndex]->Base) {\r
+ Status = gDS->AddMemorySpace (\r
+ EfiGcdMemoryTypeMemoryMappedIo,\r
+ MemApertures[MemApertureIndex]->Base,\r
+ MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
+ EFI_MEMORY_UC\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = gDS->SetMemorySpaceAttributes (\r
+ MemApertures[MemApertureIndex]->Base,\r
+ MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
+ EFI_MEMORY_UC\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ }\r
+ //\r
+ // Insert Root Bridge Handle Instance\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &RootBridge->Handle,\r
+ &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,\r
+ &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);\r
+ }\r
+ PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().\r
+\r
+ @param HostBridge The Host Bridge Instance where the resource adjustment happens.\r
+**/\r
+VOID\r
+ResourceConflict (\r
+ IN PCI_HOST_BRIDGE_INSTANCE *HostBridge\r
+ )\r
+{\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ LIST_ENTRY *Link;\r
+ UINTN RootBridgeCount;\r
+ PCI_RESOURCE_TYPE Index;\r
+ PCI_RES_NODE *ResAllocNode;\r
+\r
+ RootBridgeCount = 0;\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridgeCount++;\r
+ }\r
+\r
+ Resources = AllocatePool (\r
+ RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +\r
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+ );\r
+ ASSERT (Resources != NULL);\r
+\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ for (Index = TypeIo; Index < TypeMax; Index++) {\r
+ ResAllocNode = &RootBridge->ResAllocNode[Index];\r
+\r
+ Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Descriptor->AddrRangeMin = ResAllocNode->Base;\r
+ Descriptor->AddrRangeMax = ResAllocNode->Alignment;\r
+ Descriptor->AddrLen = ResAllocNode->Length;\r
+ switch (ResAllocNode->Type) {\r
+\r
+ case TypeIo:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ break;\r
+\r
+ case TypePMem32:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem32:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case TypePMem64:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem64:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 64;\r
+ break;\r
+\r
+ case TypeBus:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ Descriptor++;\r
+ }\r
+ //\r
+ // Terminate the root bridge resources.\r
+ //\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0x0;\r
+\r
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);\r
+ }\r
+ //\r
+ // Terminate the host bridge resources.\r
+ //\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0x0;\r
+\r
+ DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));\r
+ PciHostBridgeResourceConflict (HostBridge->Handle, Resources);\r
+ FreePool (Resources);\r
+}\r
+\r
+UINT64\r
+AllocateResource (\r
+ BOOLEAN Mmio,\r
+ UINT64 Length,\r
+ UINTN BitsOfAlignment,\r
+ UINT64 BaseAddress,\r
+ UINT64 Limit\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (BaseAddress < Limit) {\r
+ //\r
+ // Have to make sure Aligment is handled since we are doing direct address allocation\r
+ //\r
+ BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));\r
+\r
+ while (BaseAddress + Length <= Limit + 1) {\r
+ if (Mmio) {\r
+ Status = gDS->AllocateMemorySpace (\r
+ EfiGcdAllocateAddress,\r
+ EfiGcdMemoryTypeMemoryMappedIo,\r
+ BitsOfAlignment,\r
+ Length,\r
+ &BaseAddress,\r
+ gImageHandle,\r
+ NULL\r
+ );\r
+ } else {\r
+ Status = gDS->AllocateIoSpace (\r
+ EfiGcdAllocateAddress,\r
+ EfiGcdIoTypeIo,\r
+ BitsOfAlignment,\r
+ Length,\r
+ &BaseAddress,\r
+ gImageHandle,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ return BaseAddress;\r
+ }\r
+ BaseAddress += LShiftU64 (1, BitsOfAlignment);\r
+ }\r
+ }\r
+ return MAX_UINT64;\r
+}\r
+/**\r
+\r
+ Enter a certain phase of the PCI enumeration process.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
+ @param Phase The phase during enumeration.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.\r
+ @retval EFI_NOT_READY Resources have not been submitted yet.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotifyPhase (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
+ )\r
+{\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ LIST_ENTRY *Link;\r
+ EFI_PHYSICAL_ADDRESS BaseAddress;\r
+ UINT64 AddrLen;\r
+ UINTN BitsOfAlignment;\r
+ UINT64 Alignment;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
+ PCI_RESOURCE_TYPE Index;\r
+ PCI_RESOURCE_TYPE Index1;\r
+ PCI_RESOURCE_TYPE Index2;\r
+ BOOLEAN ResNodeHandled[TypeMax];\r
+ UINT64 MaxAlignment;\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+\r
+ switch (Phase) {\r
+ case EfiPciHostBridgeBeginEnumeration:\r
+ if (!HostBridge->CanRestarted) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ //\r
+ // Reset Root Bridge\r
+ //\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ for (Index = TypeIo; Index < TypeMax; Index++) {\r
+ RootBridge->ResAllocNode[Index].Type = Index;\r
+ RootBridge->ResAllocNode[Index].Base = 0;\r
+ RootBridge->ResAllocNode[Index].Length = 0;\r
+ RootBridge->ResAllocNode[Index].Status = ResNone;\r
+\r
+ RootBridge->ResourceSubmitted = FALSE;\r
+ }\r
+ }\r
+\r
+ HostBridge->CanRestarted = TRUE;\r
+ break;\r
+\r
+ case EfiPciHostBridgeBeginBusAllocation:\r
+ //\r
+ // No specific action is required here, can perform any chipset specific programing\r
+ //\r
+ HostBridge->CanRestarted = FALSE;\r
+ break;\r
+\r
+ case EfiPciHostBridgeEndBusAllocation:\r
+ //\r
+ // No specific action is required here, can perform any chipset specific programing\r
+ //\r
+ break;\r
+\r
+ case EfiPciHostBridgeBeginResourceAllocation:\r
+ //\r
+ // No specific action is required here, can perform any chipset specific programing\r
+ //\r
+ break;\r
+\r
+ case EfiPciHostBridgeAllocateResources:\r
+ ReturnStatus = EFI_SUCCESS;\r
+\r
+ //\r
+ // Make sure the resource for all root bridges has been submitted.\r
+ //\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (!RootBridge->ResourceSubmitted) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ for (Index = TypeIo; Index < TypeBus; Index++) {\r
+ ResNodeHandled[Index] = FALSE;\r
+ }\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));\r
+\r
+ for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {\r
+ if (RootBridge->ResAllocNode[Index1].Status == ResNone) {\r
+ ResNodeHandled[Index1] = TRUE;\r
+ } else {\r
+ //\r
+ // Allocate the resource node with max alignment at first\r
+ //\r
+ MaxAlignment = 0;\r
+ Index = TypeMax;\r
+ for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {\r
+ if (ResNodeHandled[Index2]) {\r
+ continue;\r
+ }\r
+ if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {\r
+ MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;\r
+ Index = Index2;\r
+ }\r
+ }\r
+\r
+ ASSERT (Index < TypeMax);\r
+ ResNodeHandled[Index] = TRUE;\r
+ AddrLen = RootBridge->ResAllocNode[Index].Length;\r
+ Alignment = RootBridge->ResAllocNode[Index].Alignment;\r
+ BitsOfAlignment = LowBitSet64 (Alignment + 1);\r
+ BaseAddress = MAX_UINT64;\r
+\r
+ switch (Index) {\r
+ case TypeIo:\r
+ BaseAddress = AllocateResource (\r
+ FALSE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (15, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),\r
+ RootBridge->Io.Limit\r
+ );\r
+ break;\r
+\r
+ case TypeMem64:\r
+ BaseAddress = AllocateResource (\r
+ TRUE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (63, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),\r
+ RootBridge->MemAbove4G.Limit\r
+ );\r
+ if (BaseAddress != MAX_UINT64) {\r
+ break;\r
+ }\r
+ //\r
+ // If memory above 4GB is not available, try memory below 4GB\r
+ //\r
+\r
+ case TypeMem32:\r
+ BaseAddress = AllocateResource (\r
+ TRUE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (31, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),\r
+ RootBridge->Mem.Limit\r
+ );\r
+ break;\r
+\r
+ case TypePMem64:\r
+ BaseAddress = AllocateResource (\r
+ TRUE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (63, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),\r
+ RootBridge->PMemAbove4G.Limit\r
+ );\r
+ if (BaseAddress != MAX_UINT64) {\r
+ break;\r
+ }\r
+ //\r
+ // If memory above 4GB is not available, try memory below 4GB\r
+ //\r
+ case TypePMem32:\r
+ BaseAddress = AllocateResource (\r
+ TRUE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (31, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),\r
+ RootBridge->PMem.Limit\r
+ );\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",\r
+ mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));\r
+ if (BaseAddress != MAX_UINT64) {\r
+ RootBridge->ResAllocNode[Index].Base = BaseAddress;\r
+ RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
+ DEBUG ((DEBUG_INFO, "Success\n"));\r
+ } else {\r
+ ReturnStatus = EFI_OUT_OF_RESOURCES;\r
+ DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (ReturnStatus == EFI_OUT_OF_RESOURCES) {\r
+ ResourceConflict (HostBridge);\r
+ }\r
+\r
+ //\r
+ // Set resource to zero for nodes where allocation fails\r
+ //\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ for (Index = TypeIo; Index < TypeBus; Index++) {\r
+ if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {\r
+ RootBridge->ResAllocNode[Index].Length = 0;\r
+ }\r
+ }\r
+ }\r
+ return ReturnStatus;\r
+\r
+ case EfiPciHostBridgeSetResources:\r
+ //\r
+ // HostBridgeInstance->CanRestarted = FALSE;\r
+ //\r
+ break;\r
+\r
+ case EfiPciHostBridgeFreeResources:\r
+ //\r
+ // HostBridgeInstance->CanRestarted = FALSE;\r
+ //\r
+ ReturnStatus = EFI_SUCCESS;\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ for (Index = TypeIo; Index < TypeBus; Index++) {\r
+ if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {\r
+ switch (Index) {\r
+ case TypeIo:\r
+ Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
+ break;\r
+\r
+ case TypeMem32:\r
+ case TypePMem32:\r
+ case TypeMem64:\r
+ case TypePMem64:\r
+ Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ RootBridge->ResAllocNode[Index].Type = Index;\r
+ RootBridge->ResAllocNode[Index].Base = 0;\r
+ RootBridge->ResAllocNode[Index].Length = 0;\r
+ RootBridge->ResAllocNode[Index].Status = ResNone;\r
+ }\r
+ }\r
+\r
+ RootBridge->ResourceSubmitted = FALSE;\r
+ }\r
+\r
+ HostBridge->CanRestarted = TRUE;\r
+ return ReturnStatus;\r
+\r
+ case EfiPciHostBridgeEndResourceAllocation:\r
+ //\r
+ // The resource allocation phase is completed. No specific action is required\r
+ // here. This notification can be used to perform any chipset specific programming.\r
+ //\r
+ break;\r
+\r
+ case EfiPciHostBridgeEndEnumeration:\r
+ //\r
+ // The Host Bridge Enumeration is completed. No specific action is required here.\r
+ // This notification can be used to perform any chipset specific programming.\r
+ //\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Return the device handle of the next PCI root bridge that is associated with\r
+ this Host Bridge.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.\r
+ On input, it holds the RootBridgeHandle returned by the most\r
+ recent call to GetNextRootBridge().The handle for the first\r
+ PCI Root Bridge is returned if RootBridgeHandle is NULL on input.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_NOT_FOUND Next PCI root bridge not found.\r
+ @retval EFI_INVALID_PARAMETER Wrong parameter passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetNextRootBridge (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN OUT EFI_HANDLE *RootBridgeHandle\r
+ )\r
+{\r
+ BOOLEAN ReturnNext;\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ if (RootBridgeHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);\r
+\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (ReturnNext) {\r
+ *RootBridgeHandle = RootBridge->Handle;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);\r
+ }\r
+\r
+ if (ReturnNext) {\r
+ ASSERT (IsNull (&HostBridge->RootBridges, Link));\r
+ return EFI_NOT_FOUND;\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Returns the attributes of a PCI Root Bridge.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The device handle of the PCI Root Bridge\r
+ that the caller is interested in.\r
+ @param Attributes The pointer to attributes of the PCI Root Bridge.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or\r
+ RootBridgeHandle is not an EFI_HANDLE\r
+ that was returned on a previous call to\r
+ GetNextRootBridge().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetAttributes (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT UINT64 *Attributes\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ if (Attributes == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ *Attributes = RootBridge->AllocationAttributes;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ This is the request from the PCI enumerator to set up\r
+ the specified PCI Root Bridge for bus enumeration process.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge to be set up.\r
+ @param Configuration Pointer to the pointer to the PCI bus resource descriptor.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+StartBusEnumeration (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT VOID **Configuration\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+\r
+ if (Configuration == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+ if (*Configuration == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;\r
+ Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+ Descriptor->GenFlag = 0;\r
+ Descriptor->SpecificFlag = 0;\r
+ Descriptor->AddrSpaceGranularity = 0;\r
+ Descriptor->AddrRangeMin = RootBridge->Bus.Base;\r
+ Descriptor->AddrRangeMax = 0;\r
+ Descriptor->AddrTranslationOffset = 0;\r
+ Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;\r
+\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0x0;\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ This function programs the PCI Root Bridge hardware so that\r
+ it decodes the specified PCI bus range.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.\r
+ @param Configuration The pointer to the PCI bus resource descriptor.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBusNumbers (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN VOID *Configuration\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+ UINTN BusStart;\r
+ UINTN BusEnd;\r
+ UINTN BusLen;\r
+\r
+ if (Configuration == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
+\r
+ //\r
+ // Check the Configuration is valid\r
+ //\r
+ if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||\r
+ (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||\r
+ (End->Desc != ACPI_END_TAG_DESCRIPTOR)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ BusStart = (UINTN) Descriptor->AddrRangeMin;\r
+ BusLen = (UINTN) Descriptor->AddrLen;\r
+ BusEnd = BusStart + BusLen - 1;\r
+\r
+ if (Descriptor->AddrLen == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||\r
+ (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Update the Bus Range\r
+ //\r
+ RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;\r
+ RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;\r
+ RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ Submits the I/O and memory resource requirements for the specified PCI Root Bridge.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.\r
+ are being submitted.\r
+ @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SubmitResources (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN VOID *Configuration\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ PCI_RESOURCE_TYPE Type;\r
+\r
+ //\r
+ // Check the input parameter: Configuration\r
+ //\r
+ if (Configuration == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));\r
+ //\r
+ // Check the resource descriptors.\r
+ // If the Configuration includes one or more invalid resource descriptors, all the resource\r
+ // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.\r
+ //\r
+ for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
+ if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",\r
+ mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,\r
+ (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""\r
+ ));\r
+ DEBUG ((EFI_D_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));\r
+ switch (Descriptor->ResType) {\r
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
+ if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // If the PCI root bridge does not support separate windows for nonprefetchable and\r
+ // prefetchable memory, then the PCI bus driver needs to include requests for\r
+ // prefetchable memory in the nonprefetchable memory pool.\r
+ //\r
+ if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&\r
+ ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ case ACPI_ADDRESS_SPACE_TYPE_IO:\r
+ //\r
+ // Check aligment, it should be of the form 2^n-1\r
+ //\r
+ if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+ }\r
+ if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+ if (Descriptor->AddrSpaceGranularity == 32) {\r
+ if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
+ Type = TypePMem32;\r
+ } else {\r
+ Type = TypeMem32;\r
+ }\r
+ } else {\r
+ ASSERT (Descriptor->AddrSpaceGranularity == 64);\r
+ if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
+ Type = TypePMem64;\r
+ } else {\r
+ Type = TypeMem64;\r
+ }\r
+ }\r
+ } else {\r
+ ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);\r
+ Type = TypeIo;\r
+ }\r
+ RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;\r
+ RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;\r
+ RootBridge->ResAllocNode[Type].Status = ResSubmitted;\r
+ }\r
+ RootBridge->ResourceSubmitted = TRUE;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ This function returns the proposed resource settings for the specified\r
+ PCI Root Bridge.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge handle.\r
+ @param Configuration The pointer to the pointer to the PCI I/O\r
+ and memory resource descriptor.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetProposedResources (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT VOID **Configuration\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ UINTN Index;\r
+ UINTN Number;\r
+ VOID *Buffer;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+ UINT64 ResStatus;\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ for (Index = 0, Number = 0; Index < TypeBus; Index++) {\r
+ if (RootBridge->ResAllocNode[Index].Status != ResNone) {\r
+ Number++;\r
+ }\r
+ }\r
+\r
+ Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;\r
+ for (Index = 0; Index < TypeBus; Index++) {\r
+ ResStatus = RootBridge->ResAllocNode[Index].Status;\r
+ if (ResStatus != ResNone) {\r
+ Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;\r
+ Descriptor->GenFlag = 0;\r
+ Descriptor->AddrRangeMin = RootBridge->ResAllocNode[Index].Base;\r
+ Descriptor->AddrRangeMax = 0;\r
+ Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;\r
+ Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;\r
+\r
+ switch (Index) {\r
+\r
+ case TypeIo:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ break;\r
+\r
+ case TypePMem32:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem32:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case TypePMem64:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem64:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 64;\r
+ break;\r
+ }\r
+\r
+ Descriptor++;\r
+ }\r
+ }\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0;\r
+\r
+ *Configuration = Buffer;\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ This function is called for all the PCI controllers that the PCI\r
+ bus driver finds. Can be used to Preprogram the controller.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge handle.\r
+ @param PciAddress Address of the controller on the PCI bus.\r
+ @param Phase The Phase during resource allocation.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PreprocessController (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ if ((UINT32) Phase > EfiPciBeforeResourceCollection) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r