]> git.proxmox.com Git - mirror_edk2.git/commitdiff
DynamicTablesPkg: Arm ACPI FADT Generator
authorSami Mujawar <sami.mujawar@arm.com>
Sat, 15 Dec 2018 12:22:45 +0000 (12:22 +0000)
committerSami Mujawar <sami.mujawar@arm.com>
Tue, 19 Feb 2019 10:37:30 +0000 (10:37 +0000)
The FADT generator collates the relevant information required
for generating a FADT table from configuration manager using
the configuration manager protocol. It then updates a template
FADT table structure. This table data is used by the Table
Manager to install the FADT table.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Alexei Fedorov <alexei.fedorov@arm.com>
DynamicTablesPkg/DynamicTables.dsc.inc
DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf [new file with mode: 0644]
DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c [new file with mode: 0644]

index 1dde21f393e9717c1d5adfbebe8dd8840da418c3..ffdf4f13bbc88c7d4ef97d15583c951a4c9ff599 100644 (file)
@@ -27,6 +27,7 @@
   #\r
   DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf {\r
     <LibraryClasses>\r
+      NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf\r
       NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf\r
   }\r
 \r
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
new file mode 100644 (file)
index 0000000..e772409
--- /dev/null
@@ -0,0 +1,42 @@
+## @file\r
+#  FADT Table Generator\r
+#\r
+#  Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION    = 0x00010019\r
+  BASE_NAME      = AcpiFadtLibArm\r
+  FILE_GUID      = 686FE5FE-B944-485F-8B1C-7D60E0056487\r
+  VERSION_STRING = 1.0\r
+  MODULE_TYPE    = DXE_DRIVER\r
+  LIBRARY_CLASS  = NULL|DXE_DRIVER\r
+  CONSTRUCTOR    = AcpiFadtLibConstructor\r
+  DESTRUCTOR     = AcpiFadtLibDestructor\r
+\r
+[Sources]\r
+  FadtGenerator.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+  DynamicTablesPkg/DynamicTablesPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+\r
+[Pcd]\r
+\r
+[Protocols]\r
+\r
+[Guids]\r
+\r
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
new file mode 100644 (file)
index 0000000..62927b5
--- /dev/null
@@ -0,0 +1,689 @@
+/** @file\r
+  FADT Table Generator\r
+\r
+  Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+  @par Reference(s):\r
+  - ACPI 6.2 Specification - Errata A, September 2017\r
+\r
+**/\r
+\r
+#include <Library/AcpiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Protocol/AcpiTable.h>\r
+\r
+// Module specific include files.\r
+#include <AcpiTableGenerator.h>\r
+#include <ConfigurationManagerObject.h>\r
+#include <ConfigurationManagerHelper.h>\r
+#include <Library/TableHelperLib.h>\r
+#include <Protocol/ConfigurationManagerProtocol.h>\r
+\r
+/** ARM standard FADT Generator\r
+\r
+Requirements:\r
+  The following Configuration Manager Object(s) are required by\r
+  this Generator:\r
+  - EArmObjPowerManagementProfileInfo\r
+  - EArmObjBootArchInfo\r
+  - EArmObjHypervisorVendorIdentity (OPTIONAL)\r
+*/\r
+\r
+/** This macro defines the FADT flag options for ARM Platforms.\r
+*/\r
+#define FADT_FLAGS  (EFI_ACPI_6_2_HW_REDUCED_ACPI |          \\r
+                     EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE)\r
+\r
+/** This macro defines the valid mask for the FADT flag option\r
+    if HW_REDUCED_ACPI flag in the table is set.\r
+\r
+  Invalid bits are: 1, 2, 3,7, 8, 13, 14,16, 17 and\r
+    22-31 (reserved).\r
+\r
+  Valid bits are:\r
+    EFI_ACPI_6_2_WBINVD                               BIT0\r
+    EFI_ACPI_6_2_PWR_BUTTON                           BIT4\r
+    EFI_ACPI_6_2_SLP_BUTTON                           BIT5\r
+    EFI_ACPI_6_2_FIX_RTC                              BIT6\r
+    EFI_ACPI_6_2_DCK_CAP                              BIT9\r
+    EFI_ACPI_6_2_RESET_REG_SUP                        BIT10\r
+    EFI_ACPI_6_2_SEALED_CASE                          BIT11\r
+    EFI_ACPI_6_2_HEADLESS                             BIT12\r
+    EFI_ACPI_6_2_USE_PLATFORM_CLOCK                   BIT15\r
+    EFI_ACPI_6_2_FORCE_APIC_CLUSTER_MODEL             BIT18\r
+    EFI_ACPI_6_2_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19\r
+    EFI_ACPI_6_2_HW_REDUCED_ACPI                      BIT20\r
+    EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE            BIT21\r
+*/\r
+#define VALID_HARDWARE_REDUCED_FLAG_MASK  (                   \\r
+          EFI_ACPI_6_2_WBINVD                               | \\r
+          EFI_ACPI_6_2_PWR_BUTTON                           | \\r
+          EFI_ACPI_6_2_SLP_BUTTON                           | \\r
+          EFI_ACPI_6_2_FIX_RTC                              | \\r
+          EFI_ACPI_6_2_DCK_CAP                              | \\r
+          EFI_ACPI_6_2_RESET_REG_SUP                        | \\r
+          EFI_ACPI_6_2_SEALED_CASE                          | \\r
+          EFI_ACPI_6_2_HEADLESS                             | \\r
+          EFI_ACPI_6_2_USE_PLATFORM_CLOCK                   | \\r
+          EFI_ACPI_6_2_FORCE_APIC_CLUSTER_MODEL             | \\r
+          EFI_ACPI_6_2_FORCE_APIC_PHYSICAL_DESTINATION_MODE | \\r
+          EFI_ACPI_6_2_HW_REDUCED_ACPI                      | \\r
+          EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE)\r
+\r
+#pragma pack(1)\r
+\r
+/** The AcpiFadt is a template EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE\r
+    structure used for generating the FADT Table.\r
+  Note: fields marked with "{Template}" will be updated dynamically.\r
+*/\r
+STATIC\r
+EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = {\r
+  ACPI_HEADER (\r
+    EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,\r
+    EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE,\r
+    EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION\r
+    ),\r
+  // UINT32     FirmwareCtrl\r
+  0,\r
+  // UINT32     Dsdt\r
+  0,\r
+  // UINT8      Reserved0\r
+  EFI_ACPI_RESERVED_BYTE,\r
+  // UINT8      PreferredPmProfile\r
+  EFI_ACPI_6_2_PM_PROFILE_UNSPECIFIED,  // {Template}: Power Management Profile\r
+  // UINT16     SciInt\r
+  0,\r
+  // UINT32     SmiCmd\r
+  0,\r
+  // UINT8      AcpiEnable\r
+  0,\r
+  // UINT8      AcpiDisable\r
+  0,\r
+  // UINT8      S4BiosReq\r
+  0,\r
+  // UINT8      PstateCnt\r
+  0,\r
+  // UINT32     Pm1aEvtBlk\r
+  0,\r
+  // UINT32     Pm1bEvtBlk\r
+  0,\r
+  // UINT32     Pm1aCntBlk\r
+  0,\r
+  // UINT32     Pm1bCntBlk\r
+  0,\r
+  // UINT32     Pm2CntBlk\r
+  0,\r
+  // UINT32     PmTmrBlk\r
+  0,\r
+  // UINT32     Gpe0Blk\r
+  0,\r
+  // UINT32     Gpe1Blk\r
+  0,\r
+  // UINT8      Pm1EvtLen\r
+  0,\r
+  // UINT8      Pm1CntLen\r
+  0,\r
+  // UINT8      Pm2CntLen\r
+  0,\r
+  // UINT8      PmTmrLen\r
+  0,\r
+  // UINT8      Gpe0BlkLen\r
+  0,\r
+  // UINT8      Gpe1BlkLen\r
+  0,\r
+  // UINT8      Gpe1Base\r
+  0,\r
+  // UINT8      CstCnt\r
+  0,\r
+  // UINT16     PLvl2Lat\r
+  0,\r
+  // UINT16     PLvl3Lat\r
+  0,\r
+  // UINT16     FlushSize\r
+  0,\r
+  // UINT16     FlushStride\r
+  0,\r
+  // UINT8      DutyOffset\r
+  0,\r
+  // UINT8      DutyWidth\r
+  0,\r
+  // UINT8      DayAlrm\r
+  0,\r
+  // UINT8      MonAlrm\r
+  0,\r
+  // UINT8      Century\r
+  0,\r
+  // UINT16     IaPcBootArch\r
+  0,\r
+  // UINT8      Reserved1\r
+  0,\r
+  // UINT32     Flags\r
+  FADT_FLAGS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  ResetReg\r
+  NULL_GAS,\r
+  // UINT8      ResetValue\r
+  0,\r
+  // UINT16     ArmBootArch\r
+  EFI_ACPI_6_2_ARM_PSCI_COMPLIANT,  // {Template}: ARM Boot Architecture Flags\r
+  // UINT8      MinorRevision\r
+  EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION,\r
+  // UINT64     XFirmwareCtrl\r
+  0,\r
+  // UINT64     XDsdt\r
+  0,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  XPm1aEvtBlk\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  XPm1bEvtBlk\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  XPm1aCntBlk\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  XPm1bCntBlk\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  XPm2CntBlk\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  XPmTmrBlk\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  XGpe0Blk\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  XGpe1Blk\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  SleepControlReg\r
+  NULL_GAS,\r
+  // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE  SleepStatusReg\r
+  NULL_GAS,\r
+  // UINT64     HypervisorVendorIdentity\r
+  EFI_ACPI_RESERVED_QWORD  // {Template}: Hypervisor Vendor ID\r
+};\r
+\r
+#pragma pack()\r
+\r
+/** This macro expands to a function that retrieves the Power\r
+    Management Profile Information from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+  EObjNameSpaceArm,\r
+  EArmObjPowerManagementProfileInfo,\r
+  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO\r
+  );\r
+\r
+/** This macro expands to a function that retrieves the Boot\r
+    Architecture Information from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+  EObjNameSpaceArm,\r
+  EArmObjBootArchInfo,\r
+  CM_ARM_BOOT_ARCH_INFO\r
+  );\r
+\r
+/** This macro expands to a function that retrieves the Hypervisor\r
+    Vendor ID from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+  EObjNameSpaceArm,\r
+  EArmObjHypervisorVendorIdentity,\r
+  CM_ARM_HYPERVISOR_VENDOR_ID\r
+  );\r
+\r
+/** This macro expands to a function that retrieves the Fixed\r
+  feature flags for the platform from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+  EObjNameSpaceArm,\r
+  EArmObjFixedFeatureFlags,\r
+  CM_ARM_FIXED_FEATURE_FLAGS\r
+  );\r
+\r
+/** Update the Power Management Profile information in the FADT Table.\r
+\r
+  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager\r
+                              Protocol Interface.\r
+\r
+  @retval EFI_SUCCESS           Success.\r
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+  @retval EFI_NOT_FOUND         The required object was not found.\r
+  @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration\r
+                                Manager is less than the Object size for the\r
+                                requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+FadtAddPmProfileInfo (\r
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol\r
+)\r
+{\r
+  EFI_STATUS                              Status;\r
+  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO  * PmProfile;\r
+\r
+  ASSERT (CfgMgrProtocol != NULL);\r
+\r
+  // Get the Power Management Profile from the Platform Configuration Manager\r
+  Status = GetEArmObjPowerManagementProfileInfo (\r
+             CfgMgrProtocol,\r
+             CM_NULL_TOKEN,\r
+             &PmProfile,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "ERROR: FADT: Failed to get Power Management Profile information." \\r
+      " Status = %r\n",\r
+      Status\r
+      ));\r
+    goto error_handler;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "FADT: PreferredPmProfile = 0x%x\n",\r
+    PmProfile->PowerManagementProfile\r
+    ));\r
+\r
+  AcpiFadt.PreferredPmProfile = PmProfile->PowerManagementProfile;\r
+\r
+error_handler:\r
+  return Status;\r
+}\r
+\r
+/** Updates the Boot Architecture information in the FADT Table.\r
+\r
+  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager\r
+                              Protocol Interface.\r
+\r
+  @retval EFI_SUCCESS           Success.\r
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+  @retval EFI_NOT_FOUND         The required object was not found.\r
+  @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration\r
+                                Manager is less than the Object size for the\r
+                                requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+FadtAddBootArchInfo (\r
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol\r
+)\r
+{\r
+  EFI_STATUS               Status;\r
+  CM_ARM_BOOT_ARCH_INFO  * BootArchInfo;\r
+\r
+  ASSERT (CfgMgrProtocol != NULL);\r
+\r
+  // Get the Boot Architecture flags from the Platform Configuration Manager\r
+  Status = GetEArmObjBootArchInfo (\r
+             CfgMgrProtocol,\r
+             CM_NULL_TOKEN,\r
+             &BootArchInfo,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n",\r
+      Status\r
+      ));\r
+    goto error_handler;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "FADT BootArchFlag = 0x%x\n",\r
+    BootArchInfo->BootArchFlags\r
+    ));\r
+\r
+  AcpiFadt.ArmBootArch = BootArchInfo->BootArchFlags;\r
+\r
+error_handler:\r
+  return Status;\r
+}\r
+\r
+/** Update the Hypervisor Vendor ID in the FADT Table.\r
+\r
+  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager\r
+                              Protocol Interface.\r
+\r
+  @retval EFI_SUCCESS           Success.\r
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+  @retval EFI_NOT_FOUND         The required object was not found.\r
+  @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration\r
+                                Manager is less than the Object size for the\r
+                                requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+FadtAddHypervisorVendorId (\r
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol\r
+)\r
+{\r
+  EFI_STATUS                     Status;\r
+  CM_ARM_HYPERVISOR_VENDOR_ID  * HypervisorVendorInfo;\r
+\r
+  ASSERT (CfgMgrProtocol != NULL);\r
+\r
+  // Get the Hypervisor Vendor ID from the Platform Configuration Manager\r
+  Status = GetEArmObjHypervisorVendorIdentity (\r
+             CfgMgrProtocol,\r
+             CM_NULL_TOKEN,\r
+             &HypervisorVendorInfo,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "INFO: FADT: Platform does not have a Hypervisor Vendor ID."\r
+        "Status = %r\n",\r
+        Status\r
+        ));\r
+    } else {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n",\r
+        Status\r
+        ));\r
+    }\r
+    goto error_handler;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "FADT: EArmObjHypervisorVendorIdentity = 0x%lx\n",\r
+    HypervisorVendorInfo->HypervisorVendorId\r
+    ));\r
+\r
+  AcpiFadt.HypervisorVendorIdentity = HypervisorVendorInfo->HypervisorVendorId;\r
+\r
+error_handler:\r
+  return Status;\r
+}\r
+\r
+/** Update the Fixed Feature Flags in the FADT Table.\r
+\r
+  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager\r
+                              Protocol Interface.\r
+\r
+  @retval EFI_SUCCESS           Success.\r
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+  @retval EFI_NOT_FOUND         The required object was not found.\r
+  @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration\r
+                                Manager is less than the Object size for the\r
+                                requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+FadtAddFixedFeatureFlags (\r
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol\r
+)\r
+{\r
+  EFI_STATUS                    Status;\r
+  CM_ARM_FIXED_FEATURE_FLAGS  * FixedFeatureFlags;\r
+\r
+  ASSERT (CfgMgrProtocol != NULL);\r
+\r
+  // Get the Fixed feature flags from the Platform Configuration Manager\r
+  Status = GetEArmObjFixedFeatureFlags (\r
+             CfgMgrProtocol,\r
+             CM_NULL_TOKEN,\r
+             &FixedFeatureFlags,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "INFO: FADT: Platform does not define additional Fixed feature flags."\r
+        "Status = %r\n",\r
+        Status\r
+        ));\r
+    } else {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "ERROR: FADT: Failed to get Fixed feature flags. Status = %r\n",\r
+        Status\r
+        ));\r
+    }\r
+    goto error_handler;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "FADT: EArmObjFixedFeatureFlags = 0x%x\n",\r
+    FixedFeatureFlags->Flags\r
+    ));\r
+\r
+  if ((FixedFeatureFlags->Flags & ~(VALID_HARDWARE_REDUCED_FLAG_MASK)) != 0) {\r
+    DEBUG ((\r
+      DEBUG_WARN,\r
+      "FADT: Invalid Fixed feature flags defined by platform,"\r
+      "Invalid Flags bits are = 0x%x\n",\r
+      (FixedFeatureFlags->Flags & ~(VALID_HARDWARE_REDUCED_FLAG_MASK))\r
+      ));\r
+  }\r
+\r
+  AcpiFadt.Flags |= (FixedFeatureFlags->Flags &\r
+                     VALID_HARDWARE_REDUCED_FLAG_MASK);\r
+\r
+error_handler:\r
+  return Status;\r
+}\r
+\r
+/** Construct the FADT table.\r
+\r
+  This function invokes the Configuration Manager protocol interface\r
+  to get the required hardware information for generating the ACPI\r
+  table.\r
+\r
+  If this function allocates any resources then they must be freed\r
+  in the FreeXXXXTableResources function.\r
+\r
+  @param [in]  This           Pointer to the table generator.\r
+  @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.\r
+  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager\r
+                              Protocol Interface.\r
+  @param [out] Table          Pointer to the constructed ACPI Table.\r
+\r
+  @retval EFI_SUCCESS           Table generated successfully.\r
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+  @retval EFI_NOT_FOUND         The required object was not found.\r
+  @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration\r
+                                Manager is less than the Object size for the\r
+                                requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+BuildFadtTable (\r
+  IN  CONST ACPI_TABLE_GENERATOR                  * CONST This,\r
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO            * CONST AcpiTableInfo,\r
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,\r
+  OUT       EFI_ACPI_DESCRIPTION_HEADER          ** CONST Table\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  ASSERT (This != NULL);\r
+  ASSERT (AcpiTableInfo != NULL);\r
+  ASSERT (CfgMgrProtocol != NULL);\r
+  ASSERT (Table != NULL);\r
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
+\r
+  if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
+      (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "ERROR: FADT: Requested table revision = %d, is not supported."\r
+      "Supported table revision: Minimum = %d, Maximum = %d\n",\r
+      AcpiTableInfo->AcpiTableRevision,\r
+      This->MinAcpiTableRevision,\r
+      This->AcpiTableRevision\r
+      ));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Table = NULL;\r
+\r
+  Status = AddAcpiHeader (\r
+             CfgMgrProtocol,\r
+             This,\r
+             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt,\r
+             AcpiTableInfo->AcpiTableRevision,\r
+             sizeof (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE)\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "ERROR: FADT: Failed to add ACPI header. Status = %r\n",\r
+      Status\r
+      ));\r
+    goto error_handler;\r
+  }\r
+\r
+  // Update PmProfile Info\r
+  Status = FadtAddPmProfileInfo (CfgMgrProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    goto error_handler;\r
+  }\r
+\r
+  // Update BootArch Info\r
+  Status = FadtAddBootArchInfo (CfgMgrProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    goto error_handler;\r
+  }\r
+\r
+  // Add the Hypervisor Vendor Id if present\r
+  // Note if no hypervisor is present the zero bytes\r
+  // will be placed in this field.\r
+  Status = FadtAddHypervisorVendorId (CfgMgrProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "INFO: FADT: No Hypervisor Vendor ID found," \\r
+        " assuming no Hypervisor is present in the firmware.\n"\r
+        ));\r
+    } else {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r",\r
+        Status\r
+        ));\r
+      goto error_handler;\r
+    }\r
+  }\r
+\r
+  Status = FadtAddFixedFeatureFlags (CfgMgrProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "INFO: FADT: No Fixed feature flags found," \\r
+        " assuming no additional flags are defined for the platform.\n"\r
+        ));\r
+      Status = EFI_SUCCESS;\r
+    } else {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "ERROR: FADT: Error reading Fixed feature flags, Status = %r",\r
+        Status\r
+        ));\r
+      goto error_handler;\r
+    }\r
+  }\r
+\r
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt;\r
+error_handler:\r
+  return Status;\r
+}\r
+\r
+/** This macro defines the FADT Table Generator revision.\r
+*/\r
+#define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
+\r
+/** The interface for the FADT Table Generator.\r
+*/\r
+STATIC\r
+CONST\r
+ACPI_TABLE_GENERATOR FadtGenerator = {\r
+  // Generator ID\r
+  CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt),\r
+  // Generator Description\r
+  L"ACPI.STD.FADT.GENERATOR",\r
+  // ACPI Table Signature\r
+  EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,\r
+  // ACPI Table Revision supported by this Generator\r
+  EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,\r
+  // Minimum supported ACPI Table Revision\r
+  EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,\r
+  // Creator ID\r
+  TABLE_GENERATOR_CREATOR_ID_ARM,\r
+  // Creator Revision\r
+  FADT_GENERATOR_REVISION,\r
+  // Build Table function\r
+  BuildFadtTable,\r
+  // No additional resources are allocated by the generator.\r
+  // Hence the Free Resource function is not required.\r
+  NULL,\r
+  // Extended build function not needed\r
+  NULL,\r
+  // Extended build function not implemented by the generator.\r
+  // Hence extended free resource function is not required.\r
+  NULL\r
+};\r
+\r
+/** Register the Generator with the ACPI Table Factory.\r
+\r
+  @param [in]  ImageHandle  The handle to the image.\r
+  @param [in]  SystemTable  Pointer to the System Table.\r
+\r
+  @retval EFI_SUCCESS           The Generator is registered.\r
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+  @retval EFI_ALREADY_STARTED   The Generator for the Table ID\r
+                                is already registered.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiFadtLibConstructor (\r
+  IN CONST EFI_HANDLE                ImageHandle,\r
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  Status = RegisterAcpiTableGenerator (&FadtGenerator);\r
+  DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n", Status));\r
+  ASSERT_EFI_ERROR (Status);\r
+  return Status;\r
+}\r
+\r
+/** Deregister the Generator from the ACPI Table Factory.\r
+\r
+  @param [in]  ImageHandle  The handle to the image.\r
+  @param [in]  SystemTable  Pointer to the System Table.\r
+\r
+  @retval EFI_SUCCESS           The Generator is deregistered.\r
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+  @retval EFI_NOT_FOUND         The Generator is not registered.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiFadtLibDestructor (\r
+  IN CONST EFI_HANDLE                ImageHandle,\r
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  Status = DeregisterAcpiTableGenerator (&FadtGenerator);\r
+  DEBUG ((DEBUG_INFO, "FADT: Deregister Generator. Status = %r\n", Status));\r
+  ASSERT_EFI_ERROR (Status);\r
+  return Status;\r
+}\r