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 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 GLOBAL_REMOVE_IF_UNREFERENCED
19 CHAR16
*mBarTypeStr
[] = {
34 Retrieve the max bus number that is assigned to the Root Bridge hierarchy.
35 It can support the case that there are multiple bus ranges.
37 @param Bridge Bridge device instance.
39 @retval The max bus number that is assigned to this Root Bridge hierarchy.
44 IN PCI_IO_DEVICE
*Bridge
47 PCI_IO_DEVICE
*RootBridge
;
48 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
49 UINT64 MaxNumberInRange
;
52 // Get PCI Root Bridge device
55 while (RootBridge
->Parent
!= NULL
) {
56 RootBridge
= RootBridge
->Parent
;
60 // Iterate the bus number ranges to get max PCI bus number
62 BusNumberRanges
= RootBridge
->BusNumberRanges
;
63 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
64 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
67 return (UINT16
) MaxNumberInRange
;
71 Retrieve the PCI Card device BAR information via PciIo interface.
73 @param PciIoDevice PCI Card device instance.
78 IN PCI_IO_DEVICE
*PciIoDevice
83 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
88 // Read PciBar information from the bar register
90 if (!gFullEnumeration
) {
92 PciIoDevice
->PciIo
.Pci
.Read (
93 &(PciIoDevice
->PciIo
),
95 PCI_CARD_MEMORY_BASE_0
,
100 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
101 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
102 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
105 PciIoDevice
->PciIo
.Pci
.Read (
106 &(PciIoDevice
->PciIo
),
108 PCI_CARD_MEMORY_BASE_1
,
112 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
113 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
114 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
117 PciIoDevice
->PciIo
.Pci
.Read (
118 &(PciIoDevice
->PciIo
),
120 PCI_CARD_IO_BASE_0_LOWER
,
124 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
125 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
126 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
129 PciIoDevice
->PciIo
.Pci
.Read (
130 &(PciIoDevice
->PciIo
),
132 PCI_CARD_IO_BASE_1_LOWER
,
136 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
137 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
138 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
142 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
143 GetResourcePaddingForHpb (PciIoDevice
);
148 Remove rejected pci device from specific root bridge
151 @param RootBridgeHandle Specific parent root bridge handle.
152 @param Bridge Bridge device instance.
156 RemoveRejectedPciDevices (
157 IN EFI_HANDLE RootBridgeHandle
,
158 IN PCI_IO_DEVICE
*Bridge
162 LIST_ENTRY
*CurrentLink
;
163 LIST_ENTRY
*LastLink
;
165 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
169 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
171 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
173 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
175 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
177 // Remove rejected devices recusively
179 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
182 // Skip rejection for all PPBs, while detect rejection for others
184 if (IsPciDeviceRejected (Temp
)) {
187 // For P2C, remove all devices on it
189 if (!IsListEmpty (&Temp
->ChildList
)) {
190 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
194 // Finally remove itself
196 LastLink
= CurrentLink
->BackLink
;
197 RemoveEntryList (CurrentLink
);
198 FreePciDevice (Temp
);
200 CurrentLink
= LastLink
;
204 CurrentLink
= CurrentLink
->ForwardLink
;
209 Dump the resourc map of the bridge device.
211 @param[in] BridgeResource Resource descriptor of the bridge device.
215 IN PCI_RESOURCE_NODE
*BridgeResource
219 PCI_RESOURCE_NODE
*Resource
;
222 if ((BridgeResource
!= NULL
) && (BridgeResource
->Length
!= 0)) {
224 EFI_D_INFO
, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",
225 mBarTypeStr
[MIN (BridgeResource
->ResType
, PciBarTypeMaxType
)],
226 BridgeResource
->PciDev
->PciBar
[BridgeResource
->Bar
].BaseAddress
,
227 BridgeResource
->Length
, BridgeResource
->Alignment
229 for ( Link
= GetFirstNode (&BridgeResource
->ChildList
)
230 ; !IsNull (&BridgeResource
->ChildList
, Link
)
231 ; Link
= GetNextNode (&BridgeResource
->ChildList
, Link
)
233 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
234 if (Resource
->ResourceUsage
== PciResUsageTypical
) {
235 Bar
= Resource
->Virtual
? Resource
->PciDev
->VfPciBar
: Resource
->PciDev
->PciBar
;
237 EFI_D_INFO
, " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",
238 Bar
[Resource
->Bar
].BaseAddress
, Resource
->Length
, Resource
->Alignment
,
239 IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"PPB" :
240 IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"P2C" :
242 Resource
->PciDev
->BusNumber
, 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
))
251 // The resource requirement comes from the device itself.
253 DEBUG ((EFI_D_INFO
, "%02x]", Bar
[Resource
->Bar
].Offset
));
256 // The resource requirement comes from the subordinate devices.
258 DEBUG ((EFI_D_INFO
, "**]"));
261 DEBUG ((EFI_D_INFO
, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource
->Length
, Resource
->Alignment
));
263 if (BridgeResource
->ResType
!= Resource
->ResType
) {
264 DEBUG ((EFI_D_INFO
, "; Type = %s", mBarTypeStr
[MIN (Resource
->ResType
, PciBarTypeMaxType
)]));
266 DEBUG ((EFI_D_INFO
, "\n"));
272 Find the corresponding resource node for the Device in child list of BridgeResource.
274 @param[in] Device Pointer to PCI_IO_DEVICE.
275 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.
276 @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.
278 @return Count of the resource descriptors returned.
282 IN PCI_IO_DEVICE
*Device
,
283 IN PCI_RESOURCE_NODE
*BridgeResource
,
284 OUT PCI_RESOURCE_NODE
**DeviceResources OPTIONAL
288 PCI_RESOURCE_NODE
*Resource
;
292 for ( Link
= BridgeResource
->ChildList
.ForwardLink
293 ; Link
!= &BridgeResource
->ChildList
294 ; Link
= Link
->ForwardLink
296 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
297 if (Resource
->PciDev
== Device
) {
298 if (DeviceResources
!= NULL
) {
299 DeviceResources
[Count
] = Resource
;
309 Dump the resource map of all the devices under Bridge.
311 @param[in] Bridge Bridge device instance.
312 @param[in] Resources Resource descriptors for the bridge device.
313 @param[in] ResourceCount Count of resource descriptors.
317 IN PCI_IO_DEVICE
*Bridge
,
318 IN PCI_RESOURCE_NODE
**Resources
,
319 IN UINTN ResourceCount
324 PCI_IO_DEVICE
*Device
;
327 PCI_RESOURCE_NODE
**ChildResources
;
328 UINTN ChildResourceCount
;
330 DEBUG ((EFI_D_INFO
, "PciBus: Resource Map for "));
332 Status
= gBS
->OpenProtocol (
334 &gEfiPciRootBridgeIoProtocolGuid
,
338 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
340 if (EFI_ERROR (Status
)) {
342 EFI_D_INFO
, "Bridge [%02x|%02x|%02x]\n",
343 Bridge
->BusNumber
, Bridge
->DeviceNumber
, Bridge
->FunctionNumber
346 Str
= ConvertDevicePathToText (
347 DevicePathFromHandle (Bridge
->Handle
),
351 DEBUG ((EFI_D_INFO
, "Root Bridge %s\n", Str
!= NULL
? Str
: L
""));
357 for (Index
= 0; Index
< ResourceCount
; Index
++) {
358 DumpBridgeResource (Resources
[Index
]);
360 DEBUG ((EFI_D_INFO
, "\n"));
362 for ( Link
= Bridge
->ChildList
.ForwardLink
363 ; Link
!= &Bridge
->ChildList
364 ; Link
= Link
->ForwardLink
366 Device
= PCI_IO_DEVICE_FROM_LINK (Link
);
367 if (IS_PCI_BRIDGE (&Device
->Pci
)) {
369 ChildResourceCount
= 0;
370 for (Index
= 0; Index
< ResourceCount
; Index
++) {
371 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], NULL
);
373 ChildResources
= AllocatePool (sizeof (PCI_RESOURCE_NODE
*) * ChildResourceCount
);
374 ASSERT (ChildResources
!= NULL
);
375 ChildResourceCount
= 0;
376 for (Index
= 0; Index
< ResourceCount
; Index
++) {
377 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], &ChildResources
[ChildResourceCount
]);
380 DumpResourceMap (Device
, ChildResources
, ChildResourceCount
);
381 FreePool (ChildResources
);
387 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
389 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
391 @retval EFI_SUCCESS Successfully finished resource allocation.
392 @retval EFI_NOT_FOUND Cannot get root bridge instance.
393 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
394 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
396 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
400 PciHostBridgeResourceAllocator (
401 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
404 PCI_IO_DEVICE
*RootBridgeDev
;
405 EFI_HANDLE RootBridgeHandle
;
414 UINT64 Mem32ResStatus
;
415 UINT64 PMem32ResStatus
;
416 UINT64 Mem64ResStatus
;
417 UINT64 PMem64ResStatus
;
418 UINT32 MaxOptionRomSize
;
419 PCI_RESOURCE_NODE
*IoBridge
;
420 PCI_RESOURCE_NODE
*Mem32Bridge
;
421 PCI_RESOURCE_NODE
*PMem32Bridge
;
422 PCI_RESOURCE_NODE
*Mem64Bridge
;
423 PCI_RESOURCE_NODE
*PMem64Bridge
;
424 PCI_RESOURCE_NODE IoPool
;
425 PCI_RESOURCE_NODE Mem32Pool
;
426 PCI_RESOURCE_NODE PMem32Pool
;
427 PCI_RESOURCE_NODE Mem64Pool
;
428 PCI_RESOURCE_NODE PMem64Pool
;
429 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
430 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
433 // It may try several times if the resource allocation fails
437 // Initialize resource pool
439 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
440 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
441 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
442 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
443 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
445 RootBridgeDev
= NULL
;
446 RootBridgeHandle
= 0;
448 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
450 // Get Root Bridge Device by handle
452 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
454 if (RootBridgeDev
== NULL
) {
455 return EFI_NOT_FOUND
;
459 // Create the entire system resource map from the information collected by
460 // enumerator. Several resource tree was created
464 // If non-standard PCI Bridge I/O window alignment is supported,
465 // set I/O aligment to minimum possible alignment for root bridge.
467 IoBridge
= CreateResourceNode (
470 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
) ? 0x1FF: 0xFFF,
476 Mem32Bridge
= CreateResourceNode (
485 PMem32Bridge
= CreateResourceNode (
494 Mem64Bridge
= CreateResourceNode (
503 PMem64Bridge
= CreateResourceNode (
513 // Get the max ROM size that the root bridge can process
514 // Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.
515 // All devices' Option ROM share the same MEM32 resource.
517 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
518 if (MaxOptionRomSize
!= 0) {
519 RootBridgeDev
->PciBar
[0].BarType
= PciBarTypeOpRom
;
520 RootBridgeDev
->PciBar
[0].Length
= MaxOptionRomSize
;
521 RootBridgeDev
->PciBar
[0].Alignment
= MaxOptionRomSize
- 1;
522 GetResourceFromDevice (RootBridgeDev
, IoBridge
, Mem32Bridge
, PMem32Bridge
, Mem64Bridge
, PMem64Bridge
);
526 // Create resourcemap by going through all the devices subject to this root bridge
538 // Based on the all the resource tree, construct ACPI resource node to
539 // submit the resource aperture to pci host bridge protocol
541 Status
= ConstructAcpiResourceRequestor (
552 // Insert these resource nodes into the database
554 InsertResourceNode (&IoPool
, IoBridge
);
555 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
556 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
557 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
558 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
560 if (Status
== EFI_SUCCESS
) {
562 // Submit the resource requirement
564 Status
= PciResAlloc
->SubmitResources (
566 RootBridgeDev
->Handle
,
570 // If SubmitResources returns error, PciBus isn't able to start.
571 // It's a fatal error so assertion is added.
573 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->SubmitResources() - %r\n", Status
));
574 ASSERT_EFI_ERROR (Status
);
578 // Free acpi resource node
580 if (AcpiConfig
!= NULL
) {
581 FreePool (AcpiConfig
);
584 if (EFI_ERROR (Status
)) {
586 // Destroy all the resource tree
588 DestroyResourceTree (&IoPool
);
589 DestroyResourceTree (&Mem32Pool
);
590 DestroyResourceTree (&PMem32Pool
);
591 DestroyResourceTree (&Mem64Pool
);
592 DestroyResourceTree (&PMem64Pool
);
597 // End while, at least one Root Bridge should be found.
599 ASSERT (RootBridgeDev
!= NULL
);
602 // Notify platform to start to program the resource
604 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
605 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status
));
606 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
608 // If Hot Plug is not supported
610 if (EFI_ERROR (Status
)) {
612 // Allocation failed, then return
614 return EFI_OUT_OF_RESOURCES
;
617 // Allocation succeed.
618 // Get host bridge handle for status report, and then skip the main while
620 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
626 // If Hot Plug is supported
628 if (!EFI_ERROR (Status
)) {
630 // Allocation succeed, then continue the following
636 // If the resource allocation is unsuccessful, free resources on bridge
639 RootBridgeDev
= NULL
;
640 RootBridgeHandle
= 0;
642 IoResStatus
= EFI_RESOURCE_SATISFIED
;
643 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
644 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
645 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
646 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
648 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
650 // Get RootBridg Device by handle
652 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
653 if (RootBridgeDev
== NULL
) {
654 return EFI_NOT_FOUND
;
658 // Get host bridge handle for status report
660 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
663 // Get acpi resource node for all the resource types
667 Status
= PciResAlloc
->GetProposedResources (
669 RootBridgeDev
->Handle
,
673 if (EFI_ERROR (Status
)) {
677 if (AcpiConfig
!= NULL
) {
679 // Adjust resource allocation policy for each RB
681 GetResourceAllocationStatus (
689 FreePool (AcpiConfig
);
697 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
700 // It is very difficult to follow the spec here
701 // Device path , Bar index can not be get here
703 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
705 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
707 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
708 (VOID
*) &AllocFailExtendedData
,
709 sizeof (AllocFailExtendedData
)
712 Status
= PciHostBridgeAdjustAllocation (
726 // Destroy all the resource tree
728 DestroyResourceTree (&IoPool
);
729 DestroyResourceTree (&Mem32Pool
);
730 DestroyResourceTree (&PMem32Pool
);
731 DestroyResourceTree (&Mem64Pool
);
732 DestroyResourceTree (&PMem64Pool
);
734 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
736 if (EFI_ERROR (Status
)) {
746 // Raise the EFI_IOB_PCI_RES_ALLOC status code
748 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
750 EFI_IO_BUS_PCI
| EFI_IOB_PCI_RES_ALLOC
,
751 (VOID
*) &HandleExtendedData
,
752 sizeof (HandleExtendedData
)
756 // Notify pci bus driver starts to program the resource
758 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
760 if (EFI_ERROR (Status
)) {
764 RootBridgeDev
= NULL
;
766 RootBridgeHandle
= 0;
768 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
770 // Get RootBridg Device by handle
772 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
774 if (RootBridgeDev
== NULL
) {
775 return EFI_NOT_FOUND
;
779 // Get acpi resource node for all the resource types
782 Status
= PciResAlloc
->GetProposedResources (
784 RootBridgeDev
->Handle
,
788 if (EFI_ERROR (Status
)) {
793 // Get the resource base by interpreting acpi resource node
806 // Create the entire system resource map from the information collected by
807 // enumerator. Several resource tree was created
809 FindResourceNode (RootBridgeDev
, &IoPool
, &IoBridge
);
810 FindResourceNode (RootBridgeDev
, &Mem32Pool
, &Mem32Bridge
);
811 FindResourceNode (RootBridgeDev
, &PMem32Pool
, &PMem32Bridge
);
812 FindResourceNode (RootBridgeDev
, &Mem64Pool
, &Mem64Bridge
);
813 FindResourceNode (RootBridgeDev
, &PMem64Pool
, &PMem64Bridge
);
815 ASSERT (IoBridge
!= NULL
);
816 ASSERT (Mem32Bridge
!= NULL
);
817 ASSERT (PMem32Bridge
!= NULL
);
818 ASSERT (Mem64Bridge
!= NULL
);
819 ASSERT (PMem64Bridge
!= NULL
);
822 // Program IO resources
830 // Program Mem32 resources
838 // Program PMem32 resources
846 // Program Mem64 resources
854 // Program PMem64 resources
862 // Process Option ROM for this root bridge after all BARs are programmed.
863 // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to
864 // shadow the Option ROM of the devices under the PPB.
865 // After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE
866 // BAR is restored back to the original value.
867 // The original value is programmed by ProgramResource() above.
870 DEBUG_INFO
, "Process Option ROM: BAR Base/Length = %lx/%lx\n",
871 RootBridgeDev
->PciBar
[0].BaseAddress
, RootBridgeDev
->PciBar
[0].Length
873 ProcessOptionRom (RootBridgeDev
, RootBridgeDev
->PciBar
[0].BaseAddress
, RootBridgeDev
->PciBar
[0].Length
);
875 IoBridge
->PciDev
->PciBar
[IoBridge
->Bar
].BaseAddress
= IoBase
;
876 Mem32Bridge
->PciDev
->PciBar
[Mem32Bridge
->Bar
].BaseAddress
= Mem32Base
;
877 PMem32Bridge
->PciDev
->PciBar
[PMem32Bridge
->Bar
].BaseAddress
= PMem32Base
;
878 Mem64Bridge
->PciDev
->PciBar
[Mem64Bridge
->Bar
].BaseAddress
= Mem64Base
;
879 PMem64Bridge
->PciDev
->PciBar
[PMem64Bridge
->Bar
].BaseAddress
= PMem64Base
;
882 // Dump the resource map for current root bridge
885 PCI_RESOURCE_NODE
*Resources
[5];
886 Resources
[0] = IoBridge
;
887 Resources
[1] = Mem32Bridge
;
888 Resources
[2] = PMem32Bridge
;
889 Resources
[3] = Mem64Bridge
;
890 Resources
[4] = PMem64Bridge
;
891 DumpResourceMap (RootBridgeDev
, Resources
, ARRAY_SIZE (Resources
));
894 FreePool (AcpiConfig
);
898 // Destroy all the resource tree
900 DestroyResourceTree (&IoPool
);
901 DestroyResourceTree (&Mem32Pool
);
902 DestroyResourceTree (&PMem32Pool
);
903 DestroyResourceTree (&Mem64Pool
);
904 DestroyResourceTree (&PMem64Pool
);
907 // Notify the resource allocation phase is to end
909 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
915 Allocate NumberOfBuses buses and return the next available PCI bus number.
917 @param Bridge Bridge device instance.
918 @param StartBusNumber Current available PCI bus number.
919 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.
920 @param NextBusNumber Next available PCI bus number.
922 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number
923 is returned in NextBusNumber.
924 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.
928 PciAllocateBusNumber (
929 IN PCI_IO_DEVICE
*Bridge
,
930 IN UINT8 StartBusNumber
,
931 IN UINT8 NumberOfBuses
,
932 OUT UINT8
*NextBusNumber
935 PCI_IO_DEVICE
*RootBridge
;
936 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
938 UINT64 MaxNumberInRange
;
941 // Get PCI Root Bridge device
944 while (RootBridge
->Parent
!= NULL
) {
945 RootBridge
= RootBridge
->Parent
;
949 // Get next available PCI bus number
951 BusNumberRanges
= RootBridge
->BusNumberRanges
;
952 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
953 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
954 if (StartBusNumber
>= BusNumberRanges
->AddrRangeMin
&& StartBusNumber
<= MaxNumberInRange
) {
955 NextNumber
= (UINT8
)(StartBusNumber
+ NumberOfBuses
);
956 while (NextNumber
> MaxNumberInRange
) {
958 if (BusNumberRanges
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
959 return EFI_OUT_OF_RESOURCES
;
961 NextNumber
= (UINT8
)(NextNumber
+ (BusNumberRanges
->AddrRangeMin
- (MaxNumberInRange
+ 1)));
962 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
964 *NextBusNumber
= NextNumber
;
969 return EFI_OUT_OF_RESOURCES
;
973 Scan pci bus and assign bus number to the given PCI bus system.
975 @param Bridge Bridge device instance.
976 @param StartBusNumber start point.
977 @param SubBusNumber Point to sub bus number.
978 @param PaddedBusRange Customized bus number.
980 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
981 @retval other Some error occurred when scanning pci bus.
983 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
988 IN PCI_IO_DEVICE
*Bridge
,
989 IN UINT8 StartBusNumber
,
990 OUT UINT8
*SubBusNumber
,
991 OUT UINT8
*PaddedBusRange
1003 PCI_IO_DEVICE
*PciDevice
;
1005 EFI_HPC_STATE State
;
1007 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1008 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1009 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*NextDescriptors
;
1011 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1013 UINT32 TempReservedBusNum
;
1015 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1019 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1025 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1026 TempReservedBusNum
= 0;
1027 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1030 // Check to see whether a pci device is present
1032 Status
= PciDevicePresent (
1040 if (EFI_ERROR (Status
) && Func
== 0) {
1042 // go to next device if there is no Function 0
1047 if (EFI_ERROR (Status
)) {
1052 // Get the PCI device information
1054 Status
= PciSearchDevice (
1063 ASSERT (!EFI_ERROR (Status
));
1065 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1067 if (!IS_PCI_BRIDGE (&Pci
)) {
1069 // PCI bridges will be called later
1070 // Here just need for PCI device or PCI to cardbus controller
1071 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1073 PreprocessController (
1075 PciDevice
->BusNumber
,
1076 PciDevice
->DeviceNumber
,
1077 PciDevice
->FunctionNumber
,
1078 EfiPciBeforeChildBusEnumeration
1082 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1084 // For Pci Hotplug controller devcie only
1086 if (gPciHotPlugInit
!= NULL
) {
1088 // Check if it is a Hotplug PCI controller
1090 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1091 gPciRootHpcData
[HpIndex
].Found
= TRUE
;
1093 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1095 Status
= CreateEventForHpc (HpIndex
, &Event
);
1097 ASSERT (!EFI_ERROR (Status
));
1099 Status
= gPciHotPlugInit
->InitializeRootHpc (
1101 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1107 PreprocessController (
1109 PciDevice
->BusNumber
,
1110 PciDevice
->DeviceNumber
,
1111 PciDevice
->FunctionNumber
,
1112 EfiPciBeforeChildBusEnumeration
1119 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1123 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1125 // If Hot Plug is not supported,
1126 // get the bridge information
1128 Status
= PciSearchDevice (
1137 if (EFI_ERROR (Status
)) {
1142 // If Hot Plug is supported,
1143 // Get the bridge information
1146 if (gPciHotPlugInit
!= NULL
) {
1148 if (IsPciHotPlugBus (PciDevice
)) {
1151 // If it is initialized, get the padded bus range
1153 Status
= gPciHotPlugInit
->GetResourcePadding (
1155 PciDevice
->DevicePath
,
1158 (VOID
**) &Descriptors
,
1162 if (EFI_ERROR (Status
)) {
1167 NextDescriptors
= Descriptors
;
1168 Status
= PciGetBusRange (
1175 FreePool (Descriptors
);
1177 if (!EFI_ERROR (Status
)) {
1179 } else if (Status
!= EFI_NOT_FOUND
) {
1181 // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.
1189 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
1190 if (EFI_ERROR (Status
)) {
1193 SecondBus
= *SubBusNumber
;
1195 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1196 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
1198 Status
= PciRootBridgeIo
->Pci
.Write (
1208 // If it is PPB, resursively search down this bridge
1210 if (IS_PCI_BRIDGE (&Pci
)) {
1213 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1214 // PCI configuration transaction to go through any PPB
1216 Register
= PciGetMaxBusNumber (Bridge
);
1217 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1218 Status
= PciRootBridgeIo
->Pci
.Write (
1227 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1229 PreprocessController (
1231 PciDevice
->BusNumber
,
1232 PciDevice
->DeviceNumber
,
1233 PciDevice
->FunctionNumber
,
1234 EfiPciBeforeChildBusEnumeration
1237 Status
= PciScanBus (
1243 if (EFI_ERROR (Status
)) {
1248 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
1250 // Ensure the device is enabled and initialized
1252 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1253 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
1254 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
1255 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) + *PaddedBusRange
);
1258 // Reserve the larger one between the actual occupied bus number and padded bus number
1260 Status
= PciAllocateBusNumber (PciDevice
, SecondBus
, (UINT8
) (BusRange
), &PaddedSubBus
);
1261 if (EFI_ERROR (Status
)) {
1264 *SubBusNumber
= MAX (PaddedSubBus
, *SubBusNumber
);
1269 // Set the current maximum bus number under the PPB
1271 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1273 Status
= PciRootBridgeIo
->Pci
.Write (
1282 // It is device. Check PCI IOV for Bus reservation
1283 // Go through each function, just reserve the MAX ReservedBusNum for one device
1285 if (PcdGetBool (PcdSrIovSupport
) && PciDevice
->SrIovCapabilityOffset
!= 0) {
1286 if (TempReservedBusNum
< PciDevice
->ReservedBusNum
) {
1288 Status
= PciAllocateBusNumber (PciDevice
, *SubBusNumber
, (UINT8
) (PciDevice
->ReservedBusNum
- TempReservedBusNum
), SubBusNumber
);
1289 if (EFI_ERROR (Status
)) {
1292 TempReservedBusNum
= PciDevice
->ReservedBusNum
;
1295 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber
));
1297 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber
));
1303 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1306 // Skip sub functions, this is not a multi function device
1309 Func
= PCI_MAX_FUNC
;
1318 Process Option Rom on the specified root bridge.
1320 @param Bridge Pci root bridge device instance.
1322 @retval EFI_SUCCESS Success process.
1323 @retval other Some error occurred when processing Option Rom on the root bridge.
1327 PciRootBridgeP2CProcess (
1328 IN PCI_IO_DEVICE
*Bridge
1331 LIST_ENTRY
*CurrentLink
;
1332 PCI_IO_DEVICE
*Temp
;
1333 EFI_HPC_STATE State
;
1337 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1339 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1341 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1343 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1345 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1348 // Raise the EFI_IOB_PCI_HPC_INIT status code
1350 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1352 EFI_IO_BUS_PCI
| EFI_IOB_PCI_HPC_INIT
,
1356 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1357 Status
= gPciHotPlugInit
->InitializeRootHpc (
1365 if (!EFI_ERROR (Status
)) {
1366 Status
= PciBridgeEnumerator (Temp
);
1368 if (EFI_ERROR (Status
)) {
1373 CurrentLink
= CurrentLink
->ForwardLink
;
1379 if (!IsListEmpty (&Temp
->ChildList
)) {
1380 Status
= PciRootBridgeP2CProcess (Temp
);
1383 CurrentLink
= CurrentLink
->ForwardLink
;
1390 Process Option Rom on the specified host bridge.
1392 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1394 @retval EFI_SUCCESS Success process.
1395 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1396 @retval other Some error occurred when processing Option Rom on the host bridge.
1400 PciHostBridgeP2CProcess (
1401 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1404 EFI_HANDLE RootBridgeHandle
;
1405 PCI_IO_DEVICE
*RootBridgeDev
;
1408 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1412 RootBridgeHandle
= NULL
;
1414 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1417 // Get RootBridg Device by handle
1419 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1421 if (RootBridgeDev
== NULL
) {
1422 return EFI_NOT_FOUND
;
1425 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1426 if (EFI_ERROR (Status
)) {
1436 This function is used to enumerate the entire host bridge
1437 in a given platform.
1439 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1441 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1442 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1443 @retval other Some error occurred when enumerating the host bridge.
1447 PciHostBridgeEnumerator (
1448 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1451 EFI_HANDLE RootBridgeHandle
;
1452 PCI_IO_DEVICE
*RootBridgeDev
;
1454 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1456 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1457 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1458 UINT8 StartBusNumber
;
1459 LIST_ENTRY RootBridgeList
;
1462 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1463 InitializeHotPlugSupport ();
1466 InitializeListHead (&RootBridgeList
);
1469 // Notify the bus allocation phase is about to start
1471 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1473 if (EFI_ERROR (Status
)) {
1477 DEBUG((EFI_D_INFO
, "PCI Bus First Scanning\n"));
1478 RootBridgeHandle
= NULL
;
1479 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1482 // if a root bridge instance is found, create root bridge device for it
1485 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1487 if (RootBridgeDev
== NULL
) {
1488 return EFI_OUT_OF_RESOURCES
;
1492 // Enumerate all the buses under this root bridge
1494 Status
= PciRootBridgeEnumerator (
1499 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1500 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1502 DestroyRootBridge (RootBridgeDev
);
1504 if (EFI_ERROR (Status
)) {
1510 // Notify the bus allocation phase is finished for the first time
1512 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1514 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1516 // Reset all assigned PCI bus number in all PPB
1518 RootBridgeHandle
= NULL
;
1519 Link
= GetFirstNode (&RootBridgeList
);
1520 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1521 (!IsNull (&RootBridgeList
, Link
))) {
1522 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1524 // Get the Bus information
1526 Status
= PciResAlloc
->StartBusEnumeration (
1529 (VOID
**) &Configuration
1531 if (EFI_ERROR (Status
)) {
1536 // Get the bus number to start with
1538 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1540 ResetAllPpbBusNumber (
1545 FreePool (Configuration
);
1546 Link
= RemoveEntryList (Link
);
1547 DestroyRootBridge (RootBridgeDev
);
1551 // Wait for all HPC initialized
1553 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1555 if (EFI_ERROR (Status
)) {
1556 DEBUG ((EFI_D_ERROR
, "Some root HPC failed to initialize\n"));
1561 // Notify the bus allocation phase is about to start for the 2nd time
1563 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1565 if (EFI_ERROR (Status
)) {
1569 DEBUG((EFI_D_INFO
, "PCI Bus Second Scanning\n"));
1570 RootBridgeHandle
= NULL
;
1571 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1574 // if a root bridge instance is found, create root bridge device for it
1576 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1578 if (RootBridgeDev
== NULL
) {
1579 return EFI_OUT_OF_RESOURCES
;
1583 // Enumerate all the buses under this root bridge
1585 Status
= PciRootBridgeEnumerator (
1590 DestroyRootBridge (RootBridgeDev
);
1591 if (EFI_ERROR (Status
)) {
1597 // Notify the bus allocation phase is to end for the 2nd time
1599 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1603 // Notify the resource allocation phase is to start
1605 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1607 if (EFI_ERROR (Status
)) {
1611 RootBridgeHandle
= NULL
;
1612 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1615 // if a root bridge instance is found, create root bridge device for it
1617 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1619 if (RootBridgeDev
== NULL
) {
1620 return EFI_OUT_OF_RESOURCES
;
1623 Status
= StartManagingRootBridge (RootBridgeDev
);
1625 if (EFI_ERROR (Status
)) {
1629 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1630 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1632 if (EFI_ERROR (Status
)) {
1636 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1638 if (EFI_ERROR (Status
)) {
1643 // Determine root bridge attribute by calling interface of Pcihostbridge
1646 DetermineRootBridgeAttributes (
1652 // Collect all the resource information under this root bridge
1653 // A database that records all the information about pci device subject to this
1654 // root bridge will then be created
1656 Status
= PciPciDeviceInfoCollector (
1661 if (EFI_ERROR (Status
)) {
1665 InsertRootBridge (RootBridgeDev
);
1668 // Record the hostbridge handle
1670 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);