4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - ACPI 6.3 Specification, January 2019
12 #include <Library/AcpiLib.h>
13 #include <Library/DebugLib.h>
14 #include <Protocol/AcpiTable.h>
16 // Module specific include files.
17 #include <AcpiTableGenerator.h>
18 #include <ConfigurationManagerObject.h>
19 #include <ConfigurationManagerHelper.h>
20 #include <Library/TableHelperLib.h>
21 #include <Protocol/ConfigurationManagerProtocol.h>
23 /** ARM standard FADT Generator
26 The following Configuration Manager Object(s) are required by
28 - EArmObjPowerManagementProfileInfo
30 - EArmObjHypervisorVendorIdentity (OPTIONAL)
33 /** This macro defines the FADT flag options for ARM Platforms.
35 #define FADT_FLAGS (EFI_ACPI_6_3_HW_REDUCED_ACPI | \
36 EFI_ACPI_6_3_LOW_POWER_S0_IDLE_CAPABLE)
38 /** This macro defines the valid mask for the FADT flag option
39 if HW_REDUCED_ACPI flag in the table is set.
41 Invalid bits are: 1, 2, 3,7, 8, 13, 14,16, 17 and
45 EFI_ACPI_6_3_WBINVD BIT0
46 EFI_ACPI_6_3_PWR_BUTTON BIT4
47 EFI_ACPI_6_3_SLP_BUTTON BIT5
48 EFI_ACPI_6_3_FIX_RTC BIT6
49 EFI_ACPI_6_3_DCK_CAP BIT9
50 EFI_ACPI_6_3_RESET_REG_SUP BIT10
51 EFI_ACPI_6_3_SEALED_CASE BIT11
52 EFI_ACPI_6_3_HEADLESS BIT12
53 EFI_ACPI_6_3_USE_PLATFORM_CLOCK BIT15
54 EFI_ACPI_6_3_FORCE_APIC_CLUSTER_MODEL BIT18
55 EFI_ACPI_6_3_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19
56 EFI_ACPI_6_3_HW_REDUCED_ACPI BIT20
57 EFI_ACPI_6_3_LOW_POWER_S0_IDLE_CAPABLE BIT21
59 #define VALID_HARDWARE_REDUCED_FLAG_MASK ( \
60 EFI_ACPI_6_3_WBINVD | \
61 EFI_ACPI_6_3_PWR_BUTTON | \
62 EFI_ACPI_6_3_SLP_BUTTON | \
63 EFI_ACPI_6_3_FIX_RTC | \
64 EFI_ACPI_6_3_DCK_CAP | \
65 EFI_ACPI_6_3_RESET_REG_SUP | \
66 EFI_ACPI_6_3_SEALED_CASE | \
67 EFI_ACPI_6_3_HEADLESS | \
68 EFI_ACPI_6_3_USE_PLATFORM_CLOCK | \
69 EFI_ACPI_6_3_FORCE_APIC_CLUSTER_MODEL | \
70 EFI_ACPI_6_3_FORCE_APIC_PHYSICAL_DESTINATION_MODE | \
71 EFI_ACPI_6_3_HW_REDUCED_ACPI | \
72 EFI_ACPI_6_3_LOW_POWER_S0_IDLE_CAPABLE)
76 /** The AcpiFadt is a template EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE
77 structure used for generating the FADT Table.
78 Note: fields marked with "{Template}" will be updated dynamically.
81 EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt
= {
83 EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
,
84 EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE
,
85 EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
87 // UINT32 FirmwareCtrl
92 EFI_ACPI_RESERVED_BYTE
,
93 // UINT8 PreferredPmProfile
94 EFI_ACPI_6_3_PM_PROFILE_UNSPECIFIED
, // {Template}: Power Management Profile
145 // UINT16 FlushStride
157 // UINT16 IaPcBootArch
163 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE ResetReg
167 // UINT16 ArmBootArch
168 EFI_ACPI_6_3_ARM_PSCI_COMPLIANT
, // {Template}: ARM Boot Architecture Flags
169 // UINT8 MinorRevision
170 EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION
,
171 // UINT64 XFirmwareCtrl
175 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk
177 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk
179 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk
181 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk
183 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk
185 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk
187 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE XGpe0Blk
189 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE XGpe1Blk
191 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE SleepControlReg
193 // EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE SleepStatusReg
195 // UINT64 HypervisorVendorIdentity
196 EFI_ACPI_RESERVED_QWORD
// {Template}: Hypervisor Vendor ID
201 /** This macro expands to a function that retrieves the Power
202 Management Profile Information from the Configuration Manager.
206 EArmObjPowerManagementProfileInfo
,
207 CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
210 /** This macro expands to a function that retrieves the Boot
211 Architecture Information from the Configuration Manager.
216 CM_ARM_BOOT_ARCH_INFO
219 /** This macro expands to a function that retrieves the Hypervisor
220 Vendor ID from the Configuration Manager.
224 EArmObjHypervisorVendorIdentity
,
225 CM_ARM_HYPERVISOR_VENDOR_ID
228 /** This macro expands to a function that retrieves the Fixed
229 feature flags for the platform from the Configuration Manager.
233 EArmObjFixedFeatureFlags
,
234 CM_ARM_FIXED_FEATURE_FLAGS
237 /** Update the Power Management Profile information in the FADT Table.
239 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
242 @retval EFI_SUCCESS Success.
243 @retval EFI_INVALID_PARAMETER A parameter is invalid.
244 @retval EFI_NOT_FOUND The required object was not found.
245 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
246 Manager is less than the Object size for the
252 FadtAddPmProfileInfo (
253 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
257 CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
* PmProfile
;
259 ASSERT (CfgMgrProtocol
!= NULL
);
261 // Get the Power Management Profile from the Platform Configuration Manager
262 Status
= GetEArmObjPowerManagementProfileInfo (
268 if (EFI_ERROR (Status
)) {
271 "ERROR: FADT: Failed to get Power Management Profile information." \
280 "FADT: PreferredPmProfile = 0x%x\n",
281 PmProfile
->PowerManagementProfile
284 AcpiFadt
.PreferredPmProfile
= PmProfile
->PowerManagementProfile
;
290 /** Updates the Boot Architecture information in the FADT Table.
292 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
295 @retval EFI_SUCCESS Success.
296 @retval EFI_INVALID_PARAMETER A parameter is invalid.
297 @retval EFI_NOT_FOUND The required object was not found.
298 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
299 Manager is less than the Object size for the
305 FadtAddBootArchInfo (
306 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
310 CM_ARM_BOOT_ARCH_INFO
* BootArchInfo
;
312 ASSERT (CfgMgrProtocol
!= NULL
);
314 // Get the Boot Architecture flags from the Platform Configuration Manager
315 Status
= GetEArmObjBootArchInfo (
321 if (EFI_ERROR (Status
)) {
324 "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n",
332 "FADT BootArchFlag = 0x%x\n",
333 BootArchInfo
->BootArchFlags
336 AcpiFadt
.ArmBootArch
= BootArchInfo
->BootArchFlags
;
342 /** Update the Hypervisor Vendor ID in the FADT Table.
344 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
347 @retval EFI_SUCCESS Success.
348 @retval EFI_INVALID_PARAMETER A parameter is invalid.
349 @retval EFI_NOT_FOUND The required object was not found.
350 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
351 Manager is less than the Object size for the
357 FadtAddHypervisorVendorId (
358 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
362 CM_ARM_HYPERVISOR_VENDOR_ID
* HypervisorVendorInfo
;
364 ASSERT (CfgMgrProtocol
!= NULL
);
366 // Get the Hypervisor Vendor ID from the Platform Configuration Manager
367 Status
= GetEArmObjHypervisorVendorIdentity (
370 &HypervisorVendorInfo
,
373 if (EFI_ERROR (Status
)) {
374 if (Status
== EFI_NOT_FOUND
) {
377 "INFO: FADT: Platform does not have a Hypervisor Vendor ID."
384 "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n",
393 "FADT: EArmObjHypervisorVendorIdentity = 0x%lx\n",
394 HypervisorVendorInfo
->HypervisorVendorId
397 AcpiFadt
.HypervisorVendorIdentity
= HypervisorVendorInfo
->HypervisorVendorId
;
403 /** Update the Fixed Feature Flags in the FADT Table.
405 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
408 @retval EFI_SUCCESS Success.
409 @retval EFI_INVALID_PARAMETER A parameter is invalid.
410 @retval EFI_NOT_FOUND The required object was not found.
411 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
412 Manager is less than the Object size for the
418 FadtAddFixedFeatureFlags (
419 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
423 CM_ARM_FIXED_FEATURE_FLAGS
* FixedFeatureFlags
;
425 ASSERT (CfgMgrProtocol
!= NULL
);
427 // Get the Fixed feature flags from the Platform Configuration Manager
428 Status
= GetEArmObjFixedFeatureFlags (
434 if (EFI_ERROR (Status
)) {
435 if (Status
== EFI_NOT_FOUND
) {
438 "INFO: FADT: Platform does not define additional Fixed feature flags."
445 "ERROR: FADT: Failed to get Fixed feature flags. Status = %r\n",
454 "FADT: EArmObjFixedFeatureFlags = 0x%x\n",
455 FixedFeatureFlags
->Flags
458 if ((FixedFeatureFlags
->Flags
& ~(VALID_HARDWARE_REDUCED_FLAG_MASK
)) != 0) {
461 "FADT: Invalid Fixed feature flags defined by platform,"
462 "Invalid Flags bits are = 0x%x\n",
463 (FixedFeatureFlags
->Flags
& ~(VALID_HARDWARE_REDUCED_FLAG_MASK
))
467 AcpiFadt
.Flags
|= (FixedFeatureFlags
->Flags
&
468 VALID_HARDWARE_REDUCED_FLAG_MASK
);
474 /** Construct the FADT table.
476 This function invokes the Configuration Manager protocol interface
477 to get the required hardware information for generating the ACPI
480 If this function allocates any resources then they must be freed
481 in the FreeXXXXTableResources function.
483 @param [in] This Pointer to the table generator.
484 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
485 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
487 @param [out] Table Pointer to the constructed ACPI Table.
489 @retval EFI_SUCCESS Table generated successfully.
490 @retval EFI_INVALID_PARAMETER A parameter is invalid.
491 @retval EFI_NOT_FOUND The required object was not found.
492 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
493 Manager is less than the Object size for the
500 IN CONST ACPI_TABLE_GENERATOR
* CONST This
,
501 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
502 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
503 OUT EFI_ACPI_DESCRIPTION_HEADER
** CONST Table
508 ASSERT (This
!= NULL
);
509 ASSERT (AcpiTableInfo
!= NULL
);
510 ASSERT (CfgMgrProtocol
!= NULL
);
511 ASSERT (Table
!= NULL
);
512 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
513 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
515 if ((AcpiTableInfo
->AcpiTableRevision
< This
->MinAcpiTableRevision
) ||
516 (AcpiTableInfo
->AcpiTableRevision
> This
->AcpiTableRevision
)) {
519 "ERROR: FADT: Requested table revision = %d, is not supported."
520 "Supported table revision: Minimum = %d, Maximum = %d\n",
521 AcpiTableInfo
->AcpiTableRevision
,
522 This
->MinAcpiTableRevision
,
523 This
->AcpiTableRevision
525 return EFI_INVALID_PARAMETER
;
530 Status
= AddAcpiHeader (
533 (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiFadt
,
535 sizeof (EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE
)
537 if (EFI_ERROR (Status
)) {
540 "ERROR: FADT: Failed to add ACPI header. Status = %r\n",
546 // Update PmProfile Info
547 Status
= FadtAddPmProfileInfo (CfgMgrProtocol
);
548 if (EFI_ERROR (Status
)) {
552 // Update BootArch Info
553 Status
= FadtAddBootArchInfo (CfgMgrProtocol
);
554 if (EFI_ERROR (Status
)) {
558 // Add the Hypervisor Vendor Id if present
559 // Note if no hypervisor is present the zero bytes
560 // will be placed in this field.
561 Status
= FadtAddHypervisorVendorId (CfgMgrProtocol
);
562 if (EFI_ERROR (Status
)) {
563 if (Status
== EFI_NOT_FOUND
) {
566 "INFO: FADT: No Hypervisor Vendor ID found," \
567 " assuming no Hypervisor is present in the firmware.\n"
572 "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r",
579 Status
= FadtAddFixedFeatureFlags (CfgMgrProtocol
);
580 if (EFI_ERROR (Status
)) {
581 if (Status
== EFI_NOT_FOUND
) {
584 "INFO: FADT: No Fixed feature flags found," \
585 " assuming no additional flags are defined for the platform.\n"
587 Status
= EFI_SUCCESS
;
591 "ERROR: FADT: Error reading Fixed feature flags, Status = %r",
598 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiFadt
;
603 /** This macro defines the FADT Table Generator revision.
605 #define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
607 /** The interface for the FADT Table Generator.
611 ACPI_TABLE_GENERATOR FadtGenerator
= {
613 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt
),
614 // Generator Description
615 L
"ACPI.STD.FADT.GENERATOR",
616 // ACPI Table Signature
617 EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
,
618 // ACPI Table Revision supported by this Generator
619 EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
,
620 // Minimum supported ACPI Table Revision
621 EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
,
623 TABLE_GENERATOR_CREATOR_ID_ARM
,
625 FADT_GENERATOR_REVISION
,
626 // Build Table function
628 // No additional resources are allocated by the generator.
629 // Hence the Free Resource function is not required.
631 // Extended build function not needed
633 // Extended build function not implemented by the generator.
634 // Hence extended free resource function is not required.
638 /** Register the Generator with the ACPI Table Factory.
640 @param [in] ImageHandle The handle to the image.
641 @param [in] SystemTable Pointer to the System Table.
643 @retval EFI_SUCCESS The Generator is registered.
644 @retval EFI_INVALID_PARAMETER A parameter is invalid.
645 @retval EFI_ALREADY_STARTED The Generator for the Table ID
646 is already registered.
650 AcpiFadtLibConstructor (
651 IN EFI_HANDLE ImageHandle
,
652 IN EFI_SYSTEM_TABLE
* SystemTable
656 Status
= RegisterAcpiTableGenerator (&FadtGenerator
);
657 DEBUG ((DEBUG_INFO
, "FADT: Register Generator. Status = %r\n", Status
));
658 ASSERT_EFI_ERROR (Status
);
662 /** Deregister the Generator from the ACPI Table Factory.
664 @param [in] ImageHandle The handle to the image.
665 @param [in] SystemTable Pointer to the System Table.
667 @retval EFI_SUCCESS The Generator is deregistered.
668 @retval EFI_INVALID_PARAMETER A parameter is invalid.
669 @retval EFI_NOT_FOUND The Generator is not registered.
673 AcpiFadtLibDestructor (
674 IN EFI_HANDLE ImageHandle
,
675 IN EFI_SYSTEM_TABLE
* SystemTable
679 Status
= DeregisterAcpiTableGenerator (&FadtGenerator
);
680 DEBUG ((DEBUG_INFO
, "FADT: Deregister Generator. Status = %r\n", Status
));
681 ASSERT_EFI_ERROR (Status
);