VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c

Last change on this file was 108794, checked in by vboxsync, 5 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 23.5 KB
Line 
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)
27typedef struct {
28 ACPI_HID_DEVICE_PATH AcpiDevicePath;
29 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
30} OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
31#pragma pack ()
32
33GLOBAL_REMOVE_IF_UNREFERENCED
34CHAR16 *mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[] = {
35 L"Mem", L"I/O", L"Bus"
36};
37
38STATIC
39CONST
40OVMF_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**/
111EFI_STATUS
112EFIAPI
113PciHostBridgeUtilityInitRootBridge (
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", __func__, 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 __func__,
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**/
185VOID
186EFIAPI
187PciHostBridgeUtilityUninitRootBridge (
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**/
225STATIC
226PCI_ROOT_BRIDGE *
227PciHostBridgeUtilityGetRootBridgesBusScan (
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 __func__,
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 __func__,
287 ExtraRootBridges
288 ));
289 return NULL;
290 }
291
292 DEBUG ((
293 DEBUG_INFO,
294 "%a: %Lu extra root buses reported by QEMU\n",
295 __func__,
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", __func__, 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
399FreeBridges:
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**/
418STATIC
419PCI_ROOT_BRIDGE *
420PciHostBridgeUtilityGetRootBridgesHostProvided (
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 ZeroMem (&Io, sizeof (Io));
448 ZeroMem (&Mem, sizeof (Mem));
449 ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
450 ZeroMem (&PMem, sizeof (PMem));
451 ZeroMem (&PMemAbove4G, sizeof (PMemAbove4G));
452
453 //
454 // Initialize the Hardware Info list head to start with an empty but valid
455 // list head.
456 //
457 InitializeListHead (&HwInfoList);
458 HardwareInfoBlob = NULL;
459 Initialized = 0;
460 Bridges = NULL;
461 PciHostBridgeCount = 0;
462
463 //
464 // Hypervisor can provide the specifications (resources) for one or more
465 // PCI host bridges. Such information comes through fw-cfg as part of
466 // the hardware-info file.
467 //
468 Status = QemuFwCfgFindFile ("etc/hardware-info", &FwCfgItem, &FwCfgSize);
469
470 if (EFI_ERROR (Status)) {
471 return NULL;
472 }
473
474 HardwareInfoBlob = AllocatePool (FwCfgSize);
475
476 if (HardwareInfoBlob == NULL) {
477 DEBUG ((
478 DEBUG_ERROR,
479 "%a: Failed to allocate memory for hardware resources info\n",
480 __func__
481 ));
482 return NULL;
483 }
484
485 QemuFwCfgSelectItem (FwCfgItem);
486 QemuFwCfgReadBytes (FwCfgSize, HardwareInfoBlob);
487
488 //
489 // Create the list of hardware info devices filtering for PCI host
490 // bridges
491 //
492 Status = CreateHardwareInfoList (
493 HardwareInfoBlob,
494 FwCfgSize,
495 HardwareInfoTypeHostBridge,
496 &HwInfoList
497 );
498
499 if (EFI_ERROR (Status)) {
500 DEBUG ((
501 DEBUG_ERROR,
502 "%a: Failed to create hardware info list to retrieve host "
503 "bridges information from fw-cfg\n",
504 __func__
505 ));
506
507 goto FreeBridges;
508 }
509
510 PciHostBridgeCount = GetHardwareInfoCountByType (
511 &HwInfoList,
512 HardwareInfoTypeHostBridge,
513 sizeof (HOST_BRIDGE_INFO)
514 );
515
516 if (PciHostBridgeCount == 0) {
517 goto FreeBridges;
518 }
519
520 DEBUG ((
521 DEBUG_INFO,
522 "%a: Host provided description for %Lu root bridges\n",
523 __func__,
524 PciHostBridgeCount
525 ));
526
527 //
528 // Allocate the root bridges
529 //
530 Bridges = AllocatePool (((UINTN)PciHostBridgeCount) * sizeof *Bridges);
531 if (Bridges == NULL) {
532 DEBUG ((DEBUG_ERROR, "%a: %r\n", __func__, EFI_OUT_OF_RESOURCES));
533 goto FreeBridges;
534 }
535
536 //
537 // If Host Bridges' specification was obtained from fw-cfg, the list
538 // contains information to populate all root bridges in the system
539 // including resources and attributes.
540 //
541 HwLink = GetFirstHardwareInfoByType (
542 &HwInfoList,
543 HardwareInfoTypeHostBridge,
544 sizeof (HOST_BRIDGE_INFO)
545 );
546
547 while (!EndOfHardwareInfoList (&HwInfoList, HwLink)) {
548 HwInfo = HARDWARE_INFO_FROM_LINK (HwLink);
549
550 Status = HardwareInfoPciHostBridgeGet (
551 HwInfo->Data.PciHostBridge,
552 (UINTN)HwInfo->Header.Size,
553 &RootBridgeNumber,
554 &LastRootBridgeNumber,
555 &Attributes,
556 &DmaAbove4G,
557 &NoExtendedConfigSpace,
558 &CombineMemPMem,
559 &Io,
560 &Mem,
561 &MemAbove4G,
562 &PMem,
563 &PMemAbove4G,
564 NULL
565 );
566
567 if (EFI_ERROR (Status)) {
568 goto FreeBridges;
569 }
570
571 if ((RootBridgeNumber > LastRootBridgeNumber) || (LastRootBridgeNumber > PCI_MAX_BUS)) {
572 DEBUG ((
573 DEBUG_ERROR,
574 "%a: invalid bus range with BusMin %Lu and BusMax "
575 "%Lu\n",
576 __func__,
577 (UINT64)RootBridgeNumber,
578 (UINT64)LastRootBridgeNumber
579 ));
580 goto FreeBridges;
581 }
582
583 AllocationAttributes = 0;
584 if (CombineMemPMem) {
585 AllocationAttributes |= EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;
586 }
587
588 if ((MemAbove4G.Limit > MemAbove4G.Base) ||
589 (PMemAbove4G.Limit > PMemAbove4G.Base))
590 {
591 AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
592 }
593
594 Status = PciHostBridgeUtilityInitRootBridge (
595 Attributes,
596 Attributes,
597 AllocationAttributes,
598 DmaAbove4G,
599 NoExtendedConfigSpace,
600 (UINT8)RootBridgeNumber,
601 (UINT8)LastRootBridgeNumber,
602 &Io,
603 &Mem,
604 &MemAbove4G,
605 &PMem,
606 &PMemAbove4G,
607 &Bridges[Initialized]
608 );
609
610 if (EFI_ERROR (Status)) {
611 goto FreeBridges;
612 }
613
614 ++Initialized;
615
616 HwLink = GetNextHardwareInfoByType (
617 &HwInfoList,
618 HwLink,
619 HardwareInfoTypeHostBridge,
620 sizeof (HOST_BRIDGE_INFO)
621 );
622 }
623
624 *Count = Initialized;
625
626 //
627 // If resources were allocated for host bridges info, release them
628 //
629 if (HardwareInfoBlob) {
630 FreePool (HardwareInfoBlob);
631 }
632
633 FreeHardwareInfoList (&HwInfoList);
634 return Bridges;
635
636FreeBridges:
637 while (Initialized > 0) {
638 --Initialized;
639 PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]);
640 }
641
642 if (Bridges) {
643 FreePool (Bridges);
644 }
645
646 if (HardwareInfoBlob) {
647 FreePool (HardwareInfoBlob);
648 }
649
650 FreeHardwareInfoList (&HwInfoList);
651 return NULL;
652}
653
654/**
655 Utility function to return all the root bridge instances in an array.
656
657 @param[out] Count The number of root bridge instances.
658
659 @param[in] Attributes Initial attributes.
660
661 @param[in] AllocAttributes Allocation attributes.
662
663 @param[in] DmaAbove4G DMA above 4GB memory.
664
665 @param[in] NoExtendedConfigSpace No Extended Config Space.
666
667 @param[in] BusMin Minimum Bus number, inclusive.
668
669 @param[in] BusMax Maximum Bus number, inclusive.
670
671 @param[in] Io IO aperture.
672
673 @param[in] Mem MMIO aperture.
674
675 @param[in] MemAbove4G MMIO aperture above 4G.
676
677 @param[in] PMem Prefetchable MMIO aperture.
678
679 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
680
681 @return All the root bridge instances in an array.
682**/
683PCI_ROOT_BRIDGE *
684EFIAPI
685PciHostBridgeUtilityGetRootBridges (
686 OUT UINTN *Count,
687 IN UINT64 Attributes,
688 IN UINT64 AllocationAttributes,
689 IN BOOLEAN DmaAbove4G,
690 IN BOOLEAN NoExtendedConfigSpace,
691 IN UINTN BusMin,
692 IN UINTN BusMax,
693 IN PCI_ROOT_BRIDGE_APERTURE *Io,
694 IN PCI_ROOT_BRIDGE_APERTURE *Mem,
695 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
696 IN PCI_ROOT_BRIDGE_APERTURE *PMem,
697 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G
698 )
699{
700 PCI_ROOT_BRIDGE *Bridges;
701
702 *Count = 0;
703
704 //
705 // First attempt to get the host provided descriptions of the Root Bridges
706 // if available.
707 //
708 Bridges = PciHostBridgeUtilityGetRootBridgesHostProvided (Count);
709
710 //
711 // If host did not provide Root Bridge information, scan the buses and
712 // auto populate them with default resources.
713 //
714 if (Bridges == NULL) {
715 Bridges = PciHostBridgeUtilityGetRootBridgesBusScan (
716 Count,
717 Attributes,
718 AllocationAttributes,
719 DmaAbove4G,
720 NoExtendedConfigSpace,
721 BusMin,
722 BusMax,
723 Io,
724 Mem,
725 MemAbove4G,
726 PMem,
727 PMemAbove4G
728 );
729 }
730
731 return Bridges;
732}
733
734/**
735 Utility function to free root bridge instances array from
736 PciHostBridgeUtilityGetRootBridges().
737
738 @param[in] Bridges The root bridge instances array.
739 @param[in] Count The count of the array.
740**/
741VOID
742EFIAPI
743PciHostBridgeUtilityFreeRootBridges (
744 IN PCI_ROOT_BRIDGE *Bridges,
745 IN UINTN Count
746 )
747{
748 if ((Bridges == NULL) && (Count == 0)) {
749 return;
750 }
751
752 ASSERT (Bridges != NULL && Count > 0);
753
754 do {
755 --Count;
756 PciHostBridgeUtilityUninitRootBridge (&Bridges[Count]);
757 } while (Count > 0);
758
759 FreePool (Bridges);
760}
761
762/**
763 Utility function to inform the platform that the resource conflict happens.
764
765 @param[in] Configuration Pointer to PCI I/O and PCI memory resource
766 descriptors. The Configuration contains the
767 resources for all the root bridges. The resource
768 for each root bridge is terminated with END
769 descriptor and an additional END is appended
770 indicating the end of the entire resources. The
771 resource descriptor field values follow the
772 description in
773 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
774 .SubmitResources().
775**/
776VOID
777EFIAPI
778PciHostBridgeUtilityResourceConflict (
779 IN VOID *Configuration
780 )
781{
782 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
783 UINTN RootBridgeIndex;
784
785 DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
786
787 RootBridgeIndex = 0;
788 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
789 while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
790 DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
791 for ( ; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
792 ASSERT (
793 Descriptor->ResType <
794 ARRAY_SIZE (mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr)
795 );
796 DEBUG ((
797 DEBUG_ERROR,
798 " %s: Length/Alignment = 0x%lx / 0x%lx\n",
799 mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
800 Descriptor->AddrLen,
801 Descriptor->AddrRangeMax
802 ));
803 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
804 DEBUG ((
805 DEBUG_ERROR,
806 " Granularity/SpecificFlag = %ld / %02x%s\n",
807 Descriptor->AddrSpaceGranularity,
808 Descriptor->SpecificFlag,
809 ((Descriptor->SpecificFlag &
810 EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
811 ) != 0) ? L" (Prefetchable)" : L""
812 ));
813 }
814 }
815
816 //
817 // Skip the END descriptor for root bridge
818 //
819 ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
820 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
821 (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
822 );
823 }
824}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette