]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / PciHotPlugInitDxe / PciHotPlugInit.c
1 /** @file
2 This driver implements EFI_PCI_HOT_PLUG_INIT_PROTOCOL, providing the PCI bus
3 driver with resource padding information, for PCIe hotplug purposes.
4
5 Copyright (C) 2016, Red Hat, Inc.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 **/
9
10 #include <IndustryStandard/Acpi10.h>
11 #include <IndustryStandard/Q35MchIch9.h>
12 #include <IndustryStandard/QemuPciBridgeCapabilities.h>
13
14 #include <Library/BaseLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/DevicePathLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/PciCapLib.h>
20 #include <Library/PciCapPciSegmentLib.h>
21 #include <Library/PciLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23
24 #include <Protocol/PciHotPlugInit.h>
25 #include <Protocol/PciRootBridgeIo.h>
26
27 //
28 // TRUE if the PCI platform supports extended config space, FALSE otherwise.
29 //
30 STATIC BOOLEAN mPciExtConfSpaceSupported;
31
32 //
33 // The protocol interface this driver produces.
34 //
35 // Refer to 12.6 "PCI Hot Plug PCI Initialization Protocol" in the Platform
36 // Init 1.4a Spec, Volume 5.
37 //
38 STATIC EFI_PCI_HOT_PLUG_INIT_PROTOCOL mPciHotPlugInit;
39
40 //
41 // Resource padding template for the GetResourcePadding() protocol member
42 // function.
43 //
44 // Refer to Table 8 "ACPI 2.0 & 3.0 QWORD Address Space Descriptor Usage" in
45 // the Platform Init 1.4a Spec, Volume 5.
46 //
47 // This structure is interpreted by the ApplyResourcePadding() function in the
48 // edk2 PCI Bus UEFI_DRIVER.
49 //
50 // We can request padding for at most four resource types, each of which is
51 // optional, independently of the others:
52 // (a) bus numbers,
53 // (b) IO space,
54 // (c) non-prefetchable MMIO space (32-bit only),
55 // (d) prefetchable MMIO space (either 32-bit or 64-bit, never both).
56 //
57 #pragma pack (1)
58 typedef struct {
59 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Padding[4];
60 EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
61 } RESOURCE_PADDING;
62 #pragma pack ()
63
64 /**
65 Initialize a RESOURCE_PADDING object.
66
67 @param[out] ResourcePadding The caller-allocated RESOURCE_PADDING object to
68 initialize.
69 **/
70 STATIC
71 VOID
72 InitializeResourcePadding (
73 OUT RESOURCE_PADDING *ResourcePadding
74 )
75 {
76 UINTN Index;
77
78 ZeroMem (ResourcePadding, sizeof *ResourcePadding);
79
80 //
81 // Fill in the Padding fields that don't vary across resource types.
82 //
83 for (Index = 0; Index < ARRAY_SIZE (ResourcePadding->Padding); ++Index) {
84 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
85
86 Descriptor = ResourcePadding->Padding + Index;
87 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
88 Descriptor->Len = (UINT16)(
89 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) -
90 OFFSET_OF (
91 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR,
92 ResType
93 )
94 );
95 }
96
97 //
98 // Fill in the End Tag.
99 //
100 ResourcePadding->EndDesc.Desc = ACPI_END_TAG_DESCRIPTOR;
101 }
102
103 /**
104 Set up a descriptor entry for reserving IO space.
105
106 @param[in,out] Descriptor The descriptor to configure. The caller shall have
107 initialized Descriptor earlier, with
108 InitializeResourcePadding().
109
110 @param[in] SizeExponent The size and natural alignment of the reservation
111 are determined by raising two to this power.
112 **/
113 STATIC
114 VOID
115 SetIoPadding (
116 IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor,
117 IN UINTN SizeExponent
118 )
119 {
120 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
121 Descriptor->AddrLen = LShiftU64 (1, SizeExponent);
122 Descriptor->AddrRangeMax = Descriptor->AddrLen - 1;
123 }
124
125 /**
126 Set up a descriptor entry for reserving MMIO space.
127
128 @param[in,out] Descriptor The descriptor to configure. The caller shall
129 have initialized Descriptor earlier, with
130 InitializeResourcePadding().
131
132 @param[in] Prefetchable TRUE if the descriptor should reserve
133 prefetchable MMIO space. Pass FALSE for
134 reserving non-prefetchable MMIO space.
135
136 @param[in] ThirtyTwoBitOnly TRUE if the reservation should be limited to
137 32-bit address space. FALSE if the reservation
138 can be satisfied from 64-bit address space.
139 ThirtyTwoBitOnly is ignored if Prefetchable is
140 FALSE; in that case ThirtyTwoBitOnly is always
141 considered TRUE.
142
143 @param[in] SizeExponent The size and natural alignment of the
144 reservation are determined by raising two to
145 this power.
146 **/
147 STATIC
148 VOID
149 SetMmioPadding (
150 IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor,
151 IN BOOLEAN Prefetchable,
152 IN BOOLEAN ThirtyTwoBitOnly,
153 IN UINTN SizeExponent
154 )
155 {
156 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
157 if (Prefetchable) {
158 Descriptor->SpecificFlag =
159 EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
160 Descriptor->AddrSpaceGranularity = ThirtyTwoBitOnly ? 32 : 64;
161 } else {
162 Descriptor->SpecificFlag =
163 EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_NON_CACHEABLE;
164 Descriptor->AddrSpaceGranularity = 32;
165 }
166
167 Descriptor->AddrLen = LShiftU64 (1, SizeExponent);
168 Descriptor->AddrRangeMax = Descriptor->AddrLen - 1;
169 }
170
171 /**
172 Round up a positive 32-bit value to the next whole power of two, and return
173 the bit position of the highest bit set in the result. Equivalent to
174 ceil(log2(x)).
175
176 @param[in] Operand The 32-bit operand to evaluate.
177
178 @retval -1 Operand is zero.
179
180 @retval -1 Operand is positive, not a whole power of two, and rounding it
181 up to the next power of two does not fit into 32 bits.
182
183 @retval 0..31 Otherwise, return ceil(log2(Value)).
184 **/
185 STATIC
186 INTN
187 HighBitSetRoundUp32 (
188 IN UINT32 Operand
189 )
190 {
191 INTN HighBit;
192
193 HighBit = HighBitSet32 (Operand);
194 if (HighBit == -1) {
195 //
196 // Operand is zero.
197 //
198 return HighBit;
199 }
200
201 if ((Operand & (Operand - 1)) != 0) {
202 //
203 // Operand is not a whole power of two.
204 //
205 ++HighBit;
206 }
207
208 return (HighBit < 32) ? HighBit : -1;
209 }
210
211 /**
212 Round up a positive 64-bit value to the next whole power of two, and return
213 the bit position of the highest bit set in the result. Equivalent to
214 ceil(log2(x)).
215
216 @param[in] Operand The 64-bit operand to evaluate.
217
218 @retval -1 Operand is zero.
219
220 @retval -1 Operand is positive, not a whole power of two, and rounding it
221 up to the next power of two does not fit into 64 bits.
222
223 @retval 0..63 Otherwise, return ceil(log2(Value)).
224 **/
225 STATIC
226 INTN
227 HighBitSetRoundUp64 (
228 IN UINT64 Operand
229 )
230 {
231 INTN HighBit;
232
233 HighBit = HighBitSet64 (Operand);
234 if (HighBit == -1) {
235 //
236 // Operand is zero.
237 //
238 return HighBit;
239 }
240
241 if ((Operand & (Operand - 1)) != 0) {
242 //
243 // Operand is not a whole power of two.
244 //
245 ++HighBit;
246 }
247
248 return (HighBit < 64) ? HighBit : -1;
249 }
250
251 /**
252 Look up the QEMU-specific Resource Reservation capability in the conventional
253 config space of a Hotplug Controller (that is, PCI Bridge).
254
255 On error, the contents of ReservationHint are indeterminate.
256
257 @param[in] HpcPciAddress The address of the PCI Bridge -- Bus, Device,
258 Function -- in UEFI (not PciLib) encoding.
259
260 @param[out] ReservationHint The caller-allocated capability structure to
261 populate from the PCI Bridge's config space.
262
263 @retval EFI_SUCCESS The capability has been found, ReservationHint has
264 been populated.
265
266 @retval EFI_NOT_FOUND The capability is missing.
267
268 @return Error codes from PciCapPciSegmentLib and PciCapLib.
269 **/
270 STATIC
271 EFI_STATUS
272 QueryReservationHint (
273 IN CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *HpcPciAddress,
274 OUT QEMU_PCI_BRIDGE_CAPABILITY_RESOURCE_RESERVATION *ReservationHint
275 )
276 {
277 UINT16 PciVendorId;
278 EFI_STATUS Status;
279 PCI_CAP_DEV *PciDevice;
280 PCI_CAP_LIST *CapList;
281 UINT16 VendorInstance;
282 PCI_CAP *VendorCap;
283
284 //
285 // Check the vendor identifier.
286 //
287 PciVendorId = PciRead16 (
288 PCI_LIB_ADDRESS (
289 HpcPciAddress->Bus,
290 HpcPciAddress->Device,
291 HpcPciAddress->Function,
292 PCI_VENDOR_ID_OFFSET
293 )
294 );
295 if (PciVendorId != QEMU_PCI_BRIDGE_VENDOR_ID_REDHAT) {
296 return EFI_NOT_FOUND;
297 }
298
299 //
300 // Parse the capabilities lists.
301 //
302 Status = PciCapPciSegmentDeviceInit (
303 mPciExtConfSpaceSupported ? PciCapExtended : PciCapNormal,
304 0, // Segment
305 HpcPciAddress->Bus,
306 HpcPciAddress->Device,
307 HpcPciAddress->Function,
308 &PciDevice
309 );
310 if (EFI_ERROR (Status)) {
311 return Status;
312 }
313
314 Status = PciCapListInit (PciDevice, &CapList);
315 if (EFI_ERROR (Status)) {
316 goto UninitPciDevice;
317 }
318
319 //
320 // Scan the vendor capability instances for the Resource Reservation
321 // capability.
322 //
323 VendorInstance = 0;
324 for ( ; ;) {
325 UINT8 VendorLength;
326 UINT8 BridgeCapType;
327
328 Status = PciCapListFindCap (
329 CapList,
330 PciCapNormal,
331 EFI_PCI_CAPABILITY_ID_VENDOR,
332 VendorInstance++,
333 &VendorCap
334 );
335 if (EFI_ERROR (Status)) {
336 goto UninitCapList;
337 }
338
339 //
340 // Check the vendor capability length.
341 //
342 Status = PciCapRead (
343 PciDevice,
344 VendorCap,
345 OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length),
346 &VendorLength,
347 sizeof VendorLength
348 );
349 if (EFI_ERROR (Status)) {
350 goto UninitCapList;
351 }
352
353 if (VendorLength != sizeof *ReservationHint) {
354 continue;
355 }
356
357 //
358 // Check the vendor bridge capability type.
359 //
360 Status = PciCapRead (
361 PciDevice,
362 VendorCap,
363 OFFSET_OF (QEMU_PCI_BRIDGE_CAPABILITY_HDR, Type),
364 &BridgeCapType,
365 sizeof BridgeCapType
366 );
367 if (EFI_ERROR (Status)) {
368 goto UninitCapList;
369 }
370
371 if (BridgeCapType ==
372 QEMU_PCI_BRIDGE_CAPABILITY_TYPE_RESOURCE_RESERVATION)
373 {
374 //
375 // We have a match.
376 //
377 break;
378 }
379 }
380
381 //
382 // Populate ReservationHint.
383 //
384 Status = PciCapRead (
385 PciDevice,
386 VendorCap,
387 0, // SourceOffsetInCap
388 ReservationHint,
389 sizeof *ReservationHint
390 );
391
392 UninitCapList:
393 PciCapListUninit (CapList);
394
395 UninitPciDevice:
396 PciCapPciSegmentDeviceUninit (PciDevice);
397
398 return Status;
399 }
400
401 /**
402 Returns a list of root Hot Plug Controllers (HPCs) that require
403 initialization during the boot process.
404
405 This procedure returns a list of root HPCs. The PCI bus driver must
406 initialize these controllers during the boot process. The PCI bus driver may
407 or may not be able to detect these HPCs. If the platform includes a
408 PCI-to-CardBus bridge, it can be included in this list if it requires
409 initialization. The HpcList must be self consistent. An HPC cannot control
410 any of its parent buses. Only one HPC can control a PCI bus. Because this
411 list includes only root HPCs, no HPC in the list can be a child of another
412 HPC. This policy must be enforced by the EFI_PCI_HOT_PLUG_INIT_PROTOCOL.
413 The PCI bus driver may not check for such invalid conditions. The callee
414 allocates the buffer HpcList
415
416 @param[in] This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL
417 instance.
418 @param[out] HpcCount The number of root HPCs that were returned.
419 @param[out] HpcList The list of root HPCs. HpcCount defines the number of
420 elements in this list.
421
422 @retval EFI_SUCCESS HpcList was returned.
423 @retval EFI_OUT_OF_RESOURCES HpcList was not returned due to insufficient
424 resources.
425 @retval EFI_INVALID_PARAMETER HpcCount is NULL or HpcList is NULL.
426 **/
427 STATIC
428 EFI_STATUS
429 EFIAPI
430 GetRootHpcList (
431 IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This,
432 OUT UINTN *HpcCount,
433 OUT EFI_HPC_LOCATION **HpcList
434 )
435 {
436 if ((HpcCount == NULL) || (HpcList == NULL)) {
437 return EFI_INVALID_PARAMETER;
438 }
439
440 //
441 // There are no top-level (i.e., un-enumerable) hot-plug controllers in QEMU
442 // that would require special initialization.
443 //
444 *HpcCount = 0;
445 *HpcList = NULL;
446 return EFI_SUCCESS;
447 }
448
449 /**
450 Initializes one root Hot Plug Controller (HPC). This process may causes
451 initialization of its subordinate buses.
452
453 This function initializes the specified HPC. At the end of initialization,
454 the hot-plug slots or sockets (controlled by this HPC) are powered and are
455 connected to the bus. All the necessary registers in the HPC are set up. For
456 a Standard (PCI) Hot Plug Controller (SHPC), the registers that must be set
457 up are defined in the PCI Standard Hot Plug Controller and Subsystem
458 Specification.
459
460 @param[in] This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL
461 instance.
462 @param[in] HpcDevicePath The device path to the HPC that is being
463 initialized.
464 @param[in] HpcPciAddress The address of the HPC function on the PCI bus.
465 @param[in] Event The event that should be signaled when the HPC
466 initialization is complete. Set to NULL if the
467 caller wants to wait until the entire
468 initialization process is complete.
469 @param[out] HpcState The state of the HPC hardware. The state is
470 EFI_HPC_STATE_INITIALIZED or
471 EFI_HPC_STATE_ENABLED.
472
473 @retval EFI_SUCCESS If Event is NULL, the specific HPC was
474 successfully initialized. If Event is not
475 NULL, Event will be signaled at a later time
476 when initialization is complete.
477 @retval EFI_UNSUPPORTED This instance of
478 EFI_PCI_HOT_PLUG_INIT_PROTOCOL does not
479 support the specified HPC.
480 @retval EFI_OUT_OF_RESOURCES Initialization failed due to insufficient
481 resources.
482 @retval EFI_INVALID_PARAMETER HpcState is NULL.
483 **/
484 STATIC
485 EFI_STATUS
486 EFIAPI
487 InitializeRootHpc (
488 IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This,
489 IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
490 IN UINT64 HpcPciAddress,
491 IN EFI_EVENT Event OPTIONAL,
492 OUT EFI_HPC_STATE *HpcState
493 )
494 {
495 //
496 // This function should never be called, due to the information returned by
497 // GetRootHpcList().
498 //
499 ASSERT (FALSE);
500
501 if (HpcState == NULL) {
502 return EFI_INVALID_PARAMETER;
503 }
504
505 return EFI_UNSUPPORTED;
506 }
507
508 /**
509 Returns the resource padding that is required by the PCI bus that is
510 controlled by the specified Hot Plug Controller (HPC).
511
512 This function returns the resource padding that is required by the PCI bus
513 that is controlled by the specified HPC. This member function is called for
514 all the root HPCs and nonroot HPCs that are detected by the PCI bus
515 enumerator. This function will be called before PCI resource allocation is
516 completed. This function must be called after all the root HPCs, with the
517 possible exception of a PCI-to-CardBus bridge, have completed
518 initialization.
519
520 @param[in] This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL
521 instance.
522 @param[in] HpcDevicePath The device path to the HPC.
523 @param[in] HpcPciAddress The address of the HPC function on the PCI bus.
524 @param[in] HpcState The state of the HPC hardware.
525 @param[out] Padding The amount of resource padding that is required
526 by the PCI bus under the control of the specified
527 HPC.
528 @param[out] Attributes Describes how padding is accounted for. The
529 padding is returned in the form of ACPI 2.0
530 resource descriptors.
531
532 @retval EFI_SUCCESS The resource padding was successfully
533 returned.
534 @retval EFI_UNSUPPORTED This instance of the
535 EFI_PCI_HOT_PLUG_INIT_PROTOCOL does not
536 support the specified HPC.
537 @retval EFI_NOT_READY This function was called before HPC
538 initialization is complete.
539 @retval EFI_INVALID_PARAMETER HpcState or Padding or Attributes is NULL.
540 @retval EFI_OUT_OF_RESOURCES ACPI 2.0 resource descriptors for Padding
541 cannot be allocated due to insufficient
542 resources.
543 **/
544 STATIC
545 EFI_STATUS
546 EFIAPI
547 GetResourcePadding (
548 IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This,
549 IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
550 IN UINT64 HpcPciAddress,
551 OUT EFI_HPC_STATE *HpcState,
552 OUT VOID **Padding,
553 OUT EFI_HPC_PADDING_ATTRIBUTES *Attributes
554 )
555 {
556 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *Address;
557 BOOLEAN DefaultIo;
558 BOOLEAN DefaultMmio;
559 BOOLEAN DefaultPrefMmio;
560 RESOURCE_PADDING ReservationRequest;
561 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FirstResource;
562 EFI_STATUS ReservationHintStatus;
563 QEMU_PCI_BRIDGE_CAPABILITY_RESOURCE_RESERVATION ReservationHint;
564
565 Address = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&HpcPciAddress;
566
567 DEBUG_CODE_BEGIN ();
568 CHAR16 *DevicePathString;
569
570 DevicePathString = ConvertDevicePathToText (HpcDevicePath, FALSE, FALSE);
571
572 DEBUG ((
573 DEBUG_VERBOSE,
574 "%a: Address=%02x:%02x.%x DevicePath=%s\n",
575 __FUNCTION__,
576 Address->Bus,
577 Address->Device,
578 Address->Function,
579 (DevicePathString == NULL) ? L"<unavailable>" : DevicePathString
580 ));
581
582 if (DevicePathString != NULL) {
583 FreePool (DevicePathString);
584 }
585
586 DEBUG_CODE_END ();
587
588 if ((HpcState == NULL) || (Padding == NULL) || (Attributes == NULL)) {
589 return EFI_INVALID_PARAMETER;
590 }
591
592 DefaultIo = TRUE;
593 DefaultMmio = TRUE;
594 DefaultPrefMmio = TRUE;
595
596 //
597 // Init ReservationRequest, and point FirstResource one past the last
598 // descriptor entry. We're going to build the entries backwards from
599 // ReservationRequest.EndDesc.
600 //
601 InitializeResourcePadding (&ReservationRequest);
602 FirstResource = ReservationRequest.Padding +
603 ARRAY_SIZE (ReservationRequest.Padding);
604
605 //
606 // Try to get the QEMU-specific Resource Reservation capability.
607 //
608 ReservationHintStatus = QueryReservationHint (Address, &ReservationHint);
609 if (!EFI_ERROR (ReservationHintStatus)) {
610 INTN HighBit;
611
612 DEBUG ((
613 DEBUG_VERBOSE,
614 "%a: BusNumbers=0x%x Io=0x%Lx NonPrefetchable32BitMmio=0x%x\n"
615 "%a: Prefetchable32BitMmio=0x%x Prefetchable64BitMmio=0x%Lx\n",
616 __FUNCTION__,
617 ReservationHint.BusNumbers,
618 ReservationHint.Io,
619 ReservationHint.NonPrefetchable32BitMmio,
620 __FUNCTION__,
621 ReservationHint.Prefetchable32BitMmio,
622 ReservationHint.Prefetchable64BitMmio
623 ));
624
625 //
626 // (a) Reserve bus numbers.
627 //
628 switch (ReservationHint.BusNumbers) {
629 case 0:
630 //
631 // No reservation needed.
632 //
633 break;
634 case MAX_UINT32:
635 //
636 // Firmware default (unspecified). Treat it as "no reservation needed".
637 //
638 break;
639 default:
640 //
641 // Request the specified amount.
642 //
643 --FirstResource;
644 FirstResource->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
645 FirstResource->AddrLen = ReservationHint.BusNumbers;
646 break;
647 }
648
649 //
650 // (b) Reserve IO space.
651 //
652 switch (ReservationHint.Io) {
653 case 0:
654 //
655 // No reservation needed, disable our built-in.
656 //
657 DefaultIo = FALSE;
658 break;
659 case MAX_UINT64:
660 //
661 // Firmware default (unspecified). Stick with our built-in.
662 //
663 break;
664 default:
665 //
666 // Round the specified amount up to the next power of two. If rounding is
667 // successful, reserve the rounded value. Fall back to the default
668 // otherwise.
669 //
670 HighBit = HighBitSetRoundUp64 (ReservationHint.Io);
671 if (HighBit != -1) {
672 SetIoPadding (--FirstResource, (UINTN)HighBit);
673 DefaultIo = FALSE;
674 }
675
676 break;
677 }
678
679 //
680 // (c) Reserve non-prefetchable MMIO space (32-bit only).
681 //
682 switch (ReservationHint.NonPrefetchable32BitMmio) {
683 case 0:
684 //
685 // No reservation needed, disable our built-in.
686 //
687 DefaultMmio = FALSE;
688 break;
689 case MAX_UINT32:
690 //
691 // Firmware default (unspecified). Stick with our built-in.
692 //
693 break;
694 default:
695 //
696 // Round the specified amount up to the next power of two. If rounding is
697 // successful, reserve the rounded value. Fall back to the default
698 // otherwise.
699 //
700 HighBit = HighBitSetRoundUp32 (ReservationHint.NonPrefetchable32BitMmio);
701 if (HighBit != -1) {
702 SetMmioPadding (--FirstResource, FALSE, TRUE, (UINTN)HighBit);
703 DefaultMmio = FALSE;
704 }
705
706 break;
707 }
708
709 //
710 // (d) Reserve prefetchable MMIO space (either 32-bit or 64-bit, never
711 // both).
712 //
713 // For either space, we treat 0 as "no reservation needed", and the maximum
714 // value as "firmware default". The latter is unspecified, and we interpret
715 // it as the former.
716 //
717 // Otherwise, round the specified amount up to the next power of two. If
718 // rounding is successful, reserve the rounded value. Do not reserve
719 // prefetchable MMIO space otherwise.
720 //
721 if ((ReservationHint.Prefetchable32BitMmio > 0) &&
722 (ReservationHint.Prefetchable32BitMmio < MAX_UINT32))
723 {
724 HighBit = HighBitSetRoundUp32 (ReservationHint.Prefetchable32BitMmio);
725 if (HighBit != -1) {
726 SetMmioPadding (--FirstResource, TRUE, TRUE, (UINTN)HighBit);
727 DefaultPrefMmio = FALSE;
728 }
729 } else if ((ReservationHint.Prefetchable64BitMmio > 0) &&
730 (ReservationHint.Prefetchable64BitMmio < MAX_UINT64))
731 {
732 HighBit = HighBitSetRoundUp64 (ReservationHint.Prefetchable64BitMmio);
733 if (HighBit != -1) {
734 SetMmioPadding (--FirstResource, TRUE, FALSE, (UINTN)HighBit);
735 DefaultPrefMmio = FALSE;
736 }
737 }
738 }
739
740 if (DefaultIo) {
741 //
742 // Request defaults.
743 //
744 SetIoPadding (--FirstResource, (UINTN)HighBitSetRoundUp64 (512));
745 }
746
747 if (DefaultMmio) {
748 //
749 // Request defaults.
750 //
751 SetMmioPadding (
752 --FirstResource,
753 FALSE,
754 TRUE,
755 (UINTN)HighBitSetRoundUp32 (SIZE_2MB)
756 );
757 }
758
759 if (DefaultPrefMmio) {
760 UINT64 Pci64Size = PcdGet64 (PcdPciMmio64Size);
761
762 if (Pci64Size > SIZE_32GB) {
763 SetMmioPadding (
764 --FirstResource,
765 TRUE,
766 FALSE,
767 (UINTN)HighBitSetRoundUp64 (RShiftU64 (Pci64Size, 8))
768 );
769 }
770 }
771
772 //
773 // Output a copy of ReservationRequest from the lowest-address populated
774 // entry until the end of the structure (including
775 // ReservationRequest.EndDesc). If no reservations are necessary, we'll only
776 // output the End Tag.
777 //
778 *Padding = AllocateCopyPool (
779 (UINT8 *)(&ReservationRequest + 1) - (UINT8 *)FirstResource,
780 FirstResource
781 );
782 if (*Padding == NULL) {
783 return EFI_OUT_OF_RESOURCES;
784 }
785
786 //
787 // Resource padding is required.
788 //
789 *HpcState = EFI_HPC_STATE_INITIALIZED | EFI_HPC_STATE_ENABLED;
790
791 //
792 // The padding should be applied at PCI bus level, and considered by upstream
793 // bridges, recursively.
794 //
795 *Attributes = EfiPaddingPciBus;
796 return EFI_SUCCESS;
797 }
798
799 /**
800 Entry point for this driver.
801
802 @param[in] ImageHandle Image handle of this driver.
803 @param[in] SystemTable Pointer to SystemTable.
804
805 @retval EFI_SUCESS Driver has loaded successfully.
806 @return Error codes from lower level functions.
807
808 **/
809 EFI_STATUS
810 EFIAPI
811 DriverInitialize (
812 IN EFI_HANDLE ImageHandle,
813 IN EFI_SYSTEM_TABLE *SystemTable
814 )
815 {
816 EFI_STATUS Status;
817
818 mPciExtConfSpaceSupported = (PcdGet16 (PcdOvmfHostBridgePciDevId) ==
819 INTEL_Q35_MCH_DEVICE_ID);
820 mPciHotPlugInit.GetRootHpcList = GetRootHpcList;
821 mPciHotPlugInit.InitializeRootHpc = InitializeRootHpc;
822 mPciHotPlugInit.GetResourcePadding = GetResourcePadding;
823 Status = gBS->InstallMultipleProtocolInterfaces (
824 &ImageHandle,
825 &gEfiPciHotPlugInitProtocolGuid,
826 &mPciHotPlugInit,
827 NULL
828 );
829 return Status;
830 }