2 Scan the entire PCI bus for root bridges to support coreboot UEFI payload.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 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, WITHOUT
12 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <IndustryStandard/Pci.h>
18 #include <Protocol/PciHostBridgeResourceAllocation.h>
19 #include <Protocol/PciRootBridgeIo.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/PciHostBridgeLib.h>
24 #include <Library/PciLib.h>
25 #include "PciHostBridge.h"
28 Adjust the collected PCI resource.
30 @param[in] Io IO aperture.
32 @param[in] Mem MMIO aperture.
34 @param[in] MemAbove4G MMIO aperture above 4G.
36 @param[in] PMem Prefetchable MMIO aperture.
38 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
41 AdjustRootBridgeResource (
42 IN PCI_ROOT_BRIDGE_APERTURE
*Io
,
43 IN PCI_ROOT_BRIDGE_APERTURE
*Mem
,
44 IN PCI_ROOT_BRIDGE_APERTURE
*MemAbove4G
,
45 IN PCI_ROOT_BRIDGE_APERTURE
*PMem
,
46 IN PCI_ROOT_BRIDGE_APERTURE
*PMemAbove4G
52 // For now try to downgrade everything into MEM32 since
53 // - coreboot does not assign resource above 4GB
54 // - coreboot might allocate interleaved MEM32 and PMEM32 resource
57 if (PMem
->Base
< Mem
->Base
) {
58 Mem
->Base
= PMem
->Base
;
61 if (PMem
->Limit
> Mem
->Limit
) {
62 Mem
->Limit
= PMem
->Limit
;
65 PMem
->Base
= MAX_UINT64
;
68 if (MemAbove4G
->Base
< 0x100000000ULL
) {
69 if (MemAbove4G
->Base
< Mem
->Base
) {
70 Mem
->Base
= MemAbove4G
->Base
;
72 if (MemAbove4G
->Limit
> Mem
->Limit
) {
73 Mem
->Limit
= MemAbove4G
->Limit
;
75 MemAbove4G
->Base
= MAX_UINT64
;
76 MemAbove4G
->Limit
= 0;
79 if (PMemAbove4G
->Base
< 0x100000000ULL
) {
80 if (PMemAbove4G
->Base
< Mem
->Base
) {
81 Mem
->Base
= PMemAbove4G
->Base
;
83 if (PMemAbove4G
->Limit
> Mem
->Limit
) {
84 Mem
->Limit
= PMemAbove4G
->Limit
;
86 PMemAbove4G
->Base
= MAX_UINT64
;
87 PMemAbove4G
->Limit
= 0;
91 // Align IO resource at 4K boundary
94 Io
->Limit
= ((Io
->Limit
+ Mask
) & ~Mask
) - 1;
95 if (Io
->Base
!= MAX_UINT64
) {
100 // Align MEM resource at 1MB boundary
103 Mem
->Limit
= ((Mem
->Limit
+ Mask
) & ~Mask
) - 1;
104 if (Mem
->Base
!= MAX_UINT64
) {
110 Probe a bar is existed or not.
112 @param[in] Address PCI address for the BAR.
113 @param[out] OriginalValue The original bar value returned.
114 @param[out] Value The probed bar value returned.
118 PcatPciRootBridgeBarExisted (
120 OUT UINT32
*OriginalValue
,
126 PciAddress
= (UINTN
)Address
;
129 // Preserve the original value
131 *OriginalValue
= PciRead32 (PciAddress
);
134 // Disable timer interrupt while the BAR is probed
136 DisableInterrupts ();
138 PciWrite32 (PciAddress
, 0xFFFFFFFF);
139 *Value
= PciRead32 (PciAddress
);
140 PciWrite32 (PciAddress
, *OriginalValue
);
149 Parse PCI bar and collect the assigned PCI resource information.
151 @param[in] Command Supported attributes.
153 @param[in] Bus PCI bus number.
155 @param[in] Device PCI device number.
157 @param[in] Function PCI function number.
159 @param[in] BarOffsetBase PCI bar start offset.
161 @param[in] BarOffsetEnd PCI bar end offset.
163 @param[in] Io IO aperture.
165 @param[in] Mem MMIO aperture.
167 @param[in] MemAbove4G MMIO aperture above 4G.
169 @param[in] PMem Prefetchable MMIO aperture.
171 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
175 PcatPciRootBridgeParseBars (
180 IN UINTN BarOffsetBase
,
181 IN UINTN BarOffsetEnd
,
182 IN PCI_ROOT_BRIDGE_APERTURE
*Io
,
183 IN PCI_ROOT_BRIDGE_APERTURE
*Mem
,
184 IN PCI_ROOT_BRIDGE_APERTURE
*MemAbove4G
,
185 IN PCI_ROOT_BRIDGE_APERTURE
*PMem
,
186 IN PCI_ROOT_BRIDGE_APERTURE
*PMemAbove4G
190 UINT32 OriginalValue
;
192 UINT32 OriginalUpperValue
;
200 PCI_ROOT_BRIDGE_APERTURE
*MemAperture
;
202 for (Offset
= BarOffsetBase
; Offset
< BarOffsetEnd
; Offset
+= sizeof (UINT32
)) {
203 PcatPciRootBridgeBarExisted (
204 PCI_LIB_ADDRESS (Bus
, Device
, Function
, Offset
),
205 &OriginalValue
, &Value
210 if ((Value
& BIT0
) == BIT0
) {
214 if (Command
& EFI_PCI_COMMAND_IO_SPACE
) {
216 Base
= OriginalValue
& Mask
;
217 Length
= ((~(Value
& Mask
)) & Mask
) + 0x04;
218 if (!(Value
& 0xFFFF0000)) {
219 Length
&= 0x0000FFFF;
221 Limit
= Base
+ Length
- 1;
223 if ((Base
> 0) && (Base
< Limit
)) {
224 if (Io
->Base
> Base
) {
227 if (Io
->Limit
< Limit
) {
236 if (Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) {
239 Base
= OriginalValue
& Mask
;
240 Length
= Value
& Mask
;
242 if ((Value
& (BIT1
| BIT2
)) == 0) {
246 Length
= ((~Length
) + 1) & 0xffffffff;
248 if ((Value
& BIT3
) == BIT3
) {
258 PcatPciRootBridgeBarExisted (
259 PCI_LIB_ADDRESS (Bus
, Device
, Function
, Offset
),
264 Base
= Base
| LShiftU64 ((UINT64
) OriginalUpperValue
, 32);
265 Length
= Length
| LShiftU64 ((UINT64
) UpperValue
, 32);
267 LowBit
= LowBitSet64 (Length
);
268 Length
= LShiftU64 (1ULL, LowBit
);
271 if ((Value
& BIT3
) == BIT3
) {
272 MemAperture
= PMemAbove4G
;
274 MemAperture
= MemAbove4G
;
278 Limit
= Base
+ Length
- 1;
279 if ((Base
> 0) && (Base
< Limit
)) {
280 if (MemAperture
->Base
> Base
) {
281 MemAperture
->Base
= Base
;
283 if (MemAperture
->Limit
< Limit
) {
284 MemAperture
->Limit
= Limit
;
293 Scan for all root bridges in platform.
295 @param[out] NumberOfRootBridges Number of root bridges detected
297 @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.
301 OUT UINTN
*NumberOfRootBridges
308 UINTN NumberOfDevices
;
315 PCI_ROOT_BRIDGE_APERTURE Io
, Mem
, MemAbove4G
, PMem
, PMemAbove4G
, *MemAperture
;
316 PCI_ROOT_BRIDGE
*RootBridges
;
320 *NumberOfRootBridges
= 0;
324 // After scanning all the PCI devices on the PCI root bridge's primary bus,
325 // update the Primary Bus Number for the next PCI root bridge to be this PCI
326 // root bridge's subordinate bus number + 1.
328 for (PrimaryBus
= 0; PrimaryBus
<= PCI_MAX_BUS
; PrimaryBus
= SubBus
+ 1) {
332 ZeroMem (&Io
, sizeof (Io
));
333 ZeroMem (&Mem
, sizeof (Mem
));
334 ZeroMem (&MemAbove4G
, sizeof (MemAbove4G
));
335 ZeroMem (&PMem
, sizeof (PMem
));
336 ZeroMem (&PMemAbove4G
, sizeof (PMemAbove4G
));
337 Io
.Base
= Mem
.Base
= MemAbove4G
.Base
= PMem
.Base
= PMemAbove4G
.Base
= MAX_UINT64
;
339 // Scan all the PCI devices on the primary bus of the PCI root bridge
341 for (Device
= 0, NumberOfDevices
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
343 for (Function
= 0; Function
<= PCI_MAX_FUNC
; Function
++) {
346 // Compute the PCI configuration address of the PCI device to probe
348 Address
= PCI_LIB_ADDRESS (PrimaryBus
, Device
, Function
, 0);
351 // Read the Vendor ID from the PCI Configuration Header
353 if (PciRead16 (Address
) == MAX_UINT16
) {
356 // If the PCI Configuration Read fails, or a PCI device does not
357 // exist, then skip this entire PCI device
362 // If PCI function != 0, VendorId == 0xFFFF, we continue to search
370 // Read the entire PCI Configuration Header
372 PciReadBuffer (Address
, sizeof (Pci
), &Pci
);
375 // Increment the number of PCI device found on the primary bus of the
381 // Look for devices with the VGA Palette Snoop enabled in the COMMAND
382 // register of the PCI Config Header
384 if ((Pci
.Hdr
.Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
385 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
386 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
394 if (IS_PCI_BRIDGE (&Pci
)) {
396 // Get the Bus range that the PPB is decoding
398 if (Pci
.Bridge
.SubordinateBus
> SubBus
) {
400 // If the subordinate bus number of the PCI-PCI bridge is greater
401 // than the PCI root bridge's current subordinate bus number,
402 // then update the PCI root bridge's subordinate bus number
404 SubBus
= Pci
.Bridge
.SubordinateBus
;
408 // Get the I/O range that the PPB is decoding
410 Value
= Pci
.Bridge
.IoBase
& 0x0f;
411 Base
= ((UINT32
) Pci
.Bridge
.IoBase
& 0xf0) << 8;
412 Limit
= (((UINT32
) Pci
.Bridge
.IoLimit
& 0xf0) << 8) | 0x0fff;
414 Base
|= ((UINT32
) Pci
.Bridge
.IoBaseUpper16
<< 16);
415 Limit
|= ((UINT32
) Pci
.Bridge
.IoLimitUpper16
<< 16);
417 if ((Base
> 0) && (Base
< Limit
)) {
418 if (Io
.Base
> Base
) {
421 if (Io
.Limit
< Limit
) {
427 // Get the Memory range that the PPB is decoding
429 Base
= ((UINT32
) Pci
.Bridge
.MemoryBase
& 0xfff0) << 16;
430 Limit
= (((UINT32
) Pci
.Bridge
.MemoryLimit
& 0xfff0) << 16) | 0xfffff;
431 if ((Base
> 0) && (Base
< Limit
)) {
432 if (Mem
.Base
> Base
) {
435 if (Mem
.Limit
< Limit
) {
441 // Get the Prefetchable Memory range that the PPB is decoding
443 Value
= Pci
.Bridge
.PrefetchableMemoryBase
& 0x0f;
444 Base
= ((UINT32
) Pci
.Bridge
.PrefetchableMemoryBase
& 0xfff0) << 16;
445 Limit
= (((UINT32
) Pci
.Bridge
.PrefetchableMemoryLimit
& 0xfff0)
449 Base
|= LShiftU64 (Pci
.Bridge
.PrefetchableBaseUpper32
, 32);
450 Limit
|= LShiftU64 (Pci
.Bridge
.PrefetchableLimitUpper32
, 32);
451 MemAperture
= &PMemAbove4G
;
453 if ((Base
> 0) && (Base
< Limit
)) {
454 if (MemAperture
->Base
> Base
) {
455 MemAperture
->Base
= Base
;
457 if (MemAperture
->Limit
< Limit
) {
458 MemAperture
->Limit
= Limit
;
463 // Look at the PPB Configuration for legacy decoding attributes
465 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
)
466 == EFI_PCI_BRIDGE_CONTROL_ISA
) {
467 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
468 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO_16
;
469 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
471 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
)
472 == EFI_PCI_BRIDGE_CONTROL_VGA
) {
473 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
474 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
475 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
476 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
)
478 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
479 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO_16
;
483 BarOffsetEnd
= OFFSET_OF (PCI_TYPE01
, Bridge
.Bar
[2]);
486 // Parse the BARs of the PCI device to get what I/O Ranges, Memory
487 // Ranges, and Prefetchable Memory Ranges the device is decoding
489 if ((Pci
.Hdr
.HeaderType
& HEADER_LAYOUT_CODE
) == HEADER_TYPE_DEVICE
) {
490 BarOffsetEnd
= OFFSET_OF (PCI_TYPE00
, Device
.Bar
[6]);
494 PcatPciRootBridgeParseBars (
499 OFFSET_OF (PCI_TYPE00
, Device
.Bar
),
507 // See if the PCI device is an IDE controller
509 if (IS_CLASS2 (&Pci
, PCI_CLASS_MASS_STORAGE
,
510 PCI_CLASS_MASS_STORAGE_IDE
)) {
511 if (Pci
.Hdr
.ClassCode
[0] & 0x80) {
512 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
513 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
515 if (Pci
.Hdr
.ClassCode
[0] & 0x01) {
516 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
518 if (Pci
.Hdr
.ClassCode
[0] & 0x04) {
519 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
524 // See if the PCI device is a legacy VGA controller or
525 // a standard VGA controller
527 if (IS_CLASS2 (&Pci
, PCI_CLASS_OLD
, PCI_CLASS_OLD_VGA
) ||
528 IS_CLASS2 (&Pci
, PCI_CLASS_DISPLAY
, PCI_CLASS_DISPLAY_VGA
)
530 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
531 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
532 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
533 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
534 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO_16
;
538 // See if the PCI Device is a PCI - ISA or PCI - EISA
539 // or ISA_POSITIVE_DECODE Bridge device
541 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_BRIDGE
) {
542 if (Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA
||
543 Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_EISA
||
544 Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA_PDECODE
) {
545 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
546 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO_16
;
547 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
552 // If this device is not a multi function device, then skip the rest
553 // of this PCI device
555 if (Function
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
562 // If at least one PCI device was found on the primary bus of this PCI
563 // root bridge, then the PCI root bridge exists.
565 if (NumberOfDevices
> 0) {
566 RootBridges
= ReallocatePool (
567 (*NumberOfRootBridges
) * sizeof (PCI_ROOT_BRIDGE
),
568 (*NumberOfRootBridges
+ 1) * sizeof (PCI_ROOT_BRIDGE
),
571 ASSERT (RootBridges
!= NULL
);
573 AdjustRootBridgeResource (&Io
, &Mem
, &MemAbove4G
, &PMem
, &PMemAbove4G
);
576 Attributes
, Attributes
, 0,
577 (UINT8
) PrimaryBus
, (UINT8
) SubBus
,
578 &Io
, &Mem
, &MemAbove4G
, &PMem
, &PMemAbove4G
,
579 &RootBridges
[*NumberOfRootBridges
]
581 RootBridges
[*NumberOfRootBridges
].ResourceAssigned
= TRUE
;
583 // Increment the index for the next PCI Root Bridge
585 (*NumberOfRootBridges
)++;