]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PciHostBridgeLib/XenSupport.c
OvmfPkg/PciHostBridgeLib: consolidate #includes and INF file sections
[mirror_edk2.git] / OvmfPkg / Library / PciHostBridgeLib / XenSupport.c
1 /** @file
2 Scan the entire PCI bus for root bridges to support OVMF above Xen.
3
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <IndustryStandard/Pci.h> // EFI_PCI_COMMAND_IO_SPACE
11 #include <IndustryStandard/Q35MchIch9.h> // INTEL_Q35_MCH_DEVICE_ID
12 #include <Library/BaseLib.h> // DisableInterrupts()
13 #include <Library/BaseMemoryLib.h> // ZeroMem()
14 #include <Library/DebugLib.h> // ASSERT()
15 #include <Library/MemoryAllocationLib.h> // ReallocatePool()
16 #include <Library/PcdLib.h> // PcdGet16()
17 #include <Library/PciHostBridgeLib.h> // PCI_ROOT_BRIDGE_APERTURE
18 #include <Library/PciHostBridgeUtilityLib.h> // PciHostBridgeUtilityInitRoot...
19 #include <Library/PciLib.h> // PciRead32()
20 #include <Protocol/PciRootBridgeIo.h> // EFI_PCI_ATTRIBUTE_ISA_IO
21
22 #include "PciHostBridge.h"
23
24 STATIC
25 VOID
26 PcatPciRootBridgeBarExisted (
27 IN UINTN Address,
28 OUT UINT32 *OriginalValue,
29 OUT UINT32 *Value
30 )
31 {
32 //
33 // Preserve the original value
34 //
35 *OriginalValue = PciRead32 (Address);
36
37 //
38 // Disable timer interrupt while the BAR is probed
39 //
40 DisableInterrupts ();
41
42 PciWrite32 (Address, 0xFFFFFFFF);
43 *Value = PciRead32 (Address);
44 PciWrite32 (Address, *OriginalValue);
45
46 //
47 // Enable interrupt
48 //
49 EnableInterrupts ();
50 }
51
52 #define PCI_COMMAND_DECODE ((UINT16)(EFI_PCI_COMMAND_IO_SPACE | \
53 EFI_PCI_COMMAND_MEMORY_SPACE))
54 STATIC
55 VOID
56 PcatPciRootBridgeDecodingDisable (
57 IN UINTN Address
58 )
59 {
60 UINT16 Value;
61
62 Value = PciRead16 (Address);
63 if (Value & PCI_COMMAND_DECODE) {
64 PciWrite16 (Address, Value & ~(UINT32)PCI_COMMAND_DECODE);
65 }
66 }
67
68 STATIC
69 VOID
70 PcatPciRootBridgeParseBars (
71 IN UINT16 Command,
72 IN UINTN Bus,
73 IN UINTN Device,
74 IN UINTN Function,
75 IN UINTN BarOffsetBase,
76 IN UINTN BarOffsetEnd,
77 IN PCI_ROOT_BRIDGE_APERTURE *Io,
78 IN PCI_ROOT_BRIDGE_APERTURE *Mem,
79 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G
80
81 )
82 {
83 UINT32 OriginalValue;
84 UINT32 Value;
85 UINT32 OriginalUpperValue;
86 UINT32 UpperValue;
87 UINT64 Mask;
88 UINTN Offset;
89 UINT64 Base;
90 UINT64 Length;
91 UINT64 Limit;
92 PCI_ROOT_BRIDGE_APERTURE *MemAperture;
93
94 // Disable address decoding for every device before OVMF starts sizing it
95 PcatPciRootBridgeDecodingDisable (
96 PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET)
97 );
98
99 for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {
100 PcatPciRootBridgeBarExisted (
101 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
102 &OriginalValue, &Value
103 );
104 if (Value == 0) {
105 continue;
106 }
107 if ((Value & BIT0) == BIT0) {
108 //
109 // IO Bar
110 //
111 if (Command & EFI_PCI_COMMAND_IO_SPACE) {
112 Mask = 0xfffffffc;
113 Base = OriginalValue & Mask;
114 Length = ((~(Value & Mask)) & Mask) + 0x04;
115 if (!(Value & 0xFFFF0000)) {
116 Length &= 0x0000FFFF;
117 }
118 Limit = Base + Length - 1;
119
120 if (Base < Limit) {
121 if (Io->Base > Base) {
122 Io->Base = Base;
123 }
124 if (Io->Limit < Limit) {
125 Io->Limit = Limit;
126 }
127 }
128 }
129 } else {
130 //
131 // Mem Bar
132 //
133 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
134
135 Mask = 0xfffffff0;
136 Base = OriginalValue & Mask;
137 Length = Value & Mask;
138
139 if ((Value & (BIT1 | BIT2)) == 0) {
140 //
141 // 32bit
142 //
143 Length = ((~Length) + 1) & 0xffffffff;
144
145 MemAperture = Mem;
146 } else {
147 //
148 // 64bit
149 //
150 Offset += 4;
151 PcatPciRootBridgeBarExisted (
152 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
153 &OriginalUpperValue,
154 &UpperValue
155 );
156
157 Base = Base | LShiftU64 ((UINT64) OriginalUpperValue, 32);
158 Length = Length | LShiftU64 ((UINT64) UpperValue, 32);
159 Length = (~Length) + 1;
160
161 if (Base < BASE_4GB) {
162 MemAperture = Mem;
163 } else {
164 MemAperture = MemAbove4G;
165 }
166 }
167
168 Limit = Base + Length - 1;
169 if (Base < Limit) {
170 if (MemAperture->Base > Base) {
171 MemAperture->Base = Base;
172 }
173 if (MemAperture->Limit < Limit) {
174 MemAperture->Limit = Limit;
175 }
176 }
177 }
178 }
179 }
180 }
181
182 STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
183
184 PCI_ROOT_BRIDGE *
185 ScanForRootBridges (
186 UINTN *NumberOfRootBridges
187 )
188 {
189 UINTN PrimaryBus;
190 UINTN SubBus;
191 UINT8 Device;
192 UINT8 Function;
193 UINTN NumberOfDevices;
194 UINTN Address;
195 PCI_TYPE01 Pci;
196 UINT64 Attributes;
197 UINT64 Base;
198 UINT64 Limit;
199 UINT64 Value;
200 PCI_ROOT_BRIDGE_APERTURE Io, Mem, MemAbove4G, *MemAperture;
201 PCI_ROOT_BRIDGE *RootBridges;
202 UINTN BarOffsetEnd;
203
204
205 *NumberOfRootBridges = 0;
206 RootBridges = NULL;
207
208 //
209 // After scanning all the PCI devices on the PCI root bridge's primary bus,
210 // update the Primary Bus Number for the next PCI root bridge to be this PCI
211 // root bridge's subordinate bus number + 1.
212 //
213 for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {
214 SubBus = PrimaryBus;
215 Attributes = 0;
216
217 ZeroMem (&Io, sizeof (Io));
218 ZeroMem (&Mem, sizeof (Mem));
219 ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
220 Io.Base = Mem.Base = MemAbove4G.Base = MAX_UINT64;
221 //
222 // Scan all the PCI devices on the primary bus of the PCI root bridge
223 //
224 for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
225
226 for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
227
228 //
229 // Compute the PCI configuration address of the PCI device to probe
230 //
231 Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);
232
233 //
234 // Read the Vendor ID from the PCI Configuration Header
235 //
236 if (PciRead16 (Address) == MAX_UINT16) {
237 if (Function == 0) {
238 //
239 // If the PCI Configuration Read fails, or a PCI device does not
240 // exist, then skip this entire PCI device
241 //
242 break;
243 } else {
244 //
245 // If PCI function != 0, VendorId == 0xFFFF, we continue to search
246 // PCI function.
247 //
248 continue;
249 }
250 }
251
252 //
253 // Read the entire PCI Configuration Header
254 //
255 PciReadBuffer (Address, sizeof (Pci), &Pci);
256
257 //
258 // Increment the number of PCI device found on the primary bus of the
259 // PCI root bridge
260 //
261 NumberOfDevices++;
262
263 //
264 // Look for devices with the VGA Palette Snoop enabled in the COMMAND
265 // register of the PCI Config Header
266 //
267 if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
268 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
269 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
270 }
271
272 BarOffsetEnd = 0;
273
274 //
275 // PCI-PCI Bridge
276 //
277 if (IS_PCI_BRIDGE (&Pci)) {
278 //
279 // Get the Bus range that the PPB is decoding
280 //
281 if (Pci.Bridge.SubordinateBus > SubBus) {
282 //
283 // If the subordinate bus number of the PCI-PCI bridge is greater
284 // than the PCI root bridge's current subordinate bus number,
285 // then update the PCI root bridge's subordinate bus number
286 //
287 SubBus = Pci.Bridge.SubordinateBus;
288 }
289
290 //
291 // Get the I/O range that the PPB is decoding
292 //
293 Value = Pci.Bridge.IoBase & 0x0f;
294 Base = ((UINT32) Pci.Bridge.IoBase & 0xf0) << 8;
295 Limit = (((UINT32) Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
296 if (Value == BIT0) {
297 Base |= ((UINT32) Pci.Bridge.IoBaseUpper16 << 16);
298 Limit |= ((UINT32) Pci.Bridge.IoLimitUpper16 << 16);
299 }
300 if (Base < Limit) {
301 if (Io.Base > Base) {
302 Io.Base = Base;
303 }
304 if (Io.Limit < Limit) {
305 Io.Limit = Limit;
306 }
307 }
308
309 //
310 // Get the Memory range that the PPB is decoding
311 //
312 Base = ((UINT32) Pci.Bridge.MemoryBase & 0xfff0) << 16;
313 Limit = (((UINT32) Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
314 if (Base < Limit) {
315 if (Mem.Base > Base) {
316 Mem.Base = Base;
317 }
318 if (Mem.Limit < Limit) {
319 Mem.Limit = Limit;
320 }
321 }
322
323 //
324 // Get the Prefetchable Memory range that the PPB is decoding
325 // and merge it into Memory range
326 //
327 Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;
328 Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
329 Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)
330 << 16) | 0xfffff;
331 MemAperture = &Mem;
332 if (Value == BIT0) {
333 Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);
334 Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);
335 MemAperture = &MemAbove4G;
336 }
337 if (Base < Limit) {
338 if (MemAperture->Base > Base) {
339 MemAperture->Base = Base;
340 }
341 if (MemAperture->Limit < Limit) {
342 MemAperture->Limit = Limit;
343 }
344 }
345
346 //
347 // Look at the PPB Configuration for legacy decoding attributes
348 //
349 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)
350 == EFI_PCI_BRIDGE_CONTROL_ISA) {
351 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
352 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
353 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
354 }
355 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)
356 == EFI_PCI_BRIDGE_CONTROL_VGA) {
357 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
358 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
359 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
360 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)
361 != 0) {
362 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
363 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
364 }
365 }
366
367 BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);
368 } else {
369 //
370 // Parse the BARs of the PCI device to get what I/O Ranges, Memory
371 // Ranges, and Prefetchable Memory Ranges the device is decoding
372 //
373 if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
374 BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);
375 }
376 }
377
378 PcatPciRootBridgeParseBars (
379 Pci.Hdr.Command,
380 PrimaryBus,
381 Device,
382 Function,
383 OFFSET_OF (PCI_TYPE00, Device.Bar),
384 BarOffsetEnd,
385 &Io,
386 &Mem, &MemAbove4G
387 );
388
389 //
390 // See if the PCI device is an IDE controller
391 //
392 if (IS_CLASS2 (&Pci, PCI_CLASS_MASS_STORAGE,
393 PCI_CLASS_MASS_STORAGE_IDE)) {
394 if (Pci.Hdr.ClassCode[0] & 0x80) {
395 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
396 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
397 }
398 if (Pci.Hdr.ClassCode[0] & 0x01) {
399 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
400 }
401 if (Pci.Hdr.ClassCode[0] & 0x04) {
402 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
403 }
404 }
405
406 //
407 // See if the PCI device is a legacy VGA controller or
408 // a standard VGA controller
409 //
410 if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||
411 IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)
412 ) {
413 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
414 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
415 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
416 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
417 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
418 }
419
420 //
421 // See if the PCI Device is a PCI - ISA or PCI - EISA
422 // or ISA_POSITIVE_DECODE Bridge device
423 //
424 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
425 if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA ||
426 Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA ||
427 Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) {
428 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
429 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
430 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
431 }
432 }
433
434 //
435 // If this device is not a multi function device, then skip the rest
436 // of this PCI device
437 //
438 if (Function == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
439 break;
440 }
441 }
442 }
443
444 //
445 // If at least one PCI device was found on the primary bus of this PCI
446 // root bridge, then the PCI root bridge exists.
447 //
448 if (NumberOfDevices > 0) {
449 RootBridges = ReallocatePool (
450 (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),
451 (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),
452 RootBridges
453 );
454 ASSERT (RootBridges != NULL);
455 PciHostBridgeUtilityInitRootBridge (
456 Attributes, Attributes, 0,
457 FALSE, PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,
458 (UINT8) PrimaryBus, (UINT8) SubBus,
459 &Io, &Mem, &MemAbove4G, &mNonExistAperture, &mNonExistAperture,
460 &RootBridges[*NumberOfRootBridges]
461 );
462 RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;
463 //
464 // Increment the index for the next PCI Root Bridge
465 //
466 (*NumberOfRootBridges)++;
467 }
468 }
469
470 return RootBridges;
471 }