]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiPayloadPkg / Library / PciHostBridgeLib / PciHostBridgeSupport.c
1 /** @file
2 Scan the entire PCI bus for root bridges to support coreboot UEFI payload.
3
4 Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <PiDxe.h>
11 #include <IndustryStandard/Pci.h>
12 #include <Protocol/PciHostBridgeResourceAllocation.h>
13 #include <Protocol/PciRootBridgeIo.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/PciHostBridgeLib.h>
18 #include <Library/PciLib.h>
19 #include "PciHostBridge.h"
20
21 /**
22 Probe a bar is existed or not.
23
24 @param[in] Address PCI address for the BAR.
25 @param[out] OriginalValue The original bar value returned.
26 @param[out] Value The probed bar value returned.
27 **/
28 STATIC
29 VOID
30 PcatPciRootBridgeBarExisted (
31 IN UINTN Address,
32 OUT UINT32 *OriginalValue,
33 OUT UINT32 *Value
34 )
35 {
36 //
37 // Preserve the original value
38 //
39 *OriginalValue = PciRead32 (Address);
40
41 //
42 // Disable timer interrupt while the BAR is probed
43 //
44 DisableInterrupts ();
45
46 PciWrite32 (Address, 0xFFFFFFFF);
47 *Value = PciRead32 (Address);
48 PciWrite32 (Address, *OriginalValue);
49
50 //
51 // Enable interrupt
52 //
53 EnableInterrupts ();
54 }
55
56 /**
57 Parse PCI bar and collect the assigned PCI resource information.
58
59 @param[in] Command Supported attributes.
60
61 @param[in] Bus PCI bus number.
62
63 @param[in] Device PCI device number.
64
65 @param[in] Function PCI function number.
66
67 @param[in] BarOffsetBase PCI bar start offset.
68
69 @param[in] BarOffsetEnd PCI bar end offset.
70
71 @param[in] Io IO aperture.
72
73 @param[in] Mem MMIO aperture.
74
75 @param[in] MemAbove4G MMIO aperture above 4G.
76
77 @param[in] PMem Prefetchable MMIO aperture.
78
79 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
80 **/
81 STATIC
82 VOID
83 PcatPciRootBridgeParseBars (
84 IN UINT16 Command,
85 IN UINTN Bus,
86 IN UINTN Device,
87 IN UINTN Function,
88 IN UINTN BarOffsetBase,
89 IN UINTN BarOffsetEnd,
90 IN PCI_ROOT_BRIDGE_APERTURE *Io,
91 IN PCI_ROOT_BRIDGE_APERTURE *Mem,
92 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G
93
94 )
95 {
96 UINT32 OriginalValue;
97 UINT32 Value;
98 UINT32 OriginalUpperValue;
99 UINT32 UpperValue;
100 UINT64 Mask;
101 UINTN Offset;
102 UINTN LowBit;
103 UINT64 Base;
104 UINT64 Length;
105 UINT64 Limit;
106 PCI_ROOT_BRIDGE_APERTURE *MemAperture;
107
108 for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {
109 PcatPciRootBridgeBarExisted (
110 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
111 &OriginalValue,
112 &Value
113 );
114 if (Value == 0) {
115 continue;
116 }
117
118 if ((Value & BIT0) == BIT0) {
119 //
120 // IO Bar
121 //
122 if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {
123 Mask = 0xfffffffc;
124 Base = OriginalValue & Mask;
125 Length = ((~(Value & Mask)) & Mask) + 0x04;
126 if (!(Value & 0xFFFF0000)) {
127 Length &= 0x0000FFFF;
128 }
129
130 Limit = Base + Length - 1;
131
132 if ((Base > 0) && (Base < Limit)) {
133 if (Io->Base > Base) {
134 Io->Base = Base;
135 }
136
137 if (Io->Limit < Limit) {
138 Io->Limit = Limit;
139 }
140 }
141 }
142 } else {
143 //
144 // Mem Bar
145 //
146 if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {
147 Mask = 0xfffffff0;
148 Base = OriginalValue & Mask;
149 Length = Value & Mask;
150
151 if ((Value & (BIT1 | BIT2)) == 0) {
152 //
153 // 32bit
154 //
155 Length = ((~Length) + 1) & 0xffffffff;
156
157 MemAperture = Mem;
158 } else {
159 //
160 // 64bit
161 //
162 Offset += 4;
163 PcatPciRootBridgeBarExisted (
164 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
165 &OriginalUpperValue,
166 &UpperValue
167 );
168
169 Base = Base | LShiftU64 ((UINT64)OriginalUpperValue, 32);
170 Length = Length | LShiftU64 ((UINT64)UpperValue, 32);
171 if (Length != 0) {
172 LowBit = LowBitSet64 (Length);
173 Length = LShiftU64 (1ULL, LowBit);
174 }
175
176 if (Base < BASE_4GB) {
177 MemAperture = Mem;
178 } else {
179 MemAperture = MemAbove4G;
180 }
181 }
182
183 Limit = Base + Length - 1;
184 if ((Base > 0) && (Base < Limit)) {
185 if (MemAperture->Base > Base) {
186 MemAperture->Base = Base;
187 }
188
189 if (MemAperture->Limit < Limit) {
190 MemAperture->Limit = Limit;
191 }
192 }
193 }
194 }
195 }
196 }
197
198 STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
199
200 /**
201 Scan for all root bridges in platform.
202
203 @param[out] NumberOfRootBridges Number of root bridges detected
204
205 @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.
206 **/
207 PCI_ROOT_BRIDGE *
208 ScanForRootBridges (
209 OUT UINTN *NumberOfRootBridges
210 )
211 {
212 UINTN PrimaryBus;
213 UINTN SubBus;
214 UINT8 Device;
215 UINT8 Function;
216 UINTN NumberOfDevices;
217 UINTN Address;
218 PCI_TYPE01 Pci;
219 UINT64 Attributes;
220 UINT64 Base;
221 UINT64 Limit;
222 UINT64 Value;
223 PCI_ROOT_BRIDGE_APERTURE Io;
224 PCI_ROOT_BRIDGE_APERTURE Mem;
225 PCI_ROOT_BRIDGE_APERTURE MemAbove4G;
226 PCI_ROOT_BRIDGE_APERTURE *MemAperture;
227 PCI_ROOT_BRIDGE *RootBridges;
228 UINTN BarOffsetEnd;
229
230 *NumberOfRootBridges = 0;
231 RootBridges = NULL;
232
233 //
234 // After scanning all the PCI devices on the PCI root bridge's primary bus,
235 // update the Primary Bus Number for the next PCI root bridge to be this PCI
236 // root bridge's subordinate bus number + 1.
237 //
238 for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {
239 SubBus = PrimaryBus;
240 Attributes = 0;
241
242 ZeroMem (&Io, sizeof (Io));
243 ZeroMem (&Mem, sizeof (Mem));
244 ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
245 Io.Base = Mem.Base = MemAbove4G.Base = MAX_UINT64;
246 //
247 // Scan all the PCI devices on the primary bus of the PCI root bridge
248 //
249 for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
250 for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
251 //
252 // Compute the PCI configuration address of the PCI device to probe
253 //
254 Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);
255
256 //
257 // Read the Vendor ID from the PCI Configuration Header
258 //
259 if (PciRead16 (Address) == MAX_UINT16) {
260 if (Function == 0) {
261 //
262 // If the PCI Configuration Read fails, or a PCI device does not
263 // exist, then skip this entire PCI device
264 //
265 break;
266 } else {
267 //
268 // If PCI function != 0, VendorId == 0xFFFF, we continue to search
269 // PCI function.
270 //
271 continue;
272 }
273 }
274
275 //
276 // Read the entire PCI Configuration Header
277 //
278 PciReadBuffer (Address, sizeof (Pci), &Pci);
279
280 //
281 // Increment the number of PCI device found on the primary bus of the
282 // PCI root bridge
283 //
284 NumberOfDevices++;
285
286 //
287 // Look for devices with the VGA Palette Snoop enabled in the COMMAND
288 // register of the PCI Config Header
289 //
290 if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
291 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
292 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
293 }
294
295 BarOffsetEnd = 0;
296
297 //
298 // PCI-PCI Bridge
299 //
300 if (IS_PCI_BRIDGE (&Pci)) {
301 //
302 // Get the Bus range that the PPB is decoding
303 //
304 if (Pci.Bridge.SubordinateBus > SubBus) {
305 //
306 // If the subordinate bus number of the PCI-PCI bridge is greater
307 // than the PCI root bridge's current subordinate bus number,
308 // then update the PCI root bridge's subordinate bus number
309 //
310 SubBus = Pci.Bridge.SubordinateBus;
311 }
312
313 //
314 // Get the I/O range that the PPB is decoding
315 //
316 Value = Pci.Bridge.IoBase & 0x0f;
317 Base = ((UINT32)Pci.Bridge.IoBase & 0xf0) << 8;
318 Limit = (((UINT32)Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
319 if (Value == BIT0) {
320 Base |= ((UINT32)Pci.Bridge.IoBaseUpper16 << 16);
321 Limit |= ((UINT32)Pci.Bridge.IoLimitUpper16 << 16);
322 }
323
324 if ((Base > 0) && (Base < Limit)) {
325 if (Io.Base > Base) {
326 Io.Base = Base;
327 }
328
329 if (Io.Limit < Limit) {
330 Io.Limit = Limit;
331 }
332 }
333
334 //
335 // Get the Memory range that the PPB is decoding
336 //
337 Base = ((UINT32)Pci.Bridge.MemoryBase & 0xfff0) << 16;
338 Limit = (((UINT32)Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
339 if ((Base > 0) && (Base < Limit)) {
340 if (Mem.Base > Base) {
341 Mem.Base = Base;
342 }
343
344 if (Mem.Limit < Limit) {
345 Mem.Limit = Limit;
346 }
347 }
348
349 //
350 // Get the Prefetchable Memory range that the PPB is decoding
351 // and merge it into Memory range
352 //
353 Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;
354 Base = ((UINT32)Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
355 Limit = (((UINT32)Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)
356 << 16) | 0xfffff;
357
358 if (Value == BIT0) {
359 Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);
360 Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);
361 }
362
363 if ((Base > 0) && (Base < Limit)) {
364 if (Base < BASE_4GB) {
365 MemAperture = &Mem;
366 } else {
367 MemAperture = &MemAbove4G;
368 }
369
370 if (MemAperture->Base > Base) {
371 MemAperture->Base = Base;
372 }
373
374 if (MemAperture->Limit < Limit) {
375 MemAperture->Limit = Limit;
376 }
377 }
378
379 //
380 // Look at the PPB Configuration for legacy decoding attributes
381 //
382 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)
383 == EFI_PCI_BRIDGE_CONTROL_ISA)
384 {
385 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
386 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
387 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
388 }
389
390 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)
391 == EFI_PCI_BRIDGE_CONTROL_VGA)
392 {
393 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
394 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
395 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
396 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)
397 != 0)
398 {
399 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
400 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
401 }
402 }
403
404 BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);
405 } else {
406 //
407 // Parse the BARs of the PCI device to get what I/O Ranges, Memory
408 // Ranges, and Prefetchable Memory Ranges the device is decoding
409 //
410 if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
411 BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);
412 }
413 }
414
415 PcatPciRootBridgeParseBars (
416 Pci.Hdr.Command,
417 PrimaryBus,
418 Device,
419 Function,
420 OFFSET_OF (PCI_TYPE00, Device.Bar),
421 BarOffsetEnd,
422 &Io,
423 &Mem,
424 &MemAbove4G
425 );
426
427 //
428 // See if the PCI device is an IDE controller
429 //
430 if (IS_CLASS2 (
431 &Pci,
432 PCI_CLASS_MASS_STORAGE,
433 PCI_CLASS_MASS_STORAGE_IDE
434 ))
435 {
436 if (Pci.Hdr.ClassCode[0] & 0x80) {
437 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
438 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
439 }
440
441 if (Pci.Hdr.ClassCode[0] & 0x01) {
442 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
443 }
444
445 if (Pci.Hdr.ClassCode[0] & 0x04) {
446 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
447 }
448 }
449
450 //
451 // See if the PCI device is a legacy VGA controller or
452 // a standard VGA controller
453 //
454 if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||
455 IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)
456 )
457 {
458 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
459 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
460 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
461 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
462 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
463 }
464
465 //
466 // See if the PCI Device is a PCI - ISA or PCI - EISA
467 // or ISA_POSITIVE_DECODE Bridge device
468 //
469 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
470 if ((Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) ||
471 (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA) ||
472 (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE))
473 {
474 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
475 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
476 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
477 }
478 }
479
480 //
481 // If this device is not a multi function device, then skip the rest
482 // of this PCI device
483 //
484 if ((Function == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
485 break;
486 }
487 }
488 }
489
490 //
491 // If at least one PCI device was found on the primary bus of this PCI
492 // root bridge, then the PCI root bridge exists.
493 //
494 if (NumberOfDevices > 0) {
495 RootBridges = ReallocatePool (
496 (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),
497 (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),
498 RootBridges
499 );
500 ASSERT (RootBridges != NULL);
501
502 InitRootBridge (
503 Attributes,
504 Attributes,
505 0,
506 (UINT8)PrimaryBus,
507 (UINT8)SubBus,
508 &Io,
509 &Mem,
510 &MemAbove4G,
511 &mNonExistAperture,
512 &mNonExistAperture,
513 &RootBridges[*NumberOfRootBridges]
514 );
515 RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;
516 //
517 // Increment the index for the next PCI Root Bridge
518 //
519 (*NumberOfRootBridges)++;
520 }
521 }
522
523 return RootBridges;
524 }
525
526 /**
527 Scan for all root bridges from Universal Payload PciRootBridgeInfoHob
528
529 @param[in] PciRootBridgeInfo Pointer of Universal Payload PCI Root Bridge Info Hob
530 @param[out] NumberOfRootBridges Number of root bridges detected
531
532 @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.
533
534 **/
535 PCI_ROOT_BRIDGE *
536 RetrieveRootBridgeInfoFromHob (
537 IN UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo,
538 OUT UINTN *NumberOfRootBridges
539 )
540 {
541 PCI_ROOT_BRIDGE *PciRootBridges;
542 UINTN Size;
543 UINT8 Index;
544
545 ASSERT (PciRootBridgeInfo != NULL);
546 ASSERT (NumberOfRootBridges != NULL);
547 if (PciRootBridgeInfo == NULL) {
548 return NULL;
549 }
550
551 if (PciRootBridgeInfo->Count == 0) {
552 PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);
553 return NULL;
554 }
555
556 Size = PciRootBridgeInfo->Count * sizeof (PCI_ROOT_BRIDGE);
557 PciRootBridges = (PCI_ROOT_BRIDGE *)AllocatePool (Size);
558 ASSERT (PciRootBridges != NULL);
559 if (PciRootBridges == NULL) {
560 return NULL;
561 }
562
563 ZeroMem (PciRootBridges, PciRootBridgeInfo->Count * sizeof (PCI_ROOT_BRIDGE));
564
565 //
566 // Create all root bridges with PciRootBridgeInfoHob
567 //
568 for (Index = 0; Index < PciRootBridgeInfo->Count; Index++) {
569 PciRootBridges[Index].Segment = PciRootBridgeInfo->RootBridge[Index].Segment;
570 PciRootBridges[Index].Supports = PciRootBridgeInfo->RootBridge[Index].Supports;
571 PciRootBridges[Index].Attributes = PciRootBridgeInfo->RootBridge[Index].Attributes;
572 PciRootBridges[Index].DmaAbove4G = PciRootBridgeInfo->RootBridge[Index].DmaAbove4G;
573 PciRootBridges[Index].NoExtendedConfigSpace = PciRootBridgeInfo->RootBridge[Index].NoExtendedConfigSpace;
574 PciRootBridges[Index].ResourceAssigned = PciRootBridgeInfo->ResourceAssigned;
575 PciRootBridges[Index].AllocationAttributes = PciRootBridgeInfo->RootBridge[Index].AllocationAttributes;
576 PciRootBridges[Index].DevicePath = CreateRootBridgeDevicePath (PciRootBridgeInfo->RootBridge[Index].HID, PciRootBridgeInfo->RootBridge[Index].UID);
577 CopyMem (&PciRootBridges[Index].Bus, &PciRootBridgeInfo->RootBridge[Index].Bus, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));
578 CopyMem (&PciRootBridges[Index].Io, &PciRootBridgeInfo->RootBridge[Index].Io, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));
579 CopyMem (&PciRootBridges[Index].Mem, &PciRootBridgeInfo->RootBridge[Index].Mem, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));
580 CopyMem (&PciRootBridges[Index].MemAbove4G, &PciRootBridgeInfo->RootBridge[Index].MemAbove4G, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));
581 CopyMem (&PciRootBridges[Index].PMem, &PciRootBridgeInfo->RootBridge[Index].PMem, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));
582 CopyMem (&PciRootBridges[Index].PMemAbove4G, &PciRootBridgeInfo->RootBridge[Index].PMemAbove4G, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));
583 }
584
585 *NumberOfRootBridges = PciRootBridgeInfo->Count;
586
587 //
588 // Now, this library only supports RootBridge that ResourceAssigned is True
589 //
590 if (PciRootBridgeInfo->ResourceAssigned) {
591 PcdSetBoolS (PcdPciDisableBusEnumeration, TRUE);
592 } else {
593 DEBUG ((DEBUG_INFO, "There is root bridge whose ResourceAssigned is FALSE\n"));
594 PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);
595 }
596
597 return PciRootBridges;
598 }