2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Retrieve the PCI Card device BAR information via PciIo interface.
21 @param PciIoDevice PCI Card device instance.
26 IN PCI_IO_DEVICE
*PciIoDevice
31 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
36 // Read PciBar information from the bar register
38 if (!gFullEnumeration
) {
40 PciIoDevice
->PciIo
.Pci
.Read (
41 &(PciIoDevice
->PciIo
),
43 PCI_CARD_MEMORY_BASE_0
,
48 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
49 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
50 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
53 PciIoDevice
->PciIo
.Pci
.Read (
54 &(PciIoDevice
->PciIo
),
56 PCI_CARD_MEMORY_BASE_1
,
60 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
61 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
62 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
65 PciIoDevice
->PciIo
.Pci
.Read (
66 &(PciIoDevice
->PciIo
),
68 PCI_CARD_IO_BASE_0_LOWER
,
72 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
73 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
74 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
77 PciIoDevice
->PciIo
.Pci
.Read (
78 &(PciIoDevice
->PciIo
),
80 PCI_CARD_IO_BASE_1_LOWER
,
84 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
85 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
86 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
90 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
91 GetResourcePaddingForHpb (PciIoDevice
);
96 Remove rejected pci device from specific root bridge
99 @param RootBridgeHandle Specific parent root bridge handle.
100 @param Bridge Bridge device instance.
104 RemoveRejectedPciDevices (
105 IN EFI_HANDLE RootBridgeHandle
,
106 IN PCI_IO_DEVICE
*Bridge
110 LIST_ENTRY
*CurrentLink
;
111 LIST_ENTRY
*LastLink
;
113 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
117 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
119 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
121 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
123 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
125 // Remove rejected devices recusively
127 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
130 // Skip rejection for all PPBs, while detect rejection for others
132 if (IsPciDeviceRejected (Temp
)) {
135 // For P2C, remove all devices on it
137 if (!IsListEmpty (&Temp
->ChildList
)) {
138 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
142 // Finally remove itself
144 LastLink
= CurrentLink
->BackLink
;
145 RemoveEntryList (CurrentLink
);
146 FreePciDevice (Temp
);
148 CurrentLink
= LastLink
;
152 CurrentLink
= CurrentLink
->ForwardLink
;
157 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
159 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
161 @retval EFI_SUCCESS Successfully finished resource allocation.
162 @retval EFI_NOT_FOUND Cannot get root bridge instance.
163 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
164 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
166 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
170 PciHostBridgeResourceAllocator (
171 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
174 PCI_IO_DEVICE
*RootBridgeDev
;
175 EFI_HANDLE RootBridgeHandle
;
184 UINT64 Mem32ResStatus
;
185 UINT64 PMem32ResStatus
;
186 UINT64 Mem64ResStatus
;
187 UINT64 PMem64ResStatus
;
188 UINT64 MaxOptionRomSize
;
189 PCI_RESOURCE_NODE
*IoBridge
;
190 PCI_RESOURCE_NODE
*Mem32Bridge
;
191 PCI_RESOURCE_NODE
*PMem32Bridge
;
192 PCI_RESOURCE_NODE
*Mem64Bridge
;
193 PCI_RESOURCE_NODE
*PMem64Bridge
;
194 PCI_RESOURCE_NODE IoPool
;
195 PCI_RESOURCE_NODE Mem32Pool
;
196 PCI_RESOURCE_NODE PMem32Pool
;
197 PCI_RESOURCE_NODE Mem64Pool
;
198 PCI_RESOURCE_NODE PMem64Pool
;
200 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
201 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
209 // It may try several times if the resource allocation fails
213 // Initialize resource pool
215 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
216 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
217 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
218 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
219 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
221 RootBridgeDev
= NULL
;
222 RootBridgeHandle
= 0;
224 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
226 // Get Root Bridge Device by handle
228 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
230 if (RootBridgeDev
== NULL
) {
231 return EFI_NOT_FOUND
;
235 // Create the entire system resource map from the information collected by
236 // enumerator. Several resource tree was created
239 IoBridge
= CreateResourceNode (
248 Mem32Bridge
= CreateResourceNode (
257 PMem32Bridge
= CreateResourceNode (
266 Mem64Bridge
= CreateResourceNode (
275 PMem64Bridge
= CreateResourceNode (
285 // Create resourcemap by going through all the devices subject to this root bridge
297 // Get the max ROM size that the root bridge can process
299 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
302 // Skip to enlarge the resource request during realloction
306 // Get Max Option Rom size for current root bridge
308 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
311 // Enlarger the mem32 resource to accomdate the option rom
312 // if the mem32 resource is not enough to hold the rom
314 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
316 Mem32Bridge
->Length
= MaxOptionRomSize
;
317 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
320 // Alignment should be adjusted as well
322 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
323 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
329 // Based on the all the resource tree, contruct ACPI resource node to
330 // submit the resource aperture to pci host bridge protocol
332 Status
= ConstructAcpiResourceRequestor (
343 // Insert these resource nodes into the database
345 InsertResourceNode (&IoPool
, IoBridge
);
346 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
347 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
348 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
349 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
351 if (Status
== EFI_SUCCESS
) {
353 // Submit the resource requirement
355 Status
= PciResAlloc
->SubmitResources (
357 RootBridgeDev
->Handle
,
363 // Free acpi resource node
365 if (AcpiConfig
!= NULL
) {
366 FreePool (AcpiConfig
);
369 if (EFI_ERROR (Status
)) {
371 // Destroy all the resource tree
373 DestroyResourceTree (&IoPool
);
374 DestroyResourceTree (&Mem32Pool
);
375 DestroyResourceTree (&PMem32Pool
);
376 DestroyResourceTree (&Mem64Pool
);
377 DestroyResourceTree (&PMem64Pool
);
382 // End while, at least one Root Bridge should be found.
384 ASSERT (RootBridgeDev
!= NULL
);
387 // Notify platform to start to program the resource
389 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
390 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
392 // If Hot Plug is not supported
394 if (EFI_ERROR (Status
)) {
396 // Allocation failed, then return
398 return EFI_OUT_OF_RESOURCES
;
401 // Allocation succeed.
402 // Get host bridge handle for status report, and then skip the main while
404 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
410 // If Hot Plug is supported
412 if (!EFI_ERROR (Status
)) {
414 // Allocation succeed, then continue the following
420 // If the resource allocation is unsuccessful, free resources on bridge
423 RootBridgeDev
= NULL
;
424 RootBridgeHandle
= 0;
426 IoResStatus
= EFI_RESOURCE_SATISFIED
;
427 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
428 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
429 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
430 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
432 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
434 // Get RootBridg Device by handle
436 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
437 if (RootBridgeDev
== NULL
) {
438 return EFI_NOT_FOUND
;
442 // Get host bridge handle for status report
444 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
447 // Get acpi resource node for all the resource types
451 Status
= PciResAlloc
->GetProposedResources (
453 RootBridgeDev
->Handle
,
457 if (EFI_ERROR (Status
)) {
461 if (AcpiConfig
!= NULL
) {
463 // Adjust resource allocation policy for each RB
465 GetResourceAllocationStatus (
473 FreePool (AcpiConfig
);
481 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
484 // It is very difficult to follow the spec here
485 // Device path , Bar index can not be get here
487 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
489 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
491 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
492 (VOID
*) &AllocFailExtendedData
,
493 sizeof (AllocFailExtendedData
)
496 Status
= PciHostBridgeAdjustAllocation (
510 // Destroy all the resource tree
512 DestroyResourceTree (&IoPool
);
513 DestroyResourceTree (&Mem32Pool
);
514 DestroyResourceTree (&PMem32Pool
);
515 DestroyResourceTree (&Mem64Pool
);
516 DestroyResourceTree (&PMem64Pool
);
518 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
520 if (EFI_ERROR (Status
)) {
532 // Raise the EFI_IOB_PCI_RES_ALLOC status code
534 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
536 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
537 (VOID
*) &HandleExtendedData
,
538 sizeof (HandleExtendedData
)
542 // Notify pci bus driver starts to program the resource
544 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
546 RootBridgeDev
= NULL
;
548 RootBridgeHandle
= 0;
550 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
552 // Get RootBridg Device by handle
554 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
556 if (RootBridgeDev
== NULL
) {
557 return EFI_NOT_FOUND
;
561 // Get acpi resource node for all the resource types
564 Status
= PciResAlloc
->GetProposedResources (
566 RootBridgeDev
->Handle
,
570 if (EFI_ERROR (Status
)) {
575 // Get the resource base by interpreting acpi resource node
588 // Process option rom for this root bridge
590 ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
593 // Create the entire system resource map from the information collected by
594 // enumerator. Several resource tree was created
611 // Program IO resources
619 // Program Mem32 resources
627 // Program PMem32 resources
635 // Program Mem64 resources
643 // Program PMem64 resources
650 FreePool (AcpiConfig
);
654 // Destroy all the resource tree
656 DestroyResourceTree (&IoPool
);
657 DestroyResourceTree (&Mem32Pool
);
658 DestroyResourceTree (&PMem32Pool
);
659 DestroyResourceTree (&Mem64Pool
);
660 DestroyResourceTree (&PMem64Pool
);
663 // Notify the resource allocation phase is to end
665 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
671 Scan pci bus and assign bus number to the given PCI bus system.
673 @param Bridge Bridge device instance.
674 @param StartBusNumber start point.
675 @param SubBusNumber Point to sub bus number.
676 @param PaddedBusRange Customized bus number.
678 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
679 @retval other Some error occurred when scanning pci bus.
681 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
686 IN PCI_IO_DEVICE
*Bridge
,
687 IN UINT8 StartBusNumber
,
688 OUT UINT8
*SubBusNumber
,
689 OUT UINT8
*PaddedBusRange
700 PCI_IO_DEVICE
*PciDevice
;
704 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
705 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
707 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
709 UINT32 TempReservedBusNum
;
711 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
715 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
721 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
722 TempReservedBusNum
= 0;
723 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
726 // Check to see whether a pci device is present
728 Status
= PciDevicePresent (
736 if (EFI_ERROR (Status
)) {
739 // Skip sub functions, this is not a multi function device
747 DEBUG((EFI_D_INFO
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
749 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
751 // Get the PCI device information
753 Status
= PciSearchDevice (
762 ASSERT (!EFI_ERROR (Status
));
764 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
766 if (!IS_PCI_BRIDGE (&Pci
)) {
768 // PCI bridges will be called later
769 // Here just need for PCI device or PCI to cardbus controller
770 // EfiPciBeforeChildBusEnumeration for PCI Device Node
772 PreprocessController (
774 PciDevice
->BusNumber
,
775 PciDevice
->DeviceNumber
,
776 PciDevice
->FunctionNumber
,
777 EfiPciBeforeChildBusEnumeration
782 // For Pci Hotplug controller devcie only
784 if (gPciHotPlugInit
!= NULL
) {
786 // Check if it is a Hotplug PCI controller
788 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
790 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
792 Status
= CreateEventForHpc (HpIndex
, &Event
);
794 ASSERT (!EFI_ERROR (Status
));
796 Status
= gPciHotPlugInit
->InitializeRootHpc (
798 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
804 PreprocessController (
806 PciDevice
->BusNumber
,
807 PciDevice
->DeviceNumber
,
808 PciDevice
->FunctionNumber
,
809 EfiPciBeforeChildBusEnumeration
816 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
820 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
822 // If Hot Plug is not supported,
823 // get the bridge information
825 Status
= PciSearchDevice (
834 if (EFI_ERROR (Status
)) {
839 // If Hot Plug is supported,
840 // Get the bridge information
843 if (gPciHotPlugInit
!= NULL
) {
845 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
848 // If it is initialized, get the padded bus range
850 Status
= gPciHotPlugInit
->GetResourcePadding (
852 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
855 (VOID
**) &Descriptors
,
859 if (EFI_ERROR (Status
)) {
864 Status
= PciGetBusRange (
871 FreePool (Descriptors
);
873 if (EFI_ERROR (Status
)) {
883 // Add feature to support customized secondary bus number
885 if (*SubBusNumber
== 0) {
886 *SubBusNumber
= *PaddedBusRange
;
891 SecondBus
= *SubBusNumber
;
893 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
894 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
896 Status
= PciRootBridgeIo
->Pci
.Write (
906 // If it is PPB, resursively search down this bridge
908 if (IS_PCI_BRIDGE (&Pci
)) {
911 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
912 // PCI configuration transaction to go through any PPB
915 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
916 Status
= PciRootBridgeIo
->Pci
.Write (
925 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
927 PreprocessController (
929 PciDevice
->BusNumber
,
930 PciDevice
->DeviceNumber
,
931 PciDevice
->FunctionNumber
,
932 EfiPciBeforeChildBusEnumeration
935 DEBUG((EFI_D_INFO
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
936 Status
= PciScanBus (
942 if (EFI_ERROR (Status
)) {
947 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
949 // Ensure the device is enabled and initialized
951 if ((Attributes
== EfiPaddingPciRootBridge
) &&
952 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
953 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
954 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
956 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
961 // Set the current maximum bus number under the PPB
963 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
965 Status
= PciRootBridgeIo
->Pci
.Write (
974 // It is device. Check PCI IOV for Bus reservation
976 if (PciDevice
== NULL
) {
978 // No PciDevice found, conitue Scan
983 // Go through each function, just reserve the MAX ReservedBusNum for one device
985 if ((PciDevice
->AriCapabilityOffset
!= 0) && ((FeaturePcdGet(PcdSrIovSupport
)& EFI_PCI_IOV_POLICY_SRIOV
) != 0)) {
987 if (TempReservedBusNum
< PciDevice
->ReservedBusNum
) {
989 (*SubBusNumber
) = (UINT8
)((*SubBusNumber
) + PciDevice
->ReservedBusNum
- TempReservedBusNum
);
990 TempReservedBusNum
= PciDevice
->ReservedBusNum
;
993 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber
));
995 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber
));
1001 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1004 // Skip sub functions, this is not a multi function device
1007 Func
= PCI_MAX_FUNC
;
1016 Process Option Rom on the specified root bridge.
1018 @param Bridge Pci root bridge device instance.
1020 @retval EFI_SUCCESS Success process.
1021 @retval other Some error occurred when processing Option Rom on the root bridge.
1025 PciRootBridgeP2CProcess (
1026 IN PCI_IO_DEVICE
*Bridge
1029 LIST_ENTRY
*CurrentLink
;
1030 PCI_IO_DEVICE
*Temp
;
1031 EFI_HPC_STATE State
;
1035 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1037 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1039 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1041 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1043 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1046 // Raise the EFI_IOB_PCI_HPC_INIT status code
1048 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1050 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1054 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1055 Status
= gPciHotPlugInit
->InitializeRootHpc (
1063 if (!EFI_ERROR (Status
)) {
1064 Status
= PciBridgeEnumerator (Temp
);
1066 if (EFI_ERROR (Status
)) {
1071 CurrentLink
= CurrentLink
->ForwardLink
;
1077 if (!IsListEmpty (&Temp
->ChildList
)) {
1078 Status
= PciRootBridgeP2CProcess (Temp
);
1081 CurrentLink
= CurrentLink
->ForwardLink
;
1088 Process Option Rom on the specified host bridge.
1090 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1092 @retval EFI_SUCCESS Success process.
1093 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1094 @retval other Some error occurred when processing Option Rom on the host bridge.
1098 PciHostBridgeP2CProcess (
1099 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1102 EFI_HANDLE RootBridgeHandle
;
1103 PCI_IO_DEVICE
*RootBridgeDev
;
1106 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1110 RootBridgeHandle
= NULL
;
1112 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1115 // Get RootBridg Device by handle
1117 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1119 if (RootBridgeDev
== NULL
) {
1120 return EFI_NOT_FOUND
;
1123 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1124 if (EFI_ERROR (Status
)) {
1134 This function is used to enumerate the entire host bridge
1135 in a given platform.
1137 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1139 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1140 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1141 @retval other Some error occurred when enumerating the host bridge.
1145 PciHostBridgeEnumerator (
1146 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1149 EFI_HANDLE RootBridgeHandle
;
1150 PCI_IO_DEVICE
*RootBridgeDev
;
1152 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1154 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1155 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1156 UINT8 StartBusNumber
;
1157 LIST_ENTRY RootBridgeList
;
1160 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1161 InitializeHotPlugSupport ();
1164 InitializeListHead (&RootBridgeList
);
1167 // Notify the bus allocation phase is about to start
1169 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1171 DEBUG((EFI_D_INFO
, "PCI Bus First Scanning\n"));
1172 RootBridgeHandle
= NULL
;
1173 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1176 // if a root bridge instance is found, create root bridge device for it
1179 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1181 if (RootBridgeDev
== NULL
) {
1182 return EFI_OUT_OF_RESOURCES
;
1186 // Enumerate all the buses under this root bridge
1188 Status
= PciRootBridgeEnumerator (
1193 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1194 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1196 DestroyRootBridge (RootBridgeDev
);
1198 if (EFI_ERROR (Status
)) {
1204 // Notify the bus allocation phase is finished for the first time
1206 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1208 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1210 // Reset all assigned PCI bus number in all PPB
1212 RootBridgeHandle
= NULL
;
1213 Link
= GetFirstNode (&RootBridgeList
);
1214 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1215 (!IsNull (&RootBridgeList
, Link
))) {
1216 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1218 // Get the Bus information
1220 Status
= PciResAlloc
->StartBusEnumeration (
1223 (VOID
**) &Configuration
1225 if (EFI_ERROR (Status
)) {
1230 // Get the bus number to start with
1232 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1234 ResetAllPpbBusNumber (
1239 FreePool (Configuration
);
1240 Link
= GetNextNode (&RootBridgeList
, Link
);
1241 DestroyRootBridge (RootBridgeDev
);
1245 // Wait for all HPC initialized
1247 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1249 if (EFI_ERROR (Status
)) {
1254 // Notify the bus allocation phase is about to start for the 2nd time
1256 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1258 DEBUG((EFI_D_INFO
, "PCI Bus Second Scanning\n"));
1259 RootBridgeHandle
= NULL
;
1260 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1263 // if a root bridge instance is found, create root bridge device for it
1265 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1267 if (RootBridgeDev
== NULL
) {
1268 return EFI_OUT_OF_RESOURCES
;
1272 // Enumerate all the buses under this root bridge
1274 Status
= PciRootBridgeEnumerator (
1279 DestroyRootBridge (RootBridgeDev
);
1280 if (EFI_ERROR (Status
)) {
1286 // Notify the bus allocation phase is to end for the 2nd time
1288 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1292 // Notify the resource allocation phase is to start
1294 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1296 RootBridgeHandle
= NULL
;
1297 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1300 // if a root bridge instance is found, create root bridge device for it
1302 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1304 if (RootBridgeDev
== NULL
) {
1305 return EFI_OUT_OF_RESOURCES
;
1308 Status
= StartManagingRootBridge (RootBridgeDev
);
1310 if (EFI_ERROR (Status
)) {
1314 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1315 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1317 if (EFI_ERROR (Status
)) {
1321 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1323 if (EFI_ERROR (Status
)) {
1328 // Determine root bridge attribute by calling interface of Pcihostbridge
1331 DetermineRootBridgeAttributes (
1337 // Collect all the resource information under this root bridge
1338 // A database that records all the information about pci device subject to this
1339 // root bridge will then be created
1341 Status
= PciPciDeviceInfoCollector (
1346 if (EFI_ERROR (Status
)) {
1350 InsertRootBridge (RootBridgeDev
);
1353 // Record the hostbridge handle
1355 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);