2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2019, 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
;
54 // Iterate the bus number ranges to get max PCI bus number
56 BusNumberRanges
= RootBridge
->BusNumberRanges
;
57 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
58 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
61 return (UINT16
) MaxNumberInRange
;
65 Retrieve the PCI Card device BAR information via PciIo interface.
67 @param PciIoDevice PCI Card device instance.
72 IN PCI_IO_DEVICE
*PciIoDevice
77 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
82 // Read PciBar information from the bar register
84 if (!gFullEnumeration
) {
86 PciIoDevice
->PciIo
.Pci
.Read (
87 &(PciIoDevice
->PciIo
),
89 PCI_CARD_MEMORY_BASE_0
,
94 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
95 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
96 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
99 PciIoDevice
->PciIo
.Pci
.Read (
100 &(PciIoDevice
->PciIo
),
102 PCI_CARD_MEMORY_BASE_1
,
106 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
107 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
108 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
111 PciIoDevice
->PciIo
.Pci
.Read (
112 &(PciIoDevice
->PciIo
),
114 PCI_CARD_IO_BASE_0_LOWER
,
118 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
119 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
120 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
123 PciIoDevice
->PciIo
.Pci
.Read (
124 &(PciIoDevice
->PciIo
),
126 PCI_CARD_IO_BASE_1_LOWER
,
130 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
131 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
132 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
136 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
137 GetResourcePaddingForHpb (PciIoDevice
);
142 Remove rejected pci device from specific root bridge
145 @param RootBridgeHandle Specific parent root bridge handle.
146 @param Bridge Bridge device instance.
150 RemoveRejectedPciDevices (
151 IN EFI_HANDLE RootBridgeHandle
,
152 IN PCI_IO_DEVICE
*Bridge
156 LIST_ENTRY
*CurrentLink
;
157 LIST_ENTRY
*LastLink
;
159 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
163 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
165 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
)) {
181 // For P2C, remove all devices on it
183 if (!IsListEmpty (&Temp
->ChildList
)) {
184 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
188 // Finally remove itself
190 LastLink
= CurrentLink
->BackLink
;
191 RemoveEntryList (CurrentLink
);
192 FreePciDevice (Temp
);
194 CurrentLink
= LastLink
;
198 CurrentLink
= CurrentLink
->ForwardLink
;
203 Dump the resourc map of the bridge device.
205 @param[in] BridgeResource Resource descriptor of the bridge device.
209 IN PCI_RESOURCE_NODE
*BridgeResource
213 PCI_RESOURCE_NODE
*Resource
;
216 if ((BridgeResource
!= NULL
) && (BridgeResource
->Length
!= 0)) {
218 EFI_D_INFO
, "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
, BridgeResource
->Alignment
223 for ( Link
= GetFirstNode (&BridgeResource
->ChildList
)
224 ; !IsNull (&BridgeResource
->ChildList
, Link
)
225 ; Link
= GetNextNode (&BridgeResource
->ChildList
, Link
)
227 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
228 if (Resource
->ResourceUsage
== PciResUsageTypical
) {
229 Bar
= Resource
->Virtual
? Resource
->PciDev
->VfPciBar
: Resource
->PciDev
->PciBar
;
231 EFI_D_INFO
, " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",
232 Bar
[Resource
->Bar
].BaseAddress
, Resource
->Length
, Resource
->Alignment
,
233 IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"PPB" :
234 IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"P2C" :
236 Resource
->PciDev
->BusNumber
, Resource
->PciDev
->DeviceNumber
,
237 Resource
->PciDev
->FunctionNumber
240 if ((!IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && !IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
)) ||
241 (IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< PPB_IO_RANGE
)) ||
242 (IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< P2C_MEM_1
))
245 // The resource requirement comes from the device itself.
247 DEBUG ((EFI_D_INFO
, "%02x]", Bar
[Resource
->Bar
].Offset
));
250 // The resource requirement comes from the subordinate devices.
252 DEBUG ((EFI_D_INFO
, "**]"));
255 DEBUG ((EFI_D_INFO
, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource
->Length
, Resource
->Alignment
));
257 if (BridgeResource
->ResType
!= Resource
->ResType
) {
258 DEBUG ((EFI_D_INFO
, "; Type = %s", mBarTypeStr
[MIN (Resource
->ResType
, PciBarTypeMaxType
)]));
260 DEBUG ((EFI_D_INFO
, "\n"));
266 Find the corresponding resource node for the Device in child list of BridgeResource.
268 @param[in] Device Pointer to PCI_IO_DEVICE.
269 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.
270 @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.
272 @return Count of the resource descriptors returned.
276 IN PCI_IO_DEVICE
*Device
,
277 IN PCI_RESOURCE_NODE
*BridgeResource
,
278 OUT PCI_RESOURCE_NODE
**DeviceResources OPTIONAL
282 PCI_RESOURCE_NODE
*Resource
;
286 for ( Link
= BridgeResource
->ChildList
.ForwardLink
287 ; Link
!= &BridgeResource
->ChildList
288 ; Link
= Link
->ForwardLink
290 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
291 if (Resource
->PciDev
== Device
) {
292 if (DeviceResources
!= NULL
) {
293 DeviceResources
[Count
] = Resource
;
303 Dump the resource map of all the devices under Bridge.
305 @param[in] Bridge Bridge device instance.
306 @param[in] Resources Resource descriptors for the bridge device.
307 @param[in] ResourceCount Count of resource descriptors.
311 IN PCI_IO_DEVICE
*Bridge
,
312 IN PCI_RESOURCE_NODE
**Resources
,
313 IN UINTN ResourceCount
318 PCI_IO_DEVICE
*Device
;
321 PCI_RESOURCE_NODE
**ChildResources
;
322 UINTN ChildResourceCount
;
324 DEBUG ((EFI_D_INFO
, "PciBus: Resource Map for "));
326 Status
= gBS
->OpenProtocol (
328 &gEfiPciRootBridgeIoProtocolGuid
,
332 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
334 if (EFI_ERROR (Status
)) {
336 EFI_D_INFO
, "Bridge [%02x|%02x|%02x]\n",
337 Bridge
->BusNumber
, Bridge
->DeviceNumber
, Bridge
->FunctionNumber
340 Str
= ConvertDevicePathToText (
341 DevicePathFromHandle (Bridge
->Handle
),
345 DEBUG ((EFI_D_INFO
, "Root Bridge %s\n", Str
!= NULL
? Str
: L
""));
351 for (Index
= 0; Index
< ResourceCount
; Index
++) {
352 DumpBridgeResource (Resources
[Index
]);
354 DEBUG ((EFI_D_INFO
, "\n"));
356 for ( Link
= Bridge
->ChildList
.ForwardLink
357 ; Link
!= &Bridge
->ChildList
358 ; Link
= Link
->ForwardLink
360 Device
= PCI_IO_DEVICE_FROM_LINK (Link
);
361 if (IS_PCI_BRIDGE (&Device
->Pci
)) {
363 ChildResourceCount
= 0;
364 for (Index
= 0; Index
< ResourceCount
; Index
++) {
365 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], NULL
);
367 ChildResources
= AllocatePool (sizeof (PCI_RESOURCE_NODE
*) * ChildResourceCount
);
368 ASSERT (ChildResources
!= NULL
);
369 ChildResourceCount
= 0;
370 for (Index
= 0; Index
< ResourceCount
; Index
++) {
371 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], &ChildResources
[ChildResourceCount
]);
374 DumpResourceMap (Device
, ChildResources
, ChildResourceCount
);
375 FreePool (ChildResources
);
381 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
383 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
385 @retval EFI_SUCCESS Successfully finished resource allocation.
386 @retval EFI_NOT_FOUND Cannot get root bridge instance.
387 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
388 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
390 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
394 PciHostBridgeResourceAllocator (
395 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
398 PCI_IO_DEVICE
*RootBridgeDev
;
399 EFI_HANDLE RootBridgeHandle
;
408 UINT64 Mem32ResStatus
;
409 UINT64 PMem32ResStatus
;
410 UINT64 Mem64ResStatus
;
411 UINT64 PMem64ResStatus
;
412 UINT32 MaxOptionRomSize
;
413 PCI_RESOURCE_NODE
*IoBridge
;
414 PCI_RESOURCE_NODE
*Mem32Bridge
;
415 PCI_RESOURCE_NODE
*PMem32Bridge
;
416 PCI_RESOURCE_NODE
*Mem64Bridge
;
417 PCI_RESOURCE_NODE
*PMem64Bridge
;
418 PCI_RESOURCE_NODE IoPool
;
419 PCI_RESOURCE_NODE Mem32Pool
;
420 PCI_RESOURCE_NODE PMem32Pool
;
421 PCI_RESOURCE_NODE Mem64Pool
;
422 PCI_RESOURCE_NODE PMem64Pool
;
423 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
424 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
427 // It may try several times if the resource allocation fails
431 // Initialize resource pool
433 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
434 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
435 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
436 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
437 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
439 RootBridgeDev
= NULL
;
440 RootBridgeHandle
= 0;
442 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
444 // Get Root Bridge Device by handle
446 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
448 if (RootBridgeDev
== NULL
) {
449 return EFI_NOT_FOUND
;
453 // Create the entire system resource map from the information collected by
454 // enumerator. Several resource tree was created
458 // If non-standard PCI Bridge I/O window alignment is supported,
459 // set I/O aligment to minimum possible alignment for root bridge.
461 IoBridge
= CreateResourceNode (
464 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
) ? 0x1FF: 0xFFF,
470 Mem32Bridge
= CreateResourceNode (
479 PMem32Bridge
= CreateResourceNode (
488 Mem64Bridge
= CreateResourceNode (
497 PMem64Bridge
= CreateResourceNode (
507 // Get the max ROM size that the root bridge can process
508 // Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.
509 // All devices' Option ROM share the same MEM32 resource.
511 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
512 if (MaxOptionRomSize
!= 0) {
513 RootBridgeDev
->PciBar
[0].BarType
= PciBarTypeOpRom
;
514 RootBridgeDev
->PciBar
[0].Length
= MaxOptionRomSize
;
515 RootBridgeDev
->PciBar
[0].Alignment
= MaxOptionRomSize
- 1;
516 GetResourceFromDevice (RootBridgeDev
, IoBridge
, Mem32Bridge
, PMem32Bridge
, Mem64Bridge
, PMem64Bridge
);
520 // Create resourcemap by going through all the devices subject to this root bridge
532 // Based on the all the resource tree, construct ACPI resource node to
533 // submit the resource aperture to pci host bridge protocol
535 Status
= ConstructAcpiResourceRequestor (
546 // Insert these resource nodes into the database
548 InsertResourceNode (&IoPool
, IoBridge
);
549 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
550 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
551 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
552 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
554 if (Status
== EFI_SUCCESS
) {
556 // Submit the resource requirement
558 Status
= PciResAlloc
->SubmitResources (
560 RootBridgeDev
->Handle
,
564 // If SubmitResources returns error, PciBus isn't able to start.
565 // It's a fatal error so assertion is added.
567 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->SubmitResources() - %r\n", Status
));
568 ASSERT_EFI_ERROR (Status
);
572 // Free acpi resource node
574 if (AcpiConfig
!= NULL
) {
575 FreePool (AcpiConfig
);
578 if (EFI_ERROR (Status
)) {
580 // Destroy all the resource tree
582 DestroyResourceTree (&IoPool
);
583 DestroyResourceTree (&Mem32Pool
);
584 DestroyResourceTree (&PMem32Pool
);
585 DestroyResourceTree (&Mem64Pool
);
586 DestroyResourceTree (&PMem64Pool
);
591 // End while, at least one Root Bridge should be found.
593 ASSERT (RootBridgeDev
!= NULL
);
596 // Notify platform to start to program the resource
598 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
599 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status
));
600 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
602 // If Hot Plug is not supported
604 if (EFI_ERROR (Status
)) {
606 // Allocation failed, then return
608 return EFI_OUT_OF_RESOURCES
;
611 // Allocation succeed.
612 // Get host bridge handle for status report, and then skip the main while
614 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
620 // If Hot Plug is supported
622 if (!EFI_ERROR (Status
)) {
624 // Allocation succeed, then continue the following
630 // If the resource allocation is unsuccessful, free resources on bridge
633 RootBridgeDev
= NULL
;
634 RootBridgeHandle
= 0;
636 IoResStatus
= EFI_RESOURCE_SATISFIED
;
637 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
638 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
639 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
640 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
642 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
644 // Get RootBridg Device by handle
646 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
647 if (RootBridgeDev
== NULL
) {
648 return EFI_NOT_FOUND
;
652 // Get host bridge handle for status report
654 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
657 // Get acpi resource node for all the resource types
661 Status
= PciResAlloc
->GetProposedResources (
663 RootBridgeDev
->Handle
,
667 if (EFI_ERROR (Status
)) {
671 if (AcpiConfig
!= NULL
) {
673 // Adjust resource allocation policy for each RB
675 GetResourceAllocationStatus (
683 FreePool (AcpiConfig
);
691 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
694 // It is very difficult to follow the spec here
695 // Device path , Bar index can not be get here
697 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
699 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
701 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
702 (VOID
*) &AllocFailExtendedData
,
703 sizeof (AllocFailExtendedData
)
706 Status
= PciHostBridgeAdjustAllocation (
720 // Destroy all the resource tree
722 DestroyResourceTree (&IoPool
);
723 DestroyResourceTree (&Mem32Pool
);
724 DestroyResourceTree (&PMem32Pool
);
725 DestroyResourceTree (&Mem64Pool
);
726 DestroyResourceTree (&PMem64Pool
);
728 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
730 if (EFI_ERROR (Status
)) {
740 // Raise the EFI_IOB_PCI_RES_ALLOC status code
742 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
744 EFI_IO_BUS_PCI
| EFI_IOB_PCI_RES_ALLOC
,
745 (VOID
*) &HandleExtendedData
,
746 sizeof (HandleExtendedData
)
750 // Notify pci bus driver starts to program the resource
752 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
754 if (EFI_ERROR (Status
)) {
758 RootBridgeDev
= NULL
;
760 RootBridgeHandle
= 0;
762 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
764 // Get RootBridg Device by handle
766 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
768 if (RootBridgeDev
== NULL
) {
769 return EFI_NOT_FOUND
;
773 // Get acpi resource node for all the resource types
776 Status
= PciResAlloc
->GetProposedResources (
778 RootBridgeDev
->Handle
,
782 if (EFI_ERROR (Status
)) {
787 // Get the resource base by interpreting acpi resource node
800 // Create the entire system resource map from the information collected by
801 // enumerator. Several resource tree was created
803 FindResourceNode (RootBridgeDev
, &IoPool
, &IoBridge
);
804 FindResourceNode (RootBridgeDev
, &Mem32Pool
, &Mem32Bridge
);
805 FindResourceNode (RootBridgeDev
, &PMem32Pool
, &PMem32Bridge
);
806 FindResourceNode (RootBridgeDev
, &Mem64Pool
, &Mem64Bridge
);
807 FindResourceNode (RootBridgeDev
, &PMem64Pool
, &PMem64Bridge
);
809 ASSERT (IoBridge
!= NULL
);
810 ASSERT (Mem32Bridge
!= NULL
);
811 ASSERT (PMem32Bridge
!= NULL
);
812 ASSERT (Mem64Bridge
!= NULL
);
813 ASSERT (PMem64Bridge
!= NULL
);
816 // Program IO resources
824 // Program Mem32 resources
832 // Program PMem32 resources
840 // Program Mem64 resources
848 // Program PMem64 resources
856 // Process Option ROM for this root bridge after all BARs are programmed.
857 // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to
858 // shadow the Option ROM of the devices under the PPB.
859 // After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE
860 // BAR is restored back to the original value.
861 // The original value is programmed by ProgramResource() above.
864 DEBUG_INFO
, "Process Option ROM: BAR Base/Length = %lx/%lx\n",
865 RootBridgeDev
->PciBar
[0].BaseAddress
, RootBridgeDev
->PciBar
[0].Length
867 ProcessOptionRom (RootBridgeDev
, RootBridgeDev
->PciBar
[0].BaseAddress
, RootBridgeDev
->PciBar
[0].Length
);
869 IoBridge
->PciDev
->PciBar
[IoBridge
->Bar
].BaseAddress
= IoBase
;
870 Mem32Bridge
->PciDev
->PciBar
[Mem32Bridge
->Bar
].BaseAddress
= Mem32Base
;
871 PMem32Bridge
->PciDev
->PciBar
[PMem32Bridge
->Bar
].BaseAddress
= PMem32Base
;
872 Mem64Bridge
->PciDev
->PciBar
[Mem64Bridge
->Bar
].BaseAddress
= Mem64Base
;
873 PMem64Bridge
->PciDev
->PciBar
[PMem64Bridge
->Bar
].BaseAddress
= PMem64Base
;
876 // Dump the resource map for current root bridge
879 PCI_RESOURCE_NODE
*Resources
[5];
880 Resources
[0] = IoBridge
;
881 Resources
[1] = Mem32Bridge
;
882 Resources
[2] = PMem32Bridge
;
883 Resources
[3] = Mem64Bridge
;
884 Resources
[4] = PMem64Bridge
;
885 DumpResourceMap (RootBridgeDev
, Resources
, ARRAY_SIZE (Resources
));
888 FreePool (AcpiConfig
);
892 // Destroy all the resource tree
894 DestroyResourceTree (&IoPool
);
895 DestroyResourceTree (&Mem32Pool
);
896 DestroyResourceTree (&PMem32Pool
);
897 DestroyResourceTree (&Mem64Pool
);
898 DestroyResourceTree (&PMem64Pool
);
901 // Notify the resource allocation phase is to end
903 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
909 Allocate NumberOfBuses buses and return the next available PCI bus number.
911 @param Bridge Bridge device instance.
912 @param StartBusNumber Current available PCI bus number.
913 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.
914 @param NextBusNumber Next available PCI bus number.
916 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number
917 is returned in NextBusNumber.
918 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.
922 PciAllocateBusNumber (
923 IN PCI_IO_DEVICE
*Bridge
,
924 IN UINT8 StartBusNumber
,
925 IN UINT8 NumberOfBuses
,
926 OUT UINT8
*NextBusNumber
929 PCI_IO_DEVICE
*RootBridge
;
930 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
932 UINT64 MaxNumberInRange
;
935 // Get PCI Root Bridge device
938 while (RootBridge
->Parent
!= NULL
) {
939 RootBridge
= RootBridge
->Parent
;
943 // Get next available PCI bus number
945 BusNumberRanges
= RootBridge
->BusNumberRanges
;
946 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
947 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
948 if (StartBusNumber
>= BusNumberRanges
->AddrRangeMin
&& StartBusNumber
<= MaxNumberInRange
) {
949 NextNumber
= (UINT8
)(StartBusNumber
+ NumberOfBuses
);
950 while (NextNumber
> MaxNumberInRange
) {
952 if (BusNumberRanges
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
953 return EFI_OUT_OF_RESOURCES
;
955 NextNumber
= (UINT8
)(NextNumber
+ (BusNumberRanges
->AddrRangeMin
- (MaxNumberInRange
+ 1)));
956 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
958 *NextBusNumber
= NextNumber
;
963 return EFI_OUT_OF_RESOURCES
;
967 Scan pci bus and assign bus number to the given PCI bus system.
969 @param Bridge Bridge device instance.
970 @param StartBusNumber start point.
971 @param SubBusNumber Point to sub bus number.
972 @param PaddedBusRange Customized bus number.
974 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
975 @retval other Some error occurred when scanning pci bus.
977 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
982 IN PCI_IO_DEVICE
*Bridge
,
983 IN UINT8 StartBusNumber
,
984 OUT UINT8
*SubBusNumber
,
985 OUT UINT8
*PaddedBusRange
997 PCI_IO_DEVICE
*PciDevice
;
1001 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1002 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1003 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*NextDescriptors
;
1005 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1007 UINT32 TempReservedBusNum
;
1009 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1013 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1019 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1020 TempReservedBusNum
= 0;
1021 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1024 // Check to see whether a pci device is present
1026 Status
= PciDevicePresent (
1034 if (EFI_ERROR (Status
) && Func
== 0) {
1036 // go to next device if there is no Function 0
1041 if (EFI_ERROR (Status
)) {
1046 // Get the PCI device information
1048 Status
= PciSearchDevice (
1057 ASSERT (!EFI_ERROR (Status
));
1059 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1061 if (!IS_PCI_BRIDGE (&Pci
)) {
1063 // PCI bridges will be called later
1064 // Here just need for PCI device or PCI to cardbus controller
1065 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1067 PreprocessController (
1069 PciDevice
->BusNumber
,
1070 PciDevice
->DeviceNumber
,
1071 PciDevice
->FunctionNumber
,
1072 EfiPciBeforeChildBusEnumeration
1076 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1078 // For Pci Hotplug controller devcie only
1080 if (gPciHotPlugInit
!= NULL
) {
1082 // Check if it is a Hotplug PCI controller
1084 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1085 gPciRootHpcData
[HpIndex
].Found
= TRUE
;
1087 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1089 Status
= CreateEventForHpc (HpIndex
, &Event
);
1091 ASSERT (!EFI_ERROR (Status
));
1093 Status
= gPciHotPlugInit
->InitializeRootHpc (
1095 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1101 PreprocessController (
1103 PciDevice
->BusNumber
,
1104 PciDevice
->DeviceNumber
,
1105 PciDevice
->FunctionNumber
,
1106 EfiPciBeforeChildBusEnumeration
1113 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1117 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1119 // If Hot Plug is supported,
1120 // Get the bridge information
1123 if (gPciHotPlugInit
!= NULL
) {
1125 if (IsPciHotPlugBus (PciDevice
)) {
1128 // If it is initialized, get the padded bus range
1130 Status
= gPciHotPlugInit
->GetResourcePadding (
1132 PciDevice
->DevicePath
,
1135 (VOID
**) &Descriptors
,
1139 if (EFI_ERROR (Status
)) {
1144 NextDescriptors
= Descriptors
;
1145 Status
= PciGetBusRange (
1152 FreePool (Descriptors
);
1154 if (!EFI_ERROR (Status
)) {
1156 } else if (Status
!= EFI_NOT_FOUND
) {
1158 // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.
1166 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
1167 if (EFI_ERROR (Status
)) {
1170 SecondBus
= *SubBusNumber
;
1172 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1173 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
1175 Status
= PciRootBridgeIo
->Pci
.Write (
1185 // If it is PPB, resursively search down this bridge
1187 if (IS_PCI_BRIDGE (&Pci
)) {
1190 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1191 // PCI configuration transaction to go through any PPB
1193 Register
= PciGetMaxBusNumber (Bridge
);
1194 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1195 Status
= PciRootBridgeIo
->Pci
.Write (
1204 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1206 PreprocessController (
1208 PciDevice
->BusNumber
,
1209 PciDevice
->DeviceNumber
,
1210 PciDevice
->FunctionNumber
,
1211 EfiPciBeforeChildBusEnumeration
1214 Status
= PciScanBus (
1220 if (EFI_ERROR (Status
)) {
1225 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
1227 // Ensure the device is enabled and initialized
1229 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1230 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
1231 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
1232 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) + *PaddedBusRange
);
1235 // Reserve the larger one between the actual occupied bus number and padded bus number
1237 Status
= PciAllocateBusNumber (PciDevice
, SecondBus
, (UINT8
) (BusRange
), &PaddedSubBus
);
1238 if (EFI_ERROR (Status
)) {
1241 *SubBusNumber
= MAX (PaddedSubBus
, *SubBusNumber
);
1246 // Set the current maximum bus number under the PPB
1248 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1250 Status
= PciRootBridgeIo
->Pci
.Write (
1259 // It is device. Check PCI IOV for Bus reservation
1260 // Go through each function, just reserve the MAX ReservedBusNum for one device
1262 if (PcdGetBool (PcdSrIovSupport
) && PciDevice
->SrIovCapabilityOffset
!= 0) {
1263 if (TempReservedBusNum
< PciDevice
->ReservedBusNum
) {
1265 Status
= PciAllocateBusNumber (PciDevice
, *SubBusNumber
, (UINT8
) (PciDevice
->ReservedBusNum
- TempReservedBusNum
), SubBusNumber
);
1266 if (EFI_ERROR (Status
)) {
1269 TempReservedBusNum
= PciDevice
->ReservedBusNum
;
1272 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber
));
1274 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber
));
1280 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1283 // Skip sub functions, this is not a multi function device
1286 Func
= PCI_MAX_FUNC
;
1295 Process Option Rom on the specified root bridge.
1297 @param Bridge Pci root bridge device instance.
1299 @retval EFI_SUCCESS Success process.
1300 @retval other Some error occurred when processing Option Rom on the root bridge.
1304 PciRootBridgeP2CProcess (
1305 IN PCI_IO_DEVICE
*Bridge
1308 LIST_ENTRY
*CurrentLink
;
1309 PCI_IO_DEVICE
*Temp
;
1310 EFI_HPC_STATE State
;
1314 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1316 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1318 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1320 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1322 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1325 // Raise the EFI_IOB_PCI_HPC_INIT status code
1327 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1329 EFI_IO_BUS_PCI
| EFI_IOB_PCI_HPC_INIT
,
1333 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1334 Status
= gPciHotPlugInit
->InitializeRootHpc (
1342 if (!EFI_ERROR (Status
)) {
1343 Status
= PciBridgeEnumerator (Temp
);
1345 if (EFI_ERROR (Status
)) {
1350 CurrentLink
= CurrentLink
->ForwardLink
;
1356 if (!IsListEmpty (&Temp
->ChildList
)) {
1357 Status
= PciRootBridgeP2CProcess (Temp
);
1360 CurrentLink
= CurrentLink
->ForwardLink
;
1367 Process Option Rom on the specified host bridge.
1369 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1371 @retval EFI_SUCCESS Success process.
1372 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1373 @retval other Some error occurred when processing Option Rom on the host bridge.
1377 PciHostBridgeP2CProcess (
1378 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1381 EFI_HANDLE RootBridgeHandle
;
1382 PCI_IO_DEVICE
*RootBridgeDev
;
1385 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1389 RootBridgeHandle
= NULL
;
1391 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1394 // Get RootBridg Device by handle
1396 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1398 if (RootBridgeDev
== NULL
) {
1399 return EFI_NOT_FOUND
;
1402 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1403 if (EFI_ERROR (Status
)) {
1413 This function is used to enumerate the entire host bridge
1414 in a given platform.
1416 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1418 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1419 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1420 @retval other Some error occurred when enumerating the host bridge.
1424 PciHostBridgeEnumerator (
1425 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1428 EFI_HANDLE RootBridgeHandle
;
1429 PCI_IO_DEVICE
*RootBridgeDev
;
1431 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1433 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1434 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1435 UINT8 StartBusNumber
;
1436 LIST_ENTRY RootBridgeList
;
1439 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1440 InitializeHotPlugSupport ();
1443 InitializeListHead (&RootBridgeList
);
1446 // Notify the bus allocation phase is about to start
1448 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1450 if (EFI_ERROR (Status
)) {
1454 DEBUG((EFI_D_INFO
, "PCI Bus First Scanning\n"));
1455 RootBridgeHandle
= NULL
;
1456 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1459 // if a root bridge instance is found, create root bridge device for it
1462 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1464 if (RootBridgeDev
== NULL
) {
1465 return EFI_OUT_OF_RESOURCES
;
1469 // Enumerate all the buses under this root bridge
1471 Status
= PciRootBridgeEnumerator (
1476 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1477 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1479 DestroyRootBridge (RootBridgeDev
);
1481 if (EFI_ERROR (Status
)) {
1487 // Notify the bus allocation phase is finished for the first time
1489 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1491 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1493 // Reset all assigned PCI bus number in all PPB
1495 RootBridgeHandle
= NULL
;
1496 Link
= GetFirstNode (&RootBridgeList
);
1497 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1498 (!IsNull (&RootBridgeList
, Link
))) {
1499 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1501 // Get the Bus information
1503 Status
= PciResAlloc
->StartBusEnumeration (
1506 (VOID
**) &Configuration
1508 if (EFI_ERROR (Status
)) {
1513 // Get the bus number to start with
1515 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1517 ResetAllPpbBusNumber (
1522 FreePool (Configuration
);
1523 Link
= RemoveEntryList (Link
);
1524 DestroyRootBridge (RootBridgeDev
);
1528 // Wait for all HPC initialized
1530 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1532 if (EFI_ERROR (Status
)) {
1533 DEBUG ((EFI_D_ERROR
, "Some root HPC failed to initialize\n"));
1538 // Notify the bus allocation phase is about to start for the 2nd time
1540 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1542 if (EFI_ERROR (Status
)) {
1546 DEBUG((EFI_D_INFO
, "PCI Bus Second Scanning\n"));
1547 RootBridgeHandle
= NULL
;
1548 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1551 // if a root bridge instance is found, create root bridge device for it
1553 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1555 if (RootBridgeDev
== NULL
) {
1556 return EFI_OUT_OF_RESOURCES
;
1560 // Enumerate all the buses under this root bridge
1562 Status
= PciRootBridgeEnumerator (
1567 DestroyRootBridge (RootBridgeDev
);
1568 if (EFI_ERROR (Status
)) {
1574 // Notify the bus allocation phase is to end for the 2nd time
1576 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1580 // Notify the resource allocation phase is to start
1582 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1584 if (EFI_ERROR (Status
)) {
1588 RootBridgeHandle
= NULL
;
1589 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1592 // if a root bridge instance is found, create root bridge device for it
1594 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1596 if (RootBridgeDev
== NULL
) {
1597 return EFI_OUT_OF_RESOURCES
;
1600 Status
= StartManagingRootBridge (RootBridgeDev
);
1602 if (EFI_ERROR (Status
)) {
1606 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1607 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1609 if (EFI_ERROR (Status
)) {
1613 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1615 if (EFI_ERROR (Status
)) {
1620 // Determine root bridge attribute by calling interface of Pcihostbridge
1623 DetermineRootBridgeAttributes (
1629 // Collect all the resource information under this root bridge
1630 // A database that records all the information about pci device subject to this
1631 // root bridge will then be created
1633 Status
= PciPciDeviceInfoCollector (
1638 if (EFI_ERROR (Status
)) {
1642 InsertRootBridge (RootBridgeDev
);
1645 // Record the hostbridge handle
1647 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);