2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 GLOBAL_REMOVE_IF_UNREFERENCED
13 CHAR16
*mBarTypeStr
[] = {
28 Retrieve the max bus number that is assigned to the Root Bridge hierarchy.
29 It can support the case that there are multiple bus ranges.
31 @param Bridge Bridge device instance.
33 @retval The max bus number that is assigned to this Root Bridge hierarchy.
38 IN PCI_IO_DEVICE
*Bridge
41 PCI_IO_DEVICE
*RootBridge
;
42 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
43 UINT64 MaxNumberInRange
;
46 // Get PCI Root Bridge device
49 while (RootBridge
->Parent
!= NULL
) {
50 RootBridge
= RootBridge
->Parent
;
55 // Iterate the bus number ranges to get max PCI bus number
57 BusNumberRanges
= RootBridge
->BusNumberRanges
;
58 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
59 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
63 return (UINT16
)MaxNumberInRange
;
67 Retrieve the PCI Card device BAR information via PciIo interface.
69 @param PciIoDevice PCI Card device instance.
74 IN PCI_IO_DEVICE
*PciIoDevice
79 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
84 // Read PciBar information from the bar register
86 if (!gFullEnumeration
) {
88 PciIoDevice
->PciIo
.Pci
.Read (
89 &(PciIoDevice
->PciIo
),
91 PCI_CARD_MEMORY_BASE_0
,
96 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
)(Address
);
97 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
98 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
101 PciIoDevice
->PciIo
.Pci
.Read (
102 &(PciIoDevice
->PciIo
),
104 PCI_CARD_MEMORY_BASE_1
,
108 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
)(Address
);
109 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
110 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
113 PciIoDevice
->PciIo
.Pci
.Read (
114 &(PciIoDevice
->PciIo
),
116 PCI_CARD_IO_BASE_0_LOWER
,
120 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
)(Address
);
121 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
122 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
125 PciIoDevice
->PciIo
.Pci
.Read (
126 &(PciIoDevice
->PciIo
),
128 PCI_CARD_IO_BASE_1_LOWER
,
132 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
)(Address
);
133 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
134 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
137 if ((gPciHotPlugInit
!= NULL
) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
138 GetResourcePaddingForHpb (PciIoDevice
);
143 Remove rejected pci device from specific root bridge
146 @param RootBridgeHandle Specific parent root bridge handle.
147 @param Bridge Bridge device instance.
151 RemoveRejectedPciDevices (
152 IN EFI_HANDLE RootBridgeHandle
,
153 IN PCI_IO_DEVICE
*Bridge
157 LIST_ENTRY
*CurrentLink
;
158 LIST_ENTRY
*LastLink
;
160 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
164 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
166 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
167 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
169 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
171 // Remove rejected devices recusively
173 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
176 // Skip rejection for all PPBs, while detect rejection for others
178 if (IsPciDeviceRejected (Temp
)) {
180 // For P2C, remove all devices on it
182 if (!IsListEmpty (&Temp
->ChildList
)) {
183 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
187 // Finally remove itself
189 LastLink
= CurrentLink
->BackLink
;
190 RemoveEntryList (CurrentLink
);
191 FreePciDevice (Temp
);
193 CurrentLink
= LastLink
;
197 CurrentLink
= CurrentLink
->ForwardLink
;
202 Dump the resourc map of the bridge device.
204 @param[in] BridgeResource Resource descriptor of the bridge device.
208 IN PCI_RESOURCE_NODE
*BridgeResource
212 PCI_RESOURCE_NODE
*Resource
;
215 if ((BridgeResource
!= NULL
) && (BridgeResource
->Length
!= 0)) {
218 "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",
219 mBarTypeStr
[MIN (BridgeResource
->ResType
, PciBarTypeMaxType
)],
220 BridgeResource
->PciDev
->PciBar
[BridgeResource
->Bar
].BaseAddress
,
221 BridgeResource
->Length
,
222 BridgeResource
->Alignment
224 for ( Link
= GetFirstNode (&BridgeResource
->ChildList
)
225 ; !IsNull (&BridgeResource
->ChildList
, Link
)
226 ; Link
= GetNextNode (&BridgeResource
->ChildList
, Link
)
229 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
230 if (Resource
->ResourceUsage
== PciResUsageTypical
) {
231 Bar
= Resource
->Virtual
? Resource
->PciDev
->VfPciBar
: Resource
->PciDev
->PciBar
;
234 " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",
235 Bar
[Resource
->Bar
].BaseAddress
,
238 IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"PPB" :
239 IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"P2C" :
241 Resource
->PciDev
->BusNumber
,
242 Resource
->PciDev
->DeviceNumber
,
243 Resource
->PciDev
->FunctionNumber
246 if ((!IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && !IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
)) ||
247 (IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< PPB_IO_RANGE
)) ||
248 (IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< P2C_MEM_1
))
252 // The resource requirement comes from the device itself.
254 DEBUG ((DEBUG_INFO
, "%02x]", Bar
[Resource
->Bar
].Offset
));
257 // The resource requirement comes from the subordinate devices.
259 DEBUG ((DEBUG_INFO
, "**]"));
262 DEBUG ((DEBUG_INFO
, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource
->Length
, Resource
->Alignment
));
265 if (BridgeResource
->ResType
!= Resource
->ResType
) {
266 DEBUG ((DEBUG_INFO
, "; Type = %s", mBarTypeStr
[MIN (Resource
->ResType
, PciBarTypeMaxType
)]));
269 DEBUG ((DEBUG_INFO
, "\n"));
275 Find the corresponding resource node for the Device in child list of BridgeResource.
277 @param[in] Device Pointer to PCI_IO_DEVICE.
278 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.
279 @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.
281 @return Count of the resource descriptors returned.
285 IN PCI_IO_DEVICE
*Device
,
286 IN PCI_RESOURCE_NODE
*BridgeResource
,
287 OUT PCI_RESOURCE_NODE
**DeviceResources OPTIONAL
291 PCI_RESOURCE_NODE
*Resource
;
295 for ( Link
= BridgeResource
->ChildList
.ForwardLink
296 ; Link
!= &BridgeResource
->ChildList
297 ; Link
= Link
->ForwardLink
300 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
301 if (Resource
->PciDev
== Device
) {
302 if (DeviceResources
!= NULL
) {
303 DeviceResources
[Count
] = Resource
;
314 Dump the resource map of all the devices under Bridge.
316 @param[in] Bridge Bridge device instance.
317 @param[in] Resources Resource descriptors for the bridge device.
318 @param[in] ResourceCount Count of resource descriptors.
322 IN PCI_IO_DEVICE
*Bridge
,
323 IN PCI_RESOURCE_NODE
**Resources
,
324 IN UINTN ResourceCount
329 PCI_IO_DEVICE
*Device
;
332 PCI_RESOURCE_NODE
**ChildResources
;
333 UINTN ChildResourceCount
;
335 DEBUG ((DEBUG_INFO
, "PciBus: Resource Map for "));
337 Status
= gBS
->OpenProtocol (
339 &gEfiPciRootBridgeIoProtocolGuid
,
343 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
345 if (EFI_ERROR (Status
)) {
348 "Bridge [%02x|%02x|%02x]\n",
350 Bridge
->DeviceNumber
,
351 Bridge
->FunctionNumber
354 Str
= ConvertDevicePathToText (
355 DevicePathFromHandle (Bridge
->Handle
),
359 DEBUG ((DEBUG_INFO
, "Root Bridge %s\n", Str
!= NULL
? Str
: L
""));
365 for (Index
= 0; Index
< ResourceCount
; Index
++) {
366 DumpBridgeResource (Resources
[Index
]);
369 DEBUG ((DEBUG_INFO
, "\n"));
371 for ( Link
= Bridge
->ChildList
.ForwardLink
372 ; Link
!= &Bridge
->ChildList
373 ; Link
= Link
->ForwardLink
376 Device
= PCI_IO_DEVICE_FROM_LINK (Link
);
377 if (IS_PCI_BRIDGE (&Device
->Pci
)) {
378 ChildResourceCount
= 0;
379 for (Index
= 0; Index
< ResourceCount
; Index
++) {
380 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], NULL
);
383 ChildResources
= AllocatePool (sizeof (PCI_RESOURCE_NODE
*) * ChildResourceCount
);
384 ASSERT (ChildResources
!= NULL
);
385 ChildResourceCount
= 0;
386 for (Index
= 0; Index
< ResourceCount
; Index
++) {
387 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], &ChildResources
[ChildResourceCount
]);
390 DumpResourceMap (Device
, ChildResources
, ChildResourceCount
);
391 FreePool (ChildResources
);
397 Adjust the Devices' BAR size to minimum value if it support Resizeable BAR capability.
399 @param RootBridgeDev Pointer to instance of PCI_IO_DEVICE..
401 @return TRUE if BAR size is adjusted.
405 AdjustPciDeviceBarSize (
406 IN PCI_IO_DEVICE
*RootBridgeDev
409 PCI_IO_DEVICE
*PciIoDevice
;
410 LIST_ENTRY
*CurrentLink
;
416 CurrentLink
= RootBridgeDev
->ChildList
.ForwardLink
;
418 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridgeDev
->ChildList
) {
419 PciIoDevice
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
421 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
422 if (AdjustPciDeviceBarSize (PciIoDevice
)) {
426 if (PciIoDevice
->ResizableBarOffset
!= 0) {
429 "PciBus: [%02x|%02x|%02x] Adjust Pci Device Bar Size\n",
430 PciIoDevice
->BusNumber
,
431 PciIoDevice
->DeviceNumber
,
432 PciIoDevice
->FunctionNumber
434 PciProgramResizableBar (PciIoDevice
, PciResizableBarMin
);
436 // Start to parse the bars
438 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
439 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
444 DumpPciBars (PciIoDevice
);
449 CurrentLink
= CurrentLink
->ForwardLink
;
456 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
458 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
460 @retval EFI_SUCCESS Successfully finished resource allocation.
461 @retval EFI_NOT_FOUND Cannot get root bridge instance.
462 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
463 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
465 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
469 PciHostBridgeResourceAllocator (
470 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
473 PCI_IO_DEVICE
*RootBridgeDev
;
474 EFI_HANDLE RootBridgeHandle
;
483 UINT64 Mem32ResStatus
;
484 UINT64 PMem32ResStatus
;
485 UINT64 Mem64ResStatus
;
486 UINT64 PMem64ResStatus
;
487 UINT32 MaxOptionRomSize
;
488 PCI_RESOURCE_NODE
*IoBridge
;
489 PCI_RESOURCE_NODE
*Mem32Bridge
;
490 PCI_RESOURCE_NODE
*PMem32Bridge
;
491 PCI_RESOURCE_NODE
*Mem64Bridge
;
492 PCI_RESOURCE_NODE
*PMem64Bridge
;
493 PCI_RESOURCE_NODE IoPool
;
494 PCI_RESOURCE_NODE Mem32Pool
;
495 PCI_RESOURCE_NODE PMem32Pool
;
496 PCI_RESOURCE_NODE Mem64Pool
;
497 PCI_RESOURCE_NODE PMem64Pool
;
498 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
499 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
500 BOOLEAN ResizableBarNeedAdjust
;
501 BOOLEAN ResizableBarAdjusted
;
503 ResizableBarNeedAdjust
= PcdGetBool (PcdPcieResizableBarSupport
);
506 // It may try several times if the resource allocation fails
510 // Initialize resource pool
512 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
513 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
514 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
515 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
516 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
518 RootBridgeDev
= NULL
;
519 RootBridgeHandle
= 0;
521 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
523 // Get Root Bridge Device by handle
525 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
527 if (RootBridgeDev
== NULL
) {
528 return EFI_NOT_FOUND
;
532 // Create the entire system resource map from the information collected by
533 // enumerator. Several resource tree was created
537 // If non-standard PCI Bridge I/O window alignment is supported,
538 // set I/O aligment to minimum possible alignment for root bridge.
540 IoBridge
= CreateResourceNode (
543 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
) ? 0x1FF : 0xFFF,
549 Mem32Bridge
= CreateResourceNode (
558 PMem32Bridge
= CreateResourceNode (
567 Mem64Bridge
= CreateResourceNode (
576 PMem64Bridge
= CreateResourceNode (
586 // Get the max ROM size that the root bridge can process
587 // Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.
588 // All devices' Option ROM share the same MEM32 resource.
590 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
591 if (MaxOptionRomSize
!= 0) {
592 RootBridgeDev
->PciBar
[0].BarType
= PciBarTypeOpRom
;
593 RootBridgeDev
->PciBar
[0].Length
= MaxOptionRomSize
;
594 RootBridgeDev
->PciBar
[0].Alignment
= MaxOptionRomSize
- 1;
595 GetResourceFromDevice (RootBridgeDev
, IoBridge
, Mem32Bridge
, PMem32Bridge
, Mem64Bridge
, PMem64Bridge
);
599 // Create resourcemap by going through all the devices subject to this root bridge
611 // Based on the all the resource tree, construct ACPI resource node to
612 // submit the resource aperture to pci host bridge protocol
614 Status
= ConstructAcpiResourceRequestor (
625 // Insert these resource nodes into the database
627 InsertResourceNode (&IoPool
, IoBridge
);
628 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
629 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
630 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
631 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
633 if (Status
== EFI_SUCCESS
) {
635 // Submit the resource requirement
637 Status
= PciResAlloc
->SubmitResources (
639 RootBridgeDev
->Handle
,
643 // If SubmitResources returns error, PciBus isn't able to start.
644 // It's a fatal error so assertion is added.
646 DEBUG ((DEBUG_INFO
, "PciBus: HostBridge->SubmitResources() - %r\n", Status
));
647 ASSERT_EFI_ERROR (Status
);
651 // Free acpi resource node
653 if (AcpiConfig
!= NULL
) {
654 FreePool (AcpiConfig
);
657 if (EFI_ERROR (Status
)) {
659 // Destroy all the resource tree
661 DestroyResourceTree (&IoPool
);
662 DestroyResourceTree (&Mem32Pool
);
663 DestroyResourceTree (&PMem32Pool
);
664 DestroyResourceTree (&Mem64Pool
);
665 DestroyResourceTree (&PMem64Pool
);
671 // End while, at least one Root Bridge should be found.
673 ASSERT (RootBridgeDev
!= NULL
);
676 // Notify platform to start to program the resource
678 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
679 DEBUG ((DEBUG_INFO
, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status
));
680 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
682 // If Hot Plug is not supported
684 if (EFI_ERROR (Status
)) {
686 // Allocation failed, then return
688 return EFI_OUT_OF_RESOURCES
;
692 // Allocation succeed.
693 // Get host bridge handle for status report, and then skip the main while
695 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
700 // If Hot Plug is supported
702 if (!EFI_ERROR (Status
)) {
704 // Allocation succeed, then continue the following
710 // If the resource allocation is unsuccessful, free resources on bridge
713 RootBridgeDev
= NULL
;
714 RootBridgeHandle
= 0;
716 IoResStatus
= EFI_RESOURCE_SATISFIED
;
717 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
718 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
719 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
720 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
722 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
724 // Get RootBridg Device by handle
726 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
727 if (RootBridgeDev
== NULL
) {
728 return EFI_NOT_FOUND
;
732 // Get host bridge handle for status report
734 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
737 // Get acpi resource node for all the resource types
741 Status
= PciResAlloc
->GetProposedResources (
743 RootBridgeDev
->Handle
,
747 if (EFI_ERROR (Status
)) {
751 if (AcpiConfig
!= NULL
) {
753 // Adjust resource allocation policy for each RB
755 GetResourceAllocationStatus (
763 FreePool (AcpiConfig
);
772 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
775 // It is very difficult to follow the spec here
776 // Device path , Bar index can not be get here
778 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
780 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
782 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
783 (VOID
*)&AllocFailExtendedData
,
784 sizeof (AllocFailExtendedData
)
788 // When resource conflict happens, adjust the BAR size first.
789 // Only when adjusting BAR size doesn't help or BAR size cannot be adjusted,
790 // reject the device who requests largest resource that causes conflict.
792 ResizableBarAdjusted
= FALSE
;
793 if (ResizableBarNeedAdjust
) {
794 ResizableBarAdjusted
= AdjustPciDeviceBarSize (RootBridgeDev
);
795 ResizableBarNeedAdjust
= FALSE
;
798 if (!ResizableBarAdjusted
) {
799 Status
= PciHostBridgeAdjustAllocation (
814 // Destroy all the resource tree
816 DestroyResourceTree (&IoPool
);
817 DestroyResourceTree (&Mem32Pool
);
818 DestroyResourceTree (&PMem32Pool
);
819 DestroyResourceTree (&Mem64Pool
);
820 DestroyResourceTree (&PMem64Pool
);
822 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
824 if (EFI_ERROR (Status
)) {
835 // Raise the EFI_IOB_PCI_RES_ALLOC status code
837 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
839 EFI_IO_BUS_PCI
| EFI_IOB_PCI_RES_ALLOC
,
840 (VOID
*)&HandleExtendedData
,
841 sizeof (HandleExtendedData
)
845 // Notify pci bus driver starts to program the resource
847 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
849 if (EFI_ERROR (Status
)) {
853 RootBridgeDev
= NULL
;
855 RootBridgeHandle
= 0;
857 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
859 // Get RootBridg Device by handle
861 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
863 if (RootBridgeDev
== NULL
) {
864 return EFI_NOT_FOUND
;
868 // Get acpi resource node for all the resource types
871 Status
= PciResAlloc
->GetProposedResources (
873 RootBridgeDev
->Handle
,
877 if (EFI_ERROR (Status
)) {
882 // Get the resource base by interpreting acpi resource node
895 // Create the entire system resource map from the information collected by
896 // enumerator. Several resource tree was created
898 FindResourceNode (RootBridgeDev
, &IoPool
, &IoBridge
);
899 FindResourceNode (RootBridgeDev
, &Mem32Pool
, &Mem32Bridge
);
900 FindResourceNode (RootBridgeDev
, &PMem32Pool
, &PMem32Bridge
);
901 FindResourceNode (RootBridgeDev
, &Mem64Pool
, &Mem64Bridge
);
902 FindResourceNode (RootBridgeDev
, &PMem64Pool
, &PMem64Bridge
);
904 ASSERT (IoBridge
!= NULL
);
905 ASSERT (Mem32Bridge
!= NULL
);
906 ASSERT (PMem32Bridge
!= NULL
);
907 ASSERT (Mem64Bridge
!= NULL
);
908 ASSERT (PMem64Bridge
!= NULL
);
911 // Program IO resources
919 // Program Mem32 resources
927 // Program PMem32 resources
935 // Program Mem64 resources
943 // Program PMem64 resources
951 // Process Option ROM for this root bridge after all BARs are programmed.
952 // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to
953 // shadow the Option ROM of the devices under the PPB.
954 // After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE
955 // BAR is restored back to the original value.
956 // The original value is programmed by ProgramResource() above.
960 "Process Option ROM: BAR Base/Length = %lx/%lx\n",
961 RootBridgeDev
->PciBar
[0].BaseAddress
,
962 RootBridgeDev
->PciBar
[0].Length
964 ProcessOptionRom (RootBridgeDev
, RootBridgeDev
->PciBar
[0].BaseAddress
, RootBridgeDev
->PciBar
[0].Length
);
966 IoBridge
->PciDev
->PciBar
[IoBridge
->Bar
].BaseAddress
= IoBase
;
967 Mem32Bridge
->PciDev
->PciBar
[Mem32Bridge
->Bar
].BaseAddress
= Mem32Base
;
968 PMem32Bridge
->PciDev
->PciBar
[PMem32Bridge
->Bar
].BaseAddress
= PMem32Base
;
969 Mem64Bridge
->PciDev
->PciBar
[Mem64Bridge
->Bar
].BaseAddress
= Mem64Base
;
970 PMem64Bridge
->PciDev
->PciBar
[PMem64Bridge
->Bar
].BaseAddress
= PMem64Base
;
973 // Dump the resource map for current root bridge
976 PCI_RESOURCE_NODE
*Resources
[5];
977 Resources
[0] = IoBridge
;
978 Resources
[1] = Mem32Bridge
;
979 Resources
[2] = PMem32Bridge
;
980 Resources
[3] = Mem64Bridge
;
981 Resources
[4] = PMem64Bridge
;
982 DumpResourceMap (RootBridgeDev
, Resources
, ARRAY_SIZE (Resources
));
985 FreePool (AcpiConfig
);
989 // Destroy all the resource tree
991 DestroyResourceTree (&IoPool
);
992 DestroyResourceTree (&Mem32Pool
);
993 DestroyResourceTree (&PMem32Pool
);
994 DestroyResourceTree (&Mem64Pool
);
995 DestroyResourceTree (&PMem64Pool
);
998 // Notify the resource allocation phase is to end
1000 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
1006 Allocate NumberOfBuses buses and return the next available PCI bus number.
1008 @param Bridge Bridge device instance.
1009 @param StartBusNumber Current available PCI bus number.
1010 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.
1011 @param NextBusNumber Next available PCI bus number.
1013 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number
1014 is returned in NextBusNumber.
1015 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.
1019 PciAllocateBusNumber (
1020 IN PCI_IO_DEVICE
*Bridge
,
1021 IN UINT8 StartBusNumber
,
1022 IN UINT8 NumberOfBuses
,
1023 OUT UINT8
*NextBusNumber
1026 PCI_IO_DEVICE
*RootBridge
;
1027 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
1029 UINT64 MaxNumberInRange
;
1032 // Get PCI Root Bridge device
1034 RootBridge
= Bridge
;
1035 while (RootBridge
->Parent
!= NULL
) {
1036 RootBridge
= RootBridge
->Parent
;
1040 // Get next available PCI bus number
1042 BusNumberRanges
= RootBridge
->BusNumberRanges
;
1043 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1044 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
1045 if ((StartBusNumber
>= BusNumberRanges
->AddrRangeMin
) && (StartBusNumber
<= MaxNumberInRange
)) {
1046 NextNumber
= (UINT8
)(StartBusNumber
+ NumberOfBuses
);
1047 while (NextNumber
> MaxNumberInRange
) {
1049 if (BusNumberRanges
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
1050 return EFI_OUT_OF_RESOURCES
;
1053 NextNumber
= (UINT8
)(NextNumber
+ (BusNumberRanges
->AddrRangeMin
- (MaxNumberInRange
+ 1)));
1054 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
1057 *NextBusNumber
= NextNumber
;
1064 return EFI_OUT_OF_RESOURCES
;
1068 Scan pci bus and assign bus number to the given PCI bus system.
1070 @param Bridge Bridge device instance.
1071 @param StartBusNumber start point.
1072 @param SubBusNumber Point to sub bus number.
1073 @param PaddedBusRange Customized bus number.
1075 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
1076 @retval other Some error occurred when scanning pci bus.
1078 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1083 IN PCI_IO_DEVICE
*Bridge
,
1084 IN UINT8 StartBusNumber
,
1085 OUT UINT8
*SubBusNumber
,
1086 OUT UINT8
*PaddedBusRange
1098 PCI_IO_DEVICE
*PciDevice
;
1100 EFI_HPC_STATE State
;
1102 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1103 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1104 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*NextDescriptors
;
1106 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1108 UINT32 TempReservedBusNum
;
1109 BOOLEAN IsAriEnabled
;
1111 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1115 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
)0;
1120 IsAriEnabled
= FALSE
;
1122 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1123 if (!IsAriEnabled
) {
1124 TempReservedBusNum
= 0;
1127 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1129 // Check to see whether a pci device is present
1131 Status
= PciDevicePresent (
1139 if (EFI_ERROR (Status
) && (Func
== 0)) {
1141 // go to next device if there is no Function 0
1146 if (EFI_ERROR (Status
)) {
1151 // Get the PCI device information
1153 Status
= PciSearchDevice (
1162 if (EFI_ERROR (Status
)) {
1167 // Per Pcie spec ARI Extended Capability
1168 // This capability must be implemented by each function in an ARI device.
1169 // It is not applicable to a Root Port, a Switch Downstream Port, an RCiEP, or a Root Complex Event Collector
1171 if (((Device
== 0) && (Func
== 0)) && (PciDevice
->IsAriEnabled
)) {
1172 IsAriEnabled
= TRUE
;
1175 if (PciDevice
->IsAriEnabled
!= IsAriEnabled
) {
1178 "ERROR: %02x:%02x:%02x device ARI Feature(%x) is not consistent with others Function\n",
1182 PciDevice
->IsAriEnabled
1184 return EFI_DEVICE_ERROR
;
1187 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1189 if (!IS_PCI_BRIDGE (&Pci
)) {
1191 // PCI bridges will be called later
1192 // Here just need for PCI device or PCI to cardbus controller
1193 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1195 PreprocessController (
1197 PciDevice
->BusNumber
,
1198 PciDevice
->DeviceNumber
,
1199 PciDevice
->FunctionNumber
,
1200 EfiPciBeforeChildBusEnumeration
1204 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1206 // For Pci Hotplug controller devcie only
1208 if (gPciHotPlugInit
!= NULL
) {
1210 // Check if it is a Hotplug PCI controller
1212 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1213 gPciRootHpcData
[HpIndex
].Found
= TRUE
;
1215 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1216 Status
= CreateEventForHpc (HpIndex
, &Event
);
1218 ASSERT (!EFI_ERROR (Status
));
1220 Status
= gPciHotPlugInit
->InitializeRootHpc (
1222 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1228 PreprocessController (
1230 PciDevice
->BusNumber
,
1231 PciDevice
->DeviceNumber
,
1232 PciDevice
->FunctionNumber
,
1233 EfiPciBeforeChildBusEnumeration
1240 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1244 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1246 // If Hot Plug is supported,
1247 // Get the bridge information
1250 if (gPciHotPlugInit
!= NULL
) {
1251 if (IsPciHotPlugBus (PciDevice
)) {
1253 // If it is initialized, get the padded bus range
1255 Status
= gPciHotPlugInit
->GetResourcePadding (
1257 PciDevice
->DevicePath
,
1260 (VOID
**)&Descriptors
,
1264 if (EFI_ERROR (Status
)) {
1269 NextDescriptors
= Descriptors
;
1270 Status
= PciGetBusRange (
1277 FreePool (Descriptors
);
1279 if (!EFI_ERROR (Status
)) {
1281 } else if (Status
!= EFI_NOT_FOUND
) {
1283 // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.
1291 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
1292 if (EFI_ERROR (Status
)) {
1296 SecondBus
= *SubBusNumber
;
1298 Register
= (UINT16
)((SecondBus
<< 8) | (UINT16
)StartBusNumber
);
1299 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
1301 Status
= PciRootBridgeIo
->Pci
.Write (
1310 // If it is PPB, resursively search down this bridge
1312 if (IS_PCI_BRIDGE (&Pci
)) {
1314 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1315 // PCI configuration transaction to go through any PPB
1317 Register
= PciGetMaxBusNumber (Bridge
);
1318 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1319 Status
= PciRootBridgeIo
->Pci
.Write (
1328 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1330 PreprocessController (
1332 PciDevice
->BusNumber
,
1333 PciDevice
->DeviceNumber
,
1334 PciDevice
->FunctionNumber
,
1335 EfiPciBeforeChildBusEnumeration
1338 Status
= PciScanBus (
1344 if (EFI_ERROR (Status
)) {
1349 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
1351 // Ensure the device is enabled and initialized
1353 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1354 ((State
& EFI_HPC_STATE_ENABLED
) != 0) &&
1355 ((State
& EFI_HPC_STATE_INITIALIZED
) != 0))
1357 *PaddedBusRange
= (UINT8
)((UINT8
)(BusRange
) + *PaddedBusRange
);
1360 // Reserve the larger one between the actual occupied bus number and padded bus number
1362 Status
= PciAllocateBusNumber (PciDevice
, SecondBus
, (UINT8
)(BusRange
), &PaddedSubBus
);
1363 if (EFI_ERROR (Status
)) {
1367 *SubBusNumber
= MAX (PaddedSubBus
, *SubBusNumber
);
1372 // Set the current maximum bus number under the PPB
1374 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1376 Status
= PciRootBridgeIo
->Pci
.Write (
1385 // It is device. Check PCI IOV for Bus reservation
1386 // Go through each function, just reserve the MAX ReservedBusNum for one device
1388 if (PcdGetBool (PcdSrIovSupport
) && (PciDevice
->SrIovCapabilityOffset
!= 0)) {
1389 if (TempReservedBusNum
< PciDevice
->ReservedBusNum
) {
1390 Status
= PciAllocateBusNumber (PciDevice
, *SubBusNumber
, (UINT8
)(PciDevice
->ReservedBusNum
- TempReservedBusNum
), SubBusNumber
);
1391 if (EFI_ERROR (Status
)) {
1395 TempReservedBusNum
= PciDevice
->ReservedBusNum
;
1398 DEBUG ((DEBUG_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber
));
1400 DEBUG ((DEBUG_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber
));
1406 if ((Func
== 0) && !IS_PCI_MULTI_FUNC (&Pci
)) {
1408 // Skip sub functions, this is not a multi function device
1411 Func
= PCI_MAX_FUNC
;
1420 Process Option Rom on the specified root bridge.
1422 @param Bridge Pci root bridge device instance.
1424 @retval EFI_SUCCESS Success process.
1425 @retval other Some error occurred when processing Option Rom on the root bridge.
1429 PciRootBridgeP2CProcess (
1430 IN PCI_IO_DEVICE
*Bridge
1433 LIST_ENTRY
*CurrentLink
;
1434 PCI_IO_DEVICE
*Temp
;
1435 EFI_HPC_STATE State
;
1439 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1441 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1442 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1444 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1445 if ((gPciHotPlugInit
!= NULL
) && Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1447 // Raise the EFI_IOB_PCI_HPC_INIT status code
1449 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1451 EFI_IO_BUS_PCI
| EFI_IOB_PCI_HPC_INIT
,
1455 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1456 Status
= gPciHotPlugInit
->InitializeRootHpc (
1464 if (!EFI_ERROR (Status
)) {
1465 Status
= PciBridgeEnumerator (Temp
);
1467 if (EFI_ERROR (Status
)) {
1472 CurrentLink
= CurrentLink
->ForwardLink
;
1477 if (!IsListEmpty (&Temp
->ChildList
)) {
1478 Status
= PciRootBridgeP2CProcess (Temp
);
1481 CurrentLink
= CurrentLink
->ForwardLink
;
1488 Process Option Rom on the specified host bridge.
1490 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1492 @retval EFI_SUCCESS Success process.
1493 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1494 @retval other Some error occurred when processing Option Rom on the host bridge.
1498 PciHostBridgeP2CProcess (
1499 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1502 EFI_HANDLE RootBridgeHandle
;
1503 PCI_IO_DEVICE
*RootBridgeDev
;
1506 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1510 RootBridgeHandle
= NULL
;
1512 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1514 // Get RootBridg Device by handle
1516 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1518 if (RootBridgeDev
== NULL
) {
1519 return EFI_NOT_FOUND
;
1522 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1523 if (EFI_ERROR (Status
)) {
1532 This function is used to enumerate the entire host bridge
1533 in a given platform.
1535 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1537 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1538 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1539 @retval other Some error occurred when enumerating the host bridge.
1543 PciHostBridgeEnumerator (
1544 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1547 EFI_HANDLE RootBridgeHandle
;
1548 PCI_IO_DEVICE
*RootBridgeDev
;
1550 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1552 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1553 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1554 UINT8 StartBusNumber
;
1555 LIST_ENTRY RootBridgeList
;
1557 EFI_STATUS RootBridgeEnumerationStatus
;
1559 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1560 InitializeHotPlugSupport ();
1563 InitializeListHead (&RootBridgeList
);
1566 // Notify the bus allocation phase is about to start
1568 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1570 if (EFI_ERROR (Status
)) {
1574 DEBUG ((DEBUG_INFO
, "PCI Bus First Scanning\n"));
1575 RootBridgeHandle
= NULL
;
1576 RootBridgeEnumerationStatus
= EFI_SUCCESS
;
1577 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1579 // if a root bridge instance is found, create root bridge device for it
1582 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1584 if (RootBridgeDev
== NULL
) {
1585 return EFI_OUT_OF_RESOURCES
;
1589 // Enumerate all the buses under this root bridge
1591 Status
= PciRootBridgeEnumerator (
1596 if ((gPciHotPlugInit
!= NULL
) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1597 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1599 DestroyRootBridge (RootBridgeDev
);
1602 if (EFI_ERROR (Status
)) {
1603 RootBridgeEnumerationStatus
= Status
;
1608 // Notify the bus allocation phase is finished for the first time
1610 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1612 if (EFI_ERROR (RootBridgeEnumerationStatus
)) {
1613 return RootBridgeEnumerationStatus
;
1616 if ((gPciHotPlugInit
!= NULL
) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1618 // Reset all assigned PCI bus number in all PPB
1620 RootBridgeHandle
= NULL
;
1621 Link
= GetFirstNode (&RootBridgeList
);
1622 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1623 (!IsNull (&RootBridgeList
, Link
)))
1625 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1627 // Get the Bus information
1629 Status
= PciResAlloc
->StartBusEnumeration (
1632 (VOID
**)&Configuration
1634 if (EFI_ERROR (Status
)) {
1639 // Get the bus number to start with
1641 StartBusNumber
= (UINT8
)(Configuration
->AddrRangeMin
);
1643 ResetAllPpbBusNumber (
1648 FreePool (Configuration
);
1649 Link
= RemoveEntryList (Link
);
1650 DestroyRootBridge (RootBridgeDev
);
1654 // Wait for all HPC initialized
1656 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1658 if (EFI_ERROR (Status
)) {
1659 DEBUG ((DEBUG_ERROR
, "Some root HPC failed to initialize\n"));
1664 // Notify the bus allocation phase is about to start for the 2nd time
1666 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1668 if (EFI_ERROR (Status
)) {
1672 DEBUG ((DEBUG_INFO
, "PCI Bus Second Scanning\n"));
1673 RootBridgeHandle
= NULL
;
1674 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1676 // if a root bridge instance is found, create root bridge device for it
1678 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1680 if (RootBridgeDev
== NULL
) {
1681 return EFI_OUT_OF_RESOURCES
;
1685 // Enumerate all the buses under this root bridge
1687 Status
= PciRootBridgeEnumerator (
1692 DestroyRootBridge (RootBridgeDev
);
1693 if (EFI_ERROR (Status
)) {
1694 RootBridgeEnumerationStatus
= Status
;
1699 // Notify the bus allocation phase is to end for the 2nd time
1701 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1703 if (EFI_ERROR (RootBridgeEnumerationStatus
)) {
1704 return RootBridgeEnumerationStatus
;
1709 // Notify the resource allocation phase is to start
1711 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1713 if (EFI_ERROR (Status
)) {
1717 RootBridgeHandle
= NULL
;
1718 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1720 // if a root bridge instance is found, create root bridge device for it
1722 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1724 if (RootBridgeDev
== NULL
) {
1725 return EFI_OUT_OF_RESOURCES
;
1728 Status
= StartManagingRootBridge (RootBridgeDev
);
1730 if (EFI_ERROR (Status
)) {
1734 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1735 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**)&Descriptors
);
1737 if (EFI_ERROR (Status
)) {
1741 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1743 if (EFI_ERROR (Status
)) {
1748 // Determine root bridge attribute by calling interface of Pcihostbridge
1751 DetermineRootBridgeAttributes (
1757 // Collect all the resource information under this root bridge
1758 // A database that records all the information about pci device subject to this
1759 // root bridge will then be created
1761 Status
= PciPciDeviceInfoCollector (
1766 if (EFI_ERROR (Status
)) {
1770 InsertRootBridge (RootBridgeDev
);
1773 // Record the hostbridge handle
1775 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);
1782 This function is used to program the Resizable BAR Register.
1784 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
1785 @param ResizableBarOp PciResizableBarMax: Set BAR to max size
1786 PciResizableBarMin: set BAR to min size.
1788 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1789 @retval other Some error occurred when enumerating the host bridge.
1793 PciProgramResizableBar (
1794 IN PCI_IO_DEVICE
*PciIoDevice
,
1795 IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp
1798 EFI_PCI_IO_PROTOCOL
*PciIo
;
1799 UINT64 Capabilities
;
1803 UINTN ResizableBarNumber
;
1805 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Entries
[PCI_MAX_BAR
];
1807 ASSERT (PciIoDevice
->ResizableBarOffset
!= 0);
1811 " Programs Resizable BAR register, offset: 0x%08x, number: %d\n",
1812 PciIoDevice
->ResizableBarOffset
,
1813 PciIoDevice
->ResizableBarNumber
1816 ResizableBarNumber
= MIN (PciIoDevice
->ResizableBarNumber
, PCI_MAX_BAR
);
1817 PciIo
= &PciIoDevice
->PciIo
;
1818 Status
= PciIo
->Pci
.Read (
1821 PciIoDevice
->ResizableBarOffset
+ sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER
),
1822 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY
) * ResizableBarNumber
,
1825 ASSERT_EFI_ERROR (Status
);
1827 for (Index
= 0; Index
< ResizableBarNumber
; Index
++) {
1829 // When the bit of Capabilities Set, indicates that the Function supports
1830 // operating with the BAR sized to (2^Bit) MB.
1832 // Bit 0 is set: supports operating with the BAR sized to 1 MB
1833 // Bit 1 is set: supports operating with the BAR sized to 2 MB
1834 // Bit n is set: supports operating with the BAR sized to (2^n) MB
1836 Capabilities
= LShiftU64 (Entries
[Index
].ResizableBarControl
.Bits
.BarSizeCapability
, 28)
1837 | Entries
[Index
].ResizableBarCapability
.Bits
.BarSizeCapability
;
1839 if (ResizableBarOp
== PciResizableBarMax
) {
1840 Bit
= HighBitSet64 (Capabilities
);
1842 ASSERT (ResizableBarOp
== PciResizableBarMin
);
1843 Bit
= LowBitSet64 (Capabilities
);
1848 Offset
= PciIoDevice
->ResizableBarOffset
+ sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER
)
1849 + Index
* sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY
)
1850 + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY
, ResizableBarControl
);
1852 Entries
[Index
].ResizableBarControl
.Bits
.BarSize
= (UINT32
)Bit
;
1855 " Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n",
1856 OFFSET_OF (PCI_TYPE00
, Device
.Bar
[Entries
[Index
].ResizableBarControl
.Bits
.BarIndex
]),
1858 LShiftU64 (SIZE_1MB
, Bit
)
1862 EfiPciIoWidthUint32
,
1865 &Entries
[Index
].ResizableBarControl
.Uint32