]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c
OvmfPkg/PciHostBridgeUtilityLib: Initialize RootBridges apertures with spec
[mirror_edk2.git] / OvmfPkg / Library / PciHostBridgeUtilityLib / PciHostBridgeUtilityLib.c
1 /** @file
2 Provide common utility functions to PciHostBridgeLib instances in
3 ArmVirtPkg and OvmfPkg.
4
5 Copyright (C) 2016, Red Hat, Inc.
6 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
7 Copyright (c) 2020, Huawei Corporation. All rights reserved.<BR>
8
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11 **/
12
13 #include <IndustryStandard/Acpi10.h>
14 #include <IndustryStandard/Pci.h>
15 #include <Library/BaseLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/DevicePathLib.h>
19 #include <Library/HardwareInfoLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/PciHostBridgeUtilityLib.h>
22 #include <Library/PciLib.h>
23 #include <Library/QemuFwCfgLib.h>
24 #include <Protocol/PciHostBridgeResourceAllocation.h>
25
26 #pragma pack(1)
27 typedef struct {
28 ACPI_HID_DEVICE_PATH AcpiDevicePath;
29 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
30 } OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
31 #pragma pack ()
32
33 GLOBAL_REMOVE_IF_UNREFERENCED
34 CHAR16 *mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[] = {
35 L"Mem", L"I/O", L"Bus"
36 };
37
38 STATIC
39 CONST
40 OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
41 {
42 {
43 ACPI_DEVICE_PATH,
44 ACPI_DP,
45 {
46 (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),
47 (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
48 }
49 },
50 EISA_PNP_ID (0x0A03), // HID
51 0 // UID
52 },
53
54 {
55 END_DEVICE_PATH_TYPE,
56 END_ENTIRE_DEVICE_PATH_SUBTYPE,
57 {
58 END_DEVICE_PATH_LENGTH,
59 0
60 }
61 }
62 };
63
64 /**
65 Utility function to initialize a PCI_ROOT_BRIDGE structure.
66
67 @param[in] Supports Supported attributes.
68
69 @param[in] Attributes Initial attributes.
70
71 @param[in] AllocAttributes Allocation attributes.
72
73 @param[in] DmaAbove4G DMA above 4GB memory.
74
75 @param[in] NoExtendedConfigSpace No Extended Config Space.
76
77 @param[in] RootBusNumber The bus number to store in RootBus.
78
79 @param[in] MaxSubBusNumber The inclusive maximum bus number that can
80 be assigned to any subordinate bus found
81 behind any PCI bridge hanging off this
82 root bus.
83
84 The caller is repsonsible for ensuring
85 that RootBusNumber <= MaxSubBusNumber. If
86 RootBusNumber equals MaxSubBusNumber, then
87 the root bus has no room for subordinate
88 buses.
89
90 @param[in] Io IO aperture.
91
92 @param[in] Mem MMIO aperture.
93
94 @param[in] MemAbove4G MMIO aperture above 4G.
95
96 @param[in] PMem Prefetchable MMIO aperture.
97
98 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
99
100 @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated
101 by the caller) that should be filled in by
102 this function.
103
104 @retval EFI_SUCCESS Initialization successful. A device path
105 consisting of an ACPI device path node,
106 with UID = RootBusNumber, has been
107 allocated and linked into RootBus.
108
109 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
110 **/
111 EFI_STATUS
112 EFIAPI
113 PciHostBridgeUtilityInitRootBridge (
114 IN UINT64 Supports,
115 IN UINT64 Attributes,
116 IN UINT64 AllocAttributes,
117 IN BOOLEAN DmaAbove4G,
118 IN BOOLEAN NoExtendedConfigSpace,
119 IN UINT8 RootBusNumber,
120 IN UINT8 MaxSubBusNumber,
121 IN PCI_ROOT_BRIDGE_APERTURE *Io,
122 IN PCI_ROOT_BRIDGE_APERTURE *Mem,
123 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
124 IN PCI_ROOT_BRIDGE_APERTURE *PMem,
125 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
126 OUT PCI_ROOT_BRIDGE *RootBus
127 )
128 {
129 OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
130
131 //
132 // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
133 //
134 ZeroMem (RootBus, sizeof *RootBus);
135
136 RootBus->Segment = 0;
137
138 RootBus->Supports = Supports;
139 RootBus->Attributes = Attributes;
140
141 RootBus->DmaAbove4G = DmaAbove4G;
142
143 RootBus->AllocationAttributes = AllocAttributes;
144 RootBus->Bus.Base = RootBusNumber;
145 RootBus->Bus.Limit = MaxSubBusNumber;
146 CopyMem (&RootBus->Io, Io, sizeof (*Io));
147 CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
148 CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));
149 CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
150 CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));
151
152 RootBus->NoExtendedConfigSpace = NoExtendedConfigSpace;
153
154 DevicePath = AllocateCopyPool (
155 sizeof mRootBridgeDevicePathTemplate,
156 &mRootBridgeDevicePathTemplate
157 );
158 if (DevicePath == NULL) {
159 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
160 return EFI_OUT_OF_RESOURCES;
161 }
162
163 DevicePath->AcpiDevicePath.UID = RootBusNumber;
164 RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
165
166 DEBUG ((
167 DEBUG_INFO,
168 "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
169 __FUNCTION__,
170 RootBusNumber,
171 MaxSubBusNumber - RootBusNumber
172 ));
173 return EFI_SUCCESS;
174 }
175
176 /**
177 Utility function to uninitialize a PCI_ROOT_BRIDGE structure set up with
178 PciHostBridgeUtilityInitRootBridge().
179
180 @param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and
181 initialized with PciHostBridgeUtilityInitRootBridge(),
182 that should be uninitialized. This function doesn't free
183 RootBus.
184 **/
185 VOID
186 EFIAPI
187 PciHostBridgeUtilityUninitRootBridge (
188 IN PCI_ROOT_BRIDGE *RootBus
189 )
190 {
191 FreePool (RootBus->DevicePath);
192 }
193
194 /**
195 Utility function to scan PCI root bridges and create instances for those
196 that are found not empty. Populate their resources from the default
197 provided parameters and return all the root bridge instances in an array.
198
199 @param[out] Count The number of root bridge instances.
200
201 @param[in] Attributes Initial attributes.
202
203 @param[in] AllocAttributes Allocation attributes.
204
205 @param[in] DmaAbove4G DMA above 4GB memory.
206
207 @param[in] NoExtendedConfigSpace No Extended Config Space.
208
209 @param[in] BusMin Minimum Bus number, inclusive.
210
211 @param[in] BusMax Maximum Bus number, inclusive.
212
213 @param[in] Io IO aperture.
214
215 @param[in] Mem MMIO aperture.
216
217 @param[in] MemAbove4G MMIO aperture above 4G.
218
219 @param[in] PMem Prefetchable MMIO aperture.
220
221 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
222
223 @return All the root bridge instances in an array.
224 **/
225 STATIC
226 PCI_ROOT_BRIDGE *
227 PciHostBridgeUtilityGetRootBridgesBusScan (
228 OUT UINTN *Count,
229 IN UINT64 Attributes,
230 IN UINT64 AllocationAttributes,
231 IN BOOLEAN DmaAbove4G,
232 IN BOOLEAN NoExtendedConfigSpace,
233 IN UINTN BusMin,
234 IN UINTN BusMax,
235 IN PCI_ROOT_BRIDGE_APERTURE *Io,
236 IN PCI_ROOT_BRIDGE_APERTURE *Mem,
237 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
238 IN PCI_ROOT_BRIDGE_APERTURE *PMem,
239 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G
240 )
241 {
242 EFI_STATUS Status;
243 FIRMWARE_CONFIG_ITEM FwCfgItem;
244 UINTN FwCfgSize;
245 UINT64 ExtraRootBridges;
246 PCI_ROOT_BRIDGE *Bridges;
247 UINTN Initialized;
248 UINTN LastRootBridgeNumber;
249 UINTN RootBridgeNumber;
250
251 if ((BusMin > BusMax) || (BusMax > PCI_MAX_BUS)) {
252 DEBUG ((
253 DEBUG_ERROR,
254 "%a: invalid bus range with BusMin %Lu and BusMax "
255 "%Lu\n",
256 __FUNCTION__,
257 (UINT64)BusMin,
258 (UINT64)BusMax
259 ));
260 return NULL;
261 }
262
263 //
264 // QEMU provides the number of extra root buses, shortening the exhaustive
265 // search below. If there is no hint, the feature is missing.
266 //
267 Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
268 if (EFI_ERROR (Status) || (FwCfgSize != sizeof ExtraRootBridges)) {
269 ExtraRootBridges = 0;
270 } else {
271 QemuFwCfgSelectItem (FwCfgItem);
272 QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges);
273
274 //
275 // Validate the number of extra root bridges. As BusMax is inclusive, the
276 // max bus count is (BusMax - BusMin + 1). From that, the "main" root bus
277 // is always a given, so the max count for the "extra" root bridges is one
278 // less, i.e. (BusMax - BusMin). If the QEMU hint exceeds that, we have
279 // invalid behavior.
280 //
281 if (ExtraRootBridges > BusMax - BusMin) {
282 DEBUG ((
283 DEBUG_ERROR,
284 "%a: invalid count of extra root buses (%Lu) "
285 "reported by QEMU\n",
286 __FUNCTION__,
287 ExtraRootBridges
288 ));
289 return NULL;
290 }
291
292 DEBUG ((
293 DEBUG_INFO,
294 "%a: %Lu extra root buses reported by QEMU\n",
295 __FUNCTION__,
296 ExtraRootBridges
297 ));
298 }
299
300 //
301 // Allocate the "main" root bridge, and any extra root bridges.
302 //
303 Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);
304 if (Bridges == NULL) {
305 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
306 return NULL;
307 }
308
309 Initialized = 0;
310
311 //
312 // The "main" root bus is always there.
313 //
314 LastRootBridgeNumber = BusMin;
315
316 //
317 // Scan all other root buses. If function 0 of any device on a bus returns a
318 // VendorId register value different from all-bits-one, then that bus is
319 // alive.
320 //
321 for (RootBridgeNumber = BusMin + 1;
322 RootBridgeNumber <= BusMax && Initialized < ExtraRootBridges;
323 ++RootBridgeNumber)
324 {
325 UINTN Device;
326
327 for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
328 if (PciRead16 (
329 PCI_LIB_ADDRESS (
330 RootBridgeNumber,
331 Device,
332 0,
333 PCI_VENDOR_ID_OFFSET
334 )
335 ) != MAX_UINT16)
336 {
337 break;
338 }
339 }
340
341 if (Device <= PCI_MAX_DEVICE) {
342 //
343 // Found the next root bus. We can now install the *previous* one,
344 // because now we know how big a bus number range *that* one has, for any
345 // subordinate buses that might exist behind PCI bridges hanging off it.
346 //
347 Status = PciHostBridgeUtilityInitRootBridge (
348 Attributes,
349 Attributes,
350 AllocationAttributes,
351 DmaAbove4G,
352 NoExtendedConfigSpace,
353 (UINT8)LastRootBridgeNumber,
354 (UINT8)(RootBridgeNumber - 1),
355 Io,
356 Mem,
357 MemAbove4G,
358 PMem,
359 PMemAbove4G,
360 &Bridges[Initialized]
361 );
362 if (EFI_ERROR (Status)) {
363 goto FreeBridges;
364 }
365
366 ++Initialized;
367 LastRootBridgeNumber = RootBridgeNumber;
368 }
369 }
370
371 //
372 // Install the last root bus (which might be the only, ie. main, root bus, if
373 // we've found no extra root buses).
374 //
375 Status = PciHostBridgeUtilityInitRootBridge (
376 Attributes,
377 Attributes,
378 AllocationAttributes,
379 DmaAbove4G,
380 NoExtendedConfigSpace,
381 (UINT8)LastRootBridgeNumber,
382 (UINT8)BusMax,
383 Io,
384 Mem,
385 MemAbove4G,
386 PMem,
387 PMemAbove4G,
388 &Bridges[Initialized]
389 );
390 if (EFI_ERROR (Status)) {
391 goto FreeBridges;
392 }
393
394 ++Initialized;
395
396 *Count = Initialized;
397 return Bridges;
398
399 FreeBridges:
400 while (Initialized > 0) {
401 --Initialized;
402 PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]);
403 }
404
405 FreePool (Bridges);
406 return NULL;
407 }
408
409 /**
410 Utility function to read root bridges information from host-provided fw-cfg
411 file and return them in an array.
412
413 @param[out] Count The number of root bridge instances.
414
415 @return All the root bridge instances in an array parsed from
416 host-provided fw-cfg file (hardware-info).
417 **/
418 STATIC
419 PCI_ROOT_BRIDGE *
420 PciHostBridgeUtilityGetRootBridgesHostProvided (
421 OUT UINTN *Count
422 )
423 {
424 EFI_STATUS Status;
425 FIRMWARE_CONFIG_ITEM FwCfgItem;
426 UINTN FwCfgSize;
427 PCI_ROOT_BRIDGE *Bridges;
428 UINTN Initialized;
429 UINTN LastRootBridgeNumber;
430 UINTN RootBridgeNumber;
431 UINTN PciHostBridgeCount;
432 UINT8 *HardwareInfoBlob;
433 LIST_ENTRY HwInfoList;
434 LIST_ENTRY *HwLink;
435 HARDWARE_INFO *HwInfo;
436 UINT64 Attributes;
437 UINT64 AllocationAttributes;
438 BOOLEAN DmaAbove4G;
439 BOOLEAN NoExtendedConfigSpace;
440 BOOLEAN CombineMemPMem;
441 PCI_ROOT_BRIDGE_APERTURE Io;
442 PCI_ROOT_BRIDGE_APERTURE Mem;
443 PCI_ROOT_BRIDGE_APERTURE MemAbove4G;
444 PCI_ROOT_BRIDGE_APERTURE PMem;
445 PCI_ROOT_BRIDGE_APERTURE PMemAbove4G;
446
447 //
448 // Initialize the Hardware Info list head to start with an empty but valid
449 // list head.
450 //
451 InitializeListHead (&HwInfoList);
452 HardwareInfoBlob = NULL;
453 Initialized = 0;
454 Bridges = NULL;
455 PciHostBridgeCount = 0;
456
457 //
458 // Hypervisor can provide the specifications (resources) for one or more
459 // PCI host bridges. Such information comes through fw-cfg as part of
460 // the hardware-info file.
461 //
462 Status = QemuFwCfgFindFile ("etc/hardware-info", &FwCfgItem, &FwCfgSize);
463
464 if (EFI_ERROR (Status)) {
465 return NULL;
466 }
467
468 HardwareInfoBlob = AllocatePool (FwCfgSize);
469
470 if (HardwareInfoBlob == NULL) {
471 DEBUG ((
472 DEBUG_ERROR,
473 "%a: Failed to allocate memory for hardware resources info\n",
474 __FUNCTION__
475 ));
476 return NULL;
477 }
478
479 QemuFwCfgSelectItem (FwCfgItem);
480 QemuFwCfgReadBytes (FwCfgSize, HardwareInfoBlob);
481
482 //
483 // Create the list of hardware info devices filtering for PCI host
484 // bridges
485 //
486 Status = CreateHardwareInfoList (
487 HardwareInfoBlob,
488 FwCfgSize,
489 HardwareInfoTypeHostBridge,
490 &HwInfoList
491 );
492
493 if (EFI_ERROR (Status)) {
494 DEBUG ((
495 DEBUG_ERROR,
496 "%a: Failed to create hardware info list to retrieve host "
497 "bridges information from fw-cfg\n",
498 __FUNCTION__
499 ));
500
501 goto FreeBridges;
502 }
503
504 PciHostBridgeCount = GetHardwareInfoCountByType (
505 &HwInfoList,
506 HardwareInfoTypeHostBridge,
507 sizeof (HOST_BRIDGE_INFO)
508 );
509
510 if (PciHostBridgeCount == 0) {
511 goto FreeBridges;
512 }
513
514 DEBUG ((
515 DEBUG_INFO,
516 "%a: Host provided description for %Lu root bridges\n",
517 __FUNCTION__,
518 PciHostBridgeCount
519 ));
520
521 //
522 // Allocate the root bridges
523 //
524 Bridges = AllocatePool (((UINTN)PciHostBridgeCount) * sizeof *Bridges);
525 if (Bridges == NULL) {
526 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
527 goto FreeBridges;
528 }
529
530 //
531 // If Host Bridges' specification was obtained from fw-cfg, the list
532 // contains information to populate all root bridges in the system
533 // including resources and attributes.
534 //
535 HwLink = GetFirstHardwareInfoByType (
536 &HwInfoList,
537 HardwareInfoTypeHostBridge,
538 sizeof (HOST_BRIDGE_INFO)
539 );
540
541 while (!EndOfHardwareInfoList (&HwInfoList, HwLink)) {
542 HwInfo = HARDWARE_INFO_FROM_LINK (HwLink);
543
544 Status = HardwareInfoPciHostBridgeGet (
545 HwInfo->Data.PciHostBridge,
546 (UINTN)HwInfo->Header.Size,
547 &RootBridgeNumber,
548 &LastRootBridgeNumber,
549 &Attributes,
550 &DmaAbove4G,
551 &NoExtendedConfigSpace,
552 &CombineMemPMem,
553 &Io,
554 &Mem,
555 &MemAbove4G,
556 &PMem,
557 &PMemAbove4G,
558 NULL
559 );
560
561 if (EFI_ERROR (Status)) {
562 goto FreeBridges;
563 }
564
565 if ((RootBridgeNumber > LastRootBridgeNumber) || (LastRootBridgeNumber > PCI_MAX_BUS)) {
566 DEBUG ((
567 DEBUG_ERROR,
568 "%a: invalid bus range with BusMin %Lu and BusMax "
569 "%Lu\n",
570 __FUNCTION__,
571 (UINT64)RootBridgeNumber,
572 (UINT64)LastRootBridgeNumber
573 ));
574 goto FreeBridges;
575 }
576
577 AllocationAttributes = 0;
578 if (CombineMemPMem) {
579 AllocationAttributes |= EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;
580 }
581
582 if ((MemAbove4G.Limit > MemAbove4G.Base) ||
583 (PMemAbove4G.Limit > PMemAbove4G.Base))
584 {
585 AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
586 }
587
588 Status = PciHostBridgeUtilityInitRootBridge (
589 Attributes,
590 Attributes,
591 AllocationAttributes,
592 DmaAbove4G,
593 NoExtendedConfigSpace,
594 (UINT8)RootBridgeNumber,
595 (UINT8)LastRootBridgeNumber,
596 &Io,
597 &Mem,
598 &MemAbove4G,
599 &PMem,
600 &PMemAbove4G,
601 &Bridges[Initialized]
602 );
603
604 if (EFI_ERROR (Status)) {
605 goto FreeBridges;
606 }
607
608 ++Initialized;
609
610 HwLink = GetNextHardwareInfoByType (
611 &HwInfoList,
612 HwLink,
613 HardwareInfoTypeHostBridge,
614 sizeof (HOST_BRIDGE_INFO)
615 );
616 }
617
618 *Count = Initialized;
619
620 //
621 // If resources were allocated for host bridges info, release them
622 //
623 if (HardwareInfoBlob) {
624 FreePool (HardwareInfoBlob);
625 }
626
627 FreeHardwareInfoList (&HwInfoList);
628 return Bridges;
629
630 FreeBridges:
631 while (Initialized > 0) {
632 --Initialized;
633 PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]);
634 }
635
636 if (Bridges) {
637 FreePool (Bridges);
638 }
639
640 if (HardwareInfoBlob) {
641 FreePool (HardwareInfoBlob);
642 }
643
644 FreeHardwareInfoList (&HwInfoList);
645 return NULL;
646 }
647
648 /**
649 Utility function to return all the root bridge instances in an array.
650
651 @param[out] Count The number of root bridge instances.
652
653 @param[in] Attributes Initial attributes.
654
655 @param[in] AllocAttributes Allocation attributes.
656
657 @param[in] DmaAbove4G DMA above 4GB memory.
658
659 @param[in] NoExtendedConfigSpace No Extended Config Space.
660
661 @param[in] BusMin Minimum Bus number, inclusive.
662
663 @param[in] BusMax Maximum Bus number, inclusive.
664
665 @param[in] Io IO aperture.
666
667 @param[in] Mem MMIO aperture.
668
669 @param[in] MemAbove4G MMIO aperture above 4G.
670
671 @param[in] PMem Prefetchable MMIO aperture.
672
673 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
674
675 @return All the root bridge instances in an array.
676 **/
677 PCI_ROOT_BRIDGE *
678 EFIAPI
679 PciHostBridgeUtilityGetRootBridges (
680 OUT UINTN *Count,
681 IN UINT64 Attributes,
682 IN UINT64 AllocationAttributes,
683 IN BOOLEAN DmaAbove4G,
684 IN BOOLEAN NoExtendedConfigSpace,
685 IN UINTN BusMin,
686 IN UINTN BusMax,
687 IN PCI_ROOT_BRIDGE_APERTURE *Io,
688 IN PCI_ROOT_BRIDGE_APERTURE *Mem,
689 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
690 IN PCI_ROOT_BRIDGE_APERTURE *PMem,
691 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G
692 )
693 {
694 PCI_ROOT_BRIDGE *Bridges;
695
696 *Count = 0;
697
698 //
699 // First attempt to get the host provided descriptions of the Root Bridges
700 // if available.
701 //
702 Bridges = PciHostBridgeUtilityGetRootBridgesHostProvided (Count);
703
704 //
705 // If host did not provide Root Bridge information, scan the buses and
706 // auto populate them with default resources.
707 //
708 if (Bridges == NULL) {
709 Bridges = PciHostBridgeUtilityGetRootBridgesBusScan (
710 Count,
711 Attributes,
712 AllocationAttributes,
713 DmaAbove4G,
714 NoExtendedConfigSpace,
715 BusMin,
716 BusMax,
717 Io,
718 Mem,
719 MemAbove4G,
720 PMem,
721 PMemAbove4G
722 );
723 }
724
725 return Bridges;
726 }
727
728 /**
729 Utility function to free root bridge instances array from
730 PciHostBridgeUtilityGetRootBridges().
731
732 @param[in] Bridges The root bridge instances array.
733 @param[in] Count The count of the array.
734 **/
735 VOID
736 EFIAPI
737 PciHostBridgeUtilityFreeRootBridges (
738 IN PCI_ROOT_BRIDGE *Bridges,
739 IN UINTN Count
740 )
741 {
742 if ((Bridges == NULL) && (Count == 0)) {
743 return;
744 }
745
746 ASSERT (Bridges != NULL && Count > 0);
747
748 do {
749 --Count;
750 PciHostBridgeUtilityUninitRootBridge (&Bridges[Count]);
751 } while (Count > 0);
752
753 FreePool (Bridges);
754 }
755
756 /**
757 Utility function to inform the platform that the resource conflict happens.
758
759 @param[in] Configuration Pointer to PCI I/O and PCI memory resource
760 descriptors. The Configuration contains the
761 resources for all the root bridges. The resource
762 for each root bridge is terminated with END
763 descriptor and an additional END is appended
764 indicating the end of the entire resources. The
765 resource descriptor field values follow the
766 description in
767 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
768 .SubmitResources().
769 **/
770 VOID
771 EFIAPI
772 PciHostBridgeUtilityResourceConflict (
773 IN VOID *Configuration
774 )
775 {
776 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
777 UINTN RootBridgeIndex;
778
779 DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
780
781 RootBridgeIndex = 0;
782 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
783 while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
784 DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
785 for ( ; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
786 ASSERT (
787 Descriptor->ResType <
788 ARRAY_SIZE (mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr)
789 );
790 DEBUG ((
791 DEBUG_ERROR,
792 " %s: Length/Alignment = 0x%lx / 0x%lx\n",
793 mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
794 Descriptor->AddrLen,
795 Descriptor->AddrRangeMax
796 ));
797 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
798 DEBUG ((
799 DEBUG_ERROR,
800 " Granularity/SpecificFlag = %ld / %02x%s\n",
801 Descriptor->AddrSpaceGranularity,
802 Descriptor->SpecificFlag,
803 ((Descriptor->SpecificFlag &
804 EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
805 ) != 0) ? L" (Prefetchable)" : L""
806 ));
807 }
808 }
809
810 //
811 // Skip the END descriptor for root bridge
812 //
813 ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
814 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
815 (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
816 );
817 }
818 }