]> git.proxmox.com Git - mirror_edk2.git/blame - UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c
UefiPayloadPkg: Fix ECC reported issues
[mirror_edk2.git] / UefiPayloadPkg / Library / PciHostBridgeLib / PciHostBridgeSupport.c
CommitLineData
04af8bf2
DG
1/** @file\r
2 Scan the entire PCI bus for root bridges to support coreboot UEFI payload.\r
3\r
99de2e7e 4 Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>\r
04af8bf2
DG
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include <PiDxe.h>\r
11#include <IndustryStandard/Pci.h>\r
12#include <Protocol/PciHostBridgeResourceAllocation.h>\r
13#include <Protocol/PciRootBridgeIo.h>\r
14#include <Library/BaseMemoryLib.h>\r
15#include <Library/DebugLib.h>\r
16#include <Library/MemoryAllocationLib.h>\r
17#include <Library/PciHostBridgeLib.h>\r
18#include <Library/PciLib.h>\r
19#include "PciHostBridge.h"\r
20\r
21/**\r
22 Adjust the collected PCI resource.\r
23\r
24 @param[in] Io IO aperture.\r
25\r
26 @param[in] Mem MMIO aperture.\r
27\r
28 @param[in] MemAbove4G MMIO aperture above 4G.\r
29\r
30 @param[in] PMem Prefetchable MMIO aperture.\r
31\r
32 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.\r
33**/\r
34VOID\r
35AdjustRootBridgeResource (\r
36 IN PCI_ROOT_BRIDGE_APERTURE *Io,\r
37 IN PCI_ROOT_BRIDGE_APERTURE *Mem,\r
38 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,\r
39 IN PCI_ROOT_BRIDGE_APERTURE *PMem,\r
40 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G\r
41)\r
42{\r
43 UINT64 Mask;\r
44\r
45 //\r
46 // For now try to downgrade everything into MEM32 since\r
47 // - coreboot does not assign resource above 4GB\r
48 // - coreboot might allocate interleaved MEM32 and PMEM32 resource\r
49 // in some cases\r
50 //\r
51 if (PMem->Base < Mem->Base) {\r
52 Mem->Base = PMem->Base;\r
53 }\r
54\r
55 if (PMem->Limit > Mem->Limit) {\r
56 Mem->Limit = PMem->Limit;\r
57 }\r
58\r
59 PMem->Base = MAX_UINT64;\r
60 PMem->Limit = 0;\r
61\r
62 if (MemAbove4G->Base < 0x100000000ULL) {\r
63 if (MemAbove4G->Base < Mem->Base) {\r
64 Mem->Base = MemAbove4G->Base;\r
65 }\r
66 if (MemAbove4G->Limit > Mem->Limit) {\r
67 Mem->Limit = MemAbove4G->Limit;\r
68 }\r
69 MemAbove4G->Base = MAX_UINT64;\r
70 MemAbove4G->Limit = 0;\r
71 }\r
72\r
73 if (PMemAbove4G->Base < 0x100000000ULL) {\r
74 if (PMemAbove4G->Base < Mem->Base) {\r
75 Mem->Base = PMemAbove4G->Base;\r
76 }\r
77 if (PMemAbove4G->Limit > Mem->Limit) {\r
78 Mem->Limit = PMemAbove4G->Limit;\r
79 }\r
80 PMemAbove4G->Base = MAX_UINT64;\r
81 PMemAbove4G->Limit = 0;\r
82 }\r
83\r
84 //\r
85 // Align IO resource at 4K boundary\r
86 //\r
87 Mask = 0xFFFULL;\r
88 Io->Limit = ((Io->Limit + Mask) & ~Mask) - 1;\r
89 if (Io->Base != MAX_UINT64) {\r
90 Io->Base &= ~Mask;\r
91 }\r
92\r
93 //\r
94 // Align MEM resource at 1MB boundary\r
95 //\r
96 Mask = 0xFFFFFULL;\r
97 Mem->Limit = ((Mem->Limit + Mask) & ~Mask) - 1;\r
98 if (Mem->Base != MAX_UINT64) {\r
99 Mem->Base &= ~Mask;\r
100 }\r
101}\r
102\r
103/**\r
104 Probe a bar is existed or not.\r
105\r
106 @param[in] Address PCI address for the BAR.\r
107 @param[out] OriginalValue The original bar value returned.\r
108 @param[out] Value The probed bar value returned.\r
109**/\r
110STATIC\r
111VOID\r
112PcatPciRootBridgeBarExisted (\r
113 IN UINT64 Address,\r
114 OUT UINT32 *OriginalValue,\r
115 OUT UINT32 *Value\r
116)\r
117{\r
118 UINTN PciAddress;\r
119\r
120 PciAddress = (UINTN)Address;\r
121\r
122 //\r
123 // Preserve the original value\r
124 //\r
125 *OriginalValue = PciRead32 (PciAddress);\r
126\r
127 //\r
128 // Disable timer interrupt while the BAR is probed\r
129 //\r
130 DisableInterrupts ();\r
131\r
132 PciWrite32 (PciAddress, 0xFFFFFFFF);\r
133 *Value = PciRead32 (PciAddress);\r
134 PciWrite32 (PciAddress, *OriginalValue);\r
135\r
136 //\r
137 // Enable interrupt\r
138 //\r
139 EnableInterrupts ();\r
140}\r
141\r
142/**\r
143 Parse PCI bar and collect the assigned PCI resource information.\r
144\r
145 @param[in] Command Supported attributes.\r
146\r
147 @param[in] Bus PCI bus number.\r
148\r
149 @param[in] Device PCI device number.\r
150\r
151 @param[in] Function PCI function number.\r
152\r
153 @param[in] BarOffsetBase PCI bar start offset.\r
154\r
155 @param[in] BarOffsetEnd PCI bar end offset.\r
156\r
157 @param[in] Io IO aperture.\r
158\r
159 @param[in] Mem MMIO aperture.\r
160\r
161 @param[in] MemAbove4G MMIO aperture above 4G.\r
162\r
163 @param[in] PMem Prefetchable MMIO aperture.\r
164\r
165 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.\r
166**/\r
167STATIC\r
168VOID\r
169PcatPciRootBridgeParseBars (\r
170 IN UINT16 Command,\r
171 IN UINTN Bus,\r
172 IN UINTN Device,\r
173 IN UINTN Function,\r
174 IN UINTN BarOffsetBase,\r
175 IN UINTN BarOffsetEnd,\r
176 IN PCI_ROOT_BRIDGE_APERTURE *Io,\r
177 IN PCI_ROOT_BRIDGE_APERTURE *Mem,\r
178 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,\r
179 IN PCI_ROOT_BRIDGE_APERTURE *PMem,\r
180 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G\r
181\r
182)\r
183{\r
184 UINT32 OriginalValue;\r
185 UINT32 Value;\r
186 UINT32 OriginalUpperValue;\r
187 UINT32 UpperValue;\r
188 UINT64 Mask;\r
189 UINTN Offset;\r
190 UINTN LowBit;\r
191 UINT64 Base;\r
192 UINT64 Length;\r
193 UINT64 Limit;\r
194 PCI_ROOT_BRIDGE_APERTURE *MemAperture;\r
195\r
196 for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {\r
197 PcatPciRootBridgeBarExisted (\r
198 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),\r
199 &OriginalValue, &Value\r
200 );\r
201 if (Value == 0) {\r
202 continue;\r
203 }\r
204 if ((Value & BIT0) == BIT0) {\r
205 //\r
206 // IO Bar\r
207 //\r
6ef57974 208 if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {\r
04af8bf2
DG
209 Mask = 0xfffffffc;\r
210 Base = OriginalValue & Mask;\r
211 Length = ((~(Value & Mask)) & Mask) + 0x04;\r
212 if (!(Value & 0xFFFF0000)) {\r
213 Length &= 0x0000FFFF;\r
214 }\r
215 Limit = Base + Length - 1;\r
216\r
217 if ((Base > 0) && (Base < Limit)) {\r
218 if (Io->Base > Base) {\r
219 Io->Base = Base;\r
220 }\r
221 if (Io->Limit < Limit) {\r
222 Io->Limit = Limit;\r
223 }\r
224 }\r
225 }\r
226 } else {\r
227 //\r
228 // Mem Bar\r
229 //\r
6ef57974 230 if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {\r
04af8bf2
DG
231\r
232 Mask = 0xfffffff0;\r
233 Base = OriginalValue & Mask;\r
234 Length = Value & Mask;\r
235\r
236 if ((Value & (BIT1 | BIT2)) == 0) {\r
237 //\r
238 // 32bit\r
239 //\r
240 Length = ((~Length) + 1) & 0xffffffff;\r
241\r
242 if ((Value & BIT3) == BIT3) {\r
243 MemAperture = PMem;\r
244 } else {\r
245 MemAperture = Mem;\r
246 }\r
247 } else {\r
248 //\r
249 // 64bit\r
250 //\r
251 Offset += 4;\r
252 PcatPciRootBridgeBarExisted (\r
253 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),\r
254 &OriginalUpperValue,\r
255 &UpperValue\r
256 );\r
257\r
258 Base = Base | LShiftU64 ((UINT64) OriginalUpperValue, 32);\r
259 Length = Length | LShiftU64 ((UINT64) UpperValue, 32);\r
260 if (Length != 0) {\r
261 LowBit = LowBitSet64 (Length);\r
262 Length = LShiftU64 (1ULL, LowBit);\r
263 }\r
264\r
265 if ((Value & BIT3) == BIT3) {\r
266 MemAperture = PMemAbove4G;\r
267 } else {\r
268 MemAperture = MemAbove4G;\r
269 }\r
270 }\r
271\r
272 Limit = Base + Length - 1;\r
273 if ((Base > 0) && (Base < Limit)) {\r
274 if (MemAperture->Base > Base) {\r
275 MemAperture->Base = Base;\r
276 }\r
277 if (MemAperture->Limit < Limit) {\r
278 MemAperture->Limit = Limit;\r
279 }\r
280 }\r
281 }\r
282 }\r
283 }\r
284}\r
285\r
286/**\r
287 Scan for all root bridges in platform.\r
288\r
289 @param[out] NumberOfRootBridges Number of root bridges detected\r
290\r
291 @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.\r
292**/\r
293PCI_ROOT_BRIDGE *\r
294ScanForRootBridges (\r
295 OUT UINTN *NumberOfRootBridges\r
296)\r
297{\r
298 UINTN PrimaryBus;\r
299 UINTN SubBus;\r
300 UINT8 Device;\r
301 UINT8 Function;\r
302 UINTN NumberOfDevices;\r
303 UINTN Address;\r
304 PCI_TYPE01 Pci;\r
305 UINT64 Attributes;\r
306 UINT64 Base;\r
307 UINT64 Limit;\r
308 UINT64 Value;\r
6ef57974
GD
309 PCI_ROOT_BRIDGE_APERTURE Io;\r
310 PCI_ROOT_BRIDGE_APERTURE Mem;\r
311 PCI_ROOT_BRIDGE_APERTURE MemAbove4G;\r
312 PCI_ROOT_BRIDGE_APERTURE PMem;\r
313 PCI_ROOT_BRIDGE_APERTURE PMemAbove4G;\r
314 PCI_ROOT_BRIDGE_APERTURE *MemAperture;\r
315 PCI_ROOT_BRIDGE *RootBridges;\r
316 UINTN BarOffsetEnd;\r
04af8bf2
DG
317\r
318\r
319 *NumberOfRootBridges = 0;\r
320 RootBridges = NULL;\r
321\r
322 //\r
323 // After scanning all the PCI devices on the PCI root bridge's primary bus,\r
324 // update the Primary Bus Number for the next PCI root bridge to be this PCI\r
325 // root bridge's subordinate bus number + 1.\r
326 //\r
327 for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {\r
328 SubBus = PrimaryBus;\r
329 Attributes = 0;\r
330\r
331 ZeroMem (&Io, sizeof (Io));\r
332 ZeroMem (&Mem, sizeof (Mem));\r
333 ZeroMem (&MemAbove4G, sizeof (MemAbove4G));\r
334 ZeroMem (&PMem, sizeof (PMem));\r
335 ZeroMem (&PMemAbove4G, sizeof (PMemAbove4G));\r
336 Io.Base = Mem.Base = MemAbove4G.Base = PMem.Base = PMemAbove4G.Base = MAX_UINT64;\r
337 //\r
338 // Scan all the PCI devices on the primary bus of the PCI root bridge\r
339 //\r
340 for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
341\r
342 for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {\r
343\r
344 //\r
345 // Compute the PCI configuration address of the PCI device to probe\r
346 //\r
347 Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);\r
348\r
349 //\r
350 // Read the Vendor ID from the PCI Configuration Header\r
351 //\r
352 if (PciRead16 (Address) == MAX_UINT16) {\r
353 if (Function == 0) {\r
354 //\r
355 // If the PCI Configuration Read fails, or a PCI device does not\r
356 // exist, then skip this entire PCI device\r
357 //\r
358 break;\r
359 } else {\r
360 //\r
361 // If PCI function != 0, VendorId == 0xFFFF, we continue to search\r
362 // PCI function.\r
363 //\r
364 continue;\r
365 }\r
366 }\r
367\r
368 //\r
369 // Read the entire PCI Configuration Header\r
370 //\r
371 PciReadBuffer (Address, sizeof (Pci), &Pci);\r
372\r
373 //\r
374 // Increment the number of PCI device found on the primary bus of the\r
375 // PCI root bridge\r
376 //\r
377 NumberOfDevices++;\r
378\r
379 //\r
380 // Look for devices with the VGA Palette Snoop enabled in the COMMAND\r
381 // register of the PCI Config Header\r
382 //\r
383 if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
384 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
385 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r
386 }\r
387\r
388 BarOffsetEnd = 0;\r
389\r
390 //\r
391 // PCI-PCI Bridge\r
392 //\r
393 if (IS_PCI_BRIDGE (&Pci)) {\r
394 //\r
395 // Get the Bus range that the PPB is decoding\r
396 //\r
397 if (Pci.Bridge.SubordinateBus > SubBus) {\r
398 //\r
399 // If the subordinate bus number of the PCI-PCI bridge is greater\r
400 // than the PCI root bridge's current subordinate bus number,\r
401 // then update the PCI root bridge's subordinate bus number\r
402 //\r
403 SubBus = Pci.Bridge.SubordinateBus;\r
404 }\r
405\r
406 //\r
407 // Get the I/O range that the PPB is decoding\r
408 //\r
409 Value = Pci.Bridge.IoBase & 0x0f;\r
410 Base = ((UINT32) Pci.Bridge.IoBase & 0xf0) << 8;\r
411 Limit = (((UINT32) Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;\r
412 if (Value == BIT0) {\r
413 Base |= ((UINT32) Pci.Bridge.IoBaseUpper16 << 16);\r
414 Limit |= ((UINT32) Pci.Bridge.IoLimitUpper16 << 16);\r
415 }\r
416 if ((Base > 0) && (Base < Limit)) {\r
417 if (Io.Base > Base) {\r
418 Io.Base = Base;\r
419 }\r
420 if (Io.Limit < Limit) {\r
421 Io.Limit = Limit;\r
422 }\r
423 }\r
424\r
425 //\r
426 // Get the Memory range that the PPB is decoding\r
427 //\r
428 Base = ((UINT32) Pci.Bridge.MemoryBase & 0xfff0) << 16;\r
429 Limit = (((UINT32) Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;\r
430 if ((Base > 0) && (Base < Limit)) {\r
431 if (Mem.Base > Base) {\r
432 Mem.Base = Base;\r
433 }\r
434 if (Mem.Limit < Limit) {\r
435 Mem.Limit = Limit;\r
436 }\r
437 }\r
438\r
439 //\r
440 // Get the Prefetchable Memory range that the PPB is decoding\r
441 //\r
442 Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;\r
443 Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;\r
444 Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)\r
445 << 16) | 0xfffff;\r
446 MemAperture = &PMem;\r
447 if (Value == BIT0) {\r
448 Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);\r
449 Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);\r
450 MemAperture = &PMemAbove4G;\r
451 }\r
452 if ((Base > 0) && (Base < Limit)) {\r
453 if (MemAperture->Base > Base) {\r
454 MemAperture->Base = Base;\r
455 }\r
456 if (MemAperture->Limit < Limit) {\r
457 MemAperture->Limit = Limit;\r
458 }\r
459 }\r
460\r
461 //\r
462 // Look at the PPB Configuration for legacy decoding attributes\r
463 //\r
464 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)\r
465 == EFI_PCI_BRIDGE_CONTROL_ISA) {\r
466 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
467 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;\r
468 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
469 }\r
470 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)\r
471 == EFI_PCI_BRIDGE_CONTROL_VGA) {\r
472 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
473 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
474 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
475 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)\r
476 != 0) {\r
477 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r
478 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;\r
479 }\r
480 }\r
481\r
482 BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);\r
483 } else {\r
484 //\r
485 // Parse the BARs of the PCI device to get what I/O Ranges, Memory\r
486 // Ranges, and Prefetchable Memory Ranges the device is decoding\r
487 //\r
488 if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {\r
489 BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);\r
490 }\r
491 }\r
492\r
493 PcatPciRootBridgeParseBars (\r
494 Pci.Hdr.Command,\r
495 PrimaryBus,\r
496 Device,\r
497 Function,\r
498 OFFSET_OF (PCI_TYPE00, Device.Bar),\r
499 BarOffsetEnd,\r
500 &Io,\r
501 &Mem, &MemAbove4G,\r
502 &PMem, &PMemAbove4G\r
503 );\r
504\r
505 //\r
506 // See if the PCI device is an IDE controller\r
507 //\r
508 if (IS_CLASS2 (&Pci, PCI_CLASS_MASS_STORAGE,\r
509 PCI_CLASS_MASS_STORAGE_IDE)) {\r
510 if (Pci.Hdr.ClassCode[0] & 0x80) {\r
511 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
512 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
513 }\r
514 if (Pci.Hdr.ClassCode[0] & 0x01) {\r
515 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
516 }\r
517 if (Pci.Hdr.ClassCode[0] & 0x04) {\r
518 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
519 }\r
520 }\r
521\r
522 //\r
523 // See if the PCI device is a legacy VGA controller or\r
524 // a standard VGA controller\r
525 //\r
526 if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||\r
527 IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)\r
528 ) {\r
529 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
530 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r
531 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
532 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
533 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;\r
534 }\r
535\r
536 //\r
537 // See if the PCI Device is a PCI - ISA or PCI - EISA\r
538 // or ISA_POSITIVE_DECODE Bridge device\r
539 //\r
540 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {\r
541 if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA ||\r
542 Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA ||\r
543 Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) {\r
544 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
545 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;\r
546 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
547 }\r
548 }\r
549\r
550 //\r
551 // If this device is not a multi function device, then skip the rest\r
552 // of this PCI device\r
553 //\r
554 if (Function == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
555 break;\r
556 }\r
557 }\r
558 }\r
559\r
560 //\r
561 // If at least one PCI device was found on the primary bus of this PCI\r
562 // root bridge, then the PCI root bridge exists.\r
563 //\r
564 if (NumberOfDevices > 0) {\r
565 RootBridges = ReallocatePool (\r
566 (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),\r
567 (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),\r
568 RootBridges\r
569 );\r
570 ASSERT (RootBridges != NULL);\r
571\r
572 AdjustRootBridgeResource (&Io, &Mem, &MemAbove4G, &PMem, &PMemAbove4G);\r
573\r
574 InitRootBridge (\r
575 Attributes, Attributes, 0,\r
576 (UINT8) PrimaryBus, (UINT8) SubBus,\r
577 &Io, &Mem, &MemAbove4G, &PMem, &PMemAbove4G,\r
578 &RootBridges[*NumberOfRootBridges]\r
579 );\r
580 RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;\r
581 //\r
582 // Increment the index for the next PCI Root Bridge\r
583 //\r
584 (*NumberOfRootBridges)++;\r
585 }\r
586 }\r
587\r
588 return RootBridges;\r
589}\r
99de2e7e
ZL
590\r
591/**\r
592 Scan for all root bridges from Universal Payload PciRootBridgeInfoHob\r
593\r
594 @param[in] PciRootBridgeInfo Pointer of Universal Payload PCI Root Bridge Info Hob\r
595 @param[out] NumberOfRootBridges Number of root bridges detected\r
596\r
597 @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.\r
598\r
599**/\r
600PCI_ROOT_BRIDGE *\r
601RetrieveRootBridgeInfoFromHob (\r
602 IN UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo,\r
603 OUT UINTN *NumberOfRootBridges\r
604)\r
605{\r
606 PCI_ROOT_BRIDGE *PciRootBridges;\r
607 UINTN Size;\r
608 UINT8 Index;\r
609\r
610 ASSERT (PciRootBridgeInfo != NULL);\r
611 ASSERT (NumberOfRootBridges != NULL);\r
612 if (PciRootBridgeInfo == NULL) {\r
613 return NULL;\r
614 }\r
615 if (PciRootBridgeInfo->Count == 0) {\r
616 return NULL;\r
617 }\r
618 Size = PciRootBridgeInfo->Count * sizeof (PCI_ROOT_BRIDGE);\r
619 PciRootBridges = (PCI_ROOT_BRIDGE *) AllocatePool (Size);\r
620 ASSERT (PciRootBridges != NULL);\r
621 if (PciRootBridges == NULL) {\r
622 return NULL;\r
623 }\r
624 ZeroMem (PciRootBridges, PciRootBridgeInfo->Count * sizeof (PCI_ROOT_BRIDGE));\r
625\r
626 //\r
627 // Create all root bridges with PciRootBridgeInfoHob\r
628 //\r
629 for (Index = 0; Index < PciRootBridgeInfo->Count; Index++) {\r
630 PciRootBridges[Index].Segment = PciRootBridgeInfo->RootBridge[Index].Segment;\r
631 PciRootBridges[Index].Supports = PciRootBridgeInfo->RootBridge[Index].Supports;\r
632 PciRootBridges[Index].Attributes = PciRootBridgeInfo->RootBridge[Index].Attributes;\r
633 PciRootBridges[Index].DmaAbove4G = PciRootBridgeInfo->RootBridge[Index].DmaAbove4G;\r
634 PciRootBridges[Index].NoExtendedConfigSpace = PciRootBridgeInfo->RootBridge[Index].NoExtendedConfigSpace;\r
635 PciRootBridges[Index].ResourceAssigned = PciRootBridgeInfo->ResourceAssigned;\r
636 PciRootBridges[Index].AllocationAttributes = PciRootBridgeInfo->RootBridge[Index].AllocationAttributes;\r
637 PciRootBridges[Index].DevicePath = CreateRootBridgeDevicePath(PciRootBridgeInfo->RootBridge[Index].HID, PciRootBridgeInfo->RootBridge[Index].UID);\r
638 CopyMem(&PciRootBridges[Index].Bus, &PciRootBridgeInfo->RootBridge[Index].Bus, sizeof(UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r
639 CopyMem(&PciRootBridges[Index].Io, &PciRootBridgeInfo->RootBridge[Index].Io, sizeof(UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r
640 CopyMem(&PciRootBridges[Index].Mem, &PciRootBridgeInfo->RootBridge[Index].Mem, sizeof(UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r
641 CopyMem(&PciRootBridges[Index].MemAbove4G, &PciRootBridgeInfo->RootBridge[Index].MemAbove4G, sizeof(UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r
642 CopyMem(&PciRootBridges[Index].PMem, &PciRootBridgeInfo->RootBridge[Index].PMem, sizeof(UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r
643 CopyMem(&PciRootBridges[Index].PMemAbove4G, &PciRootBridgeInfo->RootBridge[Index].PMemAbove4G, sizeof(UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r
644 }\r
645\r
646 *NumberOfRootBridges = PciRootBridgeInfo->Count;\r
647\r
648 //\r
649 // Now, this library only supports RootBridge that ResourceAssigned is True\r
650 //\r
651 if (PciRootBridgeInfo->ResourceAssigned) {\r
652 PcdSetBoolS (PcdPciDisableBusEnumeration, TRUE);\r
653 } else {\r
654 DEBUG ((DEBUG_ERROR, "There is root bridge whose ResourceAssigned is FALSE\n"));\r
655 PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);\r
656 return NULL;\r
657 }\r
658\r
659 return PciRootBridges;\r
660}\r