3 Copyright (c) 2006 - 2009, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "PciDeviceSupport.h"
19 // This device structure is serviced as a header.
20 // Its Next field points to the first root bridge device node
22 LIST_ENTRY gPciDevicePool
;
25 Initialize the gPciDevicePool.
28 InitializePciDevicePool (
32 InitializeListHead (&gPciDevicePool
);
38 Insert a root bridge into PCI device pool
40 @param RootBridge - A pointer to the PCI_IO_DEVICE.
45 PCI_IO_DEVICE
*RootBridge
49 InsertTailList (&gPciDevicePool
, &(RootBridge
->Link
));
55 This function is used to insert a PCI device node under
58 @param Bridge A pointer to the PCI_IO_DEVICE.
59 @param PciDeviceNode A pointer to the PCI_IO_DEVICE.
64 PCI_IO_DEVICE
*Bridge
,
65 PCI_IO_DEVICE
*PciDeviceNode
69 InsertTailList (&Bridge
->ChildList
, &(PciDeviceNode
->Link
));
70 PciDeviceNode
->Parent
= Bridge
;
76 Destroy root bridge and remove it from deivce tree.
78 @param RootBridge The bridge want to be removed.
83 IN PCI_IO_DEVICE
*RootBridge
86 DestroyPciDeviceTree (RootBridge
);
88 FreePciDevice (RootBridge
);
94 Destroy a pci device node.
95 Also all direct or indirect allocated resource for this node will be freed.
97 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
102 IN PCI_IO_DEVICE
*PciIoDevice
107 // Assume all children have been removed underneath this device
109 if (PciIoDevice
->ResourcePaddingDescriptors
!= NULL
) {
110 gBS
->FreePool (PciIoDevice
->ResourcePaddingDescriptors
);
113 if (PciIoDevice
->DevicePath
!= NULL
) {
114 gBS
->FreePool (PciIoDevice
->DevicePath
);
117 gBS
->FreePool (PciIoDevice
);
123 Destroy all the pci device node under the bridge.
124 Bridge itself is not included.
126 @param Bridge A pointer to the PCI_IO_DEVICE.
130 DestroyPciDeviceTree (
131 IN PCI_IO_DEVICE
*Bridge
134 LIST_ENTRY
*CurrentLink
;
137 while (!IsListEmpty (&Bridge
->ChildList
)) {
139 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
142 // Remove this node from the linked list
144 RemoveEntryList (CurrentLink
);
146 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
148 if (!IsListEmpty (&Temp
->ChildList
)) {
149 DestroyPciDeviceTree (Temp
);
152 FreePciDevice (Temp
);
159 Destroy all device nodes under the root bridge
160 specified by Controller.
161 The root bridge itself is also included.
163 @param Controller An efi handle.
167 DestroyRootBridgeByHandle (
168 EFI_HANDLE Controller
172 LIST_ENTRY
*CurrentLink
;
175 CurrentLink
= gPciDevicePool
.ForwardLink
;
177 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
178 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
180 if (Temp
->Handle
== Controller
) {
182 RemoveEntryList (CurrentLink
);
184 DestroyPciDeviceTree (Temp
);
186 FreePciDevice (Temp
);
191 CurrentLink
= CurrentLink
->ForwardLink
;
194 return EFI_NOT_FOUND
;
198 This function registers the PCI IO device. It creates a handle for this PCI IO device
199 (if the handle does not exist), attaches appropriate protocols onto the handle, does
200 necessary initialization, and sets up parent/child relationship with its bus controller.
202 @param Controller - An EFI handle for the PCI bus controller.
203 @param PciIoDevice - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
204 @param Handle - A pointer to hold the EFI handle for the PCI IO device.
206 @retval EFI_SUCCESS - The PCI device is successfully registered.
207 @retval Others - An error occurred when registering the PCI device.
212 IN EFI_HANDLE Controller
,
213 IN PCI_IO_DEVICE
*PciIoDevice
,
214 OUT EFI_HANDLE
*Handle OPTIONAL
218 VOID
*PlatformOpRomBuffer
;
219 UINTN PlatformOpRomSize
;
220 UINT8 PciExpressCapRegOffset
;
221 EFI_PCI_IO_PROTOCOL
*PciIo
;
226 // Install the pciio protocol, device path protocol
228 Status
= gBS
->InstallMultipleProtocolInterfaces (
229 &PciIoDevice
->Handle
,
230 &gEfiDevicePathProtocolGuid
,
231 PciIoDevice
->DevicePath
,
232 &gEfiPciIoProtocolGuid
,
236 if (EFI_ERROR (Status
)) {
241 // Detect if PCI Express Device
243 PciExpressCapRegOffset
= 0;
244 Status
= LocateCapabilityRegBlock (
246 EFI_PCI_CAPABILITY_ID_PCIEXP
,
247 &PciExpressCapRegOffset
,
250 if (!EFI_ERROR (Status
)) {
251 PciIoDevice
->IsPciExp
= TRUE
;
255 // Force Interrupt line to "Unknown" or "No Connection"
257 PciIo
= &(PciIoDevice
->PciIo
);
258 Data8
= PCI_INT_LINE_UNKNOWN
;
259 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &Data8
);
264 if (!PciIoDevice
->AllOpRomProcessed
) {
267 // Get the OpRom provided by platform
269 if (gPciPlatformProtocol
!= NULL
) {
270 Status
= gPciPlatformProtocol
->GetPciRom (
271 gPciPlatformProtocol
,
273 &PlatformOpRomBuffer
,
276 if (!EFI_ERROR (Status
)) {
277 PciIoDevice
->RomSize
= PlatformOpRomSize
;
278 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
279 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
281 // For OpROM read from gPciPlatformProtocol:
282 // Add the Rom Image to internal database for later PCI light enumeration
284 PciRomAddImageMapping (
286 PciIoDevice
->PciRootBridgeIo
->SegmentNumber
,
287 PciIoDevice
->BusNumber
,
288 PciIoDevice
->DeviceNumber
,
289 PciIoDevice
->FunctionNumber
,
290 (UINT64
) (UINTN
) PciIoDevice
->PciIo
.RomImage
,
291 PciIoDevice
->PciIo
.RomSize
298 // Determine if there are EFI images in the option rom
300 HasEfiImage
= ContainEfiImage (PciIoDevice
->PciIo
.RomImage
, PciIoDevice
->PciIo
.RomSize
);
303 Status
= gBS
->InstallMultipleProtocolInterfaces (
304 &PciIoDevice
->Handle
,
305 &gEfiLoadFile2ProtocolGuid
,
306 &PciIoDevice
->LoadFile2
,
309 if (EFI_ERROR (Status
)) {
310 gBS
->UninstallMultipleProtocolInterfaces (
311 &PciIoDevice
->Handle
,
312 &gEfiDevicePathProtocolGuid
,
313 PciIoDevice
->DevicePath
,
314 &gEfiPciIoProtocolGuid
,
323 if (!PciIoDevice
->AllOpRomProcessed
) {
325 PciIoDevice
->AllOpRomProcessed
= TRUE
;
328 // Dispatch the EFI OpRom for the PCI device.
329 // The OpRom is got from platform in the above code
330 // or loaded from device in the previous round of bus enumeration
333 ProcessOpRomImage (PciIoDevice
);
337 if (PciIoDevice
->BusOverride
) {
339 // Install BusSpecificDriverOverride Protocol
341 Status
= gBS
->InstallMultipleProtocolInterfaces (
342 &PciIoDevice
->Handle
,
343 &gEfiBusSpecificDriverOverrideProtocolGuid
,
344 &PciIoDevice
->PciDriverOverride
,
347 if (EFI_ERROR (Status
)) {
348 gBS
->UninstallMultipleProtocolInterfaces (
349 &PciIoDevice
->Handle
,
350 &gEfiDevicePathProtocolGuid
,
351 PciIoDevice
->DevicePath
,
352 &gEfiPciIoProtocolGuid
,
357 gBS
->UninstallMultipleProtocolInterfaces (
358 &PciIoDevice
->Handle
,
359 &gEfiLoadFile2ProtocolGuid
,
360 &PciIoDevice
->LoadFile2
,
369 Status
= gBS
->OpenProtocol (
371 &gEfiPciRootBridgeIoProtocolGuid
,
372 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
373 gPciBusDriverBinding
.DriverBindingHandle
,
375 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
377 if (EFI_ERROR (Status
)) {
381 if (Handle
!= NULL
) {
382 *Handle
= PciIoDevice
->Handle
;
386 // Indicate the pci device is registered
388 PciIoDevice
->Registered
= TRUE
;
394 This function is used to remove the whole PCI devices from the bridge.
396 @param RootBridgeHandle An efi handle.
397 @param Bridge A pointer to the PCI_IO_DEVICE.
402 RemoveAllPciDeviceOnBridge (
403 EFI_HANDLE RootBridgeHandle
,
404 PCI_IO_DEVICE
*Bridge
409 LIST_ENTRY
*CurrentLink
;
412 while (!IsListEmpty (&Bridge
->ChildList
)) {
414 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
415 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
418 // Check if the current node has been deregistered before
419 // If it is not, then deregister it
421 if (Temp
->Registered
) {
422 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
426 // Remove this node from the linked list
428 RemoveEntryList (CurrentLink
);
430 if (!IsListEmpty (&Temp
->ChildList
)) {
431 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
434 FreePciDevice (Temp
);
442 This function is used to de-register the PCI device from the EFI,
443 That includes un-installing PciIo protocol from the specified PCI
446 @param Controller - controller handle
447 @param Handle - device handle
449 @return Status of de-register pci device
452 DeRegisterPciDevice (
453 IN EFI_HANDLE Controller
,
458 EFI_PCI_IO_PROTOCOL
*PciIo
;
460 PCI_IO_DEVICE
*PciIoDevice
;
462 LIST_ENTRY
*CurrentLink
;
463 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
465 Status
= gBS
->OpenProtocol (
467 &gEfiPciIoProtocolGuid
,
469 gPciBusDriverBinding
.DriverBindingHandle
,
471 EFI_OPEN_PROTOCOL_GET_PROTOCOL
473 if (!EFI_ERROR (Status
)) {
474 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
477 // If it is already de-registered
479 if (!PciIoDevice
->Registered
) {
484 // If it is PPB, first de-register its children
487 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
489 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
491 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
492 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
493 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
495 if (EFI_ERROR (Status
)) {
499 CurrentLink
= CurrentLink
->ForwardLink
;
504 // Close the child handle
506 Status
= gBS
->CloseProtocol (
508 &gEfiPciRootBridgeIoProtocolGuid
,
509 gPciBusDriverBinding
.DriverBindingHandle
,
514 // Un-install the device path protocol and pci io protocol
516 if (PciIoDevice
->BusOverride
) {
517 Status
= gBS
->UninstallMultipleProtocolInterfaces (
519 &gEfiDevicePathProtocolGuid
,
520 PciIoDevice
->DevicePath
,
521 &gEfiPciIoProtocolGuid
,
523 &gEfiBusSpecificDriverOverrideProtocolGuid
,
524 &PciIoDevice
->PciDriverOverride
,
528 Status
= gBS
->UninstallMultipleProtocolInterfaces (
530 &gEfiDevicePathProtocolGuid
,
531 PciIoDevice
->DevicePath
,
532 &gEfiPciIoProtocolGuid
,
538 if (!EFI_ERROR (Status
)) {
540 // Try to uninstall LoadFile2 protocol if exists
542 Status
= gBS
->OpenProtocol (
544 &gEfiLoadFile2ProtocolGuid
,
546 gPciBusDriverBinding
.DriverBindingHandle
,
548 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
550 if (!EFI_ERROR (Status
)) {
551 Status
= gBS
->UninstallMultipleProtocolInterfaces (
553 &gEfiLoadFile2ProtocolGuid
,
554 &PciIoDevice
->LoadFile2
,
561 Status
= EFI_SUCCESS
;
565 if (EFI_ERROR (Status
)) {
568 &gEfiPciRootBridgeIoProtocolGuid
,
569 (VOID
**) &PciRootBridgeIo
,
570 gPciBusDriverBinding
.DriverBindingHandle
,
572 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
578 // The Device Driver should disable this device after disconnect
579 // so the Pci Bus driver will not touch this device any more.
580 // Restore the register field to the original value
582 PciIoDevice
->Registered
= FALSE
;
583 PciIoDevice
->Handle
= NULL
;
587 // Handle may be closed before
596 Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
598 @param Controller An efi handle.
599 @param RootBridge A pointer to the PCI_IO_DEVICE.
600 @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
601 @param NumberOfChildren Children number.
602 @param ChildHandleBuffer A pointer to the child handle buffer.
604 @retval EFI_NOT_READY Device is not allocated
605 @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
606 @retval EFI_NOT_FOUND Can not find the specific device
607 @retval EFI_SUCCESS Success to start Pci device on bridge
611 StartPciDevicesOnBridge (
612 IN EFI_HANDLE Controller
,
613 IN PCI_IO_DEVICE
*RootBridge
,
614 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
615 IN OUT UINT8
*NumberOfChildren
,
616 IN OUT EFI_HANDLE
*ChildHandleBuffer
620 PCI_IO_DEVICE
*PciIoDevice
;
621 EFI_DEV_PATH_PTR Node
;
622 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
624 LIST_ENTRY
*CurrentLink
;
627 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
629 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
631 PciIoDevice
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
632 if (RemainingDevicePath
!= NULL
) {
634 Node
.DevPath
= RemainingDevicePath
;
636 if (Node
.Pci
->Device
!= PciIoDevice
->DeviceNumber
||
637 Node
.Pci
->Function
!= PciIoDevice
->FunctionNumber
) {
638 CurrentLink
= CurrentLink
->ForwardLink
;
643 // Check if the device has been assigned with required resource
645 if (!PciIoDevice
->Allocated
) {
646 return EFI_NOT_READY
;
650 // Check if the current node has been registered before
651 // If it is not, register it
653 if (!PciIoDevice
->Registered
) {
654 Status
= RegisterPciDevice (
662 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
663 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
664 (*NumberOfChildren
)++;
668 // Get the next device path
670 CurrentDevicePath
= NextDevicePathNode (RemainingDevicePath
);
671 if (IsDevicePathEnd (CurrentDevicePath
)) {
678 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
679 Status
= StartPciDevicesOnBridge (
687 PciIoDevice
->PciIo
.Attributes (
688 &(PciIoDevice
->PciIo
),
689 EfiPciIoAttributeOperationSupported
,
693 Supports
&= EFI_PCI_DEVICE_ENABLE
;
694 PciIoDevice
->PciIo
.Attributes (
695 &(PciIoDevice
->PciIo
),
696 EfiPciIoAttributeOperationEnable
,
705 // Currently, the PCI bus driver only support PCI-PCI bridge
707 return EFI_UNSUPPORTED
;
713 // If remaining device path is NULL,
714 // try to enable all the pci devices under this bridge
717 if (!PciIoDevice
->Registered
&& PciIoDevice
->Allocated
) {
718 Status
= RegisterPciDevice (
726 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
727 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
728 (*NumberOfChildren
)++;
731 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
732 Status
= StartPciDevicesOnBridge (
740 PciIoDevice
->PciIo
.Attributes (
741 &(PciIoDevice
->PciIo
),
742 EfiPciIoAttributeOperationSupported
,
746 Supports
&= EFI_PCI_DEVICE_ENABLE
;
747 PciIoDevice
->PciIo
.Attributes (
748 &(PciIoDevice
->PciIo
),
749 EfiPciIoAttributeOperationEnable
,
756 CurrentLink
= CurrentLink
->ForwardLink
;
760 return EFI_NOT_FOUND
;
764 Start to manage all the PCI devices it found previously under
765 the entire host bridge.
767 @param Controller - root bridge handle.
772 IN EFI_HANDLE Controller
776 PCI_IO_DEVICE
*RootBridge
;
777 EFI_HANDLE ThisHostBridge
;
778 LIST_ENTRY
*CurrentLink
;
780 RootBridge
= GetRootBridgeByHandle (Controller
);
781 ASSERT (RootBridge
!= NULL
);
782 ThisHostBridge
= RootBridge
->PciRootBridgeIo
->ParentHandle
;
784 CurrentLink
= gPciDevicePool
.ForwardLink
;
786 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
788 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
790 // Locate the right root bridge to start
792 if (RootBridge
->PciRootBridgeIo
->ParentHandle
== ThisHostBridge
) {
793 StartPciDevicesOnBridge (
802 CurrentLink
= CurrentLink
->ForwardLink
;
809 Create root bridge device
811 @param RootBridgeHandle - Parent bridge handle.
813 @return pointer to new root bridge
817 IN EFI_HANDLE RootBridgeHandle
823 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
824 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
827 Status
= gBS
->AllocatePool (
829 sizeof (PCI_IO_DEVICE
),
833 if (EFI_ERROR (Status
)) {
837 ZeroMem (Dev
, sizeof (PCI_IO_DEVICE
));
838 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
839 Dev
->Handle
= RootBridgeHandle
;
840 InitializeListHead (&Dev
->ChildList
);
842 Status
= gBS
->OpenProtocol (
844 &gEfiDevicePathProtocolGuid
,
845 (VOID
**) &ParentDevicePath
,
846 gPciBusDriverBinding
.DriverBindingHandle
,
848 EFI_OPEN_PROTOCOL_GET_PROTOCOL
851 if (EFI_ERROR (Status
)) {
857 // Record the root bridge parent device path
859 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
862 // Get the pci root bridge io protocol
864 Status
= gBS
->OpenProtocol (
866 &gEfiPciRootBridgeIoProtocolGuid
,
867 (VOID
**) &PciRootBridgeIo
,
868 gPciBusDriverBinding
.DriverBindingHandle
,
870 EFI_OPEN_PROTOCOL_GET_PROTOCOL
873 if (EFI_ERROR (Status
)) {
878 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
881 // Initialize the PCI I/O instance structure
883 InitializePciIoInstance (Dev
);
884 InitializePciDriverOverrideInstance (Dev
);
885 InitializePciLoadFile2 (Dev
);
888 // Initialize reserved resource list and
889 // option rom driver list
891 InitializeListHead (&Dev
->ReservedResourceList
);
892 InitializeListHead (&Dev
->OptionRomDriverList
);
898 Get root bridge device instance by specific handle.
900 @param RootBridgeHandle Given root bridge handle.
902 @return root bridge device instance.
905 GetRootBridgeByHandle (
906 EFI_HANDLE RootBridgeHandle
909 PCI_IO_DEVICE
*RootBridgeDev
;
910 LIST_ENTRY
*CurrentLink
;
912 CurrentLink
= gPciDevicePool
.ForwardLink
;
914 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
916 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
917 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
918 return RootBridgeDev
;
921 CurrentLink
= CurrentLink
->ForwardLink
;
928 Judege whether Pci device existed.
930 @param Bridge Parent bridege instance.
931 @param PciIoDevice Device instance.
933 @return whether Pci device existed.
937 IN PCI_IO_DEVICE
*Bridge
,
938 IN PCI_IO_DEVICE
*PciIoDevice
943 LIST_ENTRY
*CurrentLink
;
945 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
947 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
949 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
951 if (Temp
== PciIoDevice
) {
955 if (!IsListEmpty (&Temp
->ChildList
)) {
956 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
961 CurrentLink
= CurrentLink
->ForwardLink
;
970 @param VgaDevice device instance for VGA.
972 @return device instance.
975 ActiveVGADeviceOnTheSameSegment (
976 IN PCI_IO_DEVICE
*VgaDevice
979 LIST_ENTRY
*CurrentLink
;
982 CurrentLink
= gPciDevicePool
.ForwardLink
;
984 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
986 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
988 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
990 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
997 CurrentLink
= CurrentLink
->ForwardLink
;
1004 Active VGA device on root bridge.
1006 @param RootBridge Root bridge device instance.
1008 @return VGA device instance.
1011 ActiveVGADeviceOnTheRootBridge (
1012 IN PCI_IO_DEVICE
*RootBridge
1015 LIST_ENTRY
*CurrentLink
;
1016 PCI_IO_DEVICE
*Temp
;
1018 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1020 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1022 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1024 if (IS_PCI_VGA(&Temp
->Pci
) &&
1026 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
|
1027 EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1028 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) != 0) {
1032 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
1034 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1041 CurrentLink
= CurrentLink
->ForwardLink
;
1048 Get HPC PCI address according to its device path.
1049 @param PciRootBridgeIo Root bridege Io instance.
1050 @param HpcDevicePath Given searching device path.
1051 @param PciAddress Buffer holding searched result.
1053 @retval EFI_NOT_FOUND Can not find the specific device path.
1054 @retval EFI_SUCCESS Success to get the device path.
1058 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1059 IN EFI_DEVICE_PATH_PROTOCOL
*HpcDevicePath
,
1060 OUT UINT64
*PciAddress
1063 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1064 EFI_DEV_PATH_PTR Node
;
1065 LIST_ENTRY
*CurrentLink
;
1066 PCI_IO_DEVICE
*RootBridge
;
1069 CurrentDevicePath
= HpcDevicePath
;
1072 // Get the remaining device path for this PCI device, if it is a PCI device
1074 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1076 Node
.DevPath
= CurrentDevicePath
;
1079 // Check if it is PCI device Path?
1081 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
1082 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
1083 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))) {
1084 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1092 // Check if it is not PCI device path
1094 if (IsDevicePathEnd (CurrentDevicePath
)) {
1095 return EFI_NOT_FOUND
;
1098 CurrentLink
= gPciDevicePool
.ForwardLink
;
1100 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
1102 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1104 // Locate the right root bridge to start
1106 if (RootBridge
->PciRootBridgeIo
== PciRootBridgeIo
) {
1107 Status
= GetHpcPciAddressFromRootBridge (
1112 if (EFI_ERROR (Status
)) {
1113 return EFI_NOT_FOUND
;
1120 CurrentLink
= CurrentLink
->ForwardLink
;
1123 return EFI_NOT_FOUND
;
1127 Get HPC PCI address according to its device path.
1128 @param RootBridge Root bridege Io instance.
1129 @param RemainingDevicePath Given searching device path.
1130 @param PciAddress Buffer holding searched result.
1132 @retval EFI_NOT_FOUND Can not find the specific device path.
1135 GetHpcPciAddressFromRootBridge (
1136 IN PCI_IO_DEVICE
*RootBridge
,
1137 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1138 OUT UINT64
*PciAddress
1141 EFI_DEV_PATH_PTR Node
;
1142 PCI_IO_DEVICE
*Temp
;
1143 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1144 LIST_ENTRY
*CurrentLink
;
1149 CurrentDevicePath
= RemainingDevicePath
;
1150 Node
.DevPath
= CurrentDevicePath
;
1153 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1155 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1156 Node
.DevPath
= CurrentDevicePath
;
1158 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1159 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1161 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1162 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1167 CurrentLink
= CurrentLink
->ForwardLink
;
1171 // Check if we find the bridge
1173 if (CurrentLink
== &RootBridge
->ChildList
) {
1180 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1185 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1187 if (IsDevicePathEnd (CurrentDevicePath
)) {
1188 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1192 return EFI_NOT_FOUND
;
1196 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1198 return EFI_NOT_FOUND
;