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