]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
OvmfPkg: replace old EFI_D_ debug levels with new DEBUG_ ones
[mirror_edk2.git] / OvmfPkg / Library / PciHostBridgeLib / PciHostBridgeLib.c
1 /** @file
2 OVMF's instance of the PCI Host Bridge Library.
3
4 Copyright (C) 2016, Red Hat, Inc.
5 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10 #include <PiDxe.h>
11
12 #include <IndustryStandard/Pci.h>
13 #include <IndustryStandard/Q35MchIch9.h>
14
15 #include <Protocol/PciHostBridgeResourceAllocation.h>
16 #include <Protocol/PciRootBridgeIo.h>
17
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/DevicePathLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/PciHostBridgeLib.h>
23 #include <Library/PciLib.h>
24 #include <Library/QemuFwCfgLib.h>
25 #include "PciHostBridge.h"
26
27
28 #pragma pack(1)
29 typedef struct {
30 ACPI_HID_DEVICE_PATH AcpiDevicePath;
31 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
32 } OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
33 #pragma pack ()
34
35
36 GLOBAL_REMOVE_IF_UNREFERENCED
37 CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
38 L"Mem", L"I/O", L"Bus"
39 };
40
41
42 STATIC
43 CONST
44 OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
45 {
46 {
47 ACPI_DEVICE_PATH,
48 ACPI_DP,
49 {
50 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
51 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
52 }
53 },
54 EISA_PNP_ID(0x0A03), // HID
55 0 // UID
56 },
57
58 {
59 END_DEVICE_PATH_TYPE,
60 END_ENTIRE_DEVICE_PATH_SUBTYPE,
61 {
62 END_DEVICE_PATH_LENGTH,
63 0
64 }
65 }
66 };
67
68 STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
69
70 /**
71 Initialize a PCI_ROOT_BRIDGE structure.
72
73 @param[in] Supports Supported attributes.
74
75 @param[in] Attributes Initial attributes.
76
77 @param[in] AllocAttributes Allocation attributes.
78
79 @param[in] RootBusNumber The bus number to store in RootBus.
80
81 @param[in] MaxSubBusNumber The inclusive maximum bus number that can be
82 assigned to any subordinate bus found behind any
83 PCI bridge hanging off this root bus.
84
85 The caller is repsonsible for ensuring that
86 RootBusNumber <= MaxSubBusNumber. If
87 RootBusNumber equals MaxSubBusNumber, then the
88 root bus has no room for subordinate 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 by the
101 caller) that should be filled in by this
102 function.
103
104 @retval EFI_SUCCESS Initialization successful. A device path
105 consisting of an ACPI device path node, with
106 UID = RootBusNumber, has been allocated and
107 linked into RootBus.
108
109 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
110 **/
111 EFI_STATUS
112 InitRootBridge (
113 IN UINT64 Supports,
114 IN UINT64 Attributes,
115 IN UINT64 AllocAttributes,
116 IN UINT8 RootBusNumber,
117 IN UINT8 MaxSubBusNumber,
118 IN PCI_ROOT_BRIDGE_APERTURE *Io,
119 IN PCI_ROOT_BRIDGE_APERTURE *Mem,
120 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
121 IN PCI_ROOT_BRIDGE_APERTURE *PMem,
122 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
123 OUT PCI_ROOT_BRIDGE *RootBus
124 )
125 {
126 OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
127
128 //
129 // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
130 //
131 ZeroMem (RootBus, sizeof *RootBus);
132
133 RootBus->Segment = 0;
134
135 RootBus->Supports = Supports;
136 RootBus->Attributes = Attributes;
137
138 RootBus->DmaAbove4G = FALSE;
139
140 RootBus->AllocationAttributes = AllocAttributes;
141 RootBus->Bus.Base = RootBusNumber;
142 RootBus->Bus.Limit = MaxSubBusNumber;
143 CopyMem (&RootBus->Io, Io, sizeof (*Io));
144 CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
145 CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));
146 CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
147 CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));
148
149 RootBus->NoExtendedConfigSpace = (PcdGet16 (PcdOvmfHostBridgePciDevId) !=
150 INTEL_Q35_MCH_DEVICE_ID);
151
152 DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,
153 &mRootBridgeDevicePathTemplate);
154 if (DevicePath == NULL) {
155 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
156 return EFI_OUT_OF_RESOURCES;
157 }
158 DevicePath->AcpiDevicePath.UID = RootBusNumber;
159 RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
160
161 DEBUG ((DEBUG_INFO,
162 "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
163 __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
164 return EFI_SUCCESS;
165 }
166
167
168 /**
169 Uninitialize a PCI_ROOT_BRIDGE structure set up with InitRootBridge().
170
171 param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and
172 initialized with InitRootBridge(), that should be
173 uninitialized. This function doesn't free RootBus.
174 **/
175 STATIC
176 VOID
177 UninitRootBridge (
178 IN PCI_ROOT_BRIDGE *RootBus
179 )
180 {
181 FreePool (RootBus->DevicePath);
182 }
183
184
185 /**
186 Return all the root bridge instances in an array.
187
188 @param Count Return the count of root bridge instances.
189
190 @return All the root bridge instances in an array.
191 The array should be passed into PciHostBridgeFreeRootBridges()
192 when it's not used.
193 **/
194 PCI_ROOT_BRIDGE *
195 EFIAPI
196 PciHostBridgeGetRootBridges (
197 UINTN *Count
198 )
199 {
200 EFI_STATUS Status;
201 FIRMWARE_CONFIG_ITEM FwCfgItem;
202 UINTN FwCfgSize;
203 UINT64 ExtraRootBridges;
204 PCI_ROOT_BRIDGE *Bridges;
205 UINTN Initialized;
206 UINTN LastRootBridgeNumber;
207 UINTN RootBridgeNumber;
208 UINT64 Attributes;
209 UINT64 AllocationAttributes;
210 PCI_ROOT_BRIDGE_APERTURE Io;
211 PCI_ROOT_BRIDGE_APERTURE Mem;
212 PCI_ROOT_BRIDGE_APERTURE MemAbove4G;
213
214 if (PcdGetBool (PcdPciDisableBusEnumeration)) {
215 return ScanForRootBridges (Count);
216 }
217
218 ZeroMem (&Io, sizeof (Io));
219 ZeroMem (&Mem, sizeof (Mem));
220 ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
221
222 Attributes = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
223 EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
224 EFI_PCI_ATTRIBUTE_ISA_IO_16 |
225 EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
226 EFI_PCI_ATTRIBUTE_VGA_MEMORY |
227 EFI_PCI_ATTRIBUTE_VGA_IO_16 |
228 EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
229
230 AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;
231 if (PcdGet64 (PcdPciMmio64Size) > 0) {
232 AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
233 MemAbove4G.Base = PcdGet64 (PcdPciMmio64Base);
234 MemAbove4G.Limit = PcdGet64 (PcdPciMmio64Base) +
235 PcdGet64 (PcdPciMmio64Size) - 1;
236 } else {
237 CopyMem (&MemAbove4G, &mNonExistAperture, sizeof (mNonExistAperture));
238 }
239
240 Io.Base = PcdGet64 (PcdPciIoBase);
241 Io.Limit = PcdGet64 (PcdPciIoBase) + (PcdGet64 (PcdPciIoSize) - 1);
242 Mem.Base = PcdGet64 (PcdPciMmio32Base);
243 Mem.Limit = PcdGet64 (PcdPciMmio32Base) + (PcdGet64 (PcdPciMmio32Size) - 1);
244
245 *Count = 0;
246
247 //
248 // QEMU provides the number of extra root buses, shortening the exhaustive
249 // search below. If there is no hint, the feature is missing.
250 //
251 Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
252 if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridges) {
253 ExtraRootBridges = 0;
254 } else {
255 QemuFwCfgSelectItem (FwCfgItem);
256 QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges);
257
258 if (ExtraRootBridges > PCI_MAX_BUS) {
259 DEBUG ((DEBUG_ERROR, "%a: invalid count of extra root buses (%Lu) "
260 "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));
261 return NULL;
262 }
263 DEBUG ((DEBUG_INFO, "%a: %Lu extra root buses reported by QEMU\n",
264 __FUNCTION__, ExtraRootBridges));
265 }
266
267 //
268 // Allocate the "main" root bridge, and any extra root bridges.
269 //
270 Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);
271 if (Bridges == NULL) {
272 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
273 return NULL;
274 }
275 Initialized = 0;
276
277 //
278 // The "main" root bus is always there.
279 //
280 LastRootBridgeNumber = 0;
281
282 //
283 // Scan all other root buses. If function 0 of any device on a bus returns a
284 // VendorId register value different from all-bits-one, then that bus is
285 // alive.
286 //
287 for (RootBridgeNumber = 1;
288 RootBridgeNumber <= PCI_MAX_BUS && Initialized < ExtraRootBridges;
289 ++RootBridgeNumber) {
290 UINTN Device;
291
292 for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
293 if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
294 PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
295 break;
296 }
297 }
298 if (Device <= PCI_MAX_DEVICE) {
299 //
300 // Found the next root bus. We can now install the *previous* one,
301 // because now we know how big a bus number range *that* one has, for any
302 // subordinate buses that might exist behind PCI bridges hanging off it.
303 //
304 Status = InitRootBridge (
305 Attributes,
306 Attributes,
307 AllocationAttributes,
308 (UINT8) LastRootBridgeNumber,
309 (UINT8) (RootBridgeNumber - 1),
310 &Io,
311 &Mem,
312 &MemAbove4G,
313 &mNonExistAperture,
314 &mNonExistAperture,
315 &Bridges[Initialized]
316 );
317 if (EFI_ERROR (Status)) {
318 goto FreeBridges;
319 }
320 ++Initialized;
321 LastRootBridgeNumber = RootBridgeNumber;
322 }
323 }
324
325 //
326 // Install the last root bus (which might be the only, ie. main, root bus, if
327 // we've found no extra root buses).
328 //
329 Status = InitRootBridge (
330 Attributes,
331 Attributes,
332 AllocationAttributes,
333 (UINT8) LastRootBridgeNumber,
334 PCI_MAX_BUS,
335 &Io,
336 &Mem,
337 &MemAbove4G,
338 &mNonExistAperture,
339 &mNonExistAperture,
340 &Bridges[Initialized]
341 );
342 if (EFI_ERROR (Status)) {
343 goto FreeBridges;
344 }
345 ++Initialized;
346
347 *Count = Initialized;
348 return Bridges;
349
350 FreeBridges:
351 while (Initialized > 0) {
352 --Initialized;
353 UninitRootBridge (&Bridges[Initialized]);
354 }
355
356 FreePool (Bridges);
357 return NULL;
358 }
359
360
361 /**
362 Free the root bridge instances array returned from
363 PciHostBridgeGetRootBridges().
364
365 @param The root bridge instances array.
366 @param The count of the array.
367 **/
368 VOID
369 EFIAPI
370 PciHostBridgeFreeRootBridges (
371 PCI_ROOT_BRIDGE *Bridges,
372 UINTN Count
373 )
374 {
375 if (Bridges == NULL && Count == 0) {
376 return;
377 }
378 ASSERT (Bridges != NULL && Count > 0);
379
380 do {
381 --Count;
382 UninitRootBridge (&Bridges[Count]);
383 } while (Count > 0);
384
385 FreePool (Bridges);
386 }
387
388
389 /**
390 Inform the platform that the resource conflict happens.
391
392 @param HostBridgeHandle Handle of the Host Bridge.
393 @param Configuration Pointer to PCI I/O and PCI memory resource
394 descriptors. The Configuration contains the resources
395 for all the root bridges. The resource for each root
396 bridge is terminated with END descriptor and an
397 additional END is appended indicating the end of the
398 entire resources. The resource descriptor field
399 values follow the description in
400 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
401 .SubmitResources().
402 **/
403 VOID
404 EFIAPI
405 PciHostBridgeResourceConflict (
406 EFI_HANDLE HostBridgeHandle,
407 VOID *Configuration
408 )
409 {
410 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
411 UINTN RootBridgeIndex;
412 DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
413
414 RootBridgeIndex = 0;
415 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
416 while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
417 DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
418 for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
419 ASSERT (Descriptor->ResType <
420 ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr)
421 );
422 DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
423 mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
424 Descriptor->AddrLen, Descriptor->AddrRangeMax
425 ));
426 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
427 DEBUG ((DEBUG_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",
428 Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
429 ((Descriptor->SpecificFlag &
430 EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
431 ) != 0) ? L" (Prefetchable)" : L""
432 ));
433 }
434 }
435 //
436 // Skip the END descriptor for root bridge
437 //
438 ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
439 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
440 (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
441 );
442 }
443 }