4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 - ACPI 6.2 Specification - Errata A, September 2017
18 #include <Library/AcpiLib.h>
19 #include <Library/DebugLib.h>
20 #include <Protocol/AcpiTable.h>
22 // Module specific include files.
23 #include <AcpiTableGenerator.h>
24 #include <ConfigurationManagerObject.h>
25 #include <ConfigurationManagerHelper.h>
26 #include <Library/TableHelperLib.h>
27 #include <Protocol/ConfigurationManagerProtocol.h>
29 /** ARM standard FADT Generator
32 The following Configuration Manager Object(s) are required by
34 - EArmObjPowerManagementProfileInfo
36 - EArmObjHypervisorVendorIdentity (OPTIONAL)
39 /** This macro defines the FADT flag options for ARM Platforms.
41 #define FADT_FLAGS (EFI_ACPI_6_2_HW_REDUCED_ACPI | \
42 EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE)
44 /** This macro defines the valid mask for the FADT flag option
45 if HW_REDUCED_ACPI flag in the table is set.
47 Invalid bits are: 1, 2, 3,7, 8, 13, 14,16, 17 and
51 EFI_ACPI_6_2_WBINVD BIT0
52 EFI_ACPI_6_2_PWR_BUTTON BIT4
53 EFI_ACPI_6_2_SLP_BUTTON BIT5
54 EFI_ACPI_6_2_FIX_RTC BIT6
55 EFI_ACPI_6_2_DCK_CAP BIT9
56 EFI_ACPI_6_2_RESET_REG_SUP BIT10
57 EFI_ACPI_6_2_SEALED_CASE BIT11
58 EFI_ACPI_6_2_HEADLESS BIT12
59 EFI_ACPI_6_2_USE_PLATFORM_CLOCK BIT15
60 EFI_ACPI_6_2_FORCE_APIC_CLUSTER_MODEL BIT18
61 EFI_ACPI_6_2_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19
62 EFI_ACPI_6_2_HW_REDUCED_ACPI BIT20
63 EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE BIT21
65 #define VALID_HARDWARE_REDUCED_FLAG_MASK ( \
66 EFI_ACPI_6_2_WBINVD | \
67 EFI_ACPI_6_2_PWR_BUTTON | \
68 EFI_ACPI_6_2_SLP_BUTTON | \
69 EFI_ACPI_6_2_FIX_RTC | \
70 EFI_ACPI_6_2_DCK_CAP | \
71 EFI_ACPI_6_2_RESET_REG_SUP | \
72 EFI_ACPI_6_2_SEALED_CASE | \
73 EFI_ACPI_6_2_HEADLESS | \
74 EFI_ACPI_6_2_USE_PLATFORM_CLOCK | \
75 EFI_ACPI_6_2_FORCE_APIC_CLUSTER_MODEL | \
76 EFI_ACPI_6_2_FORCE_APIC_PHYSICAL_DESTINATION_MODE | \
77 EFI_ACPI_6_2_HW_REDUCED_ACPI | \
78 EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE)
82 /** The AcpiFadt is a template EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE
83 structure used for generating the FADT Table.
84 Note: fields marked with "{Template}" will be updated dynamically.
87 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt
= {
89 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
,
90 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE
,
91 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
93 // UINT32 FirmwareCtrl
98 EFI_ACPI_RESERVED_BYTE
,
99 // UINT8 PreferredPmProfile
100 EFI_ACPI_6_2_PM_PROFILE_UNSPECIFIED
, // {Template}: Power Management Profile
151 // UINT16 FlushStride
163 // UINT16 IaPcBootArch
169 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE ResetReg
173 // UINT16 ArmBootArch
174 EFI_ACPI_6_2_ARM_PSCI_COMPLIANT
, // {Template}: ARM Boot Architecture Flags
175 // UINT8 MinorRevision
176 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION
,
177 // UINT64 XFirmwareCtrl
181 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk
183 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk
185 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk
187 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk
189 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk
191 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk
193 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XGpe0Blk
195 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XGpe1Blk
197 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE SleepControlReg
199 // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE SleepStatusReg
201 // UINT64 HypervisorVendorIdentity
202 EFI_ACPI_RESERVED_QWORD
// {Template}: Hypervisor Vendor ID
207 /** This macro expands to a function that retrieves the Power
208 Management Profile Information from the Configuration Manager.
212 EArmObjPowerManagementProfileInfo
,
213 CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
216 /** This macro expands to a function that retrieves the Boot
217 Architecture Information from the Configuration Manager.
222 CM_ARM_BOOT_ARCH_INFO
225 /** This macro expands to a function that retrieves the Hypervisor
226 Vendor ID from the Configuration Manager.
230 EArmObjHypervisorVendorIdentity
,
231 CM_ARM_HYPERVISOR_VENDOR_ID
234 /** This macro expands to a function that retrieves the Fixed
235 feature flags for the platform from the Configuration Manager.
239 EArmObjFixedFeatureFlags
,
240 CM_ARM_FIXED_FEATURE_FLAGS
243 /** Update the Power Management Profile information in the FADT Table.
245 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
248 @retval EFI_SUCCESS Success.
249 @retval EFI_INVALID_PARAMETER A parameter is invalid.
250 @retval EFI_NOT_FOUND The required object was not found.
251 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
252 Manager is less than the Object size for the
258 FadtAddPmProfileInfo (
259 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
263 CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
* PmProfile
;
265 ASSERT (CfgMgrProtocol
!= NULL
);
267 // Get the Power Management Profile from the Platform Configuration Manager
268 Status
= GetEArmObjPowerManagementProfileInfo (
274 if (EFI_ERROR (Status
)) {
277 "ERROR: FADT: Failed to get Power Management Profile information." \
286 "FADT: PreferredPmProfile = 0x%x\n",
287 PmProfile
->PowerManagementProfile
290 AcpiFadt
.PreferredPmProfile
= PmProfile
->PowerManagementProfile
;
296 /** Updates the Boot Architecture information in the FADT Table.
298 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
301 @retval EFI_SUCCESS Success.
302 @retval EFI_INVALID_PARAMETER A parameter is invalid.
303 @retval EFI_NOT_FOUND The required object was not found.
304 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
305 Manager is less than the Object size for the
311 FadtAddBootArchInfo (
312 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
316 CM_ARM_BOOT_ARCH_INFO
* BootArchInfo
;
318 ASSERT (CfgMgrProtocol
!= NULL
);
320 // Get the Boot Architecture flags from the Platform Configuration Manager
321 Status
= GetEArmObjBootArchInfo (
327 if (EFI_ERROR (Status
)) {
330 "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n",
338 "FADT BootArchFlag = 0x%x\n",
339 BootArchInfo
->BootArchFlags
342 AcpiFadt
.ArmBootArch
= BootArchInfo
->BootArchFlags
;
348 /** Update the Hypervisor Vendor ID in the FADT Table.
350 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
353 @retval EFI_SUCCESS Success.
354 @retval EFI_INVALID_PARAMETER A parameter is invalid.
355 @retval EFI_NOT_FOUND The required object was not found.
356 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
357 Manager is less than the Object size for the
363 FadtAddHypervisorVendorId (
364 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
368 CM_ARM_HYPERVISOR_VENDOR_ID
* HypervisorVendorInfo
;
370 ASSERT (CfgMgrProtocol
!= NULL
);
372 // Get the Hypervisor Vendor ID from the Platform Configuration Manager
373 Status
= GetEArmObjHypervisorVendorIdentity (
376 &HypervisorVendorInfo
,
379 if (EFI_ERROR (Status
)) {
380 if (Status
== EFI_NOT_FOUND
) {
383 "INFO: FADT: Platform does not have a Hypervisor Vendor ID."
390 "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n",
399 "FADT: EArmObjHypervisorVendorIdentity = 0x%lx\n",
400 HypervisorVendorInfo
->HypervisorVendorId
403 AcpiFadt
.HypervisorVendorIdentity
= HypervisorVendorInfo
->HypervisorVendorId
;
409 /** Update the Fixed Feature Flags in the FADT Table.
411 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
414 @retval EFI_SUCCESS Success.
415 @retval EFI_INVALID_PARAMETER A parameter is invalid.
416 @retval EFI_NOT_FOUND The required object was not found.
417 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
418 Manager is less than the Object size for the
424 FadtAddFixedFeatureFlags (
425 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
429 CM_ARM_FIXED_FEATURE_FLAGS
* FixedFeatureFlags
;
431 ASSERT (CfgMgrProtocol
!= NULL
);
433 // Get the Fixed feature flags from the Platform Configuration Manager
434 Status
= GetEArmObjFixedFeatureFlags (
440 if (EFI_ERROR (Status
)) {
441 if (Status
== EFI_NOT_FOUND
) {
444 "INFO: FADT: Platform does not define additional Fixed feature flags."
451 "ERROR: FADT: Failed to get Fixed feature flags. Status = %r\n",
460 "FADT: EArmObjFixedFeatureFlags = 0x%x\n",
461 FixedFeatureFlags
->Flags
464 if ((FixedFeatureFlags
->Flags
& ~(VALID_HARDWARE_REDUCED_FLAG_MASK
)) != 0) {
467 "FADT: Invalid Fixed feature flags defined by platform,"
468 "Invalid Flags bits are = 0x%x\n",
469 (FixedFeatureFlags
->Flags
& ~(VALID_HARDWARE_REDUCED_FLAG_MASK
))
473 AcpiFadt
.Flags
|= (FixedFeatureFlags
->Flags
&
474 VALID_HARDWARE_REDUCED_FLAG_MASK
);
480 /** Construct the FADT table.
482 This function invokes the Configuration Manager protocol interface
483 to get the required hardware information for generating the ACPI
486 If this function allocates any resources then they must be freed
487 in the FreeXXXXTableResources function.
489 @param [in] This Pointer to the table generator.
490 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
491 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
493 @param [out] Table Pointer to the constructed ACPI Table.
495 @retval EFI_SUCCESS Table generated successfully.
496 @retval EFI_INVALID_PARAMETER A parameter is invalid.
497 @retval EFI_NOT_FOUND The required object was not found.
498 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
499 Manager is less than the Object size for the
506 IN CONST ACPI_TABLE_GENERATOR
* CONST This
,
507 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
508 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
509 OUT EFI_ACPI_DESCRIPTION_HEADER
** CONST Table
514 ASSERT (This
!= NULL
);
515 ASSERT (AcpiTableInfo
!= NULL
);
516 ASSERT (CfgMgrProtocol
!= NULL
);
517 ASSERT (Table
!= NULL
);
518 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
519 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
521 if ((AcpiTableInfo
->AcpiTableRevision
< This
->MinAcpiTableRevision
) ||
522 (AcpiTableInfo
->AcpiTableRevision
> This
->AcpiTableRevision
)) {
525 "ERROR: FADT: Requested table revision = %d, is not supported."
526 "Supported table revision: Minimum = %d, Maximum = %d\n",
527 AcpiTableInfo
->AcpiTableRevision
,
528 This
->MinAcpiTableRevision
,
529 This
->AcpiTableRevision
531 return EFI_INVALID_PARAMETER
;
536 Status
= AddAcpiHeader (
539 (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiFadt
,
540 AcpiTableInfo
->AcpiTableRevision
,
541 sizeof (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE
)
543 if (EFI_ERROR (Status
)) {
546 "ERROR: FADT: Failed to add ACPI header. Status = %r\n",
552 // Update PmProfile Info
553 Status
= FadtAddPmProfileInfo (CfgMgrProtocol
);
554 if (EFI_ERROR (Status
)) {
558 // Update BootArch Info
559 Status
= FadtAddBootArchInfo (CfgMgrProtocol
);
560 if (EFI_ERROR (Status
)) {
564 // Add the Hypervisor Vendor Id if present
565 // Note if no hypervisor is present the zero bytes
566 // will be placed in this field.
567 Status
= FadtAddHypervisorVendorId (CfgMgrProtocol
);
568 if (EFI_ERROR (Status
)) {
569 if (Status
== EFI_NOT_FOUND
) {
572 "INFO: FADT: No Hypervisor Vendor ID found," \
573 " assuming no Hypervisor is present in the firmware.\n"
578 "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r",
585 Status
= FadtAddFixedFeatureFlags (CfgMgrProtocol
);
586 if (EFI_ERROR (Status
)) {
587 if (Status
== EFI_NOT_FOUND
) {
590 "INFO: FADT: No Fixed feature flags found," \
591 " assuming no additional flags are defined for the platform.\n"
593 Status
= EFI_SUCCESS
;
597 "ERROR: FADT: Error reading Fixed feature flags, Status = %r",
604 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiFadt
;
609 /** This macro defines the FADT Table Generator revision.
611 #define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
613 /** The interface for the FADT Table Generator.
617 ACPI_TABLE_GENERATOR FadtGenerator
= {
619 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt
),
620 // Generator Description
621 L
"ACPI.STD.FADT.GENERATOR",
622 // ACPI Table Signature
623 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
,
624 // ACPI Table Revision supported by this Generator
625 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
,
626 // Minimum supported ACPI Table Revision
627 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
,
629 TABLE_GENERATOR_CREATOR_ID_ARM
,
631 FADT_GENERATOR_REVISION
,
632 // Build Table function
634 // No additional resources are allocated by the generator.
635 // Hence the Free Resource function is not required.
637 // Extended build function not needed
639 // Extended build function not implemented by the generator.
640 // Hence extended free resource function is not required.
644 /** Register the Generator with the ACPI Table Factory.
646 @param [in] ImageHandle The handle to the image.
647 @param [in] SystemTable Pointer to the System Table.
649 @retval EFI_SUCCESS The Generator is registered.
650 @retval EFI_INVALID_PARAMETER A parameter is invalid.
651 @retval EFI_ALREADY_STARTED The Generator for the Table ID
652 is already registered.
656 AcpiFadtLibConstructor (
657 IN CONST EFI_HANDLE ImageHandle
,
658 IN EFI_SYSTEM_TABLE
* CONST SystemTable
662 Status
= RegisterAcpiTableGenerator (&FadtGenerator
);
663 DEBUG ((DEBUG_INFO
, "FADT: Register Generator. Status = %r\n", Status
));
664 ASSERT_EFI_ERROR (Status
);
668 /** Deregister the Generator from the ACPI Table Factory.
670 @param [in] ImageHandle The handle to the image.
671 @param [in] SystemTable Pointer to the System Table.
673 @retval EFI_SUCCESS The Generator is deregistered.
674 @retval EFI_INVALID_PARAMETER A parameter is invalid.
675 @retval EFI_NOT_FOUND The Generator is not registered.
679 AcpiFadtLibDestructor (
680 IN CONST EFI_HANDLE ImageHandle
,
681 IN EFI_SYSTEM_TABLE
* CONST SystemTable
685 Status
= DeregisterAcpiTableGenerator (&FadtGenerator
);
686 DEBUG ((DEBUG_INFO
, "FADT: Deregister Generator. Status = %r\n", Status
));
687 ASSERT_EFI_ERROR (Status
);