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