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