2 Scan the entire PCI bus for root bridges to support coreboot UEFI payload.
4 Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <IndustryStandard/Pci.h>
12 #include <Protocol/PciHostBridgeResourceAllocation.h>
13 #include <Protocol/PciRootBridgeIo.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/PciHostBridgeLib.h>
18 #include <Library/PciLib.h>
19 #include "PciHostBridge.h"
22 Probe a bar is existed or not.
24 @param[in] Address PCI address for the BAR.
25 @param[out] OriginalValue The original bar value returned.
26 @param[out] Value The probed bar value returned.
30 PcatPciRootBridgeBarExisted (
32 OUT UINT32
*OriginalValue
,
37 // Preserve the original value
39 *OriginalValue
= PciRead32 (Address
);
42 // Disable timer interrupt while the BAR is probed
46 PciWrite32 (Address
, 0xFFFFFFFF);
47 *Value
= PciRead32 (Address
);
48 PciWrite32 (Address
, *OriginalValue
);
57 Parse PCI bar and collect the assigned PCI resource information.
59 @param[in] Command Supported attributes.
61 @param[in] Bus PCI bus number.
63 @param[in] Device PCI device number.
65 @param[in] Function PCI function number.
67 @param[in] BarOffsetBase PCI bar start offset.
69 @param[in] BarOffsetEnd PCI bar end offset.
71 @param[in] Io IO aperture.
73 @param[in] Mem MMIO aperture.
75 @param[in] MemAbove4G MMIO aperture above 4G.
77 @param[in] PMem Prefetchable MMIO aperture.
79 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
83 PcatPciRootBridgeParseBars (
88 IN UINTN BarOffsetBase
,
89 IN UINTN BarOffsetEnd
,
90 IN PCI_ROOT_BRIDGE_APERTURE
*Io
,
91 IN PCI_ROOT_BRIDGE_APERTURE
*Mem
,
92 IN PCI_ROOT_BRIDGE_APERTURE
*MemAbove4G
98 UINT32 OriginalUpperValue
;
106 PCI_ROOT_BRIDGE_APERTURE
*MemAperture
;
108 for (Offset
= BarOffsetBase
; Offset
< BarOffsetEnd
; Offset
+= sizeof (UINT32
)) {
109 PcatPciRootBridgeBarExisted (
110 PCI_LIB_ADDRESS (Bus
, Device
, Function
, Offset
),
118 if ((Value
& BIT0
) == BIT0
) {
122 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
124 Base
= OriginalValue
& Mask
;
125 Length
= ((~(Value
& Mask
)) & Mask
) + 0x04;
126 if (!(Value
& 0xFFFF0000)) {
127 Length
&= 0x0000FFFF;
130 Limit
= Base
+ Length
- 1;
132 if ((Base
> 0) && (Base
< Limit
)) {
133 if (Io
->Base
> Base
) {
137 if (Io
->Limit
< Limit
) {
146 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
148 Base
= OriginalValue
& Mask
;
149 Length
= Value
& Mask
;
151 if ((Value
& (BIT1
| BIT2
)) == 0) {
155 Length
= ((~Length
) + 1) & 0xffffffff;
163 PcatPciRootBridgeBarExisted (
164 PCI_LIB_ADDRESS (Bus
, Device
, Function
, Offset
),
169 Base
= Base
| LShiftU64 ((UINT64
)OriginalUpperValue
, 32);
170 Length
= Length
| LShiftU64 ((UINT64
)UpperValue
, 32);
172 LowBit
= LowBitSet64 (Length
);
173 Length
= LShiftU64 (1ULL, LowBit
);
176 if (Base
< BASE_4GB
) {
179 MemAperture
= MemAbove4G
;
183 Limit
= Base
+ Length
- 1;
184 if ((Base
> 0) && (Base
< Limit
)) {
185 if (MemAperture
->Base
> Base
) {
186 MemAperture
->Base
= Base
;
189 if (MemAperture
->Limit
< Limit
) {
190 MemAperture
->Limit
= Limit
;
198 STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture
= { MAX_UINT64
, 0 };
201 Scan for all root bridges in platform.
203 @param[out] NumberOfRootBridges Number of root bridges detected
205 @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.
209 OUT UINTN
*NumberOfRootBridges
216 UINTN NumberOfDevices
;
223 PCI_ROOT_BRIDGE_APERTURE Io
;
224 PCI_ROOT_BRIDGE_APERTURE Mem
;
225 PCI_ROOT_BRIDGE_APERTURE MemAbove4G
;
226 PCI_ROOT_BRIDGE_APERTURE
*MemAperture
;
227 PCI_ROOT_BRIDGE
*RootBridges
;
230 *NumberOfRootBridges
= 0;
234 // After scanning all the PCI devices on the PCI root bridge's primary bus,
235 // update the Primary Bus Number for the next PCI root bridge to be this PCI
236 // root bridge's subordinate bus number + 1.
238 for (PrimaryBus
= 0; PrimaryBus
<= PCI_MAX_BUS
; PrimaryBus
= SubBus
+ 1) {
242 ZeroMem (&Io
, sizeof (Io
));
243 ZeroMem (&Mem
, sizeof (Mem
));
244 ZeroMem (&MemAbove4G
, sizeof (MemAbove4G
));
245 Io
.Base
= Mem
.Base
= MemAbove4G
.Base
= MAX_UINT64
;
247 // Scan all the PCI devices on the primary bus of the PCI root bridge
249 for (Device
= 0, NumberOfDevices
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
250 for (Function
= 0; Function
<= PCI_MAX_FUNC
; Function
++) {
252 // Compute the PCI configuration address of the PCI device to probe
254 Address
= PCI_LIB_ADDRESS (PrimaryBus
, Device
, Function
, 0);
257 // Read the Vendor ID from the PCI Configuration Header
259 if (PciRead16 (Address
) == MAX_UINT16
) {
262 // If the PCI Configuration Read fails, or a PCI device does not
263 // exist, then skip this entire PCI device
268 // If PCI function != 0, VendorId == 0xFFFF, we continue to search
276 // Read the entire PCI Configuration Header
278 PciReadBuffer (Address
, sizeof (Pci
), &Pci
);
281 // Increment the number of PCI device found on the primary bus of the
287 // Look for devices with the VGA Palette Snoop enabled in the COMMAND
288 // register of the PCI Config Header
290 if ((Pci
.Hdr
.Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
291 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
292 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
300 if (IS_PCI_BRIDGE (&Pci
)) {
302 // Get the Bus range that the PPB is decoding
304 if (Pci
.Bridge
.SubordinateBus
> SubBus
) {
306 // If the subordinate bus number of the PCI-PCI bridge is greater
307 // than the PCI root bridge's current subordinate bus number,
308 // then update the PCI root bridge's subordinate bus number
310 SubBus
= Pci
.Bridge
.SubordinateBus
;
314 // Get the I/O range that the PPB is decoding
316 Value
= Pci
.Bridge
.IoBase
& 0x0f;
317 Base
= ((UINT32
)Pci
.Bridge
.IoBase
& 0xf0) << 8;
318 Limit
= (((UINT32
)Pci
.Bridge
.IoLimit
& 0xf0) << 8) | 0x0fff;
320 Base
|= ((UINT32
)Pci
.Bridge
.IoBaseUpper16
<< 16);
321 Limit
|= ((UINT32
)Pci
.Bridge
.IoLimitUpper16
<< 16);
324 if ((Base
> 0) && (Base
< Limit
)) {
325 if (Io
.Base
> Base
) {
329 if (Io
.Limit
< Limit
) {
335 // Get the Memory range that the PPB is decoding
337 Base
= ((UINT32
)Pci
.Bridge
.MemoryBase
& 0xfff0) << 16;
338 Limit
= (((UINT32
)Pci
.Bridge
.MemoryLimit
& 0xfff0) << 16) | 0xfffff;
339 if ((Base
> 0) && (Base
< Limit
)) {
340 if (Mem
.Base
> Base
) {
344 if (Mem
.Limit
< Limit
) {
350 // Get the Prefetchable Memory range that the PPB is decoding
351 // and merge it into Memory range
353 Value
= Pci
.Bridge
.PrefetchableMemoryBase
& 0x0f;
354 Base
= ((UINT32
)Pci
.Bridge
.PrefetchableMemoryBase
& 0xfff0) << 16;
355 Limit
= (((UINT32
)Pci
.Bridge
.PrefetchableMemoryLimit
& 0xfff0)
359 Base
|= LShiftU64 (Pci
.Bridge
.PrefetchableBaseUpper32
, 32);
360 Limit
|= LShiftU64 (Pci
.Bridge
.PrefetchableLimitUpper32
, 32);
363 if ((Base
> 0) && (Base
< Limit
)) {
364 if (Base
< BASE_4GB
) {
367 MemAperture
= &MemAbove4G
;
370 if (MemAperture
->Base
> Base
) {
371 MemAperture
->Base
= Base
;
374 if (MemAperture
->Limit
< Limit
) {
375 MemAperture
->Limit
= Limit
;
380 // Look at the PPB Configuration for legacy decoding attributes
382 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
)
383 == EFI_PCI_BRIDGE_CONTROL_ISA
)
385 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
386 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO_16
;
387 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
390 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
)
391 == EFI_PCI_BRIDGE_CONTROL_VGA
)
393 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
394 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
395 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
396 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
)
399 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
400 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO_16
;
404 BarOffsetEnd
= OFFSET_OF (PCI_TYPE01
, Bridge
.Bar
[2]);
407 // Parse the BARs of the PCI device to get what I/O Ranges, Memory
408 // Ranges, and Prefetchable Memory Ranges the device is decoding
410 if ((Pci
.Hdr
.HeaderType
& HEADER_LAYOUT_CODE
) == HEADER_TYPE_DEVICE
) {
411 BarOffsetEnd
= OFFSET_OF (PCI_TYPE00
, Device
.Bar
[6]);
415 PcatPciRootBridgeParseBars (
420 OFFSET_OF (PCI_TYPE00
, Device
.Bar
),
428 // See if the PCI device is an IDE controller
432 PCI_CLASS_MASS_STORAGE
,
433 PCI_CLASS_MASS_STORAGE_IDE
436 if (Pci
.Hdr
.ClassCode
[0] & 0x80) {
437 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
438 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
441 if (Pci
.Hdr
.ClassCode
[0] & 0x01) {
442 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
445 if (Pci
.Hdr
.ClassCode
[0] & 0x04) {
446 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
451 // See if the PCI device is a legacy VGA controller or
452 // a standard VGA controller
454 if (IS_CLASS2 (&Pci
, PCI_CLASS_OLD
, PCI_CLASS_OLD_VGA
) ||
455 IS_CLASS2 (&Pci
, PCI_CLASS_DISPLAY
, PCI_CLASS_DISPLAY_VGA
)
458 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
459 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
460 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
461 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
462 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO_16
;
466 // See if the PCI Device is a PCI - ISA or PCI - EISA
467 // or ISA_POSITIVE_DECODE Bridge device
469 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_BRIDGE
) {
470 if ((Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA
) ||
471 (Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_EISA
) ||
472 (Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA_PDECODE
))
474 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
475 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO_16
;
476 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
481 // If this device is not a multi function device, then skip the rest
482 // of this PCI device
484 if ((Function
== 0) && !IS_PCI_MULTI_FUNC (&Pci
)) {
491 // If at least one PCI device was found on the primary bus of this PCI
492 // root bridge, then the PCI root bridge exists.
494 if (NumberOfDevices
> 0) {
495 RootBridges
= ReallocatePool (
496 (*NumberOfRootBridges
) * sizeof (PCI_ROOT_BRIDGE
),
497 (*NumberOfRootBridges
+ 1) * sizeof (PCI_ROOT_BRIDGE
),
500 ASSERT (RootBridges
!= NULL
);
513 &RootBridges
[*NumberOfRootBridges
]
515 RootBridges
[*NumberOfRootBridges
].ResourceAssigned
= TRUE
;
517 // Increment the index for the next PCI Root Bridge
519 (*NumberOfRootBridges
)++;
527 Scan for all root bridges from Universal Payload PciRootBridgeInfoHob
529 @param[in] PciRootBridgeInfo Pointer of Universal Payload PCI Root Bridge Info Hob
530 @param[out] NumberOfRootBridges Number of root bridges detected
532 @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.
536 RetrieveRootBridgeInfoFromHob (
537 IN UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES
*PciRootBridgeInfo
,
538 OUT UINTN
*NumberOfRootBridges
541 PCI_ROOT_BRIDGE
*PciRootBridges
;
545 ASSERT (PciRootBridgeInfo
!= NULL
);
546 ASSERT (NumberOfRootBridges
!= NULL
);
547 if (PciRootBridgeInfo
== NULL
) {
551 if (PciRootBridgeInfo
->Count
== 0) {
552 PcdSetBoolS (PcdPciDisableBusEnumeration
, FALSE
);
556 Size
= PciRootBridgeInfo
->Count
* sizeof (PCI_ROOT_BRIDGE
);
557 PciRootBridges
= (PCI_ROOT_BRIDGE
*)AllocatePool (Size
);
558 ASSERT (PciRootBridges
!= NULL
);
559 if (PciRootBridges
== NULL
) {
563 ZeroMem (PciRootBridges
, PciRootBridgeInfo
->Count
* sizeof (PCI_ROOT_BRIDGE
));
566 // Create all root bridges with PciRootBridgeInfoHob
568 for (Index
= 0; Index
< PciRootBridgeInfo
->Count
; Index
++) {
569 PciRootBridges
[Index
].Segment
= PciRootBridgeInfo
->RootBridge
[Index
].Segment
;
570 PciRootBridges
[Index
].Supports
= PciRootBridgeInfo
->RootBridge
[Index
].Supports
;
571 PciRootBridges
[Index
].Attributes
= PciRootBridgeInfo
->RootBridge
[Index
].Attributes
;
572 PciRootBridges
[Index
].DmaAbove4G
= PciRootBridgeInfo
->RootBridge
[Index
].DmaAbove4G
;
573 PciRootBridges
[Index
].NoExtendedConfigSpace
= PciRootBridgeInfo
->RootBridge
[Index
].NoExtendedConfigSpace
;
574 PciRootBridges
[Index
].ResourceAssigned
= PciRootBridgeInfo
->ResourceAssigned
;
575 PciRootBridges
[Index
].AllocationAttributes
= PciRootBridgeInfo
->RootBridge
[Index
].AllocationAttributes
;
576 PciRootBridges
[Index
].DevicePath
= CreateRootBridgeDevicePath (PciRootBridgeInfo
->RootBridge
[Index
].HID
, PciRootBridgeInfo
->RootBridge
[Index
].UID
);
577 CopyMem (&PciRootBridges
[Index
].Bus
, &PciRootBridgeInfo
->RootBridge
[Index
].Bus
, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE
));
578 CopyMem (&PciRootBridges
[Index
].Io
, &PciRootBridgeInfo
->RootBridge
[Index
].Io
, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE
));
579 CopyMem (&PciRootBridges
[Index
].Mem
, &PciRootBridgeInfo
->RootBridge
[Index
].Mem
, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE
));
580 CopyMem (&PciRootBridges
[Index
].MemAbove4G
, &PciRootBridgeInfo
->RootBridge
[Index
].MemAbove4G
, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE
));
581 CopyMem (&PciRootBridges
[Index
].PMem
, &PciRootBridgeInfo
->RootBridge
[Index
].PMem
, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE
));
582 CopyMem (&PciRootBridges
[Index
].PMemAbove4G
, &PciRootBridgeInfo
->RootBridge
[Index
].PMemAbove4G
, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE
));
585 *NumberOfRootBridges
= PciRootBridgeInfo
->Count
;
588 // Now, this library only supports RootBridge that ResourceAssigned is True
590 if (PciRootBridgeInfo
->ResourceAssigned
) {
591 PcdSetBoolS (PcdPciDisableBusEnumeration
, TRUE
);
593 DEBUG ((DEBUG_INFO
, "There is root bridge whose ResourceAssigned is FALSE\n"));
594 PcdSetBoolS (PcdPciDisableBusEnumeration
, FALSE
);
597 return PciRootBridges
;