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