TianoCore EDK2 master
Loading...
Searching...
No Matches
ScanForRootBridges.c
Go to the documentation of this file.
1
11#include <IndustryStandard/Pci.h> // EFI_PCI_COMMAND_IO_SPACE
12#include <Library/BaseLib.h> // DisableInterrupts()
13#include <Library/BaseMemoryLib.h> // ZeroMem()
14#include <Library/DebugLib.h> // ASSERT()
15#include <Library/MemoryAllocationLib.h> // ReallocatePool()
16#include <Library/PciHostBridgeLib.h> // PCI_ROOT_BRIDGE_APERTURE
17#include <Library/PciHostBridgeUtilityLib.h> // PciHostBridgeUtilityInitRoot...
18#include <Library/PciLib.h> // PciRead32()
19#include <Protocol/PciRootBridgeIo.h> // EFI_PCI_ATTRIBUTE_ISA_IO
20
21#include "PciHostBridge.h"
22
24VOID
25PcatPciRootBridgeBarExisted (
26 IN UINTN Address,
27 OUT UINT32 *OriginalValue,
28 OUT UINT32 *Value
29 )
30{
31 //
32 // Preserve the original value
33 //
34 *OriginalValue = PciRead32 (Address);
35
36 //
37 // Disable timer interrupt while the BAR is probed
38 //
40
41 PciWrite32 (Address, 0xFFFFFFFF);
42 *Value = PciRead32 (Address);
43 PciWrite32 (Address, *OriginalValue);
44
45 //
46 // Enable interrupt
47 //
49}
50
51#define PCI_COMMAND_DECODE ((UINT16)(EFI_PCI_COMMAND_IO_SPACE |\
52 EFI_PCI_COMMAND_MEMORY_SPACE))
54VOID
55PcatPciRootBridgeDecodingDisable (
56 IN UINTN Address
57 )
58{
59 UINT16 Value;
60
61 Value = PciRead16 (Address);
62 if (Value & PCI_COMMAND_DECODE) {
63 PciWrite16 (Address, Value & ~(UINT32)PCI_COMMAND_DECODE);
64 }
65}
66
68VOID
69PcatPciRootBridgeParseBars (
70 IN UINT16 Command,
71 IN UINTN Bus,
72 IN UINTN Device,
73 IN UINTN Function,
74 IN UINTN BarOffsetBase,
75 IN UINTN BarOffsetEnd,
79
80 )
81{
82 UINT32 OriginalValue;
83 UINT32 Value;
84 UINT32 OriginalUpperValue;
85 UINT32 UpperValue;
86 UINT64 Mask;
87 UINTN Offset;
88 UINT64 Base;
89 UINT64 Length;
90 UINT64 Limit;
91 PCI_ROOT_BRIDGE_APERTURE *MemAperture;
92
93 // Disable address decoding for every device before OVMF starts sizing it
94 PcatPciRootBridgeDecodingDisable (
95 PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET)
96 );
97
98 for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {
99 PcatPciRootBridgeBarExisted (
100 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
101 &OriginalValue,
102 &Value
103 );
104 if (Value == 0) {
105 continue;
106 }
107
108 if ((Value & BIT0) == BIT0) {
109 //
110 // IO Bar
111 //
112 if (Command & EFI_PCI_COMMAND_IO_SPACE) {
113 Mask = 0xfffffffc;
114 Base = OriginalValue & Mask;
115 Length = ((~(Value & Mask)) & Mask) + 0x04;
116 if (!(Value & 0xFFFF0000)) {
117 Length &= 0x0000FFFF;
118 }
119
120 Limit = Base + Length - 1;
121
122 if (Base < Limit) {
123 if (Io->Base > Base) {
124 Io->Base = Base;
125 }
126
127 if (Io->Limit < Limit) {
128 Io->Limit = Limit;
129 }
130 }
131 }
132 } else {
133 //
134 // Mem Bar
135 //
136 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
137 Mask = 0xfffffff0;
138 Base = OriginalValue & Mask;
139 Length = Value & Mask;
140
141 if ((Value & (BIT1 | BIT2)) == 0) {
142 //
143 // 32bit
144 //
145 Length = ((~Length) + 1) & 0xffffffff;
146
147 MemAperture = Mem;
148 } else {
149 //
150 // 64bit
151 //
152 Offset += 4;
153 PcatPciRootBridgeBarExisted (
154 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
155 &OriginalUpperValue,
156 &UpperValue
157 );
158
159 Base = Base | LShiftU64 ((UINT64)OriginalUpperValue, 32);
160 Length = Length | LShiftU64 ((UINT64)UpperValue, 32);
161 Length = (~Length) + 1;
162
163 if (Base < BASE_4GB) {
164 MemAperture = Mem;
165 } else {
166 MemAperture = MemAbove4G;
167 }
168 }
169
170 Limit = Base + Length - 1;
171 if (Base < Limit) {
172 if (MemAperture->Base > Base) {
173 MemAperture->Base = Base;
174 }
175
176 if (MemAperture->Limit < Limit) {
177 MemAperture->Limit = Limit;
178 }
179 }
180 }
181 }
182 }
183}
184
185STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
186
188ScanForRootBridges (
189 UINTN *NumberOfRootBridges
190 )
191{
192 UINTN PrimaryBus;
193 UINTN SubBus;
194 UINT8 Device;
195 UINT8 Function;
196 UINTN NumberOfDevices;
197 UINTN Address;
198 PCI_TYPE01 Pci;
199 UINT64 Attributes;
200 UINT64 Base;
201 UINT64 Limit;
202 UINT64 Value;
203 PCI_ROOT_BRIDGE_APERTURE Io, Mem, MemAbove4G, *MemAperture;
204 PCI_ROOT_BRIDGE *RootBridges;
205 UINTN BarOffsetEnd;
206
207 *NumberOfRootBridges = 0;
208 RootBridges = NULL;
209
210 //
211 // After scanning all the PCI devices on the PCI root bridge's primary bus,
212 // update the Primary Bus Number for the next PCI root bridge to be this PCI
213 // root bridge's subordinate bus number + 1.
214 //
215 for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {
216 SubBus = PrimaryBus;
217 Attributes = 0;
218
219 ZeroMem (&Io, sizeof (Io));
220 ZeroMem (&Mem, sizeof (Mem));
221 ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
222 Io.Base = Mem.Base = MemAbove4G.Base = MAX_UINT64;
223 //
224 // Scan all the PCI devices on the primary bus of the PCI root bridge
225 //
226 for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
227 for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
228 //
229 // Compute the PCI configuration address of the PCI device to probe
230 //
231 Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);
232
233 //
234 // Read the Vendor ID from the PCI Configuration Header
235 //
236 if (PciRead16 (Address) == MAX_UINT16) {
237 if (Function == 0) {
238 //
239 // If the PCI Configuration Read fails, or a PCI device does not
240 // exist, then skip this entire PCI device
241 //
242 break;
243 } else {
244 //
245 // If PCI function != 0, VendorId == 0xFFFF, we continue to search
246 // PCI function.
247 //
248 continue;
249 }
250 }
251
252 //
253 // Read the entire PCI Configuration Header
254 //
255 PciReadBuffer (Address, sizeof (Pci), &Pci);
256
257 //
258 // Increment the number of PCI device found on the primary bus of the
259 // PCI root bridge
260 //
261 NumberOfDevices++;
262
263 //
264 // Look for devices with the VGA Palette Snoop enabled in the COMMAND
265 // register of the PCI Config Header
266 //
267 if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
268 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
269 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
270 }
271
272 BarOffsetEnd = 0;
273
274 //
275 // PCI-PCI Bridge
276 //
277 if (IS_PCI_BRIDGE (&Pci)) {
278 //
279 // Get the Bus range that the PPB is decoding
280 //
281 if (Pci.Bridge.SubordinateBus > SubBus) {
282 //
283 // If the subordinate bus number of the PCI-PCI bridge is greater
284 // than the PCI root bridge's current subordinate bus number,
285 // then update the PCI root bridge's subordinate bus number
286 //
287 SubBus = Pci.Bridge.SubordinateBus;
288 }
289
290 //
291 // Get the I/O range that the PPB is decoding
292 //
293 Value = Pci.Bridge.IoBase & 0x0f;
294 Base = ((UINT32)Pci.Bridge.IoBase & 0xf0) << 8;
295 Limit = (((UINT32)Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
296 if (Value == BIT0) {
297 Base |= ((UINT32)Pci.Bridge.IoBaseUpper16 << 16);
298 Limit |= ((UINT32)Pci.Bridge.IoLimitUpper16 << 16);
299 }
300
301 if (Base < Limit) {
302 if (Io.Base > Base) {
303 Io.Base = Base;
304 }
305
306 if (Io.Limit < Limit) {
307 Io.Limit = Limit;
308 }
309 }
310
311 //
312 // Get the Memory range that the PPB is decoding
313 //
314 Base = ((UINT32)Pci.Bridge.MemoryBase & 0xfff0) << 16;
315 Limit = (((UINT32)Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
316 if (Base < Limit) {
317 if (Mem.Base > Base) {
318 Mem.Base = Base;
319 }
320
321 if (Mem.Limit < Limit) {
322 Mem.Limit = Limit;
323 }
324 }
325
326 //
327 // Get the Prefetchable Memory range that the PPB is decoding
328 // and merge it into Memory range
329 //
330 Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;
331 Base = ((UINT32)Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
332 Limit = (((UINT32)Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)
333 << 16) | 0xfffff;
334 MemAperture = &Mem;
335 if (Value == BIT0) {
336 Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);
337 Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);
338 MemAperture = &MemAbove4G;
339 }
340
341 if (Base < Limit) {
342 if (MemAperture->Base > Base) {
343 MemAperture->Base = Base;
344 }
345
346 if (MemAperture->Limit < Limit) {
347 MemAperture->Limit = Limit;
348 }
349 }
350
351 //
352 // Look at the PPB Configuration for legacy decoding attributes
353 //
354 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)
356 {
357 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
358 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
359 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
360 }
361
362 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)
364 {
365 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
366 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
367 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
368 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)
369 != 0)
370 {
371 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
372 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
373 }
374 }
375
376 BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);
377 } else {
378 //
379 // Parse the BARs of the PCI device to get what I/O Ranges, Memory
380 // Ranges, and Prefetchable Memory Ranges the device is decoding
381 //
382 if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
383 BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);
384 }
385 }
386
387 PcatPciRootBridgeParseBars (
388 Pci.Hdr.Command,
389 PrimaryBus,
390 Device,
391 Function,
392 OFFSET_OF (PCI_TYPE00, Device.Bar),
393 BarOffsetEnd,
394 &Io,
395 &Mem,
396 &MemAbove4G
397 );
398
399 //
400 // See if the PCI device is an IDE controller
401 //
402 if (IS_CLASS2 (
403 &Pci,
404 PCI_CLASS_MASS_STORAGE,
405 PCI_CLASS_MASS_STORAGE_IDE
406 ))
407 {
408 if (Pci.Hdr.ClassCode[0] & 0x80) {
409 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
410 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
411 }
412
413 if (Pci.Hdr.ClassCode[0] & 0x01) {
414 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
415 }
416
417 if (Pci.Hdr.ClassCode[0] & 0x04) {
418 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
419 }
420 }
421
422 //
423 // See if the PCI device is a legacy VGA controller or
424 // a standard VGA controller
425 //
426 if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||
427 IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)
428 )
429 {
430 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
431 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
432 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
433 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
434 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
435 }
436
437 //
438 // See if the PCI Device is a PCI - ISA or PCI - EISA
439 // or ISA_POSITIVE_DECODE Bridge device
440 //
441 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
442 if ((Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) ||
443 (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA) ||
444 (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE))
445 {
446 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
447 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
448 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
449 }
450 }
451
452 //
453 // If this device is not a multi function device, then skip the rest
454 // of this PCI device
455 //
456 if ((Function == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
457 break;
458 }
459 }
460 }
461
462 //
463 // If at least one PCI device was found on the primary bus of this PCI
464 // root bridge, then the PCI root bridge exists.
465 //
466 if (NumberOfDevices > 0) {
467 RootBridges = ReallocatePool (
468 (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),
469 (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),
470 RootBridges
471 );
472 ASSERT (RootBridges != NULL);
474 Attributes,
475 Attributes,
476 0,
477 FALSE,
478 TRUE /* NoExtendedConfigSpace */,
479 (UINT8)PrimaryBus,
480 (UINT8)SubBus,
481 &Io,
482 &Mem,
483 &MemAbove4G,
484 &mNonExistAperture,
485 &mNonExistAperture,
486 &RootBridges[*NumberOfRootBridges]
487 );
488 RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;
489 //
490 // Increment the index for the next PCI Root Bridge
491 //
492 (*NumberOfRootBridges)++;
493 }
494 }
495
496 return RootBridges;
497}
UINT64 UINTN
VOID EFIAPI EnableInterrupts(VOID)
Definition: CpuBreakpoint.c:67
VOID EFIAPI DisableInterrupts(VOID)
Definition: CpuBreakpoint.c:54
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI ReallocatePool(IN UINTN OldSize, IN UINTN NewSize, IN VOID *OldBuffer OPTIONAL)
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
UINT32 EFIAPI PciRead32(IN UINTN Address)
Definition: PciLib.c:739
#define PCI_LIB_ADDRESS(Bus, Device, Function, Register)
Definition: PciLib.h:34
UINT32 EFIAPI PciWrite32(IN UINTN Address, IN UINT32 Value)
Definition: PciLib.c:765
UINT16 EFIAPI PciWrite16(IN UINTN Address, IN UINT16 Value)
Definition: PciLib.c:422
UINTN EFIAPI PciReadBuffer(IN UINTN StartAddress, IN UINTN Size, OUT VOID *Buffer)
Definition: PciLib.c:1089
UINT16 EFIAPI PciRead16(IN UINTN Address)
Definition: PciLib.c:396
#define EFI_PCI_BRIDGE_CONTROL_VGA_16
0x0010
Definition: Pci22.h:609
#define IS_PCI_BRIDGE(_p)
Definition: Pci22.h:504
#define EFI_PCI_BRIDGE_CONTROL_VGA
0x0008
Definition: Pci22.h:608
#define EFI_PCI_COMMAND_MEMORY_SPACE
0x0002
Definition: Pci22.h:592
#define IS_CLASS2(_p, c, s)
Definition: Pci22.h:324
#define EFI_PCI_COMMAND_IO_SPACE
0x0001
Definition: Pci22.h:591
#define IS_PCI_MULTI_FUNC(_p)
Definition: Pci22.h:526
#define EFI_PCI_BRIDGE_CONTROL_ISA
0x0004
Definition: Pci22.h:607
#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
0x0020
Definition: Pci22.h:596
EFI_STATUS EFIAPI PciHostBridgeUtilityInitRootBridge(IN UINT64 Supports, IN UINT64 Attributes, IN UINT64 AllocAttributes, IN BOOLEAN DmaAbove4G, IN BOOLEAN NoExtendedConfigSpace, IN UINT8 RootBusNumber, IN UINT8 MaxSubBusNumber, IN PCI_ROOT_BRIDGE_APERTURE *Io, IN PCI_ROOT_BRIDGE_APERTURE *Mem, IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, IN PCI_ROOT_BRIDGE_APERTURE *PMem, IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G, OUT PCI_ROOT_BRIDGE *RootBus)
BOOLEAN ResourceAssigned