2 Supporting functions implementaion for PCI devices management.
4 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
5 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.
18 // This device structure is serviced as a header.
19 // Its next field points to the first root bridge device node.
21 LIST_ENTRY mPciDevicePool
;
24 Disable Bus Master Enable bit in all devices in the list.
26 @param Devices A device list.
30 IN LIST_ENTRY
*Devices
34 PCI_IO_DEVICE
*PciIoDevice
;
37 for ( Link
= GetFirstNode (Devices
)
38 ; !IsNull (Devices
, Link
)
39 ; Link
= GetNextNode (Devices
, Link
)
41 PciIoDevice
= PCI_IO_DEVICE_FROM_LINK (Link
);
43 // Turn off all children's Bus Master, if any
45 DisableBmeOnTree (&PciIoDevice
->ChildList
);
48 // If this is a device that supports BME, disable BME on this device.
50 if ((PciIoDevice
->Supports
& EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
) != 0) {
51 PCI_READ_COMMAND_REGISTER(PciIoDevice
, &Command
);
52 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
53 Command
&= ~EFI_PCI_COMMAND_BUS_MASTER
;
54 PCI_SET_COMMAND_REGISTER (PciIoDevice
, Command
);
56 DEBUG_INFO
," %02x %02x %02x %04x\n",
57 PciIoDevice
->BusNumber
, PciIoDevice
->DeviceNumber
, PciIoDevice
->FunctionNumber
,
66 Exit Boot Services Event notification handler.
68 Disable Bus Master on any that were enabled during BDS.
70 @param[in] Event Event whose notification function is being invoked.
71 @param[in] Context Pointer to the notification function's context.
83 "PciBus: Disable Bus Master of all devices...\n"
84 " Bus# Device# Function# NewCommand\n"
86 DisableBmeOnTree(&mPciDevicePool
);
90 Initialize the PCI devices pool.
94 InitializePciDevicePool (
98 EFI_EVENT ExitBootServicesEvent
;
101 InitializeListHead (&mPciDevicePool
);
104 // DisableBME on ExitBootServices should be synchonized with any IOMMU ExitBootServices routine.
105 // DisableBME should be run before the IOMMU protections are disabled.
106 // One way to do this is to ensure that the IOMMU ExitBootServices callback runs at TPL_CALLBACK.
108 Status
= gBS
->CreateEventEx (
113 &gEfiEventExitBootServicesGuid
,
114 &ExitBootServicesEvent
116 if (EFI_ERROR (Status
)) {
117 DEBUG ((DEBUG_ERROR
, "PciBus: Unable to hook ExitBootServices event - %r\n", Status
));
122 Insert a root bridge into PCI device pool.
124 @param RootBridge A pointer to the PCI_IO_DEVICE.
129 IN PCI_IO_DEVICE
*RootBridge
132 InsertTailList (&mPciDevicePool
, &(RootBridge
->Link
));
136 This function is used to insert a PCI device node under
139 @param Bridge The PCI bridge.
140 @param PciDeviceNode The PCI device needs inserting.
145 IN PCI_IO_DEVICE
*Bridge
,
146 IN PCI_IO_DEVICE
*PciDeviceNode
149 InsertTailList (&Bridge
->ChildList
, &(PciDeviceNode
->Link
));
150 PciDeviceNode
->Parent
= Bridge
;
154 Destroy root bridge and remove it from deivce tree.
156 @param RootBridge The bridge want to be removed.
161 IN PCI_IO_DEVICE
*RootBridge
164 DestroyPciDeviceTree (RootBridge
);
166 FreePciDevice (RootBridge
);
170 Destroy a pci device node.
172 All direct or indirect allocated resource for this node will be freed.
174 @param PciIoDevice A pointer to the PCI_IO_DEVICE to be destoried.
179 IN PCI_IO_DEVICE
*PciIoDevice
182 ASSERT (PciIoDevice
!= NULL
);
184 // Assume all children have been removed underneath this device
186 if (PciIoDevice
->ResourcePaddingDescriptors
!= NULL
) {
187 FreePool (PciIoDevice
->ResourcePaddingDescriptors
);
190 if (PciIoDevice
->DevicePath
!= NULL
) {
191 FreePool (PciIoDevice
->DevicePath
);
194 FreePool (PciIoDevice
);
198 Destroy all the pci device node under the bridge.
199 Bridge itself is not included.
201 @param Bridge A pointer to the PCI_IO_DEVICE.
205 DestroyPciDeviceTree (
206 IN PCI_IO_DEVICE
*Bridge
209 LIST_ENTRY
*CurrentLink
;
212 while (!IsListEmpty (&Bridge
->ChildList
)) {
214 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
217 // Remove this node from the linked list
219 RemoveEntryList (CurrentLink
);
221 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
223 if (!IsListEmpty (&Temp
->ChildList
)) {
224 DestroyPciDeviceTree (Temp
);
227 FreePciDevice (Temp
);
232 Destroy all device nodes under the root bridge
233 specified by Controller.
235 The root bridge itself is also included.
237 @param Controller Root bridge handle.
239 @retval EFI_SUCCESS Destory all devcie nodes successfully.
240 @retval EFI_NOT_FOUND Cannot find any PCI device under specified
245 DestroyRootBridgeByHandle (
246 IN EFI_HANDLE Controller
250 LIST_ENTRY
*CurrentLink
;
253 CurrentLink
= mPciDevicePool
.ForwardLink
;
255 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
256 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
258 if (Temp
->Handle
== Controller
) {
260 RemoveEntryList (CurrentLink
);
262 DestroyPciDeviceTree (Temp
);
264 FreePciDevice (Temp
);
269 CurrentLink
= CurrentLink
->ForwardLink
;
272 return EFI_NOT_FOUND
;
276 This function registers the PCI IO device.
278 It creates a handle for this PCI IO device (if the handle does not exist), attaches
279 appropriate protocols onto the handle, does necessary initialization, and sets up
280 parent/child relationship with its bus controller.
282 @param Controller An EFI handle for the PCI bus controller.
283 @param PciIoDevice A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
284 @param Handle A pointer to hold the returned EFI handle for the PCI IO device.
286 @retval EFI_SUCCESS The PCI device is successfully registered.
287 @retval other An error occurred when registering the PCI device.
292 IN EFI_HANDLE Controller
,
293 IN PCI_IO_DEVICE
*PciIoDevice
,
294 OUT EFI_HANDLE
*Handle OPTIONAL
298 VOID
*PlatformOpRomBuffer
;
299 UINTN PlatformOpRomSize
;
300 UINT8 PciExpressCapRegOffset
;
301 EFI_PCI_IO_PROTOCOL
*PciIo
;
306 // Install the pciio protocol, device path protocol
308 Status
= gBS
->InstallMultipleProtocolInterfaces (
309 &PciIoDevice
->Handle
,
310 &gEfiDevicePathProtocolGuid
,
311 PciIoDevice
->DevicePath
,
312 &gEfiPciIoProtocolGuid
,
316 if (EFI_ERROR (Status
)) {
321 // Detect if PCI Express Device
323 PciExpressCapRegOffset
= 0;
324 Status
= LocateCapabilityRegBlock (
326 EFI_PCI_CAPABILITY_ID_PCIEXP
,
327 &PciExpressCapRegOffset
,
330 if (!EFI_ERROR (Status
)) {
331 PciIoDevice
->IsPciExp
= TRUE
;
335 // Force Interrupt line to "Unknown" or "No Connection"
337 PciIo
= &(PciIoDevice
->PciIo
);
338 Data8
= PCI_INT_LINE_UNKNOWN
;
339 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &Data8
);
344 if (!PciIoDevice
->AllOpRomProcessed
) {
347 // Get the OpRom provided by platform
349 if (gPciPlatformProtocol
!= NULL
) {
350 Status
= gPciPlatformProtocol
->GetPciRom (
351 gPciPlatformProtocol
,
353 &PlatformOpRomBuffer
,
356 if (!EFI_ERROR (Status
)) {
357 PciIoDevice
->EmbeddedRom
= FALSE
;
358 PciIoDevice
->RomSize
= PlatformOpRomSize
;
359 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
360 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
362 // For OpROM read from gPciPlatformProtocol:
363 // Add the Rom Image to internal database for later PCI light enumeration
365 PciRomAddImageMapping (
367 PciIoDevice
->PciRootBridgeIo
->SegmentNumber
,
368 PciIoDevice
->BusNumber
,
369 PciIoDevice
->DeviceNumber
,
370 PciIoDevice
->FunctionNumber
,
371 PciIoDevice
->PciIo
.RomImage
,
372 PciIoDevice
->PciIo
.RomSize
375 } else if (gPciOverrideProtocol
!= NULL
) {
376 Status
= gPciOverrideProtocol
->GetPciRom (
377 gPciOverrideProtocol
,
379 &PlatformOpRomBuffer
,
382 if (!EFI_ERROR (Status
)) {
383 PciIoDevice
->EmbeddedRom
= FALSE
;
384 PciIoDevice
->RomSize
= PlatformOpRomSize
;
385 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
386 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
388 // For OpROM read from gPciOverrideProtocol:
389 // Add the Rom Image to internal database for later PCI light enumeration
391 PciRomAddImageMapping (
393 PciIoDevice
->PciRootBridgeIo
->SegmentNumber
,
394 PciIoDevice
->BusNumber
,
395 PciIoDevice
->DeviceNumber
,
396 PciIoDevice
->FunctionNumber
,
397 PciIoDevice
->PciIo
.RomImage
,
398 PciIoDevice
->PciIo
.RomSize
405 // Determine if there are EFI images in the option rom
407 HasEfiImage
= ContainEfiImage (PciIoDevice
->PciIo
.RomImage
, PciIoDevice
->PciIo
.RomSize
);
410 Status
= gBS
->InstallMultipleProtocolInterfaces (
411 &PciIoDevice
->Handle
,
412 &gEfiLoadFile2ProtocolGuid
,
413 &PciIoDevice
->LoadFile2
,
416 if (EFI_ERROR (Status
)) {
417 gBS
->UninstallMultipleProtocolInterfaces (
418 &PciIoDevice
->Handle
,
419 &gEfiDevicePathProtocolGuid
,
420 PciIoDevice
->DevicePath
,
421 &gEfiPciIoProtocolGuid
,
430 if (!PciIoDevice
->AllOpRomProcessed
) {
432 PciIoDevice
->AllOpRomProcessed
= TRUE
;
435 // Dispatch the EFI OpRom for the PCI device.
436 // The OpRom is got from platform in the above code
437 // or loaded from device in the previous round of bus enumeration
440 ProcessOpRomImage (PciIoDevice
);
444 if (PciIoDevice
->BusOverride
) {
446 // Install Bus Specific Driver Override Protocol
448 Status
= gBS
->InstallMultipleProtocolInterfaces (
449 &PciIoDevice
->Handle
,
450 &gEfiBusSpecificDriverOverrideProtocolGuid
,
451 &PciIoDevice
->PciDriverOverride
,
454 if (EFI_ERROR (Status
)) {
455 gBS
->UninstallMultipleProtocolInterfaces (
456 &PciIoDevice
->Handle
,
457 &gEfiDevicePathProtocolGuid
,
458 PciIoDevice
->DevicePath
,
459 &gEfiPciIoProtocolGuid
,
464 gBS
->UninstallMultipleProtocolInterfaces (
465 &PciIoDevice
->Handle
,
466 &gEfiLoadFile2ProtocolGuid
,
467 &PciIoDevice
->LoadFile2
,
476 Status
= gBS
->OpenProtocol (
478 &gEfiPciRootBridgeIoProtocolGuid
,
479 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
480 gPciBusDriverBinding
.DriverBindingHandle
,
482 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
484 if (EFI_ERROR (Status
)) {
488 if (Handle
!= NULL
) {
489 *Handle
= PciIoDevice
->Handle
;
493 // Indicate the pci device is registered
495 PciIoDevice
->Registered
= TRUE
;
501 This function is used to remove the whole PCI devices on the specified bridge from
504 @param RootBridgeHandle The root bridge device handle.
505 @param Bridge The bridge device to be removed.
509 RemoveAllPciDeviceOnBridge (
510 EFI_HANDLE RootBridgeHandle
,
511 PCI_IO_DEVICE
*Bridge
514 LIST_ENTRY
*CurrentLink
;
517 while (!IsListEmpty (&Bridge
->ChildList
)) {
519 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
520 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
523 // Check if the current node has been deregistered before
524 // If it is not, then deregister it
526 if (Temp
->Registered
) {
527 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
531 // Remove this node from the linked list
533 RemoveEntryList (CurrentLink
);
535 if (!IsListEmpty (&Temp
->ChildList
)) {
536 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
539 FreePciDevice (Temp
);
544 This function is used to de-register the PCI IO device.
546 That includes un-installing PciIo protocol from the specified PCI
549 @param Controller An EFI handle for the PCI bus controller.
550 @param Handle PCI device handle.
552 @retval EFI_SUCCESS The PCI device is successfully de-registered.
553 @retval other An error occurred when de-registering the PCI device.
557 DeRegisterPciDevice (
558 IN EFI_HANDLE Controller
,
563 EFI_PCI_IO_PROTOCOL
*PciIo
;
565 PCI_IO_DEVICE
*PciIoDevice
;
567 LIST_ENTRY
*CurrentLink
;
568 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
570 Status
= gBS
->OpenProtocol (
572 &gEfiPciIoProtocolGuid
,
574 gPciBusDriverBinding
.DriverBindingHandle
,
576 EFI_OPEN_PROTOCOL_GET_PROTOCOL
578 if (!EFI_ERROR (Status
)) {
579 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
582 // If it is already de-registered
584 if (!PciIoDevice
->Registered
) {
589 // If it is PPB, first de-register its children
592 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
594 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
596 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
597 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
598 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
600 if (EFI_ERROR (Status
)) {
604 CurrentLink
= CurrentLink
->ForwardLink
;
609 // Close the child handle
611 Status
= gBS
->CloseProtocol (
613 &gEfiPciRootBridgeIoProtocolGuid
,
614 gPciBusDriverBinding
.DriverBindingHandle
,
619 // Un-install the Device Path protocol and PCI I/O protocol
620 // and Bus Specific Driver Override protocol if needed.
622 if (PciIoDevice
->BusOverride
) {
623 Status
= gBS
->UninstallMultipleProtocolInterfaces (
625 &gEfiDevicePathProtocolGuid
,
626 PciIoDevice
->DevicePath
,
627 &gEfiPciIoProtocolGuid
,
629 &gEfiBusSpecificDriverOverrideProtocolGuid
,
630 &PciIoDevice
->PciDriverOverride
,
634 Status
= gBS
->UninstallMultipleProtocolInterfaces (
636 &gEfiDevicePathProtocolGuid
,
637 PciIoDevice
->DevicePath
,
638 &gEfiPciIoProtocolGuid
,
644 if (!EFI_ERROR (Status
)) {
646 // Try to uninstall LoadFile2 protocol if exists
648 Status
= gBS
->OpenProtocol (
650 &gEfiLoadFile2ProtocolGuid
,
652 gPciBusDriverBinding
.DriverBindingHandle
,
654 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
656 if (!EFI_ERROR (Status
)) {
657 Status
= gBS
->UninstallMultipleProtocolInterfaces (
659 &gEfiLoadFile2ProtocolGuid
,
660 &PciIoDevice
->LoadFile2
,
667 Status
= EFI_SUCCESS
;
671 if (EFI_ERROR (Status
)) {
674 &gEfiPciRootBridgeIoProtocolGuid
,
675 (VOID
**) &PciRootBridgeIo
,
676 gPciBusDriverBinding
.DriverBindingHandle
,
678 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
684 // The Device Driver should disable this device after disconnect
685 // so the Pci Bus driver will not touch this device any more.
686 // Restore the register field to the original value
688 PciIoDevice
->Registered
= FALSE
;
689 PciIoDevice
->Handle
= NULL
;
693 // Handle may be closed before
702 Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
704 @param Controller The root bridge handle.
705 @param RootBridge A pointer to the PCI_IO_DEVICE.
706 @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
707 @param NumberOfChildren Children number.
708 @param ChildHandleBuffer A pointer to the child handle buffer.
710 @retval EFI_NOT_READY Device is not allocated.
711 @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
712 @retval EFI_NOT_FOUND Can not find the specific device.
713 @retval EFI_SUCCESS Success to start Pci devices on bridge.
717 StartPciDevicesOnBridge (
718 IN EFI_HANDLE Controller
,
719 IN PCI_IO_DEVICE
*RootBridge
,
720 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
721 IN OUT UINT8
*NumberOfChildren
,
722 IN OUT EFI_HANDLE
*ChildHandleBuffer
726 PCI_IO_DEVICE
*PciIoDevice
;
727 EFI_DEV_PATH_PTR Node
;
728 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
730 LIST_ENTRY
*CurrentLink
;
734 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
736 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
738 PciIoDevice
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
739 if (RemainingDevicePath
!= NULL
) {
741 Node
.DevPath
= RemainingDevicePath
;
743 if (Node
.Pci
->Device
!= PciIoDevice
->DeviceNumber
||
744 Node
.Pci
->Function
!= PciIoDevice
->FunctionNumber
) {
745 CurrentLink
= CurrentLink
->ForwardLink
;
750 // Check if the device has been assigned with required resource
752 if (!PciIoDevice
->Allocated
) {
753 return EFI_NOT_READY
;
757 // Check if the current node has been registered before
758 // If it is not, register it
760 if (!PciIoDevice
->Registered
) {
761 Status
= RegisterPciDevice (
769 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
770 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
771 (*NumberOfChildren
)++;
775 // Get the next device path
777 CurrentDevicePath
= NextDevicePathNode (RemainingDevicePath
);
778 if (IsDevicePathEnd (CurrentDevicePath
)) {
785 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
786 Status
= StartPciDevicesOnBridge (
794 PciIoDevice
->PciIo
.Attributes (
795 &(PciIoDevice
->PciIo
),
796 EfiPciIoAttributeOperationSupported
,
801 // By default every bridge's IO and MMIO spaces are enabled.
802 // Bridge's Bus Master will be enabled when any device behind it requests
803 // to enable Bus Master.
805 Supports
&= (UINT64
) (EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
);
806 PciIoDevice
->PciIo
.Attributes (
807 &(PciIoDevice
->PciIo
),
808 EfiPciIoAttributeOperationEnable
,
817 // Currently, the PCI bus driver only support PCI-PCI bridge
819 return EFI_UNSUPPORTED
;
825 // If remaining device path is NULL,
826 // try to enable all the pci devices under this bridge
828 if (!PciIoDevice
->Registered
&& PciIoDevice
->Allocated
) {
829 Status
= RegisterPciDevice (
837 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
838 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
839 (*NumberOfChildren
)++;
842 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
843 Status
= StartPciDevicesOnBridge (
851 PciIoDevice
->PciIo
.Attributes (
852 &(PciIoDevice
->PciIo
),
853 EfiPciIoAttributeOperationSupported
,
858 // By default every bridge's IO and MMIO spaces are enabled.
859 // Bridge's Bus Master will be enabled when any device behind it requests
860 // to enable Bus Master.
862 Supports
&= (UINT64
) (EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
);
863 PciIoDevice
->PciIo
.Attributes (
864 &(PciIoDevice
->PciIo
),
865 EfiPciIoAttributeOperationEnable
,
872 CurrentLink
= CurrentLink
->ForwardLink
;
876 if (PciIoDevice
== NULL
) {
877 return EFI_NOT_FOUND
;
884 Start to manage all the PCI devices it found previously under
885 the entire host bridge.
887 @param Controller The root bridge handle.
889 @retval EFI_NOT_READY Device is not allocated.
890 @retval EFI_SUCCESS Success to start Pci device on host bridge.
895 IN EFI_HANDLE Controller
898 PCI_IO_DEVICE
*RootBridge
;
899 EFI_HANDLE ThisHostBridge
;
900 LIST_ENTRY
*CurrentLink
;
902 RootBridge
= GetRootBridgeByHandle (Controller
);
903 ASSERT (RootBridge
!= NULL
);
904 ThisHostBridge
= RootBridge
->PciRootBridgeIo
->ParentHandle
;
906 CurrentLink
= mPciDevicePool
.ForwardLink
;
908 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
910 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
912 // Locate the right root bridge to start
914 if (RootBridge
->PciRootBridgeIo
->ParentHandle
== ThisHostBridge
) {
915 StartPciDevicesOnBridge (
924 CurrentLink
= CurrentLink
->ForwardLink
;
931 Create root bridge device.
933 @param RootBridgeHandle Specified root bridge hanle.
935 @return The crated root bridge device instance, NULL means no
936 root bridge device instance created.
941 IN EFI_HANDLE RootBridgeHandle
946 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
947 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
949 Dev
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
954 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
955 Dev
->Handle
= RootBridgeHandle
;
956 InitializeListHead (&Dev
->ChildList
);
958 Status
= gBS
->OpenProtocol (
960 &gEfiDevicePathProtocolGuid
,
961 (VOID
**) &ParentDevicePath
,
962 gPciBusDriverBinding
.DriverBindingHandle
,
964 EFI_OPEN_PROTOCOL_GET_PROTOCOL
967 if (EFI_ERROR (Status
)) {
973 // Record the root bridge parent device path
975 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
978 // Get the pci root bridge io protocol
980 Status
= gBS
->OpenProtocol (
982 &gEfiPciRootBridgeIoProtocolGuid
,
983 (VOID
**) &PciRootBridgeIo
,
984 gPciBusDriverBinding
.DriverBindingHandle
,
986 EFI_OPEN_PROTOCOL_GET_PROTOCOL
989 if (EFI_ERROR (Status
)) {
994 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
997 // Initialize the PCI I/O instance structure
999 InitializePciIoInstance (Dev
);
1000 InitializePciDriverOverrideInstance (Dev
);
1001 InitializePciLoadFile2 (Dev
);
1004 // Initialize reserved resource list and
1005 // option rom driver list
1007 InitializeListHead (&Dev
->ReservedResourceList
);
1008 InitializeListHead (&Dev
->OptionRomDriverList
);
1014 Get root bridge device instance by specific root bridge handle.
1016 @param RootBridgeHandle Given root bridge handle.
1018 @return The root bridge device instance, NULL means no root bridge
1019 device instance found.
1023 GetRootBridgeByHandle (
1024 EFI_HANDLE RootBridgeHandle
1027 PCI_IO_DEVICE
*RootBridgeDev
;
1028 LIST_ENTRY
*CurrentLink
;
1030 CurrentLink
= mPciDevicePool
.ForwardLink
;
1032 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
1034 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1035 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
1036 return RootBridgeDev
;
1039 CurrentLink
= CurrentLink
->ForwardLink
;
1046 Judege whether Pci device existed.
1048 @param Bridge Parent bridege instance.
1049 @param PciIoDevice Device instance.
1051 @retval TRUE Pci device existed.
1052 @retval FALSE Pci device did not exist.
1057 IN PCI_IO_DEVICE
*Bridge
,
1058 IN PCI_IO_DEVICE
*PciIoDevice
1062 PCI_IO_DEVICE
*Temp
;
1063 LIST_ENTRY
*CurrentLink
;
1065 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1067 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1069 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1071 if (Temp
== PciIoDevice
) {
1075 if (!IsListEmpty (&Temp
->ChildList
)) {
1076 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
1081 CurrentLink
= CurrentLink
->ForwardLink
;
1088 Get the active VGA device on the same segment.
1090 @param VgaDevice PCI IO instance for the VGA device.
1092 @return The active VGA device on the same segment.
1096 ActiveVGADeviceOnTheSameSegment (
1097 IN PCI_IO_DEVICE
*VgaDevice
1100 LIST_ENTRY
*CurrentLink
;
1101 PCI_IO_DEVICE
*Temp
;
1103 CurrentLink
= mPciDevicePool
.ForwardLink
;
1105 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
1107 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1109 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
1111 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1118 CurrentLink
= CurrentLink
->ForwardLink
;
1125 Get the active VGA device on the root bridge.
1127 @param RootBridge PCI IO instance for the root bridge.
1129 @return The active VGA device.
1133 ActiveVGADeviceOnTheRootBridge (
1134 IN PCI_IO_DEVICE
*RootBridge
1137 LIST_ENTRY
*CurrentLink
;
1138 PCI_IO_DEVICE
*Temp
;
1140 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1142 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1144 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1146 if (IS_PCI_VGA(&Temp
->Pci
) &&
1148 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
|
1149 EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1150 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) != 0) {
1154 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
1156 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1163 CurrentLink
= CurrentLink
->ForwardLink
;
1171 Get HPC PCI address according to its device path.
1173 @param RootBridge Root bridege Io instance.
1174 @param RemainingDevicePath Given searching device path.
1175 @param PciAddress Buffer holding searched result.
1177 @retval EFI_SUCCESS PCI address was stored in PciAddress
1178 @retval EFI_NOT_FOUND Can not find the specific device path.
1182 GetHpcPciAddressFromRootBridge (
1183 IN PCI_IO_DEVICE
*RootBridge
,
1184 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1185 OUT UINT64
*PciAddress
1188 EFI_DEV_PATH_PTR Node
;
1189 PCI_IO_DEVICE
*Temp
;
1190 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1191 LIST_ENTRY
*CurrentLink
;
1196 CurrentDevicePath
= RemainingDevicePath
;
1197 Node
.DevPath
= CurrentDevicePath
;
1200 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1202 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1203 Node
.DevPath
= CurrentDevicePath
;
1205 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1206 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1208 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1209 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1214 CurrentLink
= CurrentLink
->ForwardLink
;
1218 // Check if we find the bridge
1220 if (CurrentLink
== &RootBridge
->ChildList
) {
1227 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1232 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1234 if (IsDevicePathEnd (CurrentDevicePath
)) {
1235 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1239 return EFI_NOT_FOUND
;
1243 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1245 return EFI_NOT_FOUND
;