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