public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 0/2] Dynamic Tables
@ 2017-10-02 19:47 evan.lloyd
  2017-10-02 19:47 ` [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework evan.lloyd
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: evan.lloyd @ 2017-10-02 19:47 UTC (permalink / raw)
  To: edk2-devel
  Cc: "ard.biesheuvel, "leif.lindholm, "Matteo.Carlini,
	"nd, "Arvind.Chauhan, "Daniil.Egranov,
	"thomas.abraham, "Stephanie.Hughes-Fitt

From: EvanLloyd <evan.lloyd@arm.com>

Historically, ACPI code, SMBIOS tables, and UEFI firmware were
often developed in isolation from each other.  This introduced
several problems, not least of which was duplication of platform
information between the various source trees.
In addition, variants of platforms introduced a plethora of
alternative builds of ACPI, SMBIOS and EDK2, with the concomitant
risk of getting the mixture wrong in a build.

In the effort to resolve these problems, the solution prototyped
here was devised.  The basic idea is to obtain the "variant"
information from a management node.  That means the firmware image
can be platform independent, with ACPI, SMBIOS (and potentially
other) tables generated with information from the management
node.  This example has the framework for that, but the
configuration information is supplied directly, as an interim solution
until a suitable management node implementation exists yet.


Sami Mujawar (1):
  MdeModulePkg: Dynamic Tables Framework

 MdeModulePkg/MdeModulePkg.dec                                                                       |  13 +
 MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc                                          |  45 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf                       |  49 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf                       |  46 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf                         |  44 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf                       |  44 ++
 MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf                         |  39 ++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf              |  57 ++
 MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf              |  47 ++
 MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h                                             | 280 ++++++++
 MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h                                            | 367 ++++++++++
 MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h                                     | 112 +++
 MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h                                     | 158 +++++
 MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h                                           | 235 +++++++
 MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h                                       |  93 +++
 MdeModulePkg/Include/DynamicTables/TableGenerator.h                                                 | 235 +++++++
 MdeModulePkg/Include/Library/TableHelperLib.h                                                       |  67 ++
 MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h                                        | 121 ++++
 MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h                                         | 113 +++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h                   |  91 +++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c                          | 440 ++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c                          | 562 +++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c                          | 652 +++++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c                          | 732 ++++++++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c                          | 336 +++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c                            | 177 +++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c                          | 323 +++++++++
 MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c                              | 165 +++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c     | 227 ++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c                |  84 +++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c | 227 ++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c                | 531 ++++++++++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc                                          |  35 +
 36 files changed, 6888 insertions(+)
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
 create mode 100644 MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
 create mode 100644 MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
 create mode 100644 MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
 create mode 100644 MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
 create mode 100644 MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
 create mode 100644 MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
 create mode 100644 MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
 create mode 100644 MdeModulePkg/Include/DynamicTables/TableGenerator.h
 create mode 100644 MdeModulePkg/Include/Library/TableHelperLib.h
 create mode 100644 MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
 create mode 100644 MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
 create mode 100644 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
 create mode 100644 MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
 create mode 100644 MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc

-- 
Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
  2017-10-02 19:47 [PATCH 0/2] Dynamic Tables evan.lloyd
@ 2017-10-02 19:47 ` evan.lloyd
  2017-10-03 14:34   ` Zeng, Star
  2017-10-02 19:47 ` [PATCH 2/2] [edk2-platforms] Platform/ARM: Dynamic Tables support for FVP evan.lloyd
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: evan.lloyd @ 2017-10-02 19:47 UTC (permalink / raw)
  To: edk2-devel
  Cc: "ard.biesheuvel, "leif.lindholm, "Matteo.Carlini,
	"nd, "Arvind.Chauhan, "Daniil.Egranov,
	"thomas.abraham

From: Sami Mujawar <sami.mujawar@arm.com>

The dynamic tables framework is designed to generate standardised
firmware tables that describe the hardware information at
run-time. A goal of standardised firmware is to have a common
firmware for a platform capable of booting both Windows and Linux
operating systems.

Traditionally the firmware tables are handcrafted using ACPI
Machine Language (AML), Table Definition Language (TDL) and
C-code. This approach can be error prone and involves time
consuming debugging. In addition, it may be desirable to configure
platform hardware at runtime such as: configuring the number of
cores available for use by the OS, or turning SoC features ON or
OFF.

The dynamic tables framework simplifies this by providing a set
of standard table generators, that are implemented as libraries.
These generators query a platform specific component, the
'Configuration Manager', to collate the information required
for generating the tables at run-time.

The framework also provisions the ability to implement custom/OEM
generators; thereby facilitating support for custom tables. The
custom generators can also utilize the existing standard generators
and override any functionality if needed.

The framework currently implements a set of standard ACPI table
generators for ARM architecture, that can generate Server Base Boot
Requirement (SBBR) compliant tables. Support for generating SMBIOS
tables is planned to be added subsequently. Although, the set
of standard generators implements the functionality required for ARM
architecture; the framework is extensible, and support for other
architectures can be easily added.

Contributions from the community are invited.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Signed-off-by: Evan Lloyd <evan.lloyd@arm.com>
---
 MdeModulePkg/MdeModulePkg.dec                                                                       |  13 +
 MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc                                          |  45 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf                       |  49 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf                       |  46 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf                         |  44 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf                       |  44 ++
 MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf                         |  39 ++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf              |  57 ++
 MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf              |  47 ++
 MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h                                             | 280 ++++++++
 MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h                                            | 367 ++++++++++
 MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h                                     | 112 +++
 MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h                                     | 158 +++++
 MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h                                           | 235 +++++++
 MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h                                       |  93 +++
 MdeModulePkg/Include/DynamicTables/TableGenerator.h                                                 | 235 +++++++
 MdeModulePkg/Include/Library/TableHelperLib.h                                                       |  67 ++
 MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h                                        | 121 ++++
 MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h                                         | 113 +++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h                   |  91 +++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c                          | 440 ++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c                          | 562 +++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c                          | 652 +++++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c                          | 732 ++++++++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c                          | 336 +++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c                            | 177 +++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c                          | 323 +++++++++
 MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c                              | 165 +++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c     | 227 ++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c                |  84 +++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c | 227 ++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c                | 531 ++++++++++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc                                          |  35 +
 36 files changed, 6888 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index a3c0633ee1ec6ab7540a1b7221850e975f95ad80..de8a658c21d11ab1396bb543b026f94a396a0710 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -7,6 +7,7 @@
 # Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
 # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
 # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+# Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
 #
 # This program and the accompanying materials are licensed and made available under
 # the terms and conditions of the BSD License that accompanies this distribution.
@@ -556,6 +557,12 @@ [Protocols]
   ## Include/Protocol/IoMmu.h
   gEdkiiIoMmuProtocolGuid = { 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed, 0xe6, 0xe1, 0xce, 0x51, 0x7c, 0x1e } }
 
+  # Configuration Manager Protocol GUID
+  gEfiConfigurationManagerProtocolGuid = { 0xd85a4835, 0x5a82, 0x4894, { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } }
+
+  # Dynamic Table Factory Protocol GUID
+  gEfiDynamicTableFactoryProtocolGuid = { 0x91d1e327, 0xfe5a, 0x49b8, { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec } }
+
 #
 # [Error.gEfiMdeModulePkgTokenSpaceGuid]
 #   0x80000001 | Invalid value provided.
@@ -867,6 +874,12 @@ [PcdsFixedAtBuild]
   # @ValidList  0x80000006 | 0x03058002
   gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UINT32|0x30001040
 
+  # Maximum number of Custom ACPI Generators
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators|1|UINT16|0xC0000001
+
+  # Maximum number of Custom SMBIOS Generators
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators|1|UINT16|0xC0000002
+
 [PcdsFixedAtBuild, PcdsPatchableInModule]
   ## Dynamic type PCD can be registered callback function for Pcd setting action.
   #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
new file mode 100644
index 0000000000000000000000000000000000000000..548c77ad971f97c43da8f7ba1b69fa6948430c17
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
@@ -0,0 +1,45 @@
+## @file
+#  Dsc include file for Dynamic Tables Framework.
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+
+[BuildOptions]
+  *_*_*_ASL_FLAGS          = -th -li
+
+[LibraryClasses.common]
+
+[Components.common]
+  #
+  # Dynamic Table Factory Dxe
+  #
+  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf {
+    <LibraryClasses>
+      TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
+  }
+
+  #
+  # Dynamic Tables Manager Dxe
+  #
+  MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf {
+    <LibraryClasses>
+      TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
+  }
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..591b6364ae86c885ca4768599d3eadf6d2842eff
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
@@ -0,0 +1,49 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiDbg2LibArm
+  FILE_GUID      = A17BA4F0-3DEB-4FE5-BD27-EC008E541B22
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiDbg2LibConstructor
+  DESTRUCTOR     = AcpiDbg2LibDestructor
+
+
+[Sources]
+  Dbg2Generator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  SerialPortLib
+
+[FixedPcd]
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+
+[Protocols]
+
+
+[Guids]
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..ae5239fd2a3e6f00574cf5f3bb4a561031e122be
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
@@ -0,0 +1,47 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiFadtLibArm
+  FILE_GUID      = 686FE5FE-B944-485F-8B1C-7D60E0056487
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiFadtLibConstructor
+  DESTRUCTOR     = AcpiFadtLibDestructor
+
+
+[Sources]
+  FadtGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
+
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..be38489c2987a81d68effd9c05b731b17cb2819c
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
@@ -0,0 +1,46 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiGtdtLibArm
+  FILE_GUID      = 26490F7A-7FA2-423C-8939-C6206329BC37
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiGtdtLibConstructor
+  DESTRUCTOR     = AcpiGtdtLibDestructor
+
+
+[Sources]
+  GtdtGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[FixedPcd]
+
+[Protocols]
+
+
+[Guids]
+
+
+
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..9807e3fe75bb785c3b400410248e6434532f2147
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
@@ -0,0 +1,47 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiMadtLibArm
+  FILE_GUID      = AF76C93B-41B5-454D-83CD-D2A80A1C1E38
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiMadtLibConstructor
+  DESTRUCTOR     = AcpiMadtLibDestructor
+
+
+[Sources]
+  MadtGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
+
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..2f879dfee4b93a56a923340c4b416c6df9656618
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
@@ -0,0 +1,47 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiMcfgLibArm
+  FILE_GUID      = 8C9BDCB2-72D4-4F30-A12D-1145C3807FF7
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiMcfgLibConstructor
+  DESTRUCTOR     = AcpiMcfgLibDestructor
+
+
+[Sources]
+  McfgGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
+
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..db208bdeb8ffce085367ee865766a0a1bd90cb28
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
@@ -0,0 +1,44 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiRawLibArm
+  FILE_GUID      = 20F31568-D687-49BA-B326-CCD9D38EDE16
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiRawLibConstructor
+  DESTRUCTOR     = AcpiRawLibDestructor
+
+
+[Sources]
+  RawGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..3d47e6ae1f7995f76fe3e93093b0185e48ecae79
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
@@ -0,0 +1,44 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiSpcrLibArm
+  FILE_GUID      = 55088136-7B78-4974-B1EE-F630150D0DE7
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiSpcrLibConstructor
+  DESTRUCTOR     = AcpiSpcrLibDestructor
+
+
+[Sources]
+  SpcrGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
new file mode 100644
index 0000000000000000000000000000000000000000..38952fba1c8056bf0c581975ca974abbef1e8096
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
@@ -0,0 +1,39 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = DynamicTableHelperLib
+  FILE_GUID      = E315C738-3A39-4D0D-A0AF-8EDFA770AB39
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = TableHelperLib
+
+
+[Sources]
+  TableHelper.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Protocols]
+
+
+[Guids]
+
+
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..c58ac3a8d6d655e38cb8460a35ce256fc4e5ada6
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
@@ -0,0 +1,57 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+
+[Defines]
+  INF_VERSION                    = 0x00010016
+  BASE_NAME                      = DynamicTableFactoryDxe
+  FILE_GUID                      = FE846898-7403-4932-B8AD-A0491F0C2CBA
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = DynamicTableFactoryDxeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ARM AARCH64
+#
+
+[Sources]
+  DynamicTableFactoryDxe.c
+  AcpiTableFactory/AcpiTableFactory.c
+  SmbiosTableFactory/SmbiosTableFactory.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  PrintLib
+  BaseLib
+  MemoryAllocationLib
+  TableHelperLib
+
+[FixedPcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+  gEfiSmbiosProtocolGuid                        # PROTOCOL ALWAYS_CONSUMED
+  gEfiConfigurationManagerProtocolGuid
+  gEfiDynamicTableFactoryProtocolGuid
+
+[Depex]
+  TRUE
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..9c5a5f6207687ca90fa11188340d09c304fc34c0
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
@@ -0,0 +1,47 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010016
+  BASE_NAME                      = DynamicTableManagerDxe
+  FILE_GUID                      = 89122868-BCFD-49E8-88A3-06635CB7B3CF
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = DynamicTableManagerDxeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ARM AARCH64
+#
+
+[Sources]
+  DynamicTableManagerDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  PrintLib
+  TableHelperLib
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+  gEfiConfigurationManagerProtocolGuid
+  gEfiDynamicTableFactoryProtocolGuid
+
+[Depex]
+  TRUE
diff --git a/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a07cd6e10217958d22a93060a0f9aa48947f264
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
@@ -0,0 +1,280 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+    - Std or STD - Standard
+**/
+
+#ifndef ACPI_TABLE_GENERATOR_H_
+#define ACPI_TABLE_GENERATOR_H_
+
+#pragma pack(1)
+
+/**
+The Dynamic Tables Framework provisions two classes of ACPI table
+generators.
+ - Standard generators: The ACPI table generators implemented by the
+                        Dynamic Tables Framework.
+ - OEM generators:      The ACPI table generatos customized by the OEM.
+
+The Dynamic Tables Framework implements the following ACPI table generators:
+  - RAW   : This is the simplest ACPI table generator. It simply installs
+            the ACPI table provided in the AcpiTableData member of the
+            CM_STD_OBJ_ACPI_TABLE_INFO. The ACPI table data is provided by
+            the Configuration Manager and is generated using an implementation
+            defined mechanism.
+  - DSDT  : The DSDT generator is clone of the RAW generator. The difference
+            is in the way the ACPI Table Data is generated from an AML file.
+  - SSDT  : The SSDT generator is clone of the RAW generator. The difference
+            is in the way the ACPI Table Data is generated from an AML file.
+  - FADT  : The FADT generator collates the required platform information for
+            building the ACPI FADT table from the Configuration Manager and
+            generates the FADT table.
+  - MADT  : The MADT generator collates the GIC information for building the
+            ACPI MADT table from the Configuration Manager and generates the
+            MADT table.
+  - GTDT  : The GTDT generator collates the Timer information for building the
+            ACPI GTDT table from the Configuration Manager and generates the
+            GTDT table.
+  - DBG2  : The DBG2 generator collates the debug serial port information for
+            building the DBG2 table from the Configuration Manager and
+            generates the GTDT table.
+  - SPCR  : The SPCR generator collates the serial port information for
+            building the SPCR table from the Configuration Manager and
+            generates the SPCR table.
+  - MCFG  : The MCFG generator collates the PCI configuration space information
+            for building the MCFG table from the Configuration Manager and
+            generates the MCFG table.
+*/
+
+/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
+*/
+typedef TABLE_GENERATOR_ID ACPI_TABLE_GENERATOR_ID;
+
+/** The ESTD_ACPI_TABLE_ID enum describes the ACPI table IDs reserved for
+  the standard generators.
+*/
+typedef enum StdAcpiTableId {
+  ESTD_ACPI_TABLE_ID_RESERVED = 0x0000,             ///< Reserved.
+  ESTD_ACPI_TABLE_ID_RAW,                           ///< RAW Generator.
+  ESTD_ACPI_TABLE_ID_DSDT = ESTD_ACPI_TABLE_ID_RAW, ///< DSDT Generator.
+  ESTD_ACPI_TABLE_ID_SSDT = ESTD_ACPI_TABLE_ID_RAW, ///< SSDT Generator.
+  ESTD_ACPI_TABLE_ID_FADT,                          ///< FADT Generator.
+  ESTD_ACPI_TABLE_ID_MADT,                          ///< MADT Generator.
+  ESTD_ACPI_TABLE_ID_GTDT,                          ///< GTDT Generator.
+  ESTD_ACPI_TABLE_ID_DBG2,                          ///< DBG2 Generator.
+  ESTD_ACPI_TABLE_ID_SPCR,                          ///< SPCR Generator.
+  ESTD_ACPI_TABLE_ID_MCFG,                          ///< MCFG Generator.
+  ESTD_ACPI_TABLE_ID_MAX
+} ESTD_ACPI_TABLE_ID;
+
+/** This macro checks if the Table Generator ID is for an ACPI Table Generator.
+    @param [in] TableGeneratorId  The table generator ID.
+
+    @returns TRUE if the table generator ID is for an ACPI Table
+          Generator.
+*/
+#define IS_GENERATOR_TYPE_ACPI(TableGeneratorId) \
+          (GET_TABLE_TYPE (TableGeneratorId) == ETableGeneratorTypeAcpi)
+
+/** This macro checks if the Table Generator ID is for a standard ACPI
+    Table Generator.
+
+    @param [in] TableGeneratorId  The table generator ID.
+
+    @returns TRUE if the table generator ID is for a standard ACPI
+            Table Generator.
+*/
+#define IS_VALID_STD_ACPI_GENERATOR_ID(TableGeneratorId)               \
+          (                                                            \
+          IS_GENERATOR_NAMESPACE_STD (TableGeneratorId) &&             \
+          IS_GENERATOR_TYPE_ACPI (TableGeneratorId)     &&             \
+          ((GET_TABLE_ID (GeneratorId) >= ESTD_ACPI_TABLE_ID_RAW) &&   \
+           (GET_TABLE_ID (GeneratorId) < ESTD_ACPI_TABLE_ID_MAX))      \
+          )
+
+/** This macro creates a standard ACPI Table Generator ID.
+
+    @param [in] TableId  The table generator ID.
+
+    @returns a standard ACPI table generator ID.
+*/
+#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId) \
+          CREATE_TABLE_GEN_ID (               \
+            ETableGeneratorTypeAcpi,          \
+            ETableGeneratorNameSpaceStd,      \
+            TableId                           \
+            )
+
+/** The Creator ID for the ACPI tables generated using
+  the standard ACPI table generators.
+*/
+#define TABLE_GENERATOR_CREATOR_ID_ARM  SIGNATURE_32('A', 'R', 'M', 'H')
+
+/** A macro to initialise the common header part of EFI ACPI tables as
+    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
+
+    @param [in] Signature The ACPI table signature.
+    @param [in] Type      The ACPI table structure.
+    @param [in] Revision  The ACPI table revision.
+*/
+#define ACPI_HEADER(Signature, Type, Revision) {              \
+          Signature,             /* UINT32  Signature */      \
+          sizeof (Type),         /* UINT32  Length */         \
+          Revision,              /* UINT8   Revision */       \
+          0,                     /* UINT8   Checksum */       \
+          { 0, 0, 0, 0, 0, 0 },  /* UINT8   OemId[6] */       \
+          0,                     /* UINT64  OemTableId */     \
+          0,                     /* UINT32  OemRevision */    \
+          0,                     /* UINT32  CreatorId */      \
+          0                      /* UINT32  CreatorRevision */\
+          }
+
+/** A macro to dump the common header part of EFI ACPI tables as
+    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
+
+    @param [in] AcpiHeader The pointer to the ACPI table header.
+*/
+#define DUMP_ACPI_TABLE_HEADER(AcpiHeader)                        \
+          DEBUG ((                                                \
+            DEBUG_INFO,                                           \
+            "ACPI TABLE %c%c%c%c : Rev 0x%x : Length : 0x%x\n",   \
+            (AcpiHeader->Signature & 0xFF),                       \
+            ((AcpiHeader->Signature >> 8) & 0xFF),                \
+            ((AcpiHeader->Signature >> 16) & 0xFF),               \
+            ((AcpiHeader->Signature >> 24) & 0xFF),               \
+            AcpiHeader->Revision,                                 \
+            AcpiHeader->Length                                    \
+            ));
+
+/** Forward declarations.
+*/
+typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
+typedef struct CmAStdObjAcpiTableInfo       CM_STD_OBJ_ACPI_TABLE_INFO;
+typedef struct AcpiTableGenerator           ACPI_TABLE_GENERATOR;
+
+/** This function pointer describes the interface to ACPI table build
+    functions provided by the ACPI table generator and called by the
+    Table Manager to build an ACPI table.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
+    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
+                                 Protocol interface.
+    @param [out] Table           Pointer to the generated ACPI table.
+
+    @returns  EFI_SUCCESS If the table is generated successfully or other
+                          failure codes as returned by the generator.
+*/
+typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_BUILD_TABLE) (
+  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        **       Table
+  );
+
+/** This function pointer describes the interface to used by the
+    Table Manager to give the generator an opportunity to free
+    any resources allocated for building the ACPI table.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
+    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
+                                 Protocol interface.
+    @param [in]  Table           Pointer to the generated ACPI table.
+
+    @returns EFI_SUCCESS  If freed successfully or other failure codes
+                          as returned by the generator.
+*/
+typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_FREE_TABLE) (
+  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        **       Table
+  );
+
+/** The ACPI_TABLE_GENERATOR structure provides an interface that the
+    Table Manager can use to invoke the functions to build ACPI tables.
+
+*/
+typedef struct AcpiTableGenerator {
+  /// The ACPI table generator ID.
+  ACPI_TABLE_GENERATOR_ID                GeneratorID;
+
+  /// String describing the ACPI table
+  /// generator.
+  CONST CHAR16                         * Description;
+
+  /// The ACPI table signature.
+  UINT32                                 AcpiTableSignature;
+
+  /// The ACPI table revision.
+  UINT32                                 AcpiTableRevision;
+
+  /// The ACPI table creator ID.
+  UINT32                                 CreatorId;
+
+  /// The ACPI table creator revision.
+  UINT32                                 CreatorRevision;
+
+  /// ACPI table build function pointer.
+  ACPI_TABLE_GENERATOR_BUILD_TABLE       BuildAcpiTable;
+
+  /// The function to free any resources
+  /// allocated for building the ACPI table.
+  ACPI_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
+} ACPI_TABLE_GENERATOR;
+
+/** Register ACPI table factory generator.
+
+    The ACPI table factory maintains a list of the Standard and OEM ACPI
+    table generators.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+
+    @retval EFI_SUCCESS           The Generator was registered
+                                  successfully.
+    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
+                                  the Generator pointer is NULL.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
+                                  already registered.
+*/
+EFI_STATUS
+EFIAPI
+RegisterAcpiTableGenerator (
+  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
+  );
+
+/** Unregister ACPI generator.
+
+    This function is called by the ACPI table generator to unregister itself
+    from the ACPI table factory.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The generator is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+UnRegisterAcpiTableGenerator (
+  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
+  );
+
+#pragma pack()
+
+#endif // ACPI_TABLE_GENERATOR_H_
+
diff --git a/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
new file mode 100644
index 0000000000000000000000000000000000000000..dbc909894d17ba9df7a78c2d8be797adabb49a34
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
@@ -0,0 +1,367 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+    - Std or STD - Standard
+**/
+
+#ifndef ARM_NAMESPACE_OBJECTS_H_
+#define ARM_NAMESPACE_OBJECTS_H_
+#pragma pack(1)
+
+/** The EARM_OBJECT_ID enum describes the Object IDs
+    in the ARM Namespace
+*/
+typedef enum ArmObjectID {
+  EArmObjReserved,                    ///<  0 - Reserved.
+  EArmObjBootArchInfo,                ///<  1 - Boot Architecture Info
+  EArmObjCpuInfo,                     ///<  2 - CPU Info
+  EArmObjPowerManagementProfileInfo,  ///<  3 - Power Management Profile Info
+  EArmObjGicCInfo,                    ///<  4 - GIC CPU Interface Info
+  EArmObjGicDInfo,                    ///<  5 - GIC Distributor Info
+  EArmObjGicMsiFrameInfo,             ///<  6 - GIC MSI Frame Info
+  EArmObjGicRedistributorInfo,        ///<  7 - GIC Redistributor Info
+  EArmObjGicItsInfo,                  ///<  8 - GIC ITS Info
+  EArmObjSerialConsolePortInfo,       ///<  9 - Serial Console Port Info
+  EArmObjSerialDebugPortInfo,         ///< 10 - Serial Debug Port Info
+  EArmObjGenericTimerInfo,            ///< 11 - Generic Timer Info
+  EArmObjPlatformGTBlockInfo,         ///< 12 - Platform GT Block Info
+  EArmObjPlatformGenericWatchdogInfo, ///< 13 - Platform Generic Watchdog
+  EArmObjPciConfigSpaceInfo,          ///< 14 - PCI Configuration Space Info
+  EArmObjHypervisorVendorIdentity,    ///< 15 - Hypervisor Vendor Id
+  EArmObjMax
+} EARM_OBJECT_ID;
+
+/** A structure that describes the
+    ARM Boot Architecture flags.
+*/
+typedef struct CmArmBootArchInfo {
+  /// This is the ARM_BOOT_ARCH flags field of the FADT Table
+  /// described in the ACPI Table Specification.
+  UINT32  BootArchFlags;
+} CM_ARM_BOOT_ARCH_INFO;
+
+typedef struct CmArmCpuInfo {
+  // Reserved for use when SMBIOS tables are implemented.
+} CM_ARM_CPU_INFO;
+
+typedef struct CmArmCpuInfoList {
+  UINT32             CpuCount;
+  CM_ARM_CPU_INFO  * CpuInfo;
+} CM_ARM_CPU_INFO_LIST;
+
+/** A structure that describes the
+    Power Management Profile Information for the Platform.
+*/
+typedef struct CmArmPowerManagementProfileInfo {
+  /// This is the Preferred_PM_Profile field of the FADT Table
+  /// described in the ACPI Specification
+  UINT8  PowerManagementProfile;
+} CM_ARM_POWER_MANAGEMENT_PROFILE_INFO;
+
+/** A structure that describes the
+    GIC CPU Interface for the Platform.
+*/
+typedef struct CmArmGicCInfo {
+  /// The GIC CPU Interface number.
+  UINT32  CPUInterfaceNumber;
+
+  /// The ACPI Processor UID. This must match the
+  /// _UID of the CPU Device object information described
+  /// in the DSDT/SSDT for the CPU.
+  UINT32  AcpiProcessorUid;
+
+  /// The flags field as described by the GICC structure
+  /// in the ACPI Specification.
+  UINT32  Flags;
+
+  /// The parking protocol version field as described by
+  /// the GICC structure in the ACPI Specification.
+  UINT32  ParkingProtocolVersion;
+
+  /// The Performance Interrupt field as described by
+  /// the GICC structure in the ACPI Specification.
+  UINT32  PerformanceInterruptGsiv;
+
+  /// The CPU Parked address field as described by
+  /// the GICC structure in the ACPI Specification.
+  UINT64  ParkedAddress;
+
+  /// The base address for the GIC CPU Interface
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  PhysicalBaseAddress;
+
+  /// The base address for GICV interface
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  GICV;
+
+  /// The base address for GICH interface
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  GICH;
+
+  /// The GICV maintainence interrupt
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT32  VGICMaintenanceInterrupt;
+
+  /// The base address for GICR interface
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  GICRBaseAddress;
+
+  /// The MPIDR for the CPU
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  MPIDR;
+
+  /// The Processor Power Efficiency class
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT8   ProcessorPowerEfficiencyClass;
+} CM_ARM_GICC_INFO;
+
+/** A structure that describes the
+    GIC Distributor information for the Platform.
+*/
+typedef struct CmArmGicDInfo {
+  /// The GIC Distributor ID.
+  UINT32  GicId;
+
+  /// The Physical Base address
+  /// for the GIC Distributor.
+  UINT64  PhysicalBaseAddress;
+
+  /// The global system interrupt
+  /// number where this GIC Distributor's
+  /// interrupt inputs start.
+  UINT32  SystemVectorBase;
+
+  /// The GIC version as described
+  /// by the GICD structure in the
+  /// ACPI Specification.
+  UINT8   GicVersion;
+} CM_ARM_GICD_INFO;
+
+/** A structure that describes the
+    GIC MSI Frame information for the Platform.
+*/
+typedef struct CmArmGicMsiFrameInfo {
+  /// The GIC MSI Frame ID
+  UINT32  GicMsiFrameId;
+
+  /// The Physical base address for the
+  /// MSI Frame.
+  UINT64  PhysicalBaseAddress;
+
+  /// The GIC MSI Frame flags
+  /// as described by the GIC MSI frame
+  /// structure in the ACPI Specification.
+  UINT32  Flags;
+
+  /// SPI Count used by this frame.
+  UINT16  SPICount;
+
+  /// SPI Base used by this frame.
+  UINT16  SPIBase;
+} CM_ARM_GIC_MSI_FRAME_INFO;
+
+/** A structure that describes the
+    GIC Redistributor information for the Platform.
+*/
+typedef struct CmArmGicRedistInfo {
+  /// The physical address of a page range
+  /// containing all GIC Redistributors.
+  UINT64  DiscoveryRangeBaseAddress;
+
+  /// Length of the GIC Redistributor
+  /// Discovery page range
+  UINT32  DiscoveryRangeLength;
+} CM_ARM_GIC_REDIST_INFO;
+
+/** A structure that describes the
+    GIC Interrupt Translation Service information for the Platform.
+*/
+typedef struct CmArmGicItsInfo {
+  /// The GIC ITS ID.
+  UINT32  GicItsId;
+
+  /// The physical address for the
+  /// Interrupt Translation Service
+  UINT64  PhysicalBaseAddress;
+} CM_ARM_GIC_ITS_INFO;
+
+/** A structure that describes the
+    Serial Port information for the Platform.
+*/
+typedef struct CmArmSerialPortInfo {
+  /// The physical base address for the
+  /// serial port.
+  UINT64  BaseAddress;
+
+  /// The serial port interrupt.
+  UINT32  Interrupt;
+
+  /// The serial port baud rate.
+  UINT64  BaudRate;
+
+  /// The serial port clock.
+  UINT32  Clock;
+} CM_ARM_SERIAL_PORT_INFO;
+
+/** A structure that describes the
+    Generic Timer information for the Platform.
+*/
+typedef struct CmArmGenericTimerInfo {
+  /// The physical base address for the
+  /// counter control frame.
+  UINT64  CounterControlBaseAddress;
+
+  /// The physical base address for the
+  /// counter read frame.
+  UINT64  CounterReadBaseAddress;
+
+  /// The secure PL1 timer interrupt.
+  UINT32  SecurePL1TimerGSIV;
+
+  /// The secure PL1 timer flags.
+  UINT32  SecurePL1TimerFlags;
+
+  /// The non-secure PL1 timer interrupt.
+  UINT32  NonSecurePL1TimerGSIV;
+
+  /// The non-secure PL1 timer flags.
+  UINT32  NonSecurePL1TimerFlags;
+
+  /// The virtual timer interrupt.
+  UINT32  VirtualTimerGSIV;
+
+  /// The virtual timer flags.
+  UINT32  VirtualTimerFlags;
+
+  /// The non-secure PL2 timer interrupt.
+  UINT32  NonSecurePL2TimerGSIV;
+
+  /// The non-secure PL2 timer flags.
+  UINT32  NonSecurePL2TimerFlags;
+} CM_ARM_GENERIC_TIMER_INFO;
+
+/** A structure that describes the
+    Platform Generic Block Timer Frame information for the Platform.
+*/
+typedef struct CmArmGTBlockTimerFrameInfo {
+  /// The Generic Timer frame number.
+  UINT8   FrameNumber;
+
+  /// The physical base address
+  /// for the CntBase block.
+  UINT64  PhysicalAddressCntBase;
+
+  /// The physical base address
+  /// for the CntEL0Base block.
+  UINT64  PhysicalAddressCntEL0Base;
+
+  /// The physical timer interrupt.
+  UINT32  PhysicalTimerGSIV;
+
+  /// The physical timer flags
+  /// as described by the GT Block
+  /// Timer frame Structure in the
+  /// ACPI Specification.
+  UINT32  PhysicalTimerFlags;
+
+  /// The virtual timer interrupt.
+  UINT32  VirtualTimerGSIV;
+
+  /// The virtual timer flags
+  /// as described by the GT Block
+  /// Timer frame Structure in the
+  /// ACPI Specification.
+  UINT32  VirtualTimerFlags;
+
+  /// The common timer flags
+  /// as described by the GT Block
+  /// Timer frame Structure in the
+  /// ACPI Specification.
+  UINT32  CommonFlags;
+} CM_ARM_GTBLOCK_TIMER_FRAME_INFO;
+
+/** A structure that describes the
+    Platform Generic Block Timer information for the Platform.
+*/
+typedef struct CmArmGTBlockInfo {
+  /// The physical base address for
+  /// the GT Block Timer structure.
+  UINT64                             GTBlockPhysicalAddress;
+
+  /// The number of timer frames
+  /// implemented in the GT Block.
+  UINT32                             GTBlockTimerFrameCount;
+
+  /// Pointer to the GT Block timer
+  /// frame list.
+  CM_ARM_GTBLOCK_TIMER_FRAME_INFO  * GTBlockTimerFrameList;
+} CM_ARM_GTBLOCK_INFO;
+
+/** A structure that describes the
+    SBSA Generic Watchdog information for the Platform.
+*/
+typedef struct CmArmGenericWatchdogInfo {
+  /// The physical base address of the
+  /// SBSA Watchdog control frame.
+  UINT64  ControlFrameAddress;
+
+  /// The physical base address of the
+  /// SBSA Watchdog refresh frame.
+  UINT64  RefreshFrameAddress;
+
+  /// The watchdog interrupt.
+  UINT32  TimerGSIV;
+
+  /// The flags for the watchdog
+  /// as described by the SBSA watchdog
+  /// structure in the ACPI specification.
+  UINT32  Flags;
+} CM_ARM_GENERIC_WATCHDOG_INFO;
+
+/** A structure that describes the
+    PCI Configuration Space information for the Platform.
+*/
+typedef struct CmArmPciConfigSpaceInfo {
+  /// The physical base address for the PCI segment.
+  UINT64  BaseAddress;
+
+  /// The PCI segment group number.
+  UINT16  PciSegmentGroupNumber;
+
+  /// The start bus number.
+  UINT8   StartBusNumber;
+
+  /// The end bus number.
+  UINT8   EndBusNumber;
+} CM_ARM_PCI_CONFIG_SPACE_INFO;
+
+/** A structure that describes the
+    Hypervisor Vendor ID information for the Platform.
+*/
+typedef struct CmArmHypervisorVendorId {
+  /// The hypervisor Vendor ID.
+  UINT64  HypervisorVendorId;
+} CM_ARM_HYPERVISOR_VENDOR_ID;
+
+#pragma pack()
+
+#endif // ARM_NAMESPACE_OBJECTS_H_
diff --git a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..23edd7c343bd09476692d2fb8af088d95b8ff28d
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
@@ -0,0 +1,112 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef CONFIGURATION_MANAGER_HELPER_H_
+#define CONFIGURATION_MANAGER_HELPER_H_
+
+/** The GET_OBJECT_LIST macro expands to a function that is used to retrieve
+    an object or an object list from the Configuration Manager using the
+    Configuration Manager Protocol interface.
+
+    The macro expands to a function which has the following prototype:
+
+    STATIC
+    EFI_STATUS
+    EFIAPI
+    Get<CmObjectId> (
+      IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+      OUT       Type                              **       List,
+      OUT       UINTN                              *       Count OPTIONAL
+      );
+
+    Generated function parameters:
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
+                                  interface.
+    @param [out] List           Pointer to the Object list.
+    @param [out] Count          Count of the objects returned in the list.
+
+    Macro Parameters:
+    @param [in] CmObjectNameSpace The Object Namespace
+    @param [in] CmObjectId        Object Id.
+    @param [in] Type              Structure used to describe the Object.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object information is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)                      \
+STATIC                                                                            \
+EFI_STATUS                                                                        \
+EFIAPI                                                                            \
+Get##CmObjectId (                                                                 \
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,           \
+  OUT       Type                               **       List,                     \
+  OUT       UINTN                               * CONST Count OPTIONAL            \
+  )                                                                               \
+{                                                                                 \
+  EFI_STATUS         Status;                                                      \
+  CM_OBJ_DESCRIPTOR  CmObjectDesc;                                                \
+  UINTN              ObjCount = 0;                                                \
+  if (List == NULL) {                                                             \
+    Status = EFI_INVALID_PARAMETER;                                               \
+    DEBUG ((                                                                      \
+      DEBUG_ERROR,                                                                \
+      "ERROR: Get" #CmObjectId ": Invalid out parameter for"                      \
+      " object list. Status = %r\n",                                              \
+      Status                                                                      \
+      ));                                                                         \
+    goto error_handler;                                                           \
+  }                                                                               \
+  Status = CfgMgrProtocol->GetObject (                                            \
+                             CfgMgrProtocol,                                      \
+                             CREATE_CM_OBJECT_ID (CmObjectNameSpace, CmObjectId), \
+                             &CmObjectDesc                                        \
+                             );                                                   \
+  if (EFI_ERROR (Status)) {                                                       \
+    DEBUG ((                                                                      \
+      DEBUG_WARN,                                                                 \
+      "WARNING: Get" #CmObjectId ": Platform does not implement "                 \
+      #CmObjectId ". Status = %r\n",                                              \
+      Status                                                                      \
+      ));                                                                         \
+    *List = NULL;                                                                 \
+    goto error_handler;                                                           \
+  }                                                                               \
+  if (CmObjectDesc.Size < sizeof (Type)) {                                        \
+    DEBUG ((                                                                      \
+      DEBUG_ERROR,                                                                \
+      "ERROR: Get" #CmObjectId ": " #CmObjectId                                   \
+      ": Buffer too small, size = 0x%x\n",                                        \
+      CmObjectDesc.Size                                                           \
+      ));                                                                         \
+    ASSERT (CmObjectDesc.Size >= sizeof (Type));                                  \
+    Status = EFI_BAD_BUFFER_SIZE;                                                 \
+    goto error_handler;                                                           \
+  }                                                                               \
+  ObjCount = CmObjectDesc.Size / sizeof (Type);                                   \
+  *List = (Type*)CmObjectDesc.Data;                                               \
+error_handler:                                                                    \
+  if (Count != NULL) {                                                            \
+    *Count = ObjCount;                                                            \
+  }                                                                               \
+  return Status;                                                                  \
+}
+
+#endif // CONFIGURATION_MANAGER_HELPER_H_
diff --git a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
new file mode 100644
index 0000000000000000000000000000000000000000..99afab094328cf830831899011a7f6fca1d6e5f2
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
@@ -0,0 +1,158 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef CONFIGURATION_MANAGER_OBJECT_H_
+#define CONFIGURATION_MANAGER_OBJECT_H_
+
+#pragma pack(1)
+
+/** The CM_OBJECT_ID type is used to identify the Configration Manager objects.
+
+ Description of Configuration Manager Object ID
+________________________________________________________________________________
+|31 |30 |29 |28 || 27 | 26 | 25 | 24 || 23 | 22 | 21 | 20 || 19 | 18 | 17 | 16 |
+--------------------------------------------------------------------------------
+| Name Space ID ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 |
+________________________________________________________________________________
+
+Bits: [31:28] - Name Space ID
+                0000 - Standard
+                0001 - ARM
+                1000 - Custom/OEM
+                All other values are reserved.
+
+Bits: [27:16] - Reserved.
+________________________________________________________________________________
+|15 |14 |13 |12 || 11 | 10 |  9 |  8 ||  7 |  6 |  5 |  4 ||  3 |  2 |  1 |  0 |
+--------------------------------------------------------------------------------
+| 0 | 0 | 0 | 0 ||  0 |  0 |  0 |  0 ||                 Object ID              |
+________________________________________________________________________________
+
+Bits: [15:8] - Are reserved and must be zero.
+
+Bits: [7:0] - Object ID
+
+Object ID's in the Standard Namespace:
+  0 - Configuration Manager Revision
+  1 - ACPI Table List
+  2 - SMBIOS Table List
+
+Object ID's in the ARM Namespace:
+   0 - Reserved
+   1 - Boot Architecture Info
+   2 - CPU Info
+   3 - Power Management Profile Info
+   4 - GICC Info
+   5 - GICD Info
+   6 - GIC MSI Frame Info
+   7 - GIC Redistributor Info
+   8 - GIC ITS Info
+   9 - Serial Console Port Info
+  10 - Serial Debug Port Info
+  12 - Generic Timer Info
+  13 - Platform GT Block Info
+  14 - Platform Generic Watchdog
+  15 - PCI Configuration Space Info
+  16 - Hypervisor Vendor Id
+*/
+typedef UINT32  CM_OBJECT_ID;
+
+/** The EOBJECT_NAMESPACE_ID enum describes the defined namespaces
+    for the Confguration Manager Objects.
+*/
+typedef enum ObjectNameSpaceID {
+  EObjNameSpaceStandard,      ///< Standard Objects Namespace
+  EObjNameSpaceArm,           ///< ARM Objects Namespace
+  EObjNameSpaceOem = 0x8,     ///< OEM Objects Namespace
+  EObjNameSpaceMax
+} EOBJECT_NAMESPACE_ID;
+
+/** The CM_OBJ_DESCRIPTOR structure describes the Configuration
+    Manager Object descriptor. The Configuration Manager Protocol
+    interface uses this descriptor to return the Configuration
+    Manager Objects.
+*/
+typedef struct CmObjDescriptor {
+  /// Size of the Object or Object List
+  /// described by this descriptor.
+  UINT32   Size;
+
+  /// Pointer to the Object or Object List
+  /// described by this descriptor.
+  UINTN  * Data;
+} CM_OBJ_DESCRIPTOR;
+
+#pragma pack()
+
+/** This macro returns the namespace ID from the CmObjectID.
+
+  @param [in] CmObjectId  The Configuration Manager Object ID.
+
+  @retval Returns the Namespace ID corresponding to the CmObjectID.
+*/
+#define GET_CM_NAMESPACE_ID(CmObjectId) (((CmObjectId) >> 28) & 0xF)
+
+/** This macro returns the Object ID from the CmObjectID.
+
+  @param [in] CmObjectId  The Configuration Manager Object ID.
+
+  @retval Returns the Object ID corresponding to the CmObjectID.
+*/
+#define GET_CM_OBJECT_ID(CmObjectId)    ((CmObjectId) & 0xFF)
+
+/** This macro returns a Configuration Manager Object ID
+    from the NameSpace ID and the ObjectID.
+
+  @param [in] NameSpaceId The namespace ID for the Object.
+  @param [in] ObjectId    The Object ID.
+
+  @retval Returns the Configuration Manager Object ID.
+*/
+#define CREATE_CM_OBJECT_ID(NameSpaceId, ObjectId) \
+          ((((NameSpaceId) & 0xF) << 28) | ((ObjectId) & 0xF))
+
+/** This macro returns a Configuration Manager Object ID
+    in the Standard Object Namespace.
+
+  @param [in] ObjectId    The Object ID.
+
+  @retval Returns a Standard Configuration Manager Object ID.
+*/
+#define CREATE_CM_STD_OBJECT_ID(ObjectId) \
+          (CREATE_CM_OBJECT_ID (EObjNameSpaceStandard, ObjectId))
+
+/** This macro returns a Configuration Manager Object ID
+    in the ARM Object Namespace.
+
+  @param [in] ObjectId    The Object ID.
+
+  @retval Returns an ARM Configuration Manager Object ID.
+*/
+#define CREATE_CM_ARM_OBJECT_ID(ObjectId) \
+          (CREATE_CM_OBJECT_ID (EObjNameSpaceArm, ObjectId))
+
+/** This macro returns a Configuration Manager Object ID
+    in the OEM Object Namespace.
+
+  @param [in] ObjectId    The Object ID.
+
+  @retval Returns an OEM Configuration Manager Object ID.
+*/
+#define CREATE_CM_OEM_OBJECT_ID(ObjectId) \
+          (CREATE_CM_OBJECT_ID (EObjNameSpaceOem, ObjectId))
+
+#endif // CONFIGURATION_MANAGER_OBJECT_H_
diff --git a/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..10d29be800a0c126ed32dcfa070f1473a8aee7a9
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
@@ -0,0 +1,235 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef SMBIOS_TABLE_GENERATOR_H_
+#define SMBIOS_TABLE_GENERATOR_H_
+
+#pragma pack(1)
+
+/** The SMBIOS_TABLE_GENERATOR_ID type describes SMBIOS table generator ID.
+*/
+typedef TABLE_GENERATOR_ID SMBIOS_TABLE_GENERATOR_ID;
+
+/** The ESTD_SMBIOS_TABLE_ID enum describes the SMBIOS table IDs reserved for
+  the standard generators.
+
+  NOTE: The SMBIOS Generator IDs do not match the table type numbers!
+          This allows 0 to be used to catch invalid parameters.
+*/
+typedef enum StdSmbiosTableGeneratorId {
+  ESTD_SMBIOS_TABLE_ID_RESERVED = 0x0000,
+  ESTD_SMBIOS_TABLE_ID_RAW,
+  ESTD_SMBIOS_TABLE_ID_TYPE00,
+  ESTD_SMBIOS_TABLE_ID_TYPE01,
+  ESTD_SMBIOS_TABLE_ID_TYPE02,
+  ESTD_SMBIOS_TABLE_ID_TYPE03,
+  ESTD_SMBIOS_TABLE_ID_TYPE04,
+  ESTD_SMBIOS_TABLE_ID_TYPE05,
+  ESTD_SMBIOS_TABLE_ID_TYPE06,
+  ESTD_SMBIOS_TABLE_ID_TYPE07,
+  ESTD_SMBIOS_TABLE_ID_TYPE08,
+  ESTD_SMBIOS_TABLE_ID_TYPE09,
+  ESTD_SMBIOS_TABLE_ID_TYPE10,
+  ESTD_SMBIOS_TABLE_ID_TYPE11,
+  ESTD_SMBIOS_TABLE_ID_TYPE12,
+  ESTD_SMBIOS_TABLE_ID_TYPE13,
+  ESTD_SMBIOS_TABLE_ID_TYPE14,
+  ESTD_SMBIOS_TABLE_ID_TYPE15,
+  ESTD_SMBIOS_TABLE_ID_TYPE16,
+  ESTD_SMBIOS_TABLE_ID_TYPE17,
+  ESTD_SMBIOS_TABLE_ID_TYPE18,
+  ESTD_SMBIOS_TABLE_ID_TYPE19,
+  ESTD_SMBIOS_TABLE_ID_TYPE20,
+  ESTD_SMBIOS_TABLE_ID_TYPE21,
+  ESTD_SMBIOS_TABLE_ID_TYPE22,
+  ESTD_SMBIOS_TABLE_ID_TYPE23,
+  ESTD_SMBIOS_TABLE_ID_TYPE24,
+  ESTD_SMBIOS_TABLE_ID_TYPE25,
+  ESTD_SMBIOS_TABLE_ID_TYPE26,
+  ESTD_SMBIOS_TABLE_ID_TYPE27,
+  ESTD_SMBIOS_TABLE_ID_TYPE28,
+  ESTD_SMBIOS_TABLE_ID_TYPE29,
+  ESTD_SMBIOS_TABLE_ID_TYPE30,
+  ESTD_SMBIOS_TABLE_ID_TYPE31,
+  ESTD_SMBIOS_TABLE_ID_TYPE32,
+  ESTD_SMBIOS_TABLE_ID_TYPE33,
+  ESTD_SMBIOS_TABLE_ID_TYPE34,
+  ESTD_SMBIOS_TABLE_ID_TYPE35,
+  ESTD_SMBIOS_TABLE_ID_TYPE36,
+  ESTD_SMBIOS_TABLE_ID_TYPE37,
+  ESTD_SMBIOS_TABLE_ID_TYPE38,
+  ESTD_SMBIOS_TABLE_ID_TYPE39,
+  ESTD_SMBIOS_TABLE_ID_TYPE40,
+  ESTD_SMBIOS_TABLE_ID_TYPE41,
+  ESTD_SMBIOS_TABLE_ID_TYPE42,
+
+  // IDs 43 - 125 are reserved
+
+  ESTD_SMBIOS_TABLE_ID_TYPE126 = (ESTD_SMBIOS_TABLE_ID_TYPE00 + 126),
+  ESTD_SMBIOS_TABLE_ID_TYPE127,
+  ESTD_SMBIOS_TABLE_ID_MAX
+} ESTD_SMBIOS_TABLE_ID;
+
+/** This macro checks if the Table Generator ID is for an SMBIOS Table
+    Generator.
+    @param [in] TableGeneratorId  The table generator ID.
+
+    @returns  TRUE if the table generator ID is for an SMBIOS Table
+              Generator.
+*/
+#define IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId) \
+          (                                        \
+          GET_TABLE_TYPE (TableGeneratorId) ==     \
+          ETableGeneratorTypeSmbios                \
+          )
+
+/** This macro checks if the Table Generator ID is for a standard SMBIOS
+    Table Generator.
+
+    @param [in] TableGeneratorId  The table generator ID.
+
+    @returns  TRUE if the table generator ID is for a standard SMBIOS
+              Table Generator.
+*/
+#define IS_VALID_STD_SMBIOS_GENERATOR_ID(TableGeneratorId)            \
+          (                                                           \
+          IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) &&             \
+          IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId)   &&             \
+          ((GET_TABLE_ID(GeneratorId) >= ESTD_SMBIOS_TABLE_ID_RAW) && \
+           (GET_TABLE_ID(GeneratorId) < ESTD_SMIOS_TABLE_ID_MAX))     \
+          )
+
+/** This macro creates a standard SMBIOS Table Generator ID.
+
+    @param [in] TableId  The table generator ID.
+
+    @returns a standard SMBIOS table generator ID.
+*/
+#define CREATE_STD_SMBIOS_TABLE_GEN_ID(TableId) \
+          CREATE_TABLE_GEN_ID (                 \
+            ETableGeneratorTypeSmbios,          \
+            ETableGeneratorNameSpaceStd,        \
+            TableId                             \
+            )
+
+/** Forward declarations.
+*/
+typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
+typedef struct CmStdObjSmbiosTableInfo      CM_STD_OBJ_SMBIOS_TABLE_INFO;
+typedef struct SmbiosTableGenerator         SMBIOS_TABLE_GENERATOR;
+
+/** This function pointer describes the interface to SMBIOS table build
+    functions provided by the SMBIOS table generator and called by the
+    Table Manager to build an SMBIOS table.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
+    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
+                                 Protocol interface.
+    @param [out] Table           Pointer to the generated SMBIOS table.
+
+    @returns EFI_SUCCESS  If the table is generated successfully or other
+                          failure codes as returned by the generator.
+*/
+typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLE) (
+  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
+  IN        CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       SMBIOS_STRUCTURE                   **       Table
+  );
+
+/** This function pointer describes the interface to used by the
+    Table Manager to give the generator an opportunity to free
+    any resources allocated for building the SMBIOS table.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
+    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
+                                 Protocol interface.
+    @param [in]  Table           Pointer to the generated SMBIOS table.
+
+    @returns  EFI_SUCCESS If freed successfully or other failure codes
+                          as returned by the generator.
+*/
+typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLE) (
+  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
+  IN  CONST CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        SMBIOS_STRUCTURE                   **       Table
+  );
+
+/** The SMBIOS_TABLE_GENERATOR structure provides an interface that the
+    Table Manager can use to invoke the functions to build SMBIOS tables.
+
+*/
+typedef struct SmbiosTableGenerator {
+  /// The SMBIOS table generator ID.
+  SMBIOS_TABLE_GENERATOR_ID                GeneratorID;
+
+  /// String describing the DT table
+  /// generator.
+  CONST CHAR16*                            Description;
+
+  /// The SMBIOS table type.
+  SMBIOS_TYPE                              Type;
+
+  /// SMBIOS table build function pointer.
+  SMBIOS_TABLE_GENERATOR_BUILD_TABLE       BuildSmbiosTable;
+
+  /// The function to free any resources
+  /// allocated for building the SMBIOS table.
+  SMBIOS_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
+} SMBIOS_TABLE_GENERATOR;
+
+/** Register SMBIOS table factory generator.
+
+    The SMBIOS table factory maintains a list of the Standard and OEM SMBIOS
+    table generators.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+
+    @retval EFI_SUCCESS           The Generator was registered
+                                  successfully.
+    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
+                                  the Generator pointer is NULL.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
+                                  already registered.
+*/
+EFI_STATUS
+EFIAPI
+RegisterSmbiosTableGenerator (
+  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
+  );
+
+/** Unregister SMBIOS generator.
+
+    This function is called by the SMBIOS table generator to unregister itself
+    from the SMBIOS table factory.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The generator is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+UnRegisterSmbiosTableGenerator (
+  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
+  );
+#pragma pack()
+
+#endif // SMBIOS_TABLE_GENERATOR_H_
+
diff --git a/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
new file mode 100644
index 0000000000000000000000000000000000000000..76ae3f2208a5c80f0ca10b75e5df94cbb43e4688
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
@@ -0,0 +1,93 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+    - Std or STD - Standard
+**/
+
+#ifndef STANDARD_NAMESPACE_OBJECTS_H_
+#define STANDARD_NAMESPACE_OBJECTS_H_
+
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+
+#pragma pack(1)
+
+/** The ESTD_OBJECT_ID enum describes the Object IDs
+    in the Standard Namespace.
+*/
+typedef enum StdObjectID {
+  EStdObjCfgMgrInfo = 0x00000000, ///< 0 - Configuration Manager Info
+  EStdObjAcpiTableList,           ///< 1 - ACPI table Info List
+  EStdObjSmbiosTableList,         ///< 2 - SMBIOS table Info List
+  EStdObjMax
+} ESTD_OBJECT_ID;
+
+/** A structure that describes the Configuration Manager Information.
+*/
+typedef struct CmStdObjConfigurationManagerInfo {
+  /// The Configuration Manager Revision.
+  UINT32  Revision;
+
+  /// The OEM ID. This information is used to
+  /// populate the ACPI table header information.
+  UINT8   OemId[6];
+} CM_STD_OBJ_CONFIGURATION_MANAGER_INFO;
+
+/** A structure used to describe the ACPI table generators to be invoked.
+
+    The AcpiTableData member of this structure may be used to directly provide
+    the binary ACPI table data which is required by the following standard
+    generators:
+      - RAW
+      - DSDT
+      - SSDT
+
+    Providing the ACPI table data is optional and depends on the generator
+    that is being invoked. If unused, set AcpiTableData to NULL.
+*/
+typedef struct CmAStdObjAcpiTableInfo {
+  /// The signature of the ACPI Table to be installed.
+  UINT32                         AcpiTableSignature;
+
+  /// The ACPI Table Generator ID.
+  ACPI_TABLE_GENERATOR_ID        TableGeneratorId;
+
+  /// Optional pointer to the ACPI table data.
+  EFI_ACPI_DESCRIPTION_HEADER  * AcpiTableData;
+
+} CM_STD_OBJ_ACPI_TABLE_INFO;
+
+/** A structure used to describe the SMBIOS table generators to be invoked.
+
+    The SmbiosTableData member of this structure is used to provide
+    the SMBIOS table data which is required by the following standard
+    generator(s):
+      - RAW
+
+    Providing the SMBIOS table data is optional and depends on the
+    generator that is being invoked. If unused, set the SmbiosTableData
+    to NULL.
+*/
+typedef struct CmStdObjSmbiosTableInfo {
+  /// The SMBIOS Table Generator ID.
+  SMBIOS_TABLE_GENERATOR_ID   TableGeneratorId;
+
+  /// Optional pointer to the SMBIOS table data.
+  SMBIOS_STRUCTURE           * SmbiosTableData;
+} CM_STD_OBJ_SMBIOS_TABLE_INFO;
+
+#pragma pack()
+
+#endif // STANDARD_NAMESPACE_OBJECTS_H_
diff --git a/MdeModulePkg/Include/DynamicTables/TableGenerator.h b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..93d557273459948f5211e1c26a6028fc12b181fb
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
@@ -0,0 +1,235 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - ACPI   - Advanced Configuration and Power Interface
+    - SMBIOS - System Management BIOS
+    - DT     - Device Tree
+**/
+
+#ifndef TABLE_GENERATOR_H_
+#define TABLE_GENERATOR_H_
+
+/** The TABLE_GENERATOR_ID type describes the Table Generator ID
+
+  Table Generator ID
+
+________________________________________________________________________________
+|  31 | 30 |29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16|
+--------------------------------------------------------------------------------
+|TNSID|  0 |   TT   |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0|  0 |
+________________________________________________________________________________
+
+
+________________________________________________________________________________
+|15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
+--------------------------------------------------------------------------------
+|                                 Table ID                                     |
+________________________________________________________________________________
+
+
+  Bit [31] - Table NameSpace ID (TNSID)
+      0 - Standard
+      1 - Custom/OEM
+
+  Bit [30] - Reserved, Must be Zero
+
+  Bit [29:28] - Table Type (TT)
+       0 - ACPI Table
+       1 - SMBIOS Table
+       2 - DT (Device Tree) Table
+       3 - Reserved (INVALID)
+
+  Bit [27:16] - Reserved, Must Be Zero
+
+  Bit [15:0] - Table ID
+
+    Standard ACPI Table IDs:
+       0 - Reserved
+       1 - RAW
+       2 - FADT
+       3 - DSDT
+       4 - SSDT
+       5 - MADT
+       6 - GTDT
+       7 - DBG2
+       8 - SPCR
+       9 - MCFG
+
+
+    Standard SMBIOS Table IDs:
+       0 - Reserved
+       1 - RAW
+       2 - Table Type00
+       3 - Table Type01
+       4 - Table Type02
+       5 - Table Type03
+       6 - Table Type04
+       7 - Table Type05
+       8 - Table Type06
+       9 - Table Type07
+      10 - Table Type08
+      11 - Table Type09
+      12 - Table Type10
+      13 - Table Type11
+      14 - Table Type12
+      15 - Table Type13
+      16 - Table Type14
+      17 - Table Type15
+      18 - Table Type16
+      19 - Table Type17
+      20 - Table Type18
+      21 - Table Type19
+      22 - Table Type20
+      23 - Table Type21
+      24 - Table Type22
+      25 - Table Type23
+      26 - Table Type24
+      27 - Table Type25
+      28 - Table Type26
+      29 - Table Type27
+      30 - Table Type28
+      31 - Table Type29
+      32 - Table Type30
+      33 - Table Type31
+      34 - Table Type32
+      35 - Table Type33
+      36 - Table Type34
+      37 - Table Type35
+      38 - Table Type36
+      39 - Table Type37
+      40 - Table Type38
+      41 - Table Type39
+      42 - Table Type40
+      43 - Table Type41
+      44 - Table Type42
+  45-127 - Reserved
+     128 - Table Type126
+     129 - Table Type127
+**/
+typedef UINT32  TABLE_GENERATOR_ID;
+
+/** This enum lists the Table Generator Types.
+*/
+typedef enum TableGeneratorType {
+  ETableGeneratorTypeAcpi = 0,  ///< ACPI Table Generator Type.
+  ETableGeneratorTypeSmbios,    ///< SMBIOS Table Generator Type.
+  ETableGeneratorTypeDt,        ///< Device Tree Table Generator Type.
+  ETableGeneratorTypeReserved
+} ETABLE_GENERATOR_TYPE;
+
+/** This enum lists the namespaces for the Table Generators.
+*/
+typedef enum TableGeneratorNameSpace {
+  ETableGeneratorNameSpaceStd = 0,  ///< Standard Namespace.
+  ETableGeneratorNameSpaceOem       ///< OEM Namespace.
+} ETABLE_GENERATOR_NAMESPACE;
+
+/** A mask for the Table ID bits of TABLE_GENERATOR_ID.
+*/
+#define TABLE_ID_MASK             0xFF
+
+/** A mask for the Namespace ID bits of TABLE_GENERATOR_ID.
+*/
+#define TABLE_NAMESPACEID_MASK    (BIT31)
+
+/** A mask for the Table Type bits of TABLE_GENERATOR_ID.
+*/
+#define TABLE_TYPE_MASK           (BIT29 | BIT28)
+
+/** This macro returns the Table ID from the TableGeneratorId.
+
+    @param [in]  TableGeneratorId  The table generator ID.
+
+    @returns the Table ID described by the TableGeneratorId.
+*/
+#define GET_TABLE_ID(TableGeneratorId)                          \
+          ((TableGeneratorId) & TABLE_ID_MASK)
+
+/** This macro returns the Table type from the TableGeneratorId.
+
+    @param [in]  TableGeneratorId  The table generator ID.
+
+    @returns the Table type described by the TableGeneratorId.
+*/
+#define GET_TABLE_TYPE(TableGeneratorId)                        \
+          (((TableGeneratorId) & TABLE_TYPE_MASK) >> 28)
+
+/** This macro returns the Namespace ID from the TableGeneratorId.
+
+    @param [in]  TableGeneratorId  The table generator ID.
+
+    @returns the Namespace described by the TableGeneratorId.
+*/
+#define GET_TABLE_NAMESPACEID(TableGeneratorId)                 \
+          (((TableGeneratorId) & TABLE_NAMESPACEID_MASK) >> 31)
+
+/** This macro checks if the TableGeneratorId is in the Standard Namespace.
+
+    @param [in]  TableGeneratorId  The table generator ID.
+
+    @returns TRUE if the TableGeneratorId is in the Standard Namespace.
+*/
+#define IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) \
+          (                                          \
+          GET_TABLE_NAMESPACEID(TableGeneratorId) == \
+          ETableGeneratorNameSpaceStd                \
+          )
+
+/** This macro creates a TableGeneratorId
+
+    @param [in]  TableType        The table type.
+    @param [in]  TableNameSpaceId The namespace ID for the table.
+    @param [in]  TableId          The table ID.
+
+    @returns a TableGeneratorId calculated from the inputs.
+*/
+#define CREATE_TABLE_GEN_ID(TableType, TableNameSpaceId, TableId)  \
+          (                                                        \
+           (((TableType) << 28) & TABLE_TYPE_MASK)               | \
+           (((TableNameSpaceId) << 31) & TABLE_NAMESPACEID_MASK) | \
+           ((TableId) & TABLE_ID_MASK)                             \
+          )
+
+/** This macro generates a Major.Minor version
+    where the Major and Minor fields are 16 bit.
+
+    @param [in]  Major  The Major Revision.
+    @param [in]  Minor  The Minor Revision.
+
+    @returns a 32 bit representation of the type Major.Minor.
+*/
+#define CREATE_REVISION(Major, Minor)                            \
+          ((((Major) & 0xFFFF) << 16) | ((Minor) & 0xFFFF))
+
+/** This macro returns the Major revison
+
+    Extracts Major from the 32 bit representation of the type Major.Minor
+
+    @param [in]  Revision  The Revision value which is 32 bit.
+
+    @returns the Major part of the revision.
+*/
+#define GET_MAJOR_REVISION(Revision)  (((Revision) >> 16) & 0xFFFF)
+
+/** This macro returns the Minor revison
+
+    Extracts Minor from the 32 bit representation of the type Major.Minor
+
+    @param [in]  Revision  The Revision value which is 32 bit.
+
+    @returns the Minor part of the revision.
+*/
+#define GET_MINOR_REVISION(Revision)  ((Revision) & 0xFFFF)
+
+#endif // TABLE_GENERATOR_H_
+
diff --git a/MdeModulePkg/Include/Library/TableHelperLib.h b/MdeModulePkg/Include/Library/TableHelperLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b22e024dee1a311e4e4b532371ccef94bc02be3
--- /dev/null
+++ b/MdeModulePkg/Include/Library/TableHelperLib.h
@@ -0,0 +1,67 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef TABLE_HELPER_LIB_H_
+#define TABLE_HELPER_LIB_H_
+
+/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
+    object from the Configuration Manager.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
+                                interface.
+    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
+                                object structure.
+
+    @retval EFI_SUCCESS           The object is returned.
+    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
+    @retval EFI_NOT_FOUND         The requested Object is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size.
+*/
+EFI_STATUS
+EFIAPI
+GetCgfMgrInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST  CfgMgrProtocol,
+  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **        CfgMfrInfo
+  );
+
+/** The AddAcpiHeader function updates the ACPI header structure pointed by
+    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
+    Manager protocol to obtain any information required for constructing the
+    header.
+
+    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
+                                   protocol interface.
+    @param [in]     Generator      Pointer to the ACPI table Generator.
+    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
+                                   updated.
+    @param [in]     Length         Length of the ACPI table.
+
+    @retval EFI_SUCCESS           The ACPI table is updated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object information is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+EFI_STATUS
+EFIAPI
+AddAcpiHeader (
+  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
+  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
+  IN      CONST UINT32                                      Length
+  );
+
+#endif // TABLE_HELPER_LIB_H_
diff --git a/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..387935943648654ef095720dec452d1c15b8fc11
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
@@ -0,0 +1,121 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef CONFIGURATION_MANAGER_PROTOCOL_H_
+#define CONFIGURATION_MANAGER_PROTOCOL_H_
+
+/** This macro defines the Configuration Manager Protocol GUID.
+
+  GUID: {D85A4835-5A82-4894-AC02-706F43D5978E}
+*/
+#define EFI_CONFIGURATION_MANAGER_PROTOCOL_GUID         \
+  { 0xd85a4835, 0x5a82, 0x4894,                         \
+    { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e }   \
+  };
+
+/** This macro defines the Configuration Manager Protocol Revision.
+*/
+#define EFI_CONFIGURATION_MANAGER_PROTOCOL_REVISION  CREATE_REVISION (1, 0)
+
+#pragma pack(1)
+
+/**
+  Forward declarations:
+*/
+typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
+typedef struct PlatformRepositoryInfo       EFI_PLATFORM_REPOSITORY_INFO;
+
+
+/** The GetObject function defines the interface implemented by the
+    Configuration Manager Protocol for returning the Configuration
+    Manager Objects.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the requested Object.
+
+    @retval Returns:
+      EFI_SUCCESS           Success.
+      EFI_INVALID_PARAMETER A parameter is invalid.
+      EFI_NOT_FOUND         The required object information is not found.
+      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                            is less than the Object size for the requested
+                            object.
+*/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_CONFIGURATION_MANAGER_GET_OBJECT) (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  );
+
+/** The SetObject function defines the interface implemented by the
+    Configuration Manager Protocol for updating the Configuration
+    Manager Objects.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the Object.
+
+    @retval Returns:
+      EFI_SUCCESS           The operation completed successfully.
+      EFI_INVALID_PARAMETER A parameter is invalid.
+      EFI_NOT_FOUND         The required object information is not found.
+      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                            is less than the Object size for the requested
+                            object.
+      EFI_UNSUPPORTED       This operation is not supported.
+*/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_CONFIGURATION_MANAGER_SET_OBJECT) (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN        CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  );
+
+/** The EFI_CONFIGURATION_MANAGER_PROTOCOL structure describes the
+    Configuration Manager Protocol interface.
+*/
+typedef struct ConfigurationManagerProtocol {
+  /// The Configuration Manager Protocol revision.
+  UINT32                                Revision;
+
+  /// The interface used to request information about
+  /// the Configuration Manager Objects.
+  EFI_CONFIGURATION_MANAGER_GET_OBJECT  GetObject;
+
+  /// The interface used to update the information stored
+  /// in the Configuration Manager repository.
+  EFI_CONFIGURATION_MANAGER_SET_OBJECT  SetObject;
+
+  /// Pointer to an implementation defined abstract repository
+  /// provisioned by the Configuration Manager.
+  EFI_PLATFORM_REPOSITORY_INFO        * PlatRepoInfo;
+} EFI_CONFIGURATION_MANAGER_PROTOCOL;
+
+/** A global GUID defined in the protocol section of the
+    MdeModulePkg.dec file.
+*/
+extern EFI_GUID gEfiConfigurationManagerProtocolGuid;
+
+#pragma pack()
+
+#endif // CONFIGURATION_MANAGER_PROTOCOL_H_
diff --git a/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ece83bb44ec2d88fbd3b49b0e7bdc6314c332c7
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
@@ -0,0 +1,113 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - ACPI   - Advanced Configuration and Power Interface
+    - SMBIOS - System Management BIOS
+**/
+
+#ifndef DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
+#define DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
+
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+
+/** This macro defines the Dynamic Table Factory Protocol GUID.
+
+  GUID: {91D1E327-FE5A-49B8-AB65-0ECE2DDB45EC}
+*/
+#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_GUID         \
+  { 0x91d1e327, 0xfe5a, 0x49b8,                         \
+    { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec }   \
+  };
+
+/** This macro defines the Configuration Manager Protocol Revision.
+*/
+#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_REVISION  CREATE_REVISION (1, 0)
+
+#pragma pack(1)
+
+/**
+  Forward declarations:
+*/
+typedef struct DynamicTableFactoryProtocol EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
+typedef struct DynamicTableFactoryInfo EFI_DYNAMIC_TABLE_FACTORY_INFO;
+
+/** Return a pointer to the ACPI table generator.
+
+    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  TableId    The ACPI table generator ID for the
+                            requested generator.
+    @param [out] Generator  Pointer to the requested ACPI table
+                            generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A paramter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+typedef
+EFI_STATUS
+EFIAPI
+(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR) (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
+  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
+  );
+
+/** Return a pointer to the SMBIOS table generator.
+
+    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  TableId    The SMBIOS table generator ID for the
+                            requested generator.
+    @param [out] Generator  Pointer to the requested SMBIOS table
+                            generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+typedef
+EFI_STATUS
+EFIAPI
+(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR) (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
+  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
+  );
+
+/** A structure describing the Dynamic Table Factory Protocol interface.
+*/
+typedef struct DynamicTableFactoryProtocol {
+  /// The Dynamic Table Factory Protocol revision.
+  UINT32                                               Revision;
+
+  /// The interface used to request an ACPI Table Generator.
+  EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR   GetAcpiTableGenerator;
+
+  /// The interface used to request a SMBIOS Table Generator.
+  EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR GetSmbiosTableGenerator;
+
+  /// Pointer to the data structure that holds the
+  /// list of registered table generators
+  EFI_DYNAMIC_TABLE_FACTORY_INFO          * TableFactoryInfo;
+} EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
+
+/** A global GUID defined in the protocol section of the
+    MdeModulePkg.dec file.
+*/
+extern EFI_GUID gEfiDynamicTableFactoryProtocolGuid;
+
+#pragma pack()
+
+#endif // DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..88d9e5a4a58307ea26ddbe75579cddc3333ccc34
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
@@ -0,0 +1,91 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Std - Standard
+    - ACPI   - Advanced Configuration and Power Interface
+    - SMBIOS - System Management BIOS
+**/
+
+#ifndef DYNAMIC_TABLE_FACTORY_H_
+#define DYNAMIC_TABLE_FACTORY_H_
+
+#pragma pack(1)
+
+/** A structure that holds the list of registered ACPI and
+    SMBIOS table generators.
+*/
+typedef struct DynamicTableFactoryInfo {
+  /// An array for holding the list of Standard ACPI Table  Generators.
+  CONST ACPI_TABLE_GENERATOR *
+          StdAcpiTableGeneratorList[ESTD_ACPI_TABLE_ID_MAX];
+
+  /// An array for holding the list of Custom ACPI Table Generators.
+  CONST ACPI_TABLE_GENERATOR *
+          CustomAcpiTableGeneratorList[FixedPcdGet16 (
+            PcdMaxCustomACPIGenerators)];
+
+  /// An array for holding the list of Standard SMBIOS Table Generators.
+  CONST SMBIOS_TABLE_GENERATOR *
+          StdSmbiosTableGeneratorList[ESTD_SMBIOS_TABLE_ID_MAX];
+
+  /// An array for holding the list of Custom SMBIOS Table Generators.
+  CONST SMBIOS_TABLE_GENERATOR *
+          CustomSmbiosTableGeneratorList[FixedPcdGet16 (
+            PcdMaxCustomSMBIOSGenerators)];
+} EFI_DYNAMIC_TABLE_FACTORY_INFO;
+
+/** Return a pointer to the ACPI table generator.
+
+    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  GeneratorId  The ACPI table generator ID for the
+                              requested generator.
+    @param [out] Generator    Pointer to the requested ACPI table
+                              generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+GetAcpiTableGenerator (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
+  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
+  );
+
+/** Return a pointer to the SMBIOS table generator.
+
+    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  GeneratorId  The SMBIOS table generator ID for the
+                              requested generator.
+    @param [out] Generator    Pointer to the requested SMBIOS table
+                              generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+GetSmbiosTableGenerator (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
+  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
+  );
+
+#pragma pack()
+
+#endif // DYNAMIC_TABLE_FACTORY_H_
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
new file mode 100644
index 0000000000000000000000000000000000000000..1bf20424b942ac08fe93d157f3869de53577cf0e
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
@@ -0,0 +1,440 @@
+/** @file
+  DBG2 Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+#include <IndustryStandard/DebugPort2Table.h>
+#include <Drivers/PL011Uart.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard DBG2 Table Generator
+
+    Generates the ACPI DBG2 Port Table for ARM UARTs
+    as specified by the Microsoft Debug Port Table 2 (DBG2)
+    Specification - December 10, 2015.
+
+    Constructs the DBG2 table for PL011 or SBSA UART peripherals.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjSerialDebugPortInfo
+*/
+
+#pragma pack(1)
+
+/** Define the number of debug ports represented by the Table.
+*/
+#define DBG2_NUM_DEBUG_PORTS                       1
+
+/** Define the number of Generic Address Registers
+    presented in the debug device information.
+*/
+#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS   1
+
+/** Define the index for the debug port 1.
+*/
+#define DBG_PORT_INDEX_PORT1                       0
+
+/** Define the string representing the debug port 1 name.
+*/
+#define NAME_STR_PORT1                            "COM1"
+
+/** Define the length of the namespace string.
+*/
+#define DBG2_NAMESPACESTRING_FIELD_SIZE            sizeof (NAME_STR_PORT1)
+
+/** Define the PL011 UART address range length.
+*/
+#define PL011_UART_LENGTH                          0x1000
+
+/** This structure provides the OS with the information required for
+    initializing a debugger connection.
+*/
+typedef struct {
+  /// The debug device information for the platform
+  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device;
+
+  /// The base address register for the serial port
+  EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE        BaseAddressRegister;
+
+  /// The address size
+  UINT32 AddressSize;
+
+  /// The debug port name string
+  UINT8  NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
+} DBG2_DEBUG_DEVICE_INFORMATION;
+
+/** This structure represents the information about the debug port(s)
+    available on the platform.
+*/
+typedef struct {
+  /// The DBG2 table header
+  EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description;
+
+  /// Debug port information list
+  DBG2_DEBUG_DEVICE_INFORMATION       Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS];
+} DBG2_TABLE;
+
+/** A helper macro used for initalizing the debug port device
+    information structure.
+
+    @param [in]  NumReg       The number of generic address registers.
+    @param [in]  SubType      The DBG Port SubType.
+    @param [in]  UartBase     The UART port base address.
+    @param [in]  UartAddrLen  The UART port address range length.
+    @param [in]  UartNameStr  The UART port name string.
+*/
+#define DBG2_DEBUG_PORT_DDI(                                          \
+          NumReg,                                                     \
+          SubType,                                                    \
+          UartBase,                                                   \
+          UartAddrLen,                                                \
+          UartNameStr                                                 \
+          ) {                                                         \
+    {                                                                 \
+      /* UINT8     Revision */                                        \
+      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,         \
+      /* UINT16    Length */                                          \
+      sizeof (DBG2_DEBUG_DEVICE_INFORMATION),                         \
+      /* UINT8     NumberofGenericAddressRegisters */                 \
+      NumReg,                                                         \
+      /* UINT16    NameSpaceStringLength */                           \
+      DBG2_NAMESPACESTRING_FIELD_SIZE,                                \
+      /* UINT16    NameSpaceStringOffset */                           \
+      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString),     \
+      /* UINT16    OemDataLength */                                   \
+      0,                                                              \
+      /* UINT16    OemDataOffset */                                   \
+      0,                                                              \
+      /* UINT16    Port Type */                                       \
+      EFI_ACPI_DBG2_PORT_TYPE_SERIAL,                                 \
+      /* UINT16    Port Subtype */                                    \
+      SubType,                                                        \
+      /* UINT8     Reserved[2] */                                     \
+      {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE},               \
+      /* UINT16    BaseAddressRegister Offset */                      \
+      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \
+      /* UINT16    AddressSize Offset */                              \
+      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize)          \
+    },                                                                \
+    /* EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */  \
+    ARM_GAS32 (UartBase),                                             \
+    /* UINT32  AddressSize */                                         \
+    UartAddrLen,                                                      \
+    /* UINT8   NameSpaceString[MAX_DBG2_NAME_LEN] */                  \
+    UartNameStr                                                       \
+  }
+
+/** The DBG2 Table template definition.
+
+    Note: fields marked with "{Template}" will be set dynamically
+*/
+STATIC
+DBG2_TABLE AcpiDbg2 = {
+  {
+    ACPI_HEADER (
+      EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
+      DBG2_TABLE,
+      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
+      ),
+    OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),
+    DBG2_NUM_DEBUG_PORTS
+  },
+  {
+    /*
+     * Debug port 1
+     */
+    DBG2_DEBUG_PORT_DDI (
+      DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS,
+      EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART,
+      0,                    // {Template}: Serial Port Base Address
+      PL011_UART_LENGTH,
+      NAME_STR_PORT1
+      )
+  }
+};
+
+#pragma pack()
+
+/** This macro expands to a function that retrieves the Serial
+    debug port information from the Configuration Manager
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjSerialDebugPortInfo,
+  CM_ARM_SERIAL_PORT_INFO
+  );
+
+/** Initialize the PL011 UART with the parameters obtained from
+    the Configuration Manager.
+
+    @param [in]  SerialPortInfo Pointer to the Serial Port Information.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The parameters for serial port initialization
+                                  are invalid.
+*/
+STATIC
+EFI_STATUS
+SetupDebugUart (
+  IN  CONST CM_ARM_SERIAL_PORT_INFO  * CONST SerialPortInfo
+  )
+{
+  EFI_STATUS          Status;
+  UINT64              BaudRate;
+  UINT32              ReceiveFifoDepth;
+  EFI_PARITY_TYPE     Parity;
+  UINT8               DataBits;
+  EFI_STOP_BITS_TYPE  StopBits;
+
+  ASSERT (SerialPortInfo != NULL);
+
+  // Initialize the Serial Debug UART
+  DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));
+  ReceiveFifoDepth = 0; // Use the default value for FIFO depth
+  Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
+  DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
+  StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
+
+  BaudRate = SerialPortInfo->BaudRate;
+  Status = PL011UartInitializePort (
+             (UINTN)SerialPortInfo->BaseAddress,
+             SerialPortInfo->Clock,
+             &BaudRate,
+             &ReceiveFifoDepth,
+             &Parity,
+             &DataBits,
+             &StopBits
+             );
+
+  DEBUG ((DEBUG_INFO, "Debug UART Configuration:\n"));
+  DEBUG ((DEBUG_INFO, "UART Base  = 0x%lx\n", SerialPortInfo->BaseAddress));
+  DEBUG ((DEBUG_INFO, "Clock      = %d\n", SerialPortInfo->Clock));
+  DEBUG ((DEBUG_INFO, "Baudrate   = %ld\n", BaudRate));
+  DEBUG ((DEBUG_INFO, "Configuring Debug UART. Status = %r\n", Status));
+
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Construct the DBG2 ACPI table
+
+    The BuildDbg2Table function is called by the Dynamic Table Manager
+    to construct the DBG2 ACPI table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildDbg2Table (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                 Status;
+  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+
+  Status = GetEArmObjSerialDebugPortInfo (
+             CfgMgrProtocol,
+             &SerialPortInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = AddAcpiHeader (
+             CfgMgrProtocol,
+             This,
+             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2,
+             sizeof (DBG2_TABLE)
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.Address =
+    SerialPortInfo->BaseAddress;
+
+  Status = SetupDebugUart (SerialPortInfo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2;
+
+error_handler:
+  return Status;
+}
+
+/** Free any resources allocated for constructing the DBG2.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS         The resources were freed successfully.
+*/
+STATIC
+EFI_STATUS
+FreeDbg2TableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the DBG2 Table Generator revision.
+*/
+#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the DBG2 Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR Dbg2Generator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_DBG2),
+  // Generator Description
+  L"ACPI.STD.DBG2.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  DBG2_GENERATOR_REVISION,
+  // Build Table function
+  BuildDbg2Table,
+  // Free Resource function
+  FreeDbg2TableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiDbg2LibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&Dbg2Generator);
+  DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiDbg2LibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&Dbg2Generator);
+  DEBUG ((DEBUG_INFO, "DBG2: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..75e0b7b50ef34a71cc091db50667a19b40b3f1c9
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
@@ -0,0 +1,562 @@
+/** @file
+  FADT Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard FADT Generator
+
+    Generates the ACPI FADT Table as specified by the
+    ACPI 6.1 Specification - January, 2016.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjPowerManagementProfileInfo
+  - EArmObjBootArchInfo
+  - EArmObjHypervisorVendorIdentity (OPTIONAL)
+*/
+
+/** This macro defines the FADT flag options for ARM Platforms.
+*/
+#define FADT_FLAGS  (EFI_ACPI_6_1_HW_REDUCED_ACPI |          \
+                     EFI_ACPI_6_1_LOW_POWER_S0_IDLE_CAPABLE)
+
+#pragma pack(1)
+
+/** The AcpiFadt is a template EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE
+    structure used for generating the FADT Table.
+  Note: fields marked with "{Template}" will be updated dynamically.
+*/
+STATIC
+EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = {
+  ACPI_HEADER (
+    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE,
+    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
+    ),
+  // UINT32     FirmwareCtrl
+  0,
+  // UINT32     Dsdt
+  0,
+  // UINT8      Reserved0
+  EFI_ACPI_RESERVED_BYTE,
+  // UINT8      PreferredPmProfile
+  EFI_ACPI_6_1_PM_PROFILE_UNSPECIFIED,  // {Template}: Power Management Profile
+  // UINT16     SciInt
+  0,
+  // UINT32     SmiCmd
+  0,
+  // UINT8      AcpiEnable
+  0,
+  // UINT8      AcpiDisable
+  0,
+  // UINT8      S4BiosReq
+  0,
+  // UINT8      PstateCnt
+  0,
+  // UINT32     Pm1aEvtBlk
+  0,
+  // UINT32     Pm1bEvtBlk
+  0,
+  // UINT32     Pm1aCntBlk
+  0,
+  // UINT32     Pm1bCntBlk
+  0,
+  // UINT32     Pm2CntBlk
+  0,
+  // UINT32     PmTmrBlk
+  0,
+  // UINT32     Gpe0Blk
+  0,
+  // UINT32     Gpe1Blk
+  0,
+  // UINT8      Pm1EvtLen
+  0,
+  // UINT8      Pm1CntLen
+  0,
+  // UINT8      Pm2CntLen
+  0,
+  // UINT8      PmTmrLen
+  0,
+  // UINT8      Gpe0BlkLen
+  0,
+  // UINT8      Gpe1BlkLen
+  0,
+  // UINT8      Gpe1Base
+  0,
+  // UINT8      CstCnt
+  0,
+  // UINT16     PLvl2Lat
+  0,
+  // UINT16     PLvl3Lat
+  0,
+  // UINT16     FlushSize
+  0,
+  // UINT16     FlushStride
+  0,
+  // UINT8      DutyOffset
+  0,
+  // UINT8      DutyWidth
+  0,
+  // UINT8      DayAlrm
+  0,
+  // UINT8      MonAlrm
+  0,
+  // UINT8      Century
+  0,
+  // UINT16     IaPcBootArch
+  0,
+  // UINT8      Reserved1
+  0,
+  // UINT32     Flags
+  FADT_FLAGS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  ResetReg
+  NULL_GAS,
+  // UINT8      ResetValue
+  0,
+  // UINT16     ArmBootArch
+  EFI_ACPI_6_1_ARM_PSCI_COMPLIANT,  // {Template}: ARM Boot Architecture Flags
+  // UINT8      MinorRevision
+  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION,
+  // UINT64     XFirmwareCtrl
+  0,
+  // UINT64     XDsdt
+  0,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aEvtBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bEvtBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aCntBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bCntBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm2CntBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPmTmrBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe0Blk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe1Blk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepControlReg
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepStatusReg
+  NULL_GAS,
+  // UINT64     HypervisorVendorIdentity
+  EFI_ACPI_RESERVED_QWORD  // {Template}: Hypervisor Vendor ID
+};
+
+#pragma pack()
+
+/** This macro expands to a function that retrieves the Power
+    Management Profile Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPowerManagementProfileInfo,
+  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
+  );
+
+/** This macro expands to a function that retrieves the Boot
+    Architecture Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjBootArchInfo,
+  CM_ARM_BOOT_ARCH_INFO
+  );
+
+/** This macro expands to a function that retrieves the Hypervisor
+    Vendor ID from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjHypervisorVendorIdentity,
+  CM_ARM_HYPERVISOR_VENDOR_ID
+  );
+
+/** Update the Power Management Profile information in the FADT Table.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                  Protocol Interface.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+FadtAddPmProfileInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
+)
+{
+  EFI_STATUS                              Status;
+  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO  * PmProfile = NULL;
+
+  ASSERT (CfgMgrProtocol != NULL);
+
+  // Get the Power Management Profile from the Platform Configuration Manager
+  Status = GetEArmObjPowerManagementProfileInfo (
+             CfgMgrProtocol,
+             &PmProfile,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: FADT: Failed to get Power Management Profile information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "FADT: PreferredPmProfile = 0x%x\n",
+    PmProfile->PowerManagementProfile
+    ));
+
+  AcpiFadt.PreferredPmProfile = PmProfile->PowerManagementProfile;
+
+error_handler:
+  return Status;
+}
+
+/** Updates the Boot Architecture information in the FADT Table.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+FadtAddBootArchInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
+)
+{
+  EFI_STATUS               Status;
+  CM_ARM_BOOT_ARCH_INFO  * BootArchInfo = NULL;
+
+  ASSERT (CfgMgrProtocol != NULL);
+
+  // Get the Boot Architecture flags from the Platform Configuration Manager
+  Status = GetEArmObjBootArchInfo (
+             CfgMgrProtocol,
+             &BootArchInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "FADT BootArchFlag = 0x%x\n",
+    BootArchInfo->BootArchFlags
+    ));
+
+  AcpiFadt.ArmBootArch = BootArchInfo->BootArchFlags;
+
+error_handler:
+  return Status;
+}
+
+/** Update the Hypervisor Vendor ID in the FADT Table.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+FadtAddHypervisorVendorId (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
+)
+{
+  EFI_STATUS                     Status;
+  CM_ARM_HYPERVISOR_VENDOR_ID  * HypervisorVendorInfo = NULL;
+
+  ASSERT (CfgMgrProtocol != NULL);
+
+  // Get the Hypervisor Vendor ID from the Platform Configuration Manager
+  Status = GetEArmObjHypervisorVendorIdentity (
+             CfgMgrProtocol,
+             &HypervisorVendorInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+      DEBUG ((
+        DEBUG_INFO,
+        "INFO: FADT: Platform does not have a Hypervisor Vendor ID. Status = %r\n",
+        Status
+        ));
+    } else {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n",
+        Status
+        ));
+    }
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "FADT: EArmObjHypervisorVendorIdentity = 0x%lx\n",
+    HypervisorVendorInfo->HypervisorVendorId
+    ));
+
+  AcpiFadt.HypervisorVendorIdentity = HypervisorVendorInfo->HypervisorVendorId;
+
+error_handler:
+  return Status;
+}
+
+/** Construct the FADT table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildFadtTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS  Status;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+
+  Status = AddAcpiHeader (
+             CfgMgrProtocol,
+             This,
+             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt,
+             sizeof (EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE)
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: FADT: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  // Update PmProfile Info
+  Status = FadtAddPmProfileInfo (CfgMgrProtocol);
+  if (EFI_ERROR (Status)) {
+    goto error_handler;
+  }
+
+  // Update BootArch Info
+  Status = FadtAddBootArchInfo (CfgMgrProtocol);
+  if (EFI_ERROR (Status)) {
+    goto error_handler;
+  }
+
+  // Add the Hypervisor Vendor Id if present
+  // Note if no hypervisor is present the zero bytes
+  // will be placed in this field.
+  Status = FadtAddHypervisorVendorId (CfgMgrProtocol);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+      DEBUG ((
+        DEBUG_INFO,
+        "INFO: FADT: No Hypervisor Vendor ID found," \
+        " assuming no Hypervisor is present in the firmware.\n"
+        ));
+    } else {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r",
+        Status
+        ));
+      goto error_handler;
+    }
+  }
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt;
+  Status = EFI_SUCCESS;
+error_handler:
+  return Status;
+}
+
+/** Free any resources allocated for constructing the FADT.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS         The resources were freed successfully.
+*/
+STATIC
+EFI_STATUS
+FreeFadtTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the FADT Table Generator revision.
+*/
+#define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the FADT Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR FadtGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT),
+  // Generator Description
+  L"ACPI.STD.FADT.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  FADT_GENERATOR_REVISION,
+  // Build Table function
+  BuildFadtTable,
+  // Free Resource function
+  FreeFadtTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiFadtLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&FadtGenerator);
+  DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiFadtLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&FadtGenerator);
+  DEBUG ((DEBUG_INFO, "FADT: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..8a243e7d2ef2fa5806116030c74337f1f8e72e8b
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
@@ -0,0 +1,652 @@
+/** @file
+  GTDT Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard GTDT Generator
+
+    Generates the ACPI GTDT Table as specified by the
+    ACPI 6.1 Specification - January, 2016.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjGenericTimerInfo
+  - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)
+  - EArmObjPlatformGTBlockInfo (OPTIONAL)
+*/
+
+/** This macro expands to a function that retrieves the Generic
+    Timer Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGenericTimerInfo,
+  CM_ARM_GENERIC_TIMER_INFO
+  );
+
+/** This macro expands to a function that retrieves the SBSA Generic
+    Watchdog Timer Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPlatformGenericWatchdogInfo,
+  CM_ARM_GENERIC_WATCHDOG_INFO
+  );
+
+/** This macro expands to a function that retrieves the Platform Generic
+    Timer Block Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPlatformGTBlockInfo,
+  CM_ARM_GTBLOCK_INFO
+  );
+
+/** Add the Generic Timer Information to the GTDT table.
+
+    Also update the Platform Timer offset information if the platform
+    implements platform timers.
+
+    @param [in]  CfgMgrProtocol     Pointer to the Configuration Manager
+                                    Protocol Interface.
+    @param [in]  Gtdt               Pointer to the GTDT Table.
+    @param [in]  PlatformTimerCount Platform timer count.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+AddGenericTimerInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,
+  IN  CONST UINT32 PlatformTimerCount
+)
+{
+  EFI_STATUS                   Status;
+  CM_ARM_GENERIC_TIMER_INFO  * GenericTimerInfo = NULL;
+
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Gtdt != NULL);
+
+  Status = GetEArmObjGenericTimerInfo (
+             CfgMgrProtocol,
+             &GenericTimerInfo,
+             NULL
+             );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to get GenericTimerInfo. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  Gtdt->CntControlBasePhysicalAddress =
+    GenericTimerInfo->CounterControlBaseAddress;
+  Gtdt->Reserved = EFI_ACPI_RESERVED_DWORD;
+  Gtdt->CntReadBasePhysicalAddress =
+    GenericTimerInfo->CounterReadBaseAddress;
+  Gtdt->PlatformTimerCount = PlatformTimerCount;
+  Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :
+    sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
+
+  Gtdt->SecurePL1TimerGSIV = GenericTimerInfo->SecurePL1TimerGSIV;
+  Gtdt->SecurePL1TimerFlags = GenericTimerInfo->SecurePL1TimerFlags;
+  Gtdt->NonSecurePL1TimerGSIV = GenericTimerInfo->NonSecurePL1TimerGSIV;
+  Gtdt->NonSecurePL1TimerFlags = GenericTimerInfo->NonSecurePL1TimerFlags;
+  Gtdt->VirtualTimerGSIV = GenericTimerInfo->VirtualTimerGSIV;
+  Gtdt->VirtualTimerFlags = GenericTimerInfo->VirtualTimerFlags;
+  Gtdt->NonSecurePL2TimerGSIV = GenericTimerInfo->NonSecurePL2TimerGSIV;
+  Gtdt->NonSecurePL2TimerFlags = GenericTimerInfo->NonSecurePL2TimerFlags;
+
+  return EFI_SUCCESS;
+}
+
+/** Add the SBSA Generic Watchdog Timers to the GTDT table.
+
+    @param [in]  Gtdt             Pointer to the GTDT Table.
+    @param [in]  WatchdogOffset   Offset to the watchdog information in the
+                                  GTDT Table.
+    @param [in]  WatchdogInfoList Pointer to the watchdog information list.
+    @param [in]  WatchdogCount    Platform timer count.
+*/
+STATIC
+VOID
+AddGenericWatchdogList (
+  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
+  IN CONST UINTN                                           WatchdogOffset,
+  IN CONST CM_ARM_GENERIC_WATCHDOG_INFO            * CONST WatchdogInfoList,
+  IN CONST UINTN                                           WatchdogCount
+  )
+{
+  UINTN                                                idx;
+  EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE  * Watchdog;
+
+  ASSERT (Gtdt != NULL);
+  ASSERT (WatchdogInfoList != NULL);
+
+  Watchdog = (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *)
+             ((UINT8*)Gtdt + WatchdogOffset);
+
+  for (idx = 0; idx < WatchdogCount; idx++) {
+    // Add watchdog entry
+    DEBUG ((DEBUG_INFO, "GTDT: Watchdog[%d] = 0x%p\n", idx, &Watchdog[idx]));
+    Watchdog[idx].Type = EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG;
+    Watchdog[idx].Length =
+      sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);
+    Watchdog[idx].Reserved = EFI_ACPI_RESERVED_BYTE;
+    Watchdog[idx].RefreshFramePhysicalAddress =
+      WatchdogInfoList[idx].RefreshFrameAddress;
+    Watchdog[idx].WatchdogControlFramePhysicalAddress =
+      WatchdogInfoList[idx].ControlFrameAddress;
+    Watchdog[idx].WatchdogTimerGSIV = WatchdogInfoList[idx].TimerGSIV;
+    Watchdog[idx].WatchdogTimerFlags = WatchdogInfoList[idx].Flags;
+
+  } // for
+}
+
+/** Update the GT Block Timer Frame lists in the GTDT Table.
+
+    @param [in]  GtBlockFrame           Pointer to the GT Block Frames
+                                        list to be updated.
+    @param [in]  GTBlockTimerFrameList  Pointer to the GT Block Frame
+                                        Information List.
+    @param [in]  GTBlockFrameCount      Number of GT Block Frames.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+*/
+STATIC
+EFI_STATUS
+AddGTBlockTimerFrames (
+  IN       EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE * CONST GtBlockFrame,
+  IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO * CONST GTBlockTimerFrameList,
+  IN CONST UINTN GTBlockFrameCount
+)
+{
+  UINTN       idx;
+
+  ASSERT (GtBlockFrame != NULL);
+  ASSERT (GTBlockTimerFrameList != NULL);
+
+  if (GTBlockFrameCount > 8) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: GT Block Frame Count %d is greater than 8\n",
+      GTBlockFrameCount
+      ));
+    ASSERT (GTBlockFrameCount <= 8);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  for (idx = 0; idx < GTBlockFrameCount; idx++) {
+    DEBUG ((
+      DEBUG_INFO,
+      "GTDT: GtBlockFrame[%d] = 0x%p\n",
+      idx,
+      GtBlockFrame[idx]
+      ));
+
+    GtBlockFrame[idx].GTFrameNumber = GTBlockTimerFrameList[idx].FrameNumber;
+    GtBlockFrame[idx].Reserved[0] = EFI_ACPI_RESERVED_BYTE;
+    GtBlockFrame[idx].Reserved[1] = EFI_ACPI_RESERVED_BYTE;
+    GtBlockFrame[idx].Reserved[2] = EFI_ACPI_RESERVED_BYTE;
+
+    GtBlockFrame[idx].CntBaseX =
+      GTBlockTimerFrameList[idx].PhysicalAddressCntBase;
+    GtBlockFrame[idx].CntEL0BaseX =
+      GTBlockTimerFrameList[idx].PhysicalAddressCntEL0Base;
+
+    GtBlockFrame[idx].GTxPhysicalTimerGSIV =
+      GTBlockTimerFrameList[idx].PhysicalTimerGSIV;
+    GtBlockFrame[idx].GTxPhysicalTimerFlags =
+      GTBlockTimerFrameList[idx].PhysicalTimerFlags;
+
+    GtBlockFrame[idx].GTxVirtualTimerGSIV =
+      GTBlockTimerFrameList[idx].VirtualTimerGSIV;
+    GtBlockFrame[idx].GTxVirtualTimerFlags =
+      GTBlockTimerFrameList[idx].VirtualTimerFlags;
+
+    GtBlockFrame[idx].GTxCommonFlags = GTBlockTimerFrameList[idx].CommonFlags;
+
+  } // for
+  return EFI_SUCCESS;
+}
+
+/** Add the GT Block Timers in the GTDT Table.
+
+    @param [in]  Gtdt             Pointer to the GTDT Table.
+    @param [in]  GTBlockOffset    Offset of the GT Block
+                                  information in the GTDT Table.
+    @param [in]  GTBlockInfo      Pointer to the GT Block
+                                  Information List.
+    @param [in]  BlockTimerCount  Number of GT Block Timers.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+
+*/
+STATIC
+EFI_STATUS
+AddGTBlockList (
+  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
+  IN CONST UINTN                                           GTBlockOffset,
+  IN CONST CM_ARM_GTBLOCK_INFO                     * CONST GTBlockInfo,
+  IN CONST UINTN                                           BlockTimerCount
+)
+{
+  EFI_STATUS                                    Status;
+  UINTN                                         idx;
+  EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE        * GTBlock;
+  EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE  * GtBlockFrame;
+
+  ASSERT (Gtdt != NULL);
+  ASSERT (GTBlockInfo != NULL);
+
+  GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)Gtdt +
+              GTBlockOffset);
+
+  for (idx = 0; idx < BlockTimerCount; idx++) {
+    DEBUG ((DEBUG_INFO, "GTDT: GTBlock[%d] = 0x%p\n",
+      idx,
+      GTBlock
+      ));
+
+    GTBlock->Type = EFI_ACPI_6_1_GTDT_GT_BLOCK;
+    GTBlock->Length = sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) +
+                        (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
+                          GTBlockInfo[idx].GTBlockTimerFrameCount);
+
+    GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;
+    GTBlock->CntCtlBase = GTBlockInfo[idx].GTBlockPhysicalAddress;
+    GTBlock->GTBlockTimerCount = GTBlockInfo[idx].GTBlockTimerFrameCount;
+    GTBlock->GTBlockTimerOffset =
+      sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE);
+
+    GtBlockFrame = (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE*)
+      ((UINT8*)GTBlock + GTBlock->GTBlockTimerOffset);
+
+    // Add GT Block Timer frames
+    Status = AddGTBlockTimerFrames (
+               GtBlockFrame,
+               GTBlockInfo[idx].GTBlockTimerFrameList,
+               GTBlockInfo[idx].GTBlockTimerFrameCount
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",
+        Status
+        ));
+      return Status;
+    }
+
+    // Next GTBlock
+    GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)GTBlock +
+                GTBlock->Length);
+  }// for
+  return EFI_SUCCESS;
+}
+
+/** Construct the GTDT ACPI table.
+
+    Called by the Dynamic Table Manager, this function invokes the
+    Confguration Manager protocol interface to get the required hardware
+    information for generating the ACPI table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildGtdtTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                                      Status;
+  UINTN                                           TableSize;
+  UINTN                                           PlatformTimerCount = 0;
+  UINTN                                           WatchdogCount;
+  UINTN                                           BlockTimerCount;
+  CM_ARM_GENERIC_WATCHDOG_INFO                  * WatchdogInfoList = NULL;
+  CM_ARM_GTBLOCK_INFO                           * GTBlockInfo = NULL;
+  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * Gtdt;
+  UINTN                                           idx;
+  UINTN                                           GTBlockOffset;
+  UINTN                                           WatchdogOffset = 0;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+  Status = GetEArmObjPlatformGTBlockInfo (
+             CfgMgrProtocol,
+             &GTBlockInfo,
+             &BlockTimerCount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to Get Platform GT Block Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = GetEArmObjPlatformGenericWatchdogInfo (
+             CfgMgrProtocol,
+             &WatchdogInfoList,
+             &WatchdogCount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",
+    BlockTimerCount,
+    WatchdogCount
+    ));
+
+  // Calculate the GTDT Table Size
+  TableSize = sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
+  if (BlockTimerCount != 0) {
+    GTBlockOffset = TableSize;
+    PlatformTimerCount += BlockTimerCount;
+    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) *
+                  BlockTimerCount);
+
+    for (idx = 0; idx < BlockTimerCount; idx++) {
+      if (GTBlockInfo[idx].GTBlockTimerFrameCount > 8) {
+        Status = EFI_INVALID_PARAMETER;
+        DEBUG ((
+          DEBUG_ERROR,
+          "GTDT: GTBockFrameCount cannot be more than 8." \
+          " GTBockFrameCount = %d, Status = %r\n",
+          GTBlockInfo[idx].GTBlockTimerFrameCount,
+          Status
+          ));
+        goto error_handler;
+      }
+      TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
+        GTBlockInfo[idx].GTBlockTimerFrameCount);
+    }
+
+    DEBUG ((
+      DEBUG_INFO,
+      "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
+      GTBlockOffset,
+      PlatformTimerCount
+      ));
+  }
+
+  if (WatchdogCount != 0) {
+    WatchdogOffset = TableSize;
+    PlatformTimerCount += WatchdogCount;
+    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE) *
+                  WatchdogCount);
+    DEBUG ((
+      DEBUG_INFO,
+      "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
+      WatchdogOffset,
+      PlatformTimerCount
+      ));
+  }
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Gtdt = (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE*)*Table;
+  DEBUG ((
+    DEBUG_INFO,
+    "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",
+    Gtdt,
+    TableSize
+    ));
+
+  Status = AddAcpiHeader (CfgMgrProtocol, This, &Gtdt->Header, TableSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = AddGenericTimerInfo (
+             CfgMgrProtocol,
+             Gtdt,
+             PlatformTimerCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  if (BlockTimerCount != 0) {
+    Status = AddGTBlockList (
+               Gtdt,
+               GTBlockOffset,
+               GTBlockInfo,
+               BlockTimerCount
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",
+        Status
+        ));
+      goto error_handler;
+    }
+  }
+
+  if (WatchdogCount != 0) {
+    AddGenericWatchdogList (
+      Gtdt,
+      WatchdogOffset,
+      WatchdogInfoList,
+      WatchdogCount
+      );
+  }
+
+  return Status;
+
+error_handler:
+  if (*Table != NULL) {
+    FreePool (*Table);
+    *Table = NULL;
+  }
+  return Status;
+}
+
+/** Free any resources allocated for constructing the GTDT.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS           The resources were freed successfully.
+    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+
+*/
+STATIC
+EFI_STATUS
+FreeGtdtTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+)
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((Table == NULL) || (*Table == NULL)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));
+    ASSERT ((Table != NULL) && (*Table != NULL));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (*Table);
+  *Table = NULL;
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the GTDT Table Generator revision.
+*/
+#define GTDT_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the GTDT Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR GtdtGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_GTDT),
+  // Generator Description
+  L"ACPI.STD.GTDT.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  GTDT_GENERATOR_REVISION,
+  // Build Table function
+  BuildGtdtTable,
+  // Free Resource function
+  FreeGtdtTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiGtdtLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&GtdtGenerator);
+  DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiGtdtLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&GtdtGenerator);
+  DEBUG ((DEBUG_INFO, "GTDT: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..cce440d91f50d8a7ac429acb6be40d4a6ac4e230
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
@@ -0,0 +1,732 @@
+/** @file
+  MADT Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard MADT Generator
+
+    Generates the ACPI MADT Table as specified by the
+    ACPI 6.1 Specification - January, 2016.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjGicCInfo
+  - EArmObjGicDInfo
+  - EArmObjGicMsiFrameInfo (OPTIONAL)
+  - EArmObjGicRedistributorInfo (OPTIONAL)
+  - EArmObjGicItsInfo (OPTIONAL)
+*/
+
+/** This macro expands to a function that retrieves the GIC
+    CPU interface Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicCInfo,
+  CM_ARM_GICC_INFO
+  );
+
+/** This macro expands to a function that retrieves the GIC
+    Distributor Information from the Configuration Manager.
+*/
+
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicDInfo,
+  CM_ARM_GICD_INFO
+  );
+
+/** This macro expands to a function that retrieves the GIC
+    MSI Frame Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicMsiFrameInfo,
+  CM_ARM_GIC_MSI_FRAME_INFO
+  );
+
+/** This macro expands to a function that retrieves the GIC
+    Redistributor Information from the Configuration Manager.
+*/
+
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicRedistributorInfo,
+  CM_ARM_GIC_REDIST_INFO
+  );
+
+/** This macro expands to a function that retrieves the GIC
+    Interrupt Translation Serice Information from the
+    Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicItsInfo,
+  CM_ARM_GIC_ITS_INFO
+  );
+
+/** This function updates the GIC CPU Interface Information in the
+    EFI_ACPI_6_1_GIC_STRUCTURE structure.
+
+    @param [in]  Gicc      Pointer to GIC CPU Interface structure.
+    @param [in]  GicCInfo  Pointer to the GIC CPU Interface Information.
+*/
+STATIC
+VOID
+AddGICC (
+  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * CONST Gicc,
+  IN  CONST CM_ARM_GICC_INFO      * CONST GicCInfo
+  )
+{
+  ASSERT (Gicc != NULL);
+  ASSERT (GicCInfo != NULL);
+
+  /* UINT8 Type */
+  Gicc->Type = EFI_ACPI_6_1_GIC;
+  /* UINT8 Length */
+  Gicc->Length = sizeof (EFI_ACPI_6_1_GIC_STRUCTURE);
+  /* UINT16 Reserved */
+  Gicc->Reserved = EFI_ACPI_RESERVED_WORD;
+
+  /* UINT32 CPUInterfaceNumber */
+  Gicc->CPUInterfaceNumber = GicCInfo->CPUInterfaceNumber;
+  /* UINT32 AcpiProcessorUid */
+  Gicc->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;
+  /* UINT32 Flags */
+  Gicc->Flags = GicCInfo->Flags;
+  /* UINT32 ParkingProtocolVersion */
+  Gicc->ParkingProtocolVersion = GicCInfo->ParkingProtocolVersion;
+  /* UINT32 PerformanceInterruptGsiv */
+  Gicc->PerformanceInterruptGsiv = GicCInfo->PerformanceInterruptGsiv;
+  /* UINT64 ParkedAddress */
+  Gicc->ParkedAddress = GicCInfo->ParkedAddress;
+
+  /* UINT64 PhysicalBaseAddress */
+  Gicc->PhysicalBaseAddress = GicCInfo->PhysicalBaseAddress;
+  /* UINT64 GICV */
+  Gicc->GICV = GicCInfo->GICV;
+  /* UINT64 GICH */
+  Gicc->GICH = GicCInfo->GICH;
+
+  /* UINT32 VGICMaintenanceInterrupt */
+  Gicc->VGICMaintenanceInterrupt = GicCInfo->VGICMaintenanceInterrupt;
+  /* UINT64 GICRBaseAddress */
+  Gicc->GICRBaseAddress = GicCInfo->GICRBaseAddress;
+
+  /* UINT64 MPIDR */
+  Gicc->MPIDR = GicCInfo->MPIDR;
+  /* UINT8 ProcessorPowerEfficiencyClass */
+  Gicc->ProcessorPowerEfficiencyClass =
+    GicCInfo->ProcessorPowerEfficiencyClass;
+  /* UINT8 Reserved2[3] */
+  Gicc->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
+  Gicc->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
+  Gicc->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
+}
+
+/** Add the GIC CPU Interface Information to the MADT Table.
+
+    @param [in]  Gicc      Pointer to GIC CPU Interface
+                            structure list.
+    @param [in]  GicCInfo  Pointer to the GIC CPU
+                            Information list.
+    @param [in]  GicCCount Count of GIC CPU Interfaces.
+*/
+STATIC
+VOID
+AddGICCList (
+  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * Gicc,
+  IN  CONST CM_ARM_GICC_INFO      * GicCInfo,
+  IN  CONST UINTN                   GicCCount
+  )
+{
+  UINTN  idx;
+
+  ASSERT (Gicc != NULL);
+  ASSERT (GicCInfo != NULL);
+
+  for (idx = 0; idx < GicCCount; idx++) {
+    AddGICC (Gicc++, GicCInfo++);
+  }
+}
+
+/** Update the GIC Distributor Information in the MADT Table.
+
+    @param [in]  Gicd      Pointer to GIC Distributor structure.
+    @param [in]  GicDInfo  Pointer to the GIC Distributor Information.
+*/
+STATIC
+VOID
+AddGICD (
+  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * CONST Gicd,
+  CONST CM_ARM_GICD_INFO                  * CONST GicDInfo
+)
+{
+  ASSERT (Gicd != NULL);
+  ASSERT (GicDInfo != NULL);
+
+  /* UINT8 Type */
+  Gicd->Type = EFI_ACPI_6_1_GICD;
+  /* UINT8 Length */
+  Gicd->Length = sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE);
+  /* UINT16 Reserved */
+  Gicd->Reserved1 = EFI_ACPI_RESERVED_WORD;
+  /* UINT32 Identifier */
+  Gicd->GicId = GicDInfo->GicId;
+  /* UINT64 PhysicalBaseAddress */
+  Gicd->PhysicalBaseAddress = GicDInfo->PhysicalBaseAddress;
+  /* UINT32 VectorBase */
+  Gicd->SystemVectorBase = GicDInfo->SystemVectorBase;
+  /* UINT8  GicVersion */
+  Gicd->GicVersion = GicDInfo->GicVersion;
+  /* UINT8  Reserved2[3] */
+  Gicd->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
+  Gicd->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
+  Gicd->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
+}
+
+/** Add the GIC Distributor Information to the MADT Table.
+
+    @param [in]  Gicd      Pointer to GIC Distributor structure list.
+    @param [in]  GicDInfo  Pointer to the GIC Distributor Information list.
+    @param [in]  GicDCount Count of GIC Distributors.
+*/
+STATIC
+VOID
+AddGICDList (
+  IN  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * Gicd,
+  IN  CONST CM_ARM_GICD_INFO                  * GicDInfo,
+  IN  CONST UINTN                               GicDCount
+  )
+{
+  UINTN  idx;
+
+  ASSERT (Gicd != NULL);
+  ASSERT (GicDInfo != NULL);
+
+  for (idx = 0; idx < GicDCount; idx++) {
+    AddGICD (Gicd++, GicDInfo++);
+  }
+}
+
+/** Update the GIC MSI Frame Information.
+
+    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure.
+    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame Information.
+*/
+STATIC
+VOID
+AddGICMsiFrame (
+  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * CONST GicMsiFrame,
+  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * CONST GicMsiFrameInfo
+)
+{
+  ASSERT (GicMsiFrame != NULL);
+  ASSERT (GicMsiFrameInfo != NULL);
+
+  GicMsiFrame->Type = EFI_ACPI_6_1_GIC_MSI_FRAME;
+  GicMsiFrame->Length = sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE);
+  GicMsiFrame->Reserved1 = EFI_ACPI_RESERVED_WORD;
+  GicMsiFrame->GicMsiFrameId = GicMsiFrameInfo->GicMsiFrameId;
+  GicMsiFrame->PhysicalBaseAddress = GicMsiFrameInfo->PhysicalBaseAddress;
+
+  GicMsiFrame->Flags = GicMsiFrameInfo->Flags;
+  GicMsiFrame->SPICount = GicMsiFrameInfo->SPICount;
+  GicMsiFrame->SPIBase = GicMsiFrameInfo->SPIBase;
+}
+
+/** Add the GIC MSI Frame Information to the MADT Table.
+
+    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure list.
+    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame info list.
+    @param [in]  GicMsiFrameCount Count of GIC MSI Frames.
+*/
+STATIC
+VOID
+AddGICMsiFrameInfoList (
+  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * GicMsiFrame,
+  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * GicMsiFrameInfo,
+  IN  CONST UINTN                             GicMsiFrameCount
+)
+{
+  UINTN  idx;
+
+  ASSERT (GicMsiFrame != NULL);
+  ASSERT (GicMsiFrameInfo != NULL);
+
+  for (idx = 0; idx < GicMsiFrameCount; idx++) {
+    AddGICMsiFrame (GicMsiFrame++, GicMsiFrameInfo++);
+  }
+}
+
+/** Update the GIC Redistributor Information.
+
+    @param [in]  Gicr                 Pointer to GIC Redistributor structure.
+    @param [in]  GicRedisributorInfo  Pointer to the GIC Redistributor Info.
+*/
+STATIC
+VOID
+AddGICRedistributor (
+  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * CONST Gicr,
+  IN  CONST CM_ARM_GIC_REDIST_INFO  * CONST GicRedisributorInfo
+  )
+{
+  ASSERT (Gicr != NULL);
+  ASSERT (GicRedisributorInfo != NULL);
+
+  Gicr->Type = EFI_ACPI_6_1_GICR;
+  Gicr->Length = sizeof (EFI_ACPI_6_1_GICR_STRUCTURE);
+  Gicr->Reserved = EFI_ACPI_RESERVED_WORD;
+  Gicr->DiscoveryRangeBaseAddress =
+    GicRedisributorInfo->DiscoveryRangeBaseAddress;
+  Gicr->DiscoveryRangeLength = GicRedisributorInfo->DiscoveryRangeLength;
+}
+
+/** Add the GIC Redistributor Information to the MADT Table.
+
+    @param [in]  Gicr      Pointer to GIC Redistributor structure list.
+    @param [in]  GicRInfo  Pointer to the GIC Distributor info list.
+    @param [in]  GicRCount Count of GIC Distributors.
+*/
+STATIC
+VOID
+AddGICRedistributorList (
+  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * Gicr,
+  IN  CONST CM_ARM_GIC_REDIST_INFO  * GicRInfo,
+  IN  CONST UINTN                     GicRCount
+)
+{
+  UINTN  idx;
+
+  ASSERT (Gicr != NULL);
+  ASSERT (GicRInfo != NULL);
+
+  for (idx = 0; idx < GicRCount; idx++) {
+    AddGICRedistributor (Gicr++, GicRInfo++);
+  }
+}
+
+/** Update the GIC Interrupt Translation Service Information
+
+    @param [in]  GicIts      Pointer to GIC ITS structure.
+    @param [in]  GicItsInfo  Pointer to the GIC ITS Information.
+*/
+STATIC
+VOID
+AddGICInterruptTranslationService (
+  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * CONST GicIts,
+  IN  CONST CM_ARM_GIC_ITS_INFO       * CONST GicItsInfo
+)
+{
+  ASSERT (GicIts != NULL);
+  ASSERT (GicItsInfo != NULL);
+
+  GicIts->Type = EFI_ACPI_6_1_GIC_ITS;
+  GicIts->Length = sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE);
+  GicIts->Reserved = EFI_ACPI_RESERVED_WORD;
+  GicIts->GicItsId = GicItsInfo->GicItsId;
+  GicIts->PhysicalBaseAddress = GicItsInfo->PhysicalBaseAddress;
+  GicIts->Reserved2 = EFI_ACPI_RESERVED_DWORD;
+}
+
+/** Add the GIC Interrupt Translation Service Information
+    to the MADT Table.
+
+    @param [in]  GicIts       Pointer to GIC ITS structure list.
+    @param [in]  GicItsInfo   Pointer to the GIC ITS list.
+    @param [in]  GicItsCount  Count of GIC ITS.
+*/
+STATIC
+VOID
+AddGICItsList (
+  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * GicIts,
+  IN  CONST CM_ARM_GIC_ITS_INFO       * GicItsInfo,
+  IN  CONST UINTN                       GicItsCount
+)
+{
+  UINTN  idx;
+
+  ASSERT (GicIts != NULL);
+  ASSERT (GicItsInfo != NULL);
+
+  for (idx = 0; idx < GicItsCount; idx++) {
+    AddGICInterruptTranslationService (GicIts++, GicItsInfo++);
+  }
+}
+
+/** Construct the MADT ACPI table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildMadtTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                   Status;
+  UINTN                        TableSize;
+  UINTN                        GicCCount;
+  UINTN                        GicDCount;
+  UINTN                        GicMSICount;
+  UINTN                        GicRedistCount;
+  UINTN                        GicItsCount;
+  CM_ARM_GICC_INFO           * GicCInfo = NULL;
+  CM_ARM_GICD_INFO           * GicDInfo = NULL;
+  CM_ARM_GIC_MSI_FRAME_INFO  * GicMSIInfo = NULL;
+  CM_ARM_GIC_REDIST_INFO     * GicRedistInfo = NULL;
+  CM_ARM_GIC_ITS_INFO        * GicItsInfo = NULL;
+  UINTN                        GicCOffset;
+  UINTN                        GicDOffset;
+  UINTN                        GicMSIOffset;
+  UINTN                        GicRedistOffset;
+  UINTN                        GicItsOffset;
+
+  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER  * Madt;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+
+  Status = GetEArmObjGicCInfo (CfgMgrProtocol, &GicCInfo, &GicCCount);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GICC Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  if (GicCCount == 0) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: GIC CPU Interface information not provided.\n"
+      ));
+    ASSERT (GicCCount != 0);
+    Status = EFI_INVALID_PARAMETER;
+    goto error_handler;
+  }
+
+  Status = GetEArmObjGicDInfo (CfgMgrProtocol, &GicDInfo, &GicDCount);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GICD Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  if (GicDCount == 0) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: GIC Distributor information not provided.\n"
+      ));
+    ASSERT (GicDCount != 0);
+    Status = EFI_INVALID_PARAMETER;
+    goto error_handler;
+  }
+
+  Status = GetEArmObjGicMsiFrameInfo (
+             CfgMgrProtocol,
+             &GicMSIInfo,
+             &GicMSICount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GIC MSI Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = GetEArmObjGicRedistributorInfo (
+             CfgMgrProtocol,
+             &GicRedistInfo,
+             &GicRedistCount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GIC Redistributor Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = GetEArmObjGicItsInfo (
+             CfgMgrProtocol,
+             &GicItsInfo,
+             &GicItsCount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GIC ITS Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  TableSize = sizeof (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
+
+  GicCOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GIC_STRUCTURE) * GicCCount);
+
+  GicDOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE) * GicDCount);
+
+  GicMSIOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE) * GicMSICount);
+
+  GicRedistOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GICR_STRUCTURE) * GicRedistCount);
+
+  GicItsOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE) * GicItsCount);
+
+  // Allocate the Buffer for MADT table
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to allocate memory for MADT Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Madt = (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER*)*Table;
+
+  DEBUG ((
+    DEBUG_INFO,
+    "MADT: Madt = 0x%p TableSize = 0x%x\n",
+    Madt,
+    TableSize
+    ));
+
+  Status = AddAcpiHeader (CfgMgrProtocol, This, &Madt->Header, TableSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  AddGICCList (
+    (EFI_ACPI_6_1_GIC_STRUCTURE*)((UINT8*)Madt + GicCOffset),
+    GicCInfo,
+    GicCCount
+    );
+
+  AddGICDList (
+    (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE*)((UINT8*)Madt + GicDOffset),
+    GicDInfo,
+    GicDCount
+    );
+
+  if (GicMSICount != 0) {
+    AddGICMsiFrameInfoList (
+      (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE*)((UINT8*)Madt + GicMSIOffset),
+      GicMSIInfo,
+      GicMSICount
+      );
+  }
+
+  if (GicRedistCount != 0) {
+    AddGICRedistributorList (
+      (EFI_ACPI_6_1_GICR_STRUCTURE*)((UINT8*)Madt + GicRedistOffset),
+      GicRedistInfo,
+      GicRedistCount
+      );
+  }
+
+  if (GicItsCount != 0) {
+    AddGICItsList (
+      (EFI_ACPI_6_1_GIC_ITS_STRUCTURE*)((UINT8*)Madt + GicItsOffset),
+      GicItsInfo,
+      GicItsCount
+      );
+  }
+
+  return EFI_SUCCESS;
+
+error_handler:
+  if (*Table != NULL) {
+    FreePool (*Table);
+    *Table = NULL;
+  }
+  return Status;
+}
+
+/** Free any resources allocated for constructing the MADT
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS           The resources were freed successfully.
+    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+*/
+STATIC
+EFI_STATUS
+FreeMadtTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((Table == NULL) || (*Table == NULL)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: MADT: Invalid Table Pointer\n"));
+    ASSERT ((Table != NULL) && (*Table != NULL));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (*Table);
+  *Table = NULL;
+  return EFI_SUCCESS;
+}
+
+/** The MADT Table Generator revision.
+*/
+#define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the MADT Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR MadtGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MADT),
+  // Generator Description
+  L"ACPI.STD.MADT.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  MADT_GENERATOR_REVISION,
+  // Build Table function
+  BuildMadtTable,
+  // Free Resource function
+  FreeMadtTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiMadtLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&MadtGenerator);
+  DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiMadtLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&MadtGenerator);
+  DEBUG ((DEBUG_INFO, "MADT: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..c023b413797379562f20ae97db9e2f2ca6d8758c
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
@@ -0,0 +1,336 @@
+/** @file
+  MCFG Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard MCFG Generator
+
+    Generates the MCFG Table as specified by the PCI Firmware
+    Specification - Revision 3.2, January 26, 2015.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjPciConfigSpaceInfo
+*/
+
+#pragma pack(1)
+
+/** This typedef is used to shorten the name of the MCFG Table
+    header structure.
+*/
+typedef
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER
+  MCFG_TABLE;
+
+/** This typedef is used to shorten the name of the Enhanced
+    Configuration Space address structure.
+*/
+typedef
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE
+  MCFG_CFG_SPACE_ADDR;
+
+#pragma pack()
+
+/** Retrieve the PCI Configuration Space Information.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPciConfigSpaceInfo,
+  CM_ARM_PCI_CONFIG_SPACE_INFO
+  );
+
+/** Add the PCI Enhanced Configuration Space Information to the MCFG Table.
+
+    @param [in]  Mcfg                Pointer to MCFG Table.
+    @param [in]  PciCfgSpaceOffset   Offset for the PCI Configuration Space
+                                     Info structure in the MCFG Table.
+    @param [in]  PciCfgSpaceInfoList Pointer to the PCI Configuration Space
+                                     Info List.
+    @param [in]  PciCfgSpaceCount    Count of PCI Configuration Space Info.
+*/
+STATIC
+VOID
+AddPciConfigurationSpaceList (
+  IN       MCFG_TABLE                   * CONST Mcfg,
+  IN CONST UINTN                                PciCfgSpaceOffset,
+  IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * CONST PciCfgSpaceInfoList,
+  IN CONST UINTN                                PciCfgSpaceCount
+)
+{
+  UINTN                  idx;
+  MCFG_CFG_SPACE_ADDR  * PciCfgSpace;
+
+  ASSERT (Mcfg != NULL);
+  ASSERT (PciCfgSpaceInfoList != NULL);
+
+  PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8*)Mcfg + PciCfgSpaceOffset);
+  for (idx = 0; idx < PciCfgSpaceCount; idx++) {
+    // Add PCI Configuration Space entry
+    PciCfgSpace[idx].BaseAddress = PciCfgSpaceInfoList[idx].BaseAddress;
+    PciCfgSpace[idx].PciSegmentGroupNumber =
+      PciCfgSpaceInfoList[idx].PciSegmentGroupNumber;
+    PciCfgSpace[idx].StartBusNumber = PciCfgSpaceInfoList[idx].StartBusNumber;
+    PciCfgSpace[idx].EndBusNumber = PciCfgSpaceInfoList[idx].EndBusNumber;
+    PciCfgSpace[idx].Reserved = EFI_ACPI_RESERVED_DWORD;
+  }
+}
+
+/** Construct the MCFG ACPI table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildMcfgTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           TableSize;
+  UINTN                           ConfigurationSpaceCount;
+  CM_ARM_PCI_CONFIG_SPACE_INFO  * PciConfigSpaceInfoList = NULL;
+  MCFG_TABLE                    * Mcfg;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+  Status = GetEArmObjPciConfigSpaceInfo (
+              CfgMgrProtocol,
+              &PciConfigSpaceInfoList,
+              &ConfigurationSpaceCount
+              );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "ERROR: MCFG: Failed to get PCI Configuration Space Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+  ASSERT (ConfigurationSpaceCount != 0);
+
+  DEBUG ((
+    DEBUG_INFO,
+    "MCFG: Configuration Space Count = %d\n",
+    ConfigurationSpaceCount
+    ));
+
+  // Calculate the MCFG Table Size
+  TableSize = sizeof (MCFG_TABLE) +
+    ((sizeof (MCFG_CFG_SPACE_ADDR) * ConfigurationSpaceCount));
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Mcfg = (MCFG_TABLE*)*Table;
+  DEBUG ((
+    DEBUG_INFO,
+    "MCFG: Mcfg = 0x%p TableSize = 0x%x\n",
+    Mcfg,
+    TableSize
+    ));
+
+  Status = AddAcpiHeader (CfgMgrProtocol, This, &Mcfg->Header, TableSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MCFG: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Mcfg->Reserved = EFI_ACPI_RESERVED_QWORD;
+
+  AddPciConfigurationSpaceList (
+    Mcfg,
+    sizeof (MCFG_TABLE),
+    PciConfigSpaceInfoList,
+    ConfigurationSpaceCount
+    );
+
+  return EFI_SUCCESS;
+
+error_handler:
+  if (*Table != NULL) {
+    FreePool (*Table);
+    *Table = NULL;
+  }
+  return Status;
+}
+
+/** Free any resources allocated for constructing the MCFG
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS           The resources were freed successfully.
+    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+*/
+STATIC
+EFI_STATUS
+FreeMcfgTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((Table == NULL) || (*Table == NULL)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: MCFG: Invalid Table Pointer\n"));
+    ASSERT ((Table != NULL) && (*Table != NULL));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (*Table);
+  *Table = NULL;
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the MCFG Table Generator revision.
+*/
+#define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the MCFG Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR McfgGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MCFG),
+  // Generator Description
+  L"ACPI.STD.MCFG.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  MCFG_GENERATOR_REVISION,
+  // Build Table function
+  BuildMcfgTable,
+  // Free Resource function
+  FreeMcfgTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiMcfgLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&McfgGenerator);
+  DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiMcfgLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&McfgGenerator);
+  DEBUG ((DEBUG_INFO, "MCFG: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..aaca70cba0a1a08c0730bd84134c1b8722edd7af
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
@@ -0,0 +1,177 @@
+/** @file
+  MCFG Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** Construct the ACPI table using the ACPI table data provided.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildRawTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableData != NULL);
+
+  if (AcpiTableInfo->AcpiTableData == NULL) {
+    *Table = NULL;
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Table = AcpiTableInfo->AcpiTableData;
+
+  return EFI_SUCCESS;
+}
+
+/** Free any resources allocated for constructing the ACPI table.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS         The resources were freed successfully.
+
+*/
+STATIC
+EFI_STATUS
+FreeRawTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the Raw Generator revision.
+*/
+#define RAW_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the Raw Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR RawGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RAW),
+  // Generator Description
+  L"ACPI.STD.RAW.GENERATOR",
+  // ACPI Table Signature - Unused
+  0,
+  // ACPI Table Revision - Unused
+  0,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  RAW_GENERATOR_REVISION,
+  // Build Table function
+  BuildRawTable,
+  // Free Resource function
+  FreeRawTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiRawLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&RawGenerator);
+  DEBUG ((DEBUG_INFO, "RAW: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+
+EFI_STATUS
+EFIAPI
+AcpiRawLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&RawGenerator);
+  DEBUG ((DEBUG_INFO, "RAW: UnRegister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..ccfbcf088cfaec1e4f9f3738f5fe09a65c93bc9e
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
@@ -0,0 +1,323 @@
+/** @file
+  SPCR Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard SPCR Table Generator
+
+    Generates the ACPI SPCR Table for ARM UARTs as specified by
+    the Microsoft Serial Port Console Redirection Table
+    Specification - Version 1.03 - August 10, 2015.
+
+    Constructs the SPCR table for PL011 or SBSA UART peripherals.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjSerialConsolePortInfo
+
+NOTE: This implementation ignores the possibility that the Serial settings may
+      be modified from the UEFI Shell.  A more complex handler would be needed
+      to (e.g.) recover serial port settings from the UART, or non-volatile
+      storage.
+*/
+
+#pragma pack(1)
+
+/** This macro defines the no flow control option.
+*/
+#define SPCR_FLOW_CONTROL_NONE           0
+
+/**A template for generating the SPCR Table.
+
+  Note: fields marked "{Template}" will be updated dynamically.
+*/
+STATIC
+EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = {
+  ACPI_HEADER (
+    EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,
+    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
+    ),
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_PL011_UART,
+  {
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE
+  },
+  ARM_GAS32 (0), // {Template}: Serial Port Base Address
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC,
+  0, // Not used on ARM
+  0, // {Template}: Serial Port Interrupt
+  0, // {Template}: Serial Port Baudrate
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
+  SPCR_FLOW_CONTROL_NONE,
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI,
+  EFI_ACPI_RESERVED_BYTE,
+  0xFFFF,
+  0xFFFF,
+  0x00,
+  0x00,
+  0x00,
+  0x00000000,
+  0x00,
+  EFI_ACPI_RESERVED_DWORD
+};
+
+#pragma pack()
+
+/** This macro expands to a function that retrieves the Serial
+    Port Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjSerialConsolePortInfo,
+  CM_ARM_SERIAL_PORT_INFO
+  )
+
+/** Construct the SPCR ACPI table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_UNSUPPORTED       An unsupported baudrate was specified by the
+                                  Confguration Manager.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSpcrTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                 Status;
+  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+
+  Status = GetEArmObjSerialConsolePortInfo (
+             CfgMgrProtocol,
+             &SerialPortInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));
+  DEBUG ((DEBUG_INFO, "  UART Base  = 0x%lx\n", SerialPortInfo->BaseAddress));
+  DEBUG ((DEBUG_INFO, "  Clock      = %d\n", SerialPortInfo->Clock));
+  DEBUG ((DEBUG_INFO, "  Baudrate   = %ld\n", SerialPortInfo->BaudRate));
+  DEBUG ((DEBUG_INFO, "  Interrupt  = %d\n", SerialPortInfo->Interrupt));
+
+  Status = AddAcpiHeader (
+             CfgMgrProtocol,
+             This,
+             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr,
+             sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE)
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
+  AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;
+
+  switch (SerialPortInfo->BaudRate) {
+    case 9600:
+      AcpiSpcr.BaudRate =
+        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;
+      break;
+    case 19200:
+      AcpiSpcr.BaudRate =
+        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;
+      break;
+    case 57600:
+      AcpiSpcr.BaudRate =
+        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;
+      break;
+    case 115200:
+      AcpiSpcr.BaudRate =
+        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;
+      break;
+    default:
+      Status = EFI_UNSUPPORTED;
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
+        SerialPortInfo->BaudRate,
+        Status
+        ));
+      goto error_handler;
+  } // switch
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
+
+error_handler:
+  return Status;
+}
+
+/** Free any resources allocated for constructing the SPCR.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS         The resources were freed successfully.
+*/
+STATIC
+EFI_STATUS
+FreeSpcrTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the SPCR Table Generator revision.
+*/
+#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the SPCR Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR SpcrGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_SPCR),
+  // Generator Description
+  L"ACPI.STD.SPCR.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  SPCR_GENERATOR_REVISION,
+  // Build Table function
+  BuildSpcrTable,
+  // Free Resource function
+  FreeSpcrTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiSpcrLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&SpcrGenerator);
+  DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiSpcrLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&SpcrGenerator);
+  DEBUG ((DEBUG_INFO, "SPCR: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
new file mode 100644
index 0000000000000000000000000000000000000000..8dc1d6b6f7c6eb71bd0ab16b690a9f5b4855dc3d
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
@@ -0,0 +1,165 @@
+/** @file
+  Table Helper
+
+Copyright (c) 2017, ARM Limited. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
+    object from the Configuration Manager.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
+                                interface.
+    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
+                                object structure.
+
+    @retval EFI_SUCCESS           The object is returned.
+    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
+    @retval EFI_NOT_FOUND         The requested Object is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size.
+*/
+EFI_STATUS
+EFIAPI
+GetCgfMgrInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST  CfgMgrProtocol,
+  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **        CfgMfrInfo
+  )
+{
+  EFI_STATUS         Status;
+  CM_OBJ_DESCRIPTOR  CmObjectDesc;
+
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (CfgMfrInfo != NULL);
+
+  *CfgMfrInfo = NULL;
+  Status = CfgMgrProtocol->GetObject (
+    CfgMgrProtocol,
+    CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
+    &CmObjectDesc
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to Get Configuration Manager Info. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  ASSERT (CmObjectDesc.Size >= sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO));
+  if (CmObjectDesc.Size < sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: EStdObjCfgMgrInfo: Buffer too small, size  = 0x%x\n",
+      CmObjectDesc.Size
+      ));
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  *CfgMfrInfo = (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO*)CmObjectDesc.Data;
+  return Status;
+}
+
+/** The AddAcpiHeader function updates the ACPI header structure pointed by
+    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
+    Manager protocol to obtain any information required for constructing the
+    header.
+
+    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
+                                   protocol interface.
+    @param [in]     Generator      Pointer to the ACPI table Generator.
+    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
+                                   updated.
+    @param [in]     Length         Length of the ACPI table.
+
+    @retval EFI_SUCCESS           The ACPI table is updated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object information is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+EFI_STATUS
+EFIAPI
+AddAcpiHeader (
+  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
+  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
+  IN      CONST UINT32                                      Length
+  )
+{
+  EFI_STATUS                               Status;
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
+
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Generator != NULL);
+  ASSERT (AcpiHeader != NULL);
+  ASSERT (Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+
+  if ((CfgMgrProtocol == NULL) ||
+      (Generator == NULL) ||
+      (AcpiHeader == NULL) ||
+      (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))
+    ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  /* UINT32  Signature */
+  AcpiHeader->Signature = Generator->AcpiTableSignature;
+  /* UINT32  Length */
+  AcpiHeader->Length = Length;
+  /* UINT8   Revision */
+  AcpiHeader->Revision = Generator->AcpiTableRevision;
+  /* UINT8   Checksum */
+  AcpiHeader->Checksum = 0;
+
+  /* UINT8   OemId[6] */
+  CopyMem (AcpiHeader->OemId, CfgMfrInfo->OemId, sizeof (AcpiHeader->OemId));
+
+  /* UINT64  OemTableId */
+  AcpiHeader->OemTableId = Generator->CreatorId; // Generator->GeneratorID;
+  AcpiHeader->OemTableId <<= 32;
+  AcpiHeader->OemTableId |= Generator->AcpiTableSignature;
+
+  /* UINT32  OemRevision */
+  AcpiHeader->OemRevision = CfgMfrInfo->Revision;
+
+  /* UINT32  CreatorId */
+  AcpiHeader->CreatorId = Generator->CreatorId;
+  /* UINT32  CreatorRevision */
+  AcpiHeader->CreatorRevision = Generator->CreatorRevision;
+
+  Status = EFI_SUCCESS;
+error_handler:
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
new file mode 100644
index 0000000000000000000000000000000000000000..79cf0f290ddb79499c71d6c553b420418dec50f1
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
@@ -0,0 +1,227 @@
+/** @file
+  ACPI Table Factory
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Std - Standard
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include "DynamicTableFactory.h"
+
+extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
+
+/** Return a pointer to the ACPI table generator.
+
+    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  GeneratorId  The ACPI table generator ID for the
+                              requested generator.
+    @param [out] Generator    Pointer to the requested ACPI table
+                              generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+GetAcpiTableGenerator (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
+  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
+  )
+{
+  UINT16                           TableId;
+  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
+
+  ASSERT (This != NULL);
+
+  FactoryInfo = This->TableFactoryInfo;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_ACPI (GeneratorId)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not ACPI\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Generator = NULL;
+  TableId = GET_TABLE_ID (GeneratorId);
+  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
+    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (FactoryInfo->StdAcpiTableGeneratorList[TableId] != NULL) {
+      *Generator = FactoryInfo->StdAcpiTableGeneratorList[TableId];
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (FactoryInfo->CustomAcpiTableGeneratorList[TableId] != NULL) {
+      *Generator = FactoryInfo->CustomAcpiTableGeneratorList[TableId];
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/** Register ACPI table factory generator.
+
+    The ACPI table factory maintains a list of the Standard and OEM ACPI
+    table generators.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+
+    @retval EFI_SUCCESS           The Generator was registered
+                                  successfully.
+    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
+                                  the Generator pointer is NULL.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
+                                  already registered.
+*/
+EFI_STATUS
+EFIAPI
+RegisterAcpiTableGenerator (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
+  )
+{
+  UINT16  TableId;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: ACPI register - Invalid Generator\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: ACPI register - Generator" \
+      " Type is not ACPI\n"
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
+
+  TableId = GET_TABLE_ID (Generator->GeneratorID);
+  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
+    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] == NULL) {
+      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = Generator;
+    } else {
+      return EFI_ALREADY_STARTED;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] == NULL) {
+      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = Generator;
+    } else {
+      return EFI_ALREADY_STARTED;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/** Unregister ACPI generator.
+
+    This function is called by the ACPI table generator to unregister itself
+    from the ACPI table factory.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The generator is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+UnRegisterAcpiTableGenerator (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
+  )
+{
+  UINT16  TableId;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: ACPI un-register - Invalid Generator\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: ACPI un-register - Generator" \
+      " Type is not ACPI\n"
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TableId = GET_TABLE_ID (Generator->GeneratorID);
+  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
+    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] != NULL) {
+      if (Generator != TableFactoryInfo.StdAcpiTableGeneratorList[TableId]) {
+        return EFI_INVALID_PARAMETER;
+      }
+      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = NULL;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] != NULL) {
+      if (Generator !=
+          TableFactoryInfo.CustomAcpiTableGeneratorList[TableId]) {
+        return EFI_INVALID_PARAMETER;
+      }
+      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = NULL;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..64a0390cdd006d8e3222ff19b269d1b4326736c3
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
@@ -0,0 +1,84 @@
+/** @file
+  Dynamic Table Factory Dxe
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include "DynamicTableFactory.h"
+
+/** The Dynamic Table Factory protocol structure that holds the
+    list of registered ACPI and SMBIOS table generators.
+*/
+EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
+
+
+/** A structure describing the Dynamic Table Factory protocol.
+*/
+STATIC
+CONST
+EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL DynamicTableFactoryProtocol = {
+  CREATE_REVISION (1, 0),
+  GetAcpiTableGenerator,
+  GetSmbiosTableGenerator,
+  &TableFactoryInfo
+};
+
+/** Entrypoint for Dynamic Table Factory Dxe.
+
+    @param  ImageHandle
+    @param  SystemTable
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+    @retval EFI_NOT_FOUND         Required interface/object was not found.
+    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
+
+*/
+EFI_STATUS
+EFIAPI
+DynamicTableFactoryDxeInitialize (
+  IN  EFI_HANDLE                 ImageHandle,
+  IN  EFI_SYSTEM_TABLE   * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->InstallProtocolInterface (
+                  &ImageHandle,
+                  &gEfiDynamicTableFactoryProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID*)&DynamicTableFactoryProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to install the Dynamic Table Factory Protocol." \
+      " Status = %r\n",
+      Status
+      ));
+  }
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
new file mode 100644
index 0000000000000000000000000000000000000000..64b578f30a3413ac2b22ccef4f09368c1af38b67
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
@@ -0,0 +1,227 @@
+/** @file
+  SMBIOS Table Factory
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Std - Standard
+**/
+
+#include <Protocol/Smbios.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include "DynamicTableFactory.h"
+
+extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
+
+/** Return a pointer to the SMBIOS table generator.
+
+    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  GeneratorId  The SMBIOS table generator ID for the
+                              requested generator.
+    @param [out] Generator    Pointer to the requested SMBIOS table
+                              generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+GetSmbiosTableGenerator (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
+  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
+  )
+{
+  UINT16                           TableId;
+  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
+
+  ASSERT (This != NULL);
+
+  FactoryInfo = This->TableFactoryInfo;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_SMBIOS (GeneratorId)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not SMBIOS\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Generator = NULL;
+  TableId = GET_TABLE_ID (GeneratorId);
+  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
+    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (FactoryInfo->StdSmbiosTableGeneratorList[TableId] != NULL) {
+      *Generator = FactoryInfo->StdSmbiosTableGeneratorList[TableId];
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (FactoryInfo->CustomSmbiosTableGeneratorList[TableId] != NULL) {
+      *Generator = FactoryInfo->CustomSmbiosTableGeneratorList[TableId];
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/** Register SMBIOS table factory generator.
+
+    The SMBIOS table factory maintains a list of the Standard and OEM SMBIOS
+    table generators.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+
+    @retval EFI_SUCCESS           The Generator was registered
+                                  successfully.
+    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
+                                  the Generator pointer is NULL.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
+                                  already registered.
+*/
+EFI_STATUS
+EFIAPI
+RegisterSmbiosTableGenerator (
+  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
+  )
+{
+  UINT16  TableId;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS register - Invalid Generator\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SMBIOS register - Generator" \
+      " Type is not SMBIOS\n"
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
+
+  TableId = GET_TABLE_ID (Generator->GeneratorID);
+  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
+    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] == NULL) {
+      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = Generator;
+    } else {
+      return EFI_ALREADY_STARTED;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] == NULL) {
+      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = Generator;
+    } else {
+      return EFI_ALREADY_STARTED;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/** Unregister SMBIOS generator.
+
+    This function is called by the SMBIOS table generator to unregister itself
+    from the SMBIOS table factory.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The generator is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+UnRegisterSmbiosTableGenerator (
+  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
+  )
+{
+  UINT16  TableId;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS un-register - Invalid Generator\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SMBIOS un-register - Generator" \
+      " Type is not SMBIOS\n"
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TableId = GET_TABLE_ID (Generator->GeneratorID);
+  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
+    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] != NULL) {
+      if (Generator != TableFactoryInfo.StdSmbiosTableGeneratorList[TableId]) {
+        return EFI_INVALID_PARAMETER;
+      }
+      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = NULL;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] != NULL) {
+      if (Generator !=
+          TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId]) {
+        return EFI_INVALID_PARAMETER;
+      }
+      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = NULL;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..f84bf3bef910ddf86629062d6d1ca1dffafa5a28
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
@@ -0,0 +1,531 @@
+/** @file
+  Dynamic Table Manager Dxe
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** This macro expands to a function that retrieves the ACPI Table
+    List from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceStandard,
+  EStdObjAcpiTableList,
+  CM_STD_OBJ_ACPI_TABLE_INFO
+  )
+
+/** A helper function to invoke a Table generator
+
+    This is a helper function that invokes the Table generator interface
+    for building an ACPI table. It uses the AcpiTableProtocol to install the
+    table, then frees the resources allocated for generating it.
+
+    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
+                                      interface.
+    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
+                                      Protocol Interface.
+    @param [in]  AcpiTableProtocol    Pointer to the AcpiTable protocol.
+    @param [in]  AcpiTableInfo        Pointer to the ACPI table Info.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         Required object is not found.
+    @retval EFI_BAD_BUFFER_SIZE   Size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildAndInstallAcpiTable (
+  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST TableFactoryProtocol,
+  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN       EFI_ACPI_TABLE_PROTOCOL             *       AcpiTableProtocol,
+  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo
+  )
+{
+  EFI_STATUS                    Status;
+  CONST ACPI_TABLE_GENERATOR  * Generator = NULL;
+  EFI_ACPI_DESCRIPTION_HEADER * AcpiTable;
+  UINTN                         TableHandle;
+
+  ASSERT (TableFactoryProtocol != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableProtocol != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: EStdObjAcpiTableList: Address = 0x%p," \
+    " TableGeneratorId = 0x%x\n",
+    AcpiTableInfo,
+    AcpiTableInfo->TableGeneratorId
+    ));
+
+  Status = TableFactoryProtocol->GetAcpiTableGenerator (
+                                   TableFactoryProtocol,
+                                   AcpiTableInfo->TableGeneratorId,
+                                   &Generator
+                                   );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Table Generator not found." \
+      " TableGeneratorId = 0x%x. Status = %r\n",
+      AcpiTableInfo->TableGeneratorId,
+      Status
+      ));
+    return Status;
+  }
+
+  ASSERT (Generator != NULL);
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: Generator found : %s\n",
+    Generator->Description
+    ));
+
+  if (Generator->BuildAcpiTable == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Table Generator does not implement the" \
+      " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
+      " TableGeneratorId = 0x%x. Status = %r\n",
+      AcpiTableInfo->TableGeneratorId,
+      Status
+      ));
+    return Status;
+  }
+
+  AcpiTable = NULL;
+  Status = Generator->BuildAcpiTable (
+                        Generator,
+                        AcpiTableInfo,
+                        CfgMgrProtocol,
+                        &AcpiTable
+                        );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to Build Table." \
+      " TableGeneratorId = 0x%x. Status = %r\n",
+      AcpiTableInfo->TableGeneratorId,
+      Status
+      ));
+    // Free any allocated resources.
+    goto error_handler;
+  }
+
+  ASSERT (AcpiTable != NULL);
+
+  // Dump ACPI Table Header
+  DUMP_ACPI_TABLE_HEADER (AcpiTable);
+
+  // Install ACPI table
+  Status = AcpiTableProtocol->InstallAcpiTable (
+                                AcpiTableProtocol,
+                                AcpiTable,
+                                AcpiTable->Length,
+                                &TableHandle
+                                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to Install ACPI Table. Status = %r\n",
+      Status
+      ));
+    // Free any allocated resources.
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: ACPI Table installed. Status = %r\n",
+    Status
+    ));
+
+error_handler:
+  // Free any resources allocated for generating the tables.
+  if ((AcpiTable != NULL) && (Generator->FreeTableResources != NULL)) {
+    Status = Generator->FreeTableResources (
+                          Generator,
+                          AcpiTableInfo,
+                          CfgMgrProtocol,
+                          &AcpiTable
+                          );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: Failed to Free Table Resources." \
+        "TableGeneratorId = 0x%x. Status = %r\n",
+        AcpiTableInfo->TableGeneratorId,
+        Status
+        ));
+    }
+  }
+  return Status;
+}
+
+/** The function checks if the Configuration Manager has provided the
+    mandatory ACPI tables for installation.
+
+    @param [in]  AcpiTableInfo      Pointer to the ACPI Table Info list.
+    @param [in]  AcpiTableCount     Count of ACPI Table Info.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_NOT_FOUND         If mandatory table is not found.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+VerifyMandatoryTablesArePresent (
+  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO  * CONST AcpiTableInfo,
+  IN CONST UINTN                               AcpiTableCount
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+  BOOLEAN     FadtFound = FALSE;
+  BOOLEAN     MadtFound = FALSE;
+  BOOLEAN     GtdtFound = FALSE;
+  BOOLEAN     DsdtFound = FALSE;
+  BOOLEAN     Dbg2Found = FALSE;
+  BOOLEAN     SpcrFound = FALSE;
+  UINTN       idx;
+
+  ASSERT (AcpiTableInfo != NULL);
+
+  for (idx = 0; idx < AcpiTableCount; idx++) {
+    switch (AcpiTableInfo[idx].AcpiTableSignature) {
+      case EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+        FadtFound = TRUE;
+        break;
+      case EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+        MadtFound = TRUE;
+        break;
+      case EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:
+        GtdtFound = TRUE;
+        break;
+      case EFI_ACPI_6_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+        DsdtFound = TRUE;
+        break;
+      case EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE:
+        Dbg2Found = TRUE;
+        break;
+      case EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
+        SpcrFound = TRUE;
+        break;
+      default:
+        break;
+    }
+  }
+
+  // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
+  if (!FadtFound) {
+    DEBUG ((DEBUG_ERROR,"ERROR: FADT Table not found\n"));
+    Status = EFI_NOT_FOUND;
+  }
+  if (!MadtFound) {
+    DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));
+    Status = EFI_NOT_FOUND;
+  }
+  if (!GtdtFound) {
+    DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));
+    Status = EFI_NOT_FOUND;
+  }
+  if (!DsdtFound) {
+    DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));
+    Status = EFI_NOT_FOUND;
+  }
+  if (!Dbg2Found) {
+    DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));
+  }
+  if (!SpcrFound) {
+    DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));
+  }
+  return Status;
+}
+
+/** Generate and install ACPI tables.
+
+    The function gathers the information necessary for installing the
+    ACPI tables from the Configuration Manager, invokes the generators
+    and installs them (via BuildAndInstallAcpiTable).
+
+    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
+                                      interface.
+    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
+                                      Protocol Interface.
+
+
+    @retval EFI_SUCCESS   Success.
+    @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+ProcessAcpiTables (
+  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST TableFactoryProtocol,
+  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_ACPI_TABLE_PROTOCOL     * AcpiTableProtocol;
+  UINTN                         AcpiTableCount;
+  CM_STD_OBJ_ACPI_TABLE_INFO  * AcpiTableInfo;
+  UINTN                         idx;
+
+  ASSERT (TableFactoryProtocol != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+
+  // Find the AcpiTable protocol
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID**)&AcpiTableProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  Status = GetEStdObjAcpiTableList (
+             CfgMgrProtocol,
+             &AcpiTableInfo,
+             &AcpiTableCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to get ACPI Table List. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  if (0 == AcpiTableCount) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
+      AcpiTableCount
+      ));
+    return EFI_NOT_FOUND;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
+    AcpiTableCount
+    ));
+
+  // Check if mandatory ACPI tables are present.
+  Status = VerifyMandatoryTablesArePresent (
+             AcpiTableInfo,
+             AcpiTableCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to find mandatory ACPI Table(s)."
+      " Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  // Add the FADT Table first.
+  for (idx = 0; idx < AcpiTableCount; idx++) {
+    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
+        AcpiTableInfo[idx].TableGeneratorId) {
+      Status = BuildAndInstallAcpiTable (
+                 TableFactoryProtocol,
+                 CfgMgrProtocol,
+                 AcpiTableProtocol,
+                 &AcpiTableInfo[idx]
+                 );
+      if (EFI_ERROR (Status)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: Failed to find build and install ACPI FADT Table." \
+          " Status = %r\n",
+          Status
+          ));
+        return Status;
+      }
+      break;
+    }
+  } // for
+
+  // Add remaining ACPI Tables
+  for (idx = 0; idx < AcpiTableCount; idx++) {
+    DEBUG ((
+      DEBUG_INFO,
+      "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
+      idx,
+      AcpiTableInfo[idx].TableGeneratorId
+      ));
+
+    // Skip FADT Table since we have already added
+    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
+        AcpiTableInfo[idx].TableGeneratorId) {
+      continue;
+    }
+
+    // Skip the Reserved table Generator ID
+    if ((CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RESERVED) >=
+           AcpiTableInfo[idx].TableGeneratorId)                     ||
+        (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MAX)      <=
+           AcpiTableInfo[idx].TableGeneratorId)) {
+      DEBUG ((
+        DEBUG_WARN,
+        "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
+        AcpiTableInfo[idx].TableGeneratorId
+        ));
+      continue;
+    }
+
+    Status = BuildAndInstallAcpiTable (
+               TableFactoryProtocol,
+               CfgMgrProtocol,
+               AcpiTableProtocol,
+               &AcpiTableInfo[idx]
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: Failed to find, build, and install ACPI Table." \
+        " Status = %r\n",
+        Status
+        ));
+      return Status;
+    }
+  } // for
+
+  return Status;
+}
+
+/** Entrypoint of Dynamic Table Manager Dxe.
+
+  The Dynamic Table Manager uses the Configuration Manager Protocol
+  to get the list of ACPI and SMBIOS tables to install. For each table
+  in the list it requests the corresponding ACPI/SMBIOS table factory for
+  a generator capable of building the ACPI/SMBIOS table.
+  If a suitable table generator is found, it invokes the generator interface
+  to build the table. The Dynamic Table Manager then installs the
+  table and invokes another generator interface to free any resources
+  allocated for building the table.
+
+    @param  ImageHandle
+    @param  SystemTable
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+    @retval EFI_NOT_FOUND         Required interface/object was not found.
+    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
+
+*/
+EFI_STATUS
+EFIAPI
+DynamicTableManagerDxeInitialize (
+  IN CONST EFI_HANDLE                 ImageHandle,
+  IN       EFI_SYSTEM_TABLE   * CONST SystemTable
+  )
+{
+  EFI_STATUS                               Status;
+  EFI_CONFIGURATION_MANAGER_PROTOCOL     * CfgMgrProtocol;
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
+  EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL     * TableFactoryProtocol;
+
+  // Locate the Dynamic Table Factory
+  Status = gBS->LocateProtocol (
+                  &gEfiDynamicTableFactoryProtocolGuid,
+                  NULL,
+                  (VOID**)&TableFactoryProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to find Dynamic Table Factory protocol." \
+      " Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  // Locate the Configuration Manager for the Platform
+  Status = gBS->LocateProtocol (
+                  &gEfiConfigurationManagerProtocolGuid,
+                  NULL,
+                  (VOID**)&CfgMgrProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",
+    CfgMfrInfo->Revision,
+    CfgMfrInfo->OemId[0],
+    CfgMfrInfo->OemId[1],
+    CfgMfrInfo->OemId[2],
+    CfgMfrInfo->OemId[3],
+    CfgMfrInfo->OemId[4],
+    CfgMfrInfo->OemId[5]
+    ));
+
+  Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: ACPI Table processing failure. Status = %r\n",
+      Status
+      ));
+  }
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
new file mode 100644
index 0000000000000000000000000000000000000000..69012cf8242c8ddd13ac4033293ac8a7053dfbd8
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
@@ -0,0 +1,35 @@
+## @file
+#  fdf include file for Dynamic Tables Framework.
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file.  This section also defines order the components and modules are positioned
+# within the image.  The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+
+  #
+  # Dynamic Table Factory Dxe
+  #
+  INF MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
+
+  #
+  # Dynamic Tables Dxe
+  #
+  INF MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
-- 
Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/2] [edk2-platforms] Platform/ARM: Dynamic Tables support for FVP
  2017-10-02 19:47 [PATCH 0/2] Dynamic Tables evan.lloyd
  2017-10-02 19:47 ` [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework evan.lloyd
@ 2017-10-02 19:47 ` evan.lloyd
  2017-10-03 17:12 ` [PATCH 0/2] Dynamic Tables Evan Lloyd
  2017-10-10  2:29 ` Yao, Jiewen
  3 siblings, 0 replies; 14+ messages in thread
From: evan.lloyd @ 2017-10-02 19:47 UTC (permalink / raw)
  To: edk2-devel
  Cc: "ard.biesheuvel, "leif.lindholm, "Matteo.Carlini,
	"nd, "Arvind.Chauhan, "Daniil.Egranov,
	"thomas.abraham

From: Sami Mujawar <sami.mujawar@arm.com>

The dynamic tables framework utilizes the configuration manager
protocol to get the platform specific information required for
building the firmware tables.

The configuration manager is a platform specific component that
collates the platform hardware information and builds an abstract
platform configuration repository. The configuration manager also
implements the configuration manager protocol which returns the
hardware information requested by the table generators.

This patch implements the configuration manager support for the FVP
platform.

The dynamic tables framework support is configurable and can be
enabled using the DYNAMIC_TABLES_FRAMEWORK build option.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Signed-off-by: Evan Lloyd <evan.lloyd@arm.com>
---
 Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManager.dsc.inc                        |  33 ++
 Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc                                              |  17 +-
 Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf                                              |  17 +-
 Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf |  79 +++
 Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/PlatformASLTablesLib.inf       |  34 ++
 Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.h      |  62 +++
 Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/Platform.h                  |  90 +++
 Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c      | 584 ++++++++++++++++++++
 Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/Dsdt.asl                       |  53 ++
 9 files changed, 967 insertions(+), 2 deletions(-)

diff --git a/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManager.dsc.inc b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManager.dsc.inc
new file mode 100644
index 0000000000000000000000000000000000000000..e536d7930f8f51efd1e1636154c92d58b5c1c01a
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManager.dsc.inc
@@ -0,0 +1,33 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+# [BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
+
+
+[BuildOptions]
+# Required for pre-processing ASL files that include ArmPlatform.h
+  *_*_*_ASLPP_FLAGS        = $(PLATFORM_FLAGS)
+
+[LibraryClasses.common]
+
+
+[Components.common]
+  # Configuration Manager
+  Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf {
+    <LibraryClasses>
+    # Platform ASL Tables
+    PlatformAslTablesLib|Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/PlatformASLTablesLib.inf
+  <BuildOptions>
+   *_*_*_PLATFORM_FLAGS = -I$(BIN_DIR)/Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/PlatformASLTablesLib/OUTPUT
+  }
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
index e9f954d926ac25a2abd2f97a4141267927dfc0a3..39b122c418c13180b464b6a54bce2fdd9ab8c57b 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
@@ -1,5 +1,5 @@
 #
-#  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+#  Copyright (c) 2011-2017, ARM Limited. All rights reserved.
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
@@ -38,6 +38,10 @@ [Defines]
   DT_SUPPORT                     = FALSE
 
 !include Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
+!ifdef DYNAMIC_TABLES_FRAMEWORK
+  !include MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
+  !include Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManager.dsc.inc
+!endif
 
 [LibraryClasses.common]
   ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
@@ -131,6 +135,15 @@ [PcdsFixedAtBuild.common]
   gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x1c090000
   gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200
   gEfiMdePkgTokenSpaceGuid.PcdUartDefaultReceiveFifoDepth|0
+  gArmPlatformTokenSpaceGuid.PL011UartInterrupt|0x25
+
+  ## PL011 Serial Debug UART
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgRegisterBase|0x1c0a0000
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgUartBaudRate|115200
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgUartClkInHz|24000000
+
+  # SBSA Generic Watchdog
+  gArmTokenSpaceGuid.PcdGenericWatchdogEl2IntrNum|59
 
   ## PL031 RealTimeClock
   gArmPlatformTokenSpaceGuid.PcdPL031RtcBase|0x1C170000
@@ -262,8 +275,10 @@ [Components.common]
 !endif
   }
 
+!ifndef DYNAMIC_TABLES_FRAMEWORK
   MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
   Platform/ARM/VExpressPkg/AcpiTables/AcpiTables.inf
+!endif
 
   ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
   ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf
index 1084eda3d367e727fa9428cfe306a060e2cb57b9..4015d4ffdedd22dd1f8fd19a81b8aa72443fd6ad 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf
@@ -1,5 +1,5 @@
 #
-#  Copyright (c) 2011 - 2015, ARM Limited. All rights reserved.
+#  Copyright (c) 2011 - 2017, ARM Limited. All rights reserved.
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
@@ -97,9 +97,13 @@ [FV.FvMain]
 
   # ACPI Support
   #
+!ifndef DYNAMIC_TABLES_FRAMEWORK
   INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
+!endif
   INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+!ifndef DYNAMIC_TABLES_FRAMEWORK
   INF RuleOverride=ACPITABLE Platform/ARM/VExpressPkg/AcpiTables/AcpiTables.inf
+!endif
 
   #
   # Multiple Console IO support
@@ -141,6 +145,15 @@ [FV.FvMain]
   # SMBIOS Support
   #
   INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+!ifdef DYNAMIC_TABLES_FRAMEWORK
+  # Configuration Manager
+  INF Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf
+
+  #
+  # Dynamic Table fdf
+  #
+  !include MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
+!endif
 
   #
   # Platform Driver
@@ -319,8 +332,10 @@ [Rule.Common.UEFI_APPLICATION.BINARY]
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
   }
 
+!ifndef DYNAMIC_TABLES_FRAMEWORK
 [Rule.Common.USER_DEFINED.ACPITABLE]
   FILE FREEFORM = $(NAMED_GUID) {
     RAW ACPI               |.acpi
     RAW ASL                |.aml
   }
+!endif
diff --git a/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..fe020fba1ee0010f3b18657c5f7476cab52bd2f4
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManagerDxe.inf
@@ -0,0 +1,79 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010016
+  BASE_NAME                      = ConfigurationManagerDxe
+  FILE_GUID                      = 29F45677-1920-4454-94A6-CF119C9491DB
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ConfigurationManagerDxeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ARM AARCH64
+#
+
+[Sources]
+  ConfigurationManager.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  ArmPlatformLib
+  PrintLib
+  PlatformAslTablesLib
+  UefiRuntimeServicesTableLib
+
+
+[Protocols]
+  gEfiConfigurationManagerProtocolGuid
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum
+
+  gArmTokenSpaceGuid.PcdGicDistributorBase
+  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+  gArmTokenSpaceGuid.PcdGicRedistributorsBase
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+  gArmPlatformTokenSpaceGuid.PL011UartClkInHz
+  gArmPlatformTokenSpaceGuid.PL011UartInterrupt
+
+  ## PL011 Serial Debug UART
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgRegisterBase
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgUartBaudRate
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgUartClkInHz
+
+  # SBSA Generic Watchdog
+  gArmTokenSpaceGuid.PcdGenericWatchdogControlBase
+  gArmTokenSpaceGuid.PcdGenericWatchdogRefreshBase
+  gArmTokenSpaceGuid.PcdGenericWatchdogEl2IntrNum
+
+[Pcd]
+
+[Depex]
+  TRUE
+
diff --git a/Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/PlatformASLTablesLib.inf b/Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/PlatformASLTablesLib.inf
new file mode 100644
index 0000000000000000000000000000000000000000..b12f6d4ffa299ae627307c7c8e8adb69d09fd884
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/PlatformASLTablesLib.inf
@@ -0,0 +1,34 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformAslTablesLib
+  FILE_GUID                      = 4000AEAB-C6D3-4F67-ADE3-D4B504FC164B
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformAslTablesLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ARM AARCH64
+#
+
+[Sources]
+  Dsdt.asl
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
diff --git a/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.h b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..a533af0fbe489ee539d01f1ead0144c262f8238a
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.h
@@ -0,0 +1,62 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef CONFIGURATION_MANAGER_H__
+#define CONFIGURATION_MANAGER_H__
+
+/** A helper macro for populating the GIC CPU information.
+*/
+#define GICC_ENTRY(                                                      \
+          CPUInterfaceNumber,                                            \
+          Mpidr,                                                         \
+          PmuIrq,                                                        \
+          VGicIrq                                                        \
+          ) {                                                            \
+    CPUInterfaceNumber,       /* UINT32  CPUInterfaceNumber           */ \
+    CPUInterfaceNumber,       /* UINT32  AcpiProcessorUid             */ \
+    EFI_ACPI_6_1_GIC_ENABLED, /* UINT32  Flags                        */ \
+    0,                        /* UINT32  ParkingProtocolVersion       */ \
+    PmuIrq,                   /* UINT32  PerformanceInterruptGsiv     */ \
+    0,                        /* UINT64  ParkedAddress                */ \
+    FixedPcdGet64 (                                                      \
+      PcdGicInterruptInterfaceBase                                       \
+      ),                      /* UINT64  PhysicalBaseAddress          */ \
+    0,                        /* UINT64  GICV                         */ \
+    0,                        /* UINT64  GICH                         */ \
+    VGicIrq,                  /* UINT32  VGICMaintenanceInterrupt     */ \
+    0,                        /* UINT64  GICRBaseAddress              */ \
+    Mpidr,                    /* UINT64  MPIDR                        */ \
+    0                         /* UINT8   ProcessorPowerEfficiencyClass*/ \
+    }
+
+/** A helper macro for returning configuration manager objects
+*/
+#define HANDLE_CM_OBJECT(CmObjectId, Object)   \
+  case CmObjectId: {                           \
+    CmObject->Size = sizeof (Object);          \
+    CmObject->Data = (UINTN*)&Object;          \
+    DEBUG ((                                   \
+      DEBUG_INFO,                              \
+      #CmObjectId ": Ptr = 0x%p, Size = %d\n", \
+      CmObject->Data,                          \
+      CmObject->Size                           \
+      ));                                      \
+    break;                                     \
+  }
+
+
+#endif // CONFIGURATION_MANAGER_H__
diff --git a/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/Platform.h b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/Platform.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b5560f33c450b5b0aaa0be084595b46aef56cd5
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/Platform.h
@@ -0,0 +1,90 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef PLATFORM_H__
+#define PLATFORM_H__
+
+#define ENABLE_MEM_MAPPED_TIMER
+
+#ifdef ENABLE_MEM_MAPPED_TIMER
+#define FVP_SYSTEM_TIMER_BASE_ADDRESS   0x2A430000
+#define FVP_CNT_READ_BASE_ADDRESS       0x2A800000
+#else
+#define FVP_SYSTEM_TIMER_BASE_ADDRESS   0xFFFFFFFFFFFFFFFF
+#define FVP_CNT_READ_BASE_ADDRESS       0xFFFFFFFFFFFFFFFF
+#endif
+
+// GT Block Timer
+#define FVP_GT_BLOCK_CTL_BASE           0x2A810000
+#define FVP_TIMER_FRAMES_COUNT          2
+
+// GT Block Timer Frames
+#define FVP_GT_BLOCK_FRAME0_CTL_BASE      0x2A820000
+#define FVP_GT_BLOCK_FRAME0_CTL_EL0_BASE  0xFFFFFFFFFFFFFFFF
+#define FVP_GT_BLOCK_FRAME0_GSIV          57
+
+#define FVP_GT_BLOCK_FRAME1_CTL_BASE      0x2A830000
+#define FVP_GT_BLOCK_FRAME1_CTL_EL0_BASE  0xFFFFFFFFFFFFFFFF
+#define FVP_GT_BLOCK_FRAME1_GSIV          58
+
+#define GTDT_TIMER_EDGE_TRIGGERED   \
+          EFI_ACPI_6_1_GTDT_TIMER_FLAG_TIMER_INTERRUPT_MODE
+#define GTDT_TIMER_LEVEL_TRIGGERED  0
+#define GTDT_TIMER_ACTIVE_LOW       \
+          EFI_ACPI_6_1_GTDT_TIMER_FLAG_TIMER_INTERRUPT_POLARITY
+#define GTDT_TIMER_ACTIVE_HIGH      0
+#define GTDT_TIMER_SAVE_CONTEXT     \
+          EFI_ACPI_6_1_GTDT_TIMER_FLAG_ALWAYS_ON_CAPABILITY
+#define GTDT_TIMER_LOSE_CONTEXT     0
+
+#define FVP_GTDT_GTIMER_FLAGS       (GTDT_TIMER_LOSE_CONTEXT   | \
+                                       GTDT_TIMER_ACTIVE_LOW   | \
+                                       GTDT_TIMER_LEVEL_TRIGGERED)
+
+// GT Block Timer Flags
+#define GTX_TIMER_EDGE_TRIGGERED    \
+          EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_MODE
+#define GTX_TIMER_LEVEL_TRIGGERED   0
+#define GTX_TIMER_ACTIVE_LOW        \
+          EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_POLARITY
+#define GTX_TIMER_ACTIVE_HIGH       0
+
+#define FVP_GTX_TIMER_FLAGS         (GTX_TIMER_ACTIVE_HIGH | \
+                                       GTX_TIMER_LEVEL_TRIGGERED)
+
+#define GTX_TIMER_SECURE            \
+          EFI_ACPI_6_1_GTDT_GT_BLOCK_COMMON_FLAG_SECURE_TIMER
+#define GTX_TIMER_NON_SECURE        0
+#define GTX_TIMER_SAVE_CONTEXT      \
+          EFI_ACPI_6_1_GTDT_GT_BLOCK_COMMON_FLAG_ALWAYS_ON_CAPABILITY
+#define GTX_TIMER_LOSE_CONTEXT      0
+
+#define FVP_GTX_COMMON_FLAGS        (GTX_TIMER_SAVE_CONTEXT | GTX_TIMER_SECURE)
+
+// Watchdog
+#define SBSA_WATCHDOG_EDGE_TRIGGERED   \
+          EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_MODE
+#define SBSA_WATCHDOG_LEVEL_TRIGGERED  0
+#define SBSA_WATCHDOG_ACTIVE_LOW       \
+          EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_POLARITY
+#define SBSA_WATCHDOG_ACTIVE_HIGH      0
+#define SBSA_WATCHDOG_SECURE           \
+          EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_SECURE_TIMER
+#define SBSA_WATCHDOG_NON_SECURE       0
+
+#define FVP_SBSA_WATCHDOG_FLAGS        (SBSA_WATCHDOG_NON_SECURE       | \
+                                          SBSA_WATCHDOG_ACTIVE_HIGH    | \
+                                          SBSA_WATCHDOG_LEVEL_TRIGGERED)
+
+#endif // PLATFORM_H__
diff --git a/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c
new file mode 100644
index 0000000000000000000000000000000000000000..768f64edc4fc61197b3a802d15a208f88425fb59
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/ConfigurationManager/ConfigurationManagerDxe/ConfigurationManager.c
@@ -0,0 +1,584 @@
+/** @file
+  Configuration Manager Dxe
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ArmLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include "Platform.h"
+#include "ConfigurationManager.h"
+
+// AML Code Include files generated by iASL Compiler
+#include <Dsdt.hex>
+
+/** A macro to define the configuration manager version.
+*/
+#define CONFIGURATION_MANAGER_REVISION CREATE_REVISION (1, 0)
+
+/** A macro describing the OEM ID.
+*/
+#define CFG_MGR_OEM_ID    { 'A', 'R', 'M', 'L', 'T', 'D' }
+
+/** A structure describing the platform configuration
+    manager repository information.
+*/
+typedef struct PlatformRepositoryInfo {
+  /// Configuration Manager Information
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  CmInfo;
+
+  /// List of ACPI tables
+  CM_STD_OBJ_ACPI_TABLE_INFO             CmAcpiTableList[6];
+
+  /// Boot architecture information
+  CM_ARM_BOOT_ARCH_INFO                  BootArchInfo;
+
+  /// Power management profile information
+  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO   PmProfileInfo;
+
+  /// GIC CPU interface information
+  CM_ARM_GICC_INFO                       GicCInfo[8];
+
+  /// GIC distributor information
+  CM_ARM_GICD_INFO                       GicDInfo;
+
+  /// GIC Redistributor information
+  CM_ARM_GIC_REDIST_INFO                 GicRedistInfo;
+
+  /// Generic timer information
+  CM_ARM_GENERIC_TIMER_INFO              GenericTimerInfo;
+
+  /// Generic timer block information
+  CM_ARM_GTBLOCK_INFO                    GTBlockInfo[1];
+
+  /// Generic timer frame information
+  CM_ARM_GTBLOCK_TIMER_FRAME_INFO        GTBlock0TimerInfo[2];
+
+  /// Watchdog information
+  CM_ARM_GENERIC_WATCHDOG_INFO           Watchdog;
+
+  /// Serial port information for the
+  /// serial port console redirection port.
+  CM_ARM_SERIAL_PORT_INFO                SpcrSerialPort;
+
+  /// Serial port information for the
+  /// DBG2 UART port
+  CM_ARM_SERIAL_PORT_INFO                DbgSerialPort;
+
+  /// GIC ITS information
+  CM_ARM_GIC_ITS_INFO                    GicItsInfo;
+} EFI_PLATFORM_REPOSITORY_INFO;
+
+/** The platform configuration repository information.
+*/
+EFI_PLATFORM_REPOSITORY_INFO ArmVExpressPlatformRepositoryInfo = {
+  /// Configuration Manager information
+  { CONFIGURATION_MANAGER_REVISION, CFG_MGR_OEM_ID },
+
+  // ACPI Table List
+  {
+    // FADT Table
+    {
+      EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+      CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT),
+      NULL
+    },
+    // GTDT Table
+    {
+      EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
+      CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_GTDT),
+      NULL
+    },
+    // MADT Table
+    {
+      EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+      CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MADT),
+      NULL
+    },
+    // SPCR Table
+    {
+      EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+      CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_SPCR),
+      NULL
+    },
+    // DSDT Table
+    {
+      EFI_ACPI_6_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+      CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_DSDT),
+      (EFI_ACPI_DESCRIPTION_HEADER*)DsdtAmlCode
+    },
+    // DBG2 Table
+    {
+      EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
+      CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_DBG2),
+      NULL
+    }
+  },
+
+  // Boot architecture information
+  { EFI_ACPI_6_1_ARM_PSCI_COMPLIANT },              // BootArchFlags
+
+  // Power management profile information
+  { EFI_ACPI_6_1_PM_PROFILE_ENTERPRISE_SERVER },    // PowerManagement Profile
+
+  // GIC CPU Interface information
+  {
+    GICC_ENTRY (0, GET_MPID (0, 0), 92, 25),
+    GICC_ENTRY (1, GET_MPID (0, 1), 93, 25),
+    GICC_ENTRY (2, GET_MPID (0, 2), 94, 25),
+    GICC_ENTRY (3, GET_MPID (0, 3), 95, 25),
+
+    GICC_ENTRY (4, GET_MPID (1, 0), 96, 25),
+    GICC_ENTRY (5, GET_MPID (1, 1), 97, 25),
+    GICC_ENTRY (6, GET_MPID (1, 2), 98, 25),
+    GICC_ENTRY (7, GET_MPID (1, 3), 99, 25)
+  },
+
+  // GIC Distributor Info
+  {
+    0,                                      // UINT32  GicId
+    FixedPcdGet64 (PcdGicDistributorBase),  // UINT64  PhysicalBaseAddress
+    0,                                      // UINT32  SystemVectorBase
+    3                                       // UINT8   GicVersion
+  },
+
+
+  /// GIC Re-Distributor Info
+  {
+    // UINT64  DiscoveryRangeBaseAddress
+    FixedPcdGet64 (PcdGicRedistributorsBase),
+    // UINT32  DiscoveryRangeLength
+    0x00200000
+  },
+
+  // Generic Timer Info
+  {
+    FVP_SYSTEM_TIMER_BASE_ADDRESS,
+    FVP_CNT_READ_BASE_ADDRESS,
+    FixedPcdGet32 (PcdArmArchTimerSecIntrNum),
+    FVP_GTDT_GTIMER_FLAGS,
+    FixedPcdGet32 (PcdArmArchTimerIntrNum),
+    FVP_GTDT_GTIMER_FLAGS,
+    FixedPcdGet32 (PcdArmArchTimerVirtIntrNum),
+    FVP_GTDT_GTIMER_FLAGS,
+    FixedPcdGet32 (PcdArmArchTimerHypIntrNum),
+    FVP_GTDT_GTIMER_FLAGS
+  },
+
+  // Generic Timer Block Information
+  {
+    {
+      FVP_GT_BLOCK_CTL_BASE,
+      FVP_TIMER_FRAMES_COUNT,
+      (CM_ARM_GTBLOCK_TIMER_FRAME_INFO*)((UINT8*)&ArmVExpressPlatformRepositoryInfo +
+        OFFSET_OF (EFI_PLATFORM_REPOSITORY_INFO, GTBlock0TimerInfo))
+    }
+  },
+
+  // GT Block Timer Frames
+  {
+    // Frame 0
+    {
+      0,                                //UINT8   FrameNumber
+      FVP_GT_BLOCK_FRAME0_CTL_BASE,     //UINT64  PhysicalAddressCntBase
+      FVP_GT_BLOCK_FRAME0_CTL_EL0_BASE, //UINT64  PhysicalAddressCntEL0Base
+      FVP_GT_BLOCK_FRAME0_GSIV,         //UINT32  PhysicalTimerGSIV
+      FVP_GTX_TIMER_FLAGS,              //UINT32  PhysicalTimerFlags
+      0,                                //UINT32  VirtualTimerGSIV
+      0,                                //UINT32  VirtualTimerFlags
+      FVP_GTX_COMMON_FLAGS              //UINT32  CommonFlags
+    },
+    // Frame 1
+    {
+      1,                                //UINT8   FrameNumber
+      FVP_GT_BLOCK_FRAME1_CTL_BASE,     //UINT64  PhysicalAddressCntBase
+      FVP_GT_BLOCK_FRAME1_CTL_EL0_BASE, //UINT64  PhysicalAddressCntEL0Base
+      FVP_GT_BLOCK_FRAME1_GSIV,         //UINT32  PhysicalTimerGSIV
+      FVP_GTX_TIMER_FLAGS,              //UINT32  PhysicalTimerFlags
+      0,                                //UINT32  VirtualTimerGSIV
+      0,                                //UINT32  VirtualTimerFlags
+      FVP_GTX_COMMON_FLAGS              //UINT32  CommonFlags
+    },
+  },
+
+  // Watchdog Info
+  {
+    FixedPcdGet64 (PcdGenericWatchdogControlBase),
+    FixedPcdGet64 (PcdGenericWatchdogRefreshBase),
+    FixedPcdGet32 (PcdGenericWatchdogEl2IntrNum),
+    FVP_SBSA_WATCHDOG_FLAGS
+  },
+
+  // SPCR Serial Port
+  {
+    FixedPcdGet64 (PcdSerialRegisterBase),  // UINT64  BaseAddress
+    FixedPcdGet32 (PL011UartInterrupt),     // UINT32  Interrupt
+    FixedPcdGet64 (PcdUartDefaultBaudRate), // UINT64  BaudRate
+    FixedPcdGet32 (PL011UartClkInHz)        // UINT32  Clock
+  },
+  // Debug Serial Port
+  {
+    FixedPcdGet64 (PcdSerialDbgRegisterBase), // UINT64  BaseAddress
+    38,                                       // UINT32  Interrupt
+    FixedPcdGet64 (PcdSerialDbgUartBaudRate), // UINT64  BaudRate
+    FixedPcdGet32 (PcdSerialDbgUartClkInHz)   // UINT32  Clock
+  },
+
+  // GIC ITS
+  {
+    // The GIC ITS ID.
+    0,
+
+    // The physical address for the
+    // Interrupt Translation Service
+    0x2f020000
+  }
+};
+
+/** Initialize the platform configuration repository.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+
+    @retval
+      EFI_SUCCESS   Success
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+InitializePlatformRepository (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/** Return a standard namespace object.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the requested Object.
+
+    @retval Returns:
+      EFI_SUCCESS           Success.
+      EFI_INVALID_PARAMETER A parameter is invalid.
+      EFI_NOT_FOUND         The required object information is not found.
+*/
+EFI_STATUS
+EFIAPI
+GetStandardNameSpaceObject (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  )
+{
+  EFI_STATUS                      Status = EFI_SUCCESS;
+  EFI_PLATFORM_REPOSITORY_INFO  * PlatformRepo;
+
+  if ((This == NULL) || (CmObject == NULL)) {
+    ASSERT (This != NULL);
+    ASSERT (CmObject != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+  PlatformRepo = This->PlatRepoInfo;
+
+  switch (GET_CM_OBJECT_ID (CmObjectId)) {
+    HANDLE_CM_OBJECT (EStdObjCfgMgrInfo, PlatformRepo->CmInfo);
+    HANDLE_CM_OBJECT (EStdObjAcpiTableList, PlatformRepo->CmAcpiTableList);
+    default: {
+      Status = EFI_NOT_FOUND;
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: Object 0x%x. Status = %r\n",
+        CmObjectId,
+        Status
+        ));
+      break;
+    }
+  }
+
+  return Status;
+}
+
+/** Return an ARM namespace object.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the requested Object.
+
+    @retval Returns:
+      EFI_SUCCESS           Success.
+      EFI_INVALID_PARAMETER A parameter is invalid.
+      EFI_NOT_FOUND         The required object information is not found.
+*/
+EFI_STATUS
+EFIAPI
+GetArmNameSpaceObject (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  )
+{
+  EFI_STATUS                      Status = EFI_SUCCESS;
+  EFI_PLATFORM_REPOSITORY_INFO  * PlatformRepo;
+
+  if ((This == NULL) || (CmObject == NULL)) {
+    ASSERT (This != NULL);
+    ASSERT (CmObject != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+  PlatformRepo = This->PlatRepoInfo;
+
+  switch (GET_CM_OBJECT_ID (CmObjectId)) {
+    HANDLE_CM_OBJECT (EArmObjBootArchInfo, PlatformRepo->BootArchInfo);
+    HANDLE_CM_OBJECT (
+      EArmObjPowerManagementProfileInfo,
+      PlatformRepo->PmProfileInfo
+      );
+    HANDLE_CM_OBJECT (EArmObjGenericTimerInfo, PlatformRepo->GenericTimerInfo);
+    HANDLE_CM_OBJECT (
+      EArmObjPlatformGenericWatchdogInfo,
+      PlatformRepo->Watchdog
+      );
+    HANDLE_CM_OBJECT (EArmObjPlatformGTBlockInfo, PlatformRepo->GTBlockInfo);
+    HANDLE_CM_OBJECT (EArmObjGicCInfo, PlatformRepo->GicCInfo);
+    HANDLE_CM_OBJECT (EArmObjGicDInfo, PlatformRepo->GicDInfo);
+    HANDLE_CM_OBJECT (
+      EArmObjGicRedistributorInfo,
+      PlatformRepo->GicRedistInfo
+      );
+    HANDLE_CM_OBJECT (
+      EArmObjSerialConsolePortInfo,
+      PlatformRepo->SpcrSerialPort
+      );
+    HANDLE_CM_OBJECT (EArmObjSerialDebugPortInfo, PlatformRepo->DbgSerialPort);
+    HANDLE_CM_OBJECT (EArmObjGicItsInfo, PlatformRepo->GicItsInfo);
+
+    default: {
+      Status = EFI_NOT_FOUND;
+      DEBUG ((
+        DEBUG_WARN,
+        "WARNING: Object 0x%x. Status = %r\n",
+        CmObjectId,
+        Status
+        ));
+      break;
+    }
+  }//switch
+
+  return Status;
+}
+
+/** Return an OEM namespace object.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the requested Object.
+
+    @retval Returns:
+      EFI_SUCCESS           Success.
+      EFI_INVALID_PARAMETER A parameter is invalid.
+      EFI_NOT_FOUND         The required object information is not found.
+      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                            is less than the Object size for the requested
+                            object.
+*/
+EFI_STATUS
+EFIAPI
+GetOemNameSpaceObject (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+
+  if ((This == NULL) || (CmObject == NULL)) {
+    ASSERT (This != NULL);
+    ASSERT (CmObject != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  switch (GET_CM_OBJECT_ID (CmObjectId)) {
+    default: {
+      Status = EFI_NOT_FOUND;
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: Object 0x%x, Status = %r\n",
+        CmObjectId,
+        Status
+        ));
+      break;
+    }
+  }
+
+  return Status;
+}
+
+/** The GetObject function defines the interface implemented by the
+    Configuration Manager Protocol for returning the Configuration
+    Manager Objects.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the requested Object.
+
+    @retval Returns:
+      EFI_SUCCESS           Success.
+      EFI_INVALID_PARAMETER A parameter is invalid.
+      EFI_NOT_FOUND         The required object information is not found.
+*/
+EFI_STATUS
+EFIAPI
+ArmVExpressPlatformGetObject (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  )
+{
+  EFI_STATUS  Status;
+
+  if ((This == NULL) || (CmObject == NULL)) {
+    ASSERT (This != NULL);
+    ASSERT (CmObject != NULL);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  switch (GET_CM_NAMESPACE_ID (CmObjectId)) {
+    case EObjNameSpaceStandard:
+      Status = GetStandardNameSpaceObject (This, CmObjectId, CmObject);
+      break;
+    case EObjNameSpaceArm:
+      Status = GetArmNameSpaceObject (This, CmObjectId, CmObject);
+      break;
+    case EObjNameSpaceOem:
+      Status = GetOemNameSpaceObject (This, CmObjectId, CmObject);
+      break;
+    default: {
+      Status = EFI_INVALID_PARAMETER;
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: Unknown Namespace Object = 0x%x, Status = %r\n",
+        CmObjectId,
+        Status
+        ));
+      break;
+    }
+  }
+
+  return Status;
+}
+
+/** The SetObject function defines the interface implemented by the
+    Configuration Manager Protocol for updating the Configuration
+    Manager Objects.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the Object.
+
+    @retval Returns:
+      EFI_UNSUPPORTED       This operation is not supported.
+*/
+EFI_STATUS
+EFIAPI
+ArmVExpressPlatformSetObject (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN        CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/** A structure describing the configuration manager protocol interface.
+*/
+STATIC
+CONST
+EFI_CONFIGURATION_MANAGER_PROTOCOL ArmVExpressPlatformConfigurationManagerProtocol = {
+  CREATE_REVISION(1,0),
+  ArmVExpressPlatformGetObject,
+  ArmVExpressPlatformSetObject,
+  &ArmVExpressPlatformRepositoryInfo
+};
+
+/**
+  Entrypoint of Configuration Manager Dxe.
+
+  @param  ImageHandle
+  @param  SystemTable
+
+  @return EFI_SUCCESS
+  @return EFI_LOAD_ERROR
+  @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+ConfigurationManagerDxeInitialize (
+  IN EFI_HANDLE          ImageHandle,
+  IN EFI_SYSTEM_TABLE  * SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->InstallProtocolInterface (
+                  &ImageHandle,
+                  &gEfiConfigurationManagerProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID*)&ArmVExpressPlatformConfigurationManagerProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to get Install Configuration Manager Protocol." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = InitializePlatformRepository (
+    &ArmVExpressPlatformConfigurationManagerProtocol
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to initialize the Platform Configuration Repository." \
+      " Status = %r\n",
+      Status
+      ));
+  }
+
+error_handler:
+  return Status;
+}
diff --git a/Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/Dsdt.asl b/Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/Dsdt.asl
new file mode 100644
index 0000000000000000000000000000000000000000..3411f10bb8d47b234a546de1a6ca3ed0b858fa07
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/ConfigurationManager/PlatformASLTablesLib/Dsdt.asl
@@ -0,0 +1,53 @@
+/** @file
+  Differentiated System Description Table Fields (DSDT)
+
+  Copyright (c) 2014-2017, ARM Ltd. All rights reserved.<BR>
+    This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+DefinitionBlock("DsdtTable.aml", "DSDT", 1, "ARMLTD", "ARM-VEXPRESS", 1) {
+  Scope(_SB) {
+    //
+    // Processor
+    //
+  Device(CPU0) {
+    Name(_HID, "ACPI0007")
+    Name(_UID, Zero)
+  }
+  Device(CPU1) {
+    Name(_HID, "ACPI0007")
+    Name(_UID, One)
+  }
+  Device(CPU2) {
+    Name(_HID, "ACPI0007")
+    Name(_UID, 2)
+  }
+  Device(CPU3) {
+    Name(_HID, "ACPI0007")
+    Name(_UID, 3)
+  }
+  Device(CPU4) {
+    Name(_HID, "ACPI0007")
+    Name(_UID, 4)
+  }
+  Device(CPU5) {
+    Name(_HID, "ACPI0007")
+    Name(_UID, 5)
+  }
+  Device(CPU6) {
+    Name(_HID, "ACPI0007")
+    Name(_UID, 6)
+  }
+  Device(CPU7) {
+    Name(_HID, "ACPI0007")
+    Name(_UID, 7)
+  }
+  } // Scope(_SB)
+}
-- 
Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
  2017-10-02 19:47 ` [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework evan.lloyd
@ 2017-10-03 14:34   ` Zeng, Star
  2017-10-03 16:03     ` Leif Lindholm
  2017-10-03 17:03     ` Evan Lloyd
  0 siblings, 2 replies; 14+ messages in thread
From: Zeng, Star @ 2017-10-03 14:34 UTC (permalink / raw)
  To: evan.lloyd@arm.com, edk2-devel@lists.01.org
  Cc: "Matteo.Carlini@arm.com"@arm.com,
	"nd@arm.com"@arm.com,
	"ard.biesheuvel@linaro.org"@arm.com,
	"thomas.abraham@arm.com"@arm.com,
	"Arvind.Chauhan@arm.com"@arm.com,
	"leif.lindholm@linaro.org"@arm.com,
	"Daniil.Egranov@arm.com"@arm.com, Kinney, Michael D,
	Yao, Jiewen, Zeng, Star

Hi Evan,

May I ask you are proposing edk2-platforms(https://github.com/tianocore/edk2-platforms) change or edk2 master(https://github.com/tianocore/edk2) change?

Please note, we may have no/occasional email response during PRC holiday (10/1 - 10/8).

Thanks,
Star
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of evan.lloyd@arm.com
Sent: Tuesday, October 3, 2017 3:48 AM
To: edk2-devel@lists.01.org
Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com; "ard.biesheuvel@linaro.org"@arm.com; "thomas.abraham@arm.com"@arm.com; "Arvind.Chauhan@arm.com"@arm.com; "leif.lindholm@linaro.org"@arm.com; "Daniil.Egranov@arm.com"@arm.com
Subject: [edk2] [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework

From: Sami Mujawar <sami.mujawar@arm.com>

The dynamic tables framework is designed to generate standardised
firmware tables that describe the hardware information at
run-time. A goal of standardised firmware is to have a common
firmware for a platform capable of booting both Windows and Linux
operating systems.

Traditionally the firmware tables are handcrafted using ACPI
Machine Language (AML), Table Definition Language (TDL) and
C-code. This approach can be error prone and involves time
consuming debugging. In addition, it may be desirable to configure
platform hardware at runtime such as: configuring the number of
cores available for use by the OS, or turning SoC features ON or
OFF.

The dynamic tables framework simplifies this by providing a set
of standard table generators, that are implemented as libraries.
These generators query a platform specific component, the
'Configuration Manager', to collate the information required
for generating the tables at run-time.

The framework also provisions the ability to implement custom/OEM
generators; thereby facilitating support for custom tables. The
custom generators can also utilize the existing standard generators
and override any functionality if needed.

The framework currently implements a set of standard ACPI table
generators for ARM architecture, that can generate Server Base Boot
Requirement (SBBR) compliant tables. Support for generating SMBIOS
tables is planned to be added subsequently. Although, the set
of standard generators implements the functionality required for ARM
architecture; the framework is extensible, and support for other
architectures can be easily added.

Contributions from the community are invited.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Signed-off-by: Evan Lloyd <evan.lloyd@arm.com>
---
 MdeModulePkg/MdeModulePkg.dec                                                                       |  13 +
 MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc                                          |  45 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf                       |  49 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf                       |  46 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf                       |  47 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf                         |  44 ++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf                       |  44 ++
 MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf                         |  39 ++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf              |  57 ++
 MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf              |  47 ++
 MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h                                             | 280 ++++++++
 MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h                                            | 367 ++++++++++
 MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h                                     | 112 +++
 MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h                                     | 158 +++++
 MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h                                           | 235 +++++++
 MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h                                       |  93 +++
 MdeModulePkg/Include/DynamicTables/TableGenerator.h                                                 | 235 +++++++
 MdeModulePkg/Include/Library/TableHelperLib.h                                                       |  67 ++
 MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h                                        | 121 ++++
 MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h                                         | 113 +++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h                   |  91 +++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c                          | 440 ++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c                          | 562 +++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c                          | 652 +++++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c                          | 732 ++++++++++++++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c                          | 336 +++++++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c                            | 177 +++++
 MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c                          | 323 +++++++++
 MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c                              | 165 +++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c     | 227 ++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c                |  84 +++
 MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c | 227 ++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c                | 531 ++++++++++++++
 MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc                                          |  35 +
 36 files changed, 6888 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index a3c0633ee1ec6ab7540a1b7221850e975f95ad80..de8a658c21d11ab1396bb543b026f94a396a0710 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -7,6 +7,7 @@
 # Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
 # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
 # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+# Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
 #
 # This program and the accompanying materials are licensed and made available under
 # the terms and conditions of the BSD License that accompanies this distribution.
@@ -556,6 +557,12 @@ [Protocols]
   ## Include/Protocol/IoMmu.h
   gEdkiiIoMmuProtocolGuid = { 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed, 0xe6, 0xe1, 0xce, 0x51, 0x7c, 0x1e } }
 
+  # Configuration Manager Protocol GUID
+  gEfiConfigurationManagerProtocolGuid = { 0xd85a4835, 0x5a82, 0x4894, { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } }
+
+  # Dynamic Table Factory Protocol GUID
+  gEfiDynamicTableFactoryProtocolGuid = { 0x91d1e327, 0xfe5a, 0x49b8, { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec } }
+
 #
 # [Error.gEfiMdeModulePkgTokenSpaceGuid]
 #   0x80000001 | Invalid value provided.
@@ -867,6 +874,12 @@ [PcdsFixedAtBuild]
   # @ValidList  0x80000006 | 0x03058002
   gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UINT32|0x30001040
 
+  # Maximum number of Custom ACPI Generators
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators|1|UINT16|0xC0000001
+
+  # Maximum number of Custom SMBIOS Generators
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators|1|UINT16|0xC0000002
+
 [PcdsFixedAtBuild, PcdsPatchableInModule]
   ## Dynamic type PCD can be registered callback function for Pcd setting action.
   #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
new file mode 100644
index 0000000000000000000000000000000000000000..548c77ad971f97c43da8f7ba1b69fa6948430c17
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
@@ -0,0 +1,45 @@
+## @file
+#  Dsc include file for Dynamic Tables Framework.
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+
+[BuildOptions]
+  *_*_*_ASL_FLAGS          = -th -li
+
+[LibraryClasses.common]
+
+[Components.common]
+  #
+  # Dynamic Table Factory Dxe
+  #
+  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf {
+    <LibraryClasses>
+      TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
+      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
+  }
+
+  #
+  # Dynamic Tables Manager Dxe
+  #
+  MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf {
+    <LibraryClasses>
+      TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
+  }
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..591b6364ae86c885ca4768599d3eadf6d2842eff
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
@@ -0,0 +1,49 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiDbg2LibArm
+  FILE_GUID      = A17BA4F0-3DEB-4FE5-BD27-EC008E541B22
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiDbg2LibConstructor
+  DESTRUCTOR     = AcpiDbg2LibDestructor
+
+
+[Sources]
+  Dbg2Generator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  SerialPortLib
+
+[FixedPcd]
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+
+[Protocols]
+
+
+[Guids]
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..ae5239fd2a3e6f00574cf5f3bb4a561031e122be
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
@@ -0,0 +1,47 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiFadtLibArm
+  FILE_GUID      = 686FE5FE-B944-485F-8B1C-7D60E0056487
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiFadtLibConstructor
+  DESTRUCTOR     = AcpiFadtLibDestructor
+
+
+[Sources]
+  FadtGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
+
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..be38489c2987a81d68effd9c05b731b17cb2819c
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
@@ -0,0 +1,46 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiGtdtLibArm
+  FILE_GUID      = 26490F7A-7FA2-423C-8939-C6206329BC37
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiGtdtLibConstructor
+  DESTRUCTOR     = AcpiGtdtLibDestructor
+
+
+[Sources]
+  GtdtGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[FixedPcd]
+
+[Protocols]
+
+
+[Guids]
+
+
+
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..9807e3fe75bb785c3b400410248e6434532f2147
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
@@ -0,0 +1,47 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiMadtLibArm
+  FILE_GUID      = AF76C93B-41B5-454D-83CD-D2A80A1C1E38
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiMadtLibConstructor
+  DESTRUCTOR     = AcpiMadtLibDestructor
+
+
+[Sources]
+  MadtGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
+
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..2f879dfee4b93a56a923340c4b416c6df9656618
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
@@ -0,0 +1,47 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiMcfgLibArm
+  FILE_GUID      = 8C9BDCB2-72D4-4F30-A12D-1145C3807FF7
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiMcfgLibConstructor
+  DESTRUCTOR     = AcpiMcfgLibDestructor
+
+
+[Sources]
+  McfgGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
+
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..db208bdeb8ffce085367ee865766a0a1bd90cb28
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
@@ -0,0 +1,44 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiRawLibArm
+  FILE_GUID      = 20F31568-D687-49BA-B326-CCD9D38EDE16
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiRawLibConstructor
+  DESTRUCTOR     = AcpiRawLibDestructor
+
+
+[Sources]
+  RawGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
new file mode 100644
index 0000000000000000000000000000000000000000..3d47e6ae1f7995f76fe3e93093b0185e48ecae79
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
@@ -0,0 +1,44 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiSpcrLibArm
+  FILE_GUID      = 55088136-7B78-4974-B1EE-F630150D0DE7
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiSpcrLibConstructor
+  DESTRUCTOR     = AcpiSpcrLibDestructor
+
+
+[Sources]
+  SpcrGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Pcd]
+
+
+[Protocols]
+
+
+[Guids]
+
+
diff --git a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
new file mode 100644
index 0000000000000000000000000000000000000000..38952fba1c8056bf0c581975ca974abbef1e8096
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
@@ -0,0 +1,39 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = DynamicTableHelperLib
+  FILE_GUID      = E315C738-3A39-4D0D-A0AF-8EDFA770AB39
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = TableHelperLib
+
+
+[Sources]
+  TableHelper.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
+[Protocols]
+
+
+[Guids]
+
+
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..c58ac3a8d6d655e38cb8460a35ce256fc4e5ada6
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
@@ -0,0 +1,57 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+
+[Defines]
+  INF_VERSION                    = 0x00010016
+  BASE_NAME                      = DynamicTableFactoryDxe
+  FILE_GUID                      = FE846898-7403-4932-B8AD-A0491F0C2CBA
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = DynamicTableFactoryDxeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ARM AARCH64
+#
+
+[Sources]
+  DynamicTableFactoryDxe.c
+  AcpiTableFactory/AcpiTableFactory.c
+  SmbiosTableFactory/SmbiosTableFactory.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  PrintLib
+  BaseLib
+  MemoryAllocationLib
+  TableHelperLib
+
+[FixedPcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+  gEfiSmbiosProtocolGuid                        # PROTOCOL ALWAYS_CONSUMED
+  gEfiConfigurationManagerProtocolGuid
+  gEfiDynamicTableFactoryProtocolGuid
+
+[Depex]
+  TRUE
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..9c5a5f6207687ca90fa11188340d09c304fc34c0
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
@@ -0,0 +1,47 @@
+## @file
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010016
+  BASE_NAME                      = DynamicTableManagerDxe
+  FILE_GUID                      = 89122868-BCFD-49E8-88A3-06635CB7B3CF
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = DynamicTableManagerDxeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ARM AARCH64
+#
+
+[Sources]
+  DynamicTableManagerDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  PrintLib
+  TableHelperLib
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+  gEfiConfigurationManagerProtocolGuid
+  gEfiDynamicTableFactoryProtocolGuid
+
+[Depex]
+  TRUE
diff --git a/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a07cd6e10217958d22a93060a0f9aa48947f264
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
@@ -0,0 +1,280 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+    - Std or STD - Standard
+**/
+
+#ifndef ACPI_TABLE_GENERATOR_H_
+#define ACPI_TABLE_GENERATOR_H_
+
+#pragma pack(1)
+
+/**
+The Dynamic Tables Framework provisions two classes of ACPI table
+generators.
+ - Standard generators: The ACPI table generators implemented by the
+                        Dynamic Tables Framework.
+ - OEM generators:      The ACPI table generatos customized by the OEM.
+
+The Dynamic Tables Framework implements the following ACPI table generators:
+  - RAW   : This is the simplest ACPI table generator. It simply installs
+            the ACPI table provided in the AcpiTableData member of the
+            CM_STD_OBJ_ACPI_TABLE_INFO. The ACPI table data is provided by
+            the Configuration Manager and is generated using an implementation
+            defined mechanism.
+  - DSDT  : The DSDT generator is clone of the RAW generator. The difference
+            is in the way the ACPI Table Data is generated from an AML file.
+  - SSDT  : The SSDT generator is clone of the RAW generator. The difference
+            is in the way the ACPI Table Data is generated from an AML file.
+  - FADT  : The FADT generator collates the required platform information for
+            building the ACPI FADT table from the Configuration Manager and
+            generates the FADT table.
+  - MADT  : The MADT generator collates the GIC information for building the
+            ACPI MADT table from the Configuration Manager and generates the
+            MADT table.
+  - GTDT  : The GTDT generator collates the Timer information for building the
+            ACPI GTDT table from the Configuration Manager and generates the
+            GTDT table.
+  - DBG2  : The DBG2 generator collates the debug serial port information for
+            building the DBG2 table from the Configuration Manager and
+            generates the GTDT table.
+  - SPCR  : The SPCR generator collates the serial port information for
+            building the SPCR table from the Configuration Manager and
+            generates the SPCR table.
+  - MCFG  : The MCFG generator collates the PCI configuration space information
+            for building the MCFG table from the Configuration Manager and
+            generates the MCFG table.
+*/
+
+/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
+*/
+typedef TABLE_GENERATOR_ID ACPI_TABLE_GENERATOR_ID;
+
+/** The ESTD_ACPI_TABLE_ID enum describes the ACPI table IDs reserved for
+  the standard generators.
+*/
+typedef enum StdAcpiTableId {
+  ESTD_ACPI_TABLE_ID_RESERVED = 0x0000,             ///< Reserved.
+  ESTD_ACPI_TABLE_ID_RAW,                           ///< RAW Generator.
+  ESTD_ACPI_TABLE_ID_DSDT = ESTD_ACPI_TABLE_ID_RAW, ///< DSDT Generator.
+  ESTD_ACPI_TABLE_ID_SSDT = ESTD_ACPI_TABLE_ID_RAW, ///< SSDT Generator.
+  ESTD_ACPI_TABLE_ID_FADT,                          ///< FADT Generator.
+  ESTD_ACPI_TABLE_ID_MADT,                          ///< MADT Generator.
+  ESTD_ACPI_TABLE_ID_GTDT,                          ///< GTDT Generator.
+  ESTD_ACPI_TABLE_ID_DBG2,                          ///< DBG2 Generator.
+  ESTD_ACPI_TABLE_ID_SPCR,                          ///< SPCR Generator.
+  ESTD_ACPI_TABLE_ID_MCFG,                          ///< MCFG Generator.
+  ESTD_ACPI_TABLE_ID_MAX
+} ESTD_ACPI_TABLE_ID;
+
+/** This macro checks if the Table Generator ID is for an ACPI Table Generator.
+    @param [in] TableGeneratorId  The table generator ID.
+
+    @returns TRUE if the table generator ID is for an ACPI Table
+          Generator.
+*/
+#define IS_GENERATOR_TYPE_ACPI(TableGeneratorId) \
+          (GET_TABLE_TYPE (TableGeneratorId) == ETableGeneratorTypeAcpi)
+
+/** This macro checks if the Table Generator ID is for a standard ACPI
+    Table Generator.
+
+    @param [in] TableGeneratorId  The table generator ID.
+
+    @returns TRUE if the table generator ID is for a standard ACPI
+            Table Generator.
+*/
+#define IS_VALID_STD_ACPI_GENERATOR_ID(TableGeneratorId)               \
+          (                                                            \
+          IS_GENERATOR_NAMESPACE_STD (TableGeneratorId) &&             \
+          IS_GENERATOR_TYPE_ACPI (TableGeneratorId)     &&             \
+          ((GET_TABLE_ID (GeneratorId) >= ESTD_ACPI_TABLE_ID_RAW) &&   \
+           (GET_TABLE_ID (GeneratorId) < ESTD_ACPI_TABLE_ID_MAX))      \
+          )
+
+/** This macro creates a standard ACPI Table Generator ID.
+
+    @param [in] TableId  The table generator ID.
+
+    @returns a standard ACPI table generator ID.
+*/
+#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId) \
+          CREATE_TABLE_GEN_ID (               \
+            ETableGeneratorTypeAcpi,          \
+            ETableGeneratorNameSpaceStd,      \
+            TableId                           \
+            )
+
+/** The Creator ID for the ACPI tables generated using
+  the standard ACPI table generators.
+*/
+#define TABLE_GENERATOR_CREATOR_ID_ARM  SIGNATURE_32('A', 'R', 'M', 'H')
+
+/** A macro to initialise the common header part of EFI ACPI tables as
+    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
+
+    @param [in] Signature The ACPI table signature.
+    @param [in] Type      The ACPI table structure.
+    @param [in] Revision  The ACPI table revision.
+*/
+#define ACPI_HEADER(Signature, Type, Revision) {              \
+          Signature,             /* UINT32  Signature */      \
+          sizeof (Type),         /* UINT32  Length */         \
+          Revision,              /* UINT8   Revision */       \
+          0,                     /* UINT8   Checksum */       \
+          { 0, 0, 0, 0, 0, 0 },  /* UINT8   OemId[6] */       \
+          0,                     /* UINT64  OemTableId */     \
+          0,                     /* UINT32  OemRevision */    \
+          0,                     /* UINT32  CreatorId */      \
+          0                      /* UINT32  CreatorRevision */\
+          }
+
+/** A macro to dump the common header part of EFI ACPI tables as
+    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
+
+    @param [in] AcpiHeader The pointer to the ACPI table header.
+*/
+#define DUMP_ACPI_TABLE_HEADER(AcpiHeader)                        \
+          DEBUG ((                                                \
+            DEBUG_INFO,                                           \
+            "ACPI TABLE %c%c%c%c : Rev 0x%x : Length : 0x%x\n",   \
+            (AcpiHeader->Signature & 0xFF),                       \
+            ((AcpiHeader->Signature >> 8) & 0xFF),                \
+            ((AcpiHeader->Signature >> 16) & 0xFF),               \
+            ((AcpiHeader->Signature >> 24) & 0xFF),               \
+            AcpiHeader->Revision,                                 \
+            AcpiHeader->Length                                    \
+            ));
+
+/** Forward declarations.
+*/
+typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
+typedef struct CmAStdObjAcpiTableInfo       CM_STD_OBJ_ACPI_TABLE_INFO;
+typedef struct AcpiTableGenerator           ACPI_TABLE_GENERATOR;
+
+/** This function pointer describes the interface to ACPI table build
+    functions provided by the ACPI table generator and called by the
+    Table Manager to build an ACPI table.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
+    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
+                                 Protocol interface.
+    @param [out] Table           Pointer to the generated ACPI table.
+
+    @returns  EFI_SUCCESS If the table is generated successfully or other
+                          failure codes as returned by the generator.
+*/
+typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_BUILD_TABLE) (
+  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        **       Table
+  );
+
+/** This function pointer describes the interface to used by the
+    Table Manager to give the generator an opportunity to free
+    any resources allocated for building the ACPI table.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
+    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
+                                 Protocol interface.
+    @param [in]  Table           Pointer to the generated ACPI table.
+
+    @returns EFI_SUCCESS  If freed successfully or other failure codes
+                          as returned by the generator.
+*/
+typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_FREE_TABLE) (
+  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        **       Table
+  );
+
+/** The ACPI_TABLE_GENERATOR structure provides an interface that the
+    Table Manager can use to invoke the functions to build ACPI tables.
+
+*/
+typedef struct AcpiTableGenerator {
+  /// The ACPI table generator ID.
+  ACPI_TABLE_GENERATOR_ID                GeneratorID;
+
+  /// String describing the ACPI table
+  /// generator.
+  CONST CHAR16                         * Description;
+
+  /// The ACPI table signature.
+  UINT32                                 AcpiTableSignature;
+
+  /// The ACPI table revision.
+  UINT32                                 AcpiTableRevision;
+
+  /// The ACPI table creator ID.
+  UINT32                                 CreatorId;
+
+  /// The ACPI table creator revision.
+  UINT32                                 CreatorRevision;
+
+  /// ACPI table build function pointer.
+  ACPI_TABLE_GENERATOR_BUILD_TABLE       BuildAcpiTable;
+
+  /// The function to free any resources
+  /// allocated for building the ACPI table.
+  ACPI_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
+} ACPI_TABLE_GENERATOR;
+
+/** Register ACPI table factory generator.
+
+    The ACPI table factory maintains a list of the Standard and OEM ACPI
+    table generators.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+
+    @retval EFI_SUCCESS           The Generator was registered
+                                  successfully.
+    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
+                                  the Generator pointer is NULL.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
+                                  already registered.
+*/
+EFI_STATUS
+EFIAPI
+RegisterAcpiTableGenerator (
+  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
+  );
+
+/** Unregister ACPI generator.
+
+    This function is called by the ACPI table generator to unregister itself
+    from the ACPI table factory.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The generator is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+UnRegisterAcpiTableGenerator (
+  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
+  );
+
+#pragma pack()
+
+#endif // ACPI_TABLE_GENERATOR_H_
+
diff --git a/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
new file mode 100644
index 0000000000000000000000000000000000000000..dbc909894d17ba9df7a78c2d8be797adabb49a34
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
@@ -0,0 +1,367 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+    - Std or STD - Standard
+**/
+
+#ifndef ARM_NAMESPACE_OBJECTS_H_
+#define ARM_NAMESPACE_OBJECTS_H_
+#pragma pack(1)
+
+/** The EARM_OBJECT_ID enum describes the Object IDs
+    in the ARM Namespace
+*/
+typedef enum ArmObjectID {
+  EArmObjReserved,                    ///<  0 - Reserved.
+  EArmObjBootArchInfo,                ///<  1 - Boot Architecture Info
+  EArmObjCpuInfo,                     ///<  2 - CPU Info
+  EArmObjPowerManagementProfileInfo,  ///<  3 - Power Management Profile Info
+  EArmObjGicCInfo,                    ///<  4 - GIC CPU Interface Info
+  EArmObjGicDInfo,                    ///<  5 - GIC Distributor Info
+  EArmObjGicMsiFrameInfo,             ///<  6 - GIC MSI Frame Info
+  EArmObjGicRedistributorInfo,        ///<  7 - GIC Redistributor Info
+  EArmObjGicItsInfo,                  ///<  8 - GIC ITS Info
+  EArmObjSerialConsolePortInfo,       ///<  9 - Serial Console Port Info
+  EArmObjSerialDebugPortInfo,         ///< 10 - Serial Debug Port Info
+  EArmObjGenericTimerInfo,            ///< 11 - Generic Timer Info
+  EArmObjPlatformGTBlockInfo,         ///< 12 - Platform GT Block Info
+  EArmObjPlatformGenericWatchdogInfo, ///< 13 - Platform Generic Watchdog
+  EArmObjPciConfigSpaceInfo,          ///< 14 - PCI Configuration Space Info
+  EArmObjHypervisorVendorIdentity,    ///< 15 - Hypervisor Vendor Id
+  EArmObjMax
+} EARM_OBJECT_ID;
+
+/** A structure that describes the
+    ARM Boot Architecture flags.
+*/
+typedef struct CmArmBootArchInfo {
+  /// This is the ARM_BOOT_ARCH flags field of the FADT Table
+  /// described in the ACPI Table Specification.
+  UINT32  BootArchFlags;
+} CM_ARM_BOOT_ARCH_INFO;
+
+typedef struct CmArmCpuInfo {
+  // Reserved for use when SMBIOS tables are implemented.
+} CM_ARM_CPU_INFO;
+
+typedef struct CmArmCpuInfoList {
+  UINT32             CpuCount;
+  CM_ARM_CPU_INFO  * CpuInfo;
+} CM_ARM_CPU_INFO_LIST;
+
+/** A structure that describes the
+    Power Management Profile Information for the Platform.
+*/
+typedef struct CmArmPowerManagementProfileInfo {
+  /// This is the Preferred_PM_Profile field of the FADT Table
+  /// described in the ACPI Specification
+  UINT8  PowerManagementProfile;
+} CM_ARM_POWER_MANAGEMENT_PROFILE_INFO;
+
+/** A structure that describes the
+    GIC CPU Interface for the Platform.
+*/
+typedef struct CmArmGicCInfo {
+  /// The GIC CPU Interface number.
+  UINT32  CPUInterfaceNumber;
+
+  /// The ACPI Processor UID. This must match the
+  /// _UID of the CPU Device object information described
+  /// in the DSDT/SSDT for the CPU.
+  UINT32  AcpiProcessorUid;
+
+  /// The flags field as described by the GICC structure
+  /// in the ACPI Specification.
+  UINT32  Flags;
+
+  /// The parking protocol version field as described by
+  /// the GICC structure in the ACPI Specification.
+  UINT32  ParkingProtocolVersion;
+
+  /// The Performance Interrupt field as described by
+  /// the GICC structure in the ACPI Specification.
+  UINT32  PerformanceInterruptGsiv;
+
+  /// The CPU Parked address field as described by
+  /// the GICC structure in the ACPI Specification.
+  UINT64  ParkedAddress;
+
+  /// The base address for the GIC CPU Interface
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  PhysicalBaseAddress;
+
+  /// The base address for GICV interface
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  GICV;
+
+  /// The base address for GICH interface
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  GICH;
+
+  /// The GICV maintainence interrupt
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT32  VGICMaintenanceInterrupt;
+
+  /// The base address for GICR interface
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  GICRBaseAddress;
+
+  /// The MPIDR for the CPU
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT64  MPIDR;
+
+  /// The Processor Power Efficiency class
+  /// as described by the GICC structure in the
+  /// ACPI Specification.
+  UINT8   ProcessorPowerEfficiencyClass;
+} CM_ARM_GICC_INFO;
+
+/** A structure that describes the
+    GIC Distributor information for the Platform.
+*/
+typedef struct CmArmGicDInfo {
+  /// The GIC Distributor ID.
+  UINT32  GicId;
+
+  /// The Physical Base address
+  /// for the GIC Distributor.
+  UINT64  PhysicalBaseAddress;
+
+  /// The global system interrupt
+  /// number where this GIC Distributor's
+  /// interrupt inputs start.
+  UINT32  SystemVectorBase;
+
+  /// The GIC version as described
+  /// by the GICD structure in the
+  /// ACPI Specification.
+  UINT8   GicVersion;
+} CM_ARM_GICD_INFO;
+
+/** A structure that describes the
+    GIC MSI Frame information for the Platform.
+*/
+typedef struct CmArmGicMsiFrameInfo {
+  /// The GIC MSI Frame ID
+  UINT32  GicMsiFrameId;
+
+  /// The Physical base address for the
+  /// MSI Frame.
+  UINT64  PhysicalBaseAddress;
+
+  /// The GIC MSI Frame flags
+  /// as described by the GIC MSI frame
+  /// structure in the ACPI Specification.
+  UINT32  Flags;
+
+  /// SPI Count used by this frame.
+  UINT16  SPICount;
+
+  /// SPI Base used by this frame.
+  UINT16  SPIBase;
+} CM_ARM_GIC_MSI_FRAME_INFO;
+
+/** A structure that describes the
+    GIC Redistributor information for the Platform.
+*/
+typedef struct CmArmGicRedistInfo {
+  /// The physical address of a page range
+  /// containing all GIC Redistributors.
+  UINT64  DiscoveryRangeBaseAddress;
+
+  /// Length of the GIC Redistributor
+  /// Discovery page range
+  UINT32  DiscoveryRangeLength;
+} CM_ARM_GIC_REDIST_INFO;
+
+/** A structure that describes the
+    GIC Interrupt Translation Service information for the Platform.
+*/
+typedef struct CmArmGicItsInfo {
+  /// The GIC ITS ID.
+  UINT32  GicItsId;
+
+  /// The physical address for the
+  /// Interrupt Translation Service
+  UINT64  PhysicalBaseAddress;
+} CM_ARM_GIC_ITS_INFO;
+
+/** A structure that describes the
+    Serial Port information for the Platform.
+*/
+typedef struct CmArmSerialPortInfo {
+  /// The physical base address for the
+  /// serial port.
+  UINT64  BaseAddress;
+
+  /// The serial port interrupt.
+  UINT32  Interrupt;
+
+  /// The serial port baud rate.
+  UINT64  BaudRate;
+
+  /// The serial port clock.
+  UINT32  Clock;
+} CM_ARM_SERIAL_PORT_INFO;
+
+/** A structure that describes the
+    Generic Timer information for the Platform.
+*/
+typedef struct CmArmGenericTimerInfo {
+  /// The physical base address for the
+  /// counter control frame.
+  UINT64  CounterControlBaseAddress;
+
+  /// The physical base address for the
+  /// counter read frame.
+  UINT64  CounterReadBaseAddress;
+
+  /// The secure PL1 timer interrupt.
+  UINT32  SecurePL1TimerGSIV;
+
+  /// The secure PL1 timer flags.
+  UINT32  SecurePL1TimerFlags;
+
+  /// The non-secure PL1 timer interrupt.
+  UINT32  NonSecurePL1TimerGSIV;
+
+  /// The non-secure PL1 timer flags.
+  UINT32  NonSecurePL1TimerFlags;
+
+  /// The virtual timer interrupt.
+  UINT32  VirtualTimerGSIV;
+
+  /// The virtual timer flags.
+  UINT32  VirtualTimerFlags;
+
+  /// The non-secure PL2 timer interrupt.
+  UINT32  NonSecurePL2TimerGSIV;
+
+  /// The non-secure PL2 timer flags.
+  UINT32  NonSecurePL2TimerFlags;
+} CM_ARM_GENERIC_TIMER_INFO;
+
+/** A structure that describes the
+    Platform Generic Block Timer Frame information for the Platform.
+*/
+typedef struct CmArmGTBlockTimerFrameInfo {
+  /// The Generic Timer frame number.
+  UINT8   FrameNumber;
+
+  /// The physical base address
+  /// for the CntBase block.
+  UINT64  PhysicalAddressCntBase;
+
+  /// The physical base address
+  /// for the CntEL0Base block.
+  UINT64  PhysicalAddressCntEL0Base;
+
+  /// The physical timer interrupt.
+  UINT32  PhysicalTimerGSIV;
+
+  /// The physical timer flags
+  /// as described by the GT Block
+  /// Timer frame Structure in the
+  /// ACPI Specification.
+  UINT32  PhysicalTimerFlags;
+
+  /// The virtual timer interrupt.
+  UINT32  VirtualTimerGSIV;
+
+  /// The virtual timer flags
+  /// as described by the GT Block
+  /// Timer frame Structure in the
+  /// ACPI Specification.
+  UINT32  VirtualTimerFlags;
+
+  /// The common timer flags
+  /// as described by the GT Block
+  /// Timer frame Structure in the
+  /// ACPI Specification.
+  UINT32  CommonFlags;
+} CM_ARM_GTBLOCK_TIMER_FRAME_INFO;
+
+/** A structure that describes the
+    Platform Generic Block Timer information for the Platform.
+*/
+typedef struct CmArmGTBlockInfo {
+  /// The physical base address for
+  /// the GT Block Timer structure.
+  UINT64                             GTBlockPhysicalAddress;
+
+  /// The number of timer frames
+  /// implemented in the GT Block.
+  UINT32                             GTBlockTimerFrameCount;
+
+  /// Pointer to the GT Block timer
+  /// frame list.
+  CM_ARM_GTBLOCK_TIMER_FRAME_INFO  * GTBlockTimerFrameList;
+} CM_ARM_GTBLOCK_INFO;
+
+/** A structure that describes the
+    SBSA Generic Watchdog information for the Platform.
+*/
+typedef struct CmArmGenericWatchdogInfo {
+  /// The physical base address of the
+  /// SBSA Watchdog control frame.
+  UINT64  ControlFrameAddress;
+
+  /// The physical base address of the
+  /// SBSA Watchdog refresh frame.
+  UINT64  RefreshFrameAddress;
+
+  /// The watchdog interrupt.
+  UINT32  TimerGSIV;
+
+  /// The flags for the watchdog
+  /// as described by the SBSA watchdog
+  /// structure in the ACPI specification.
+  UINT32  Flags;
+} CM_ARM_GENERIC_WATCHDOG_INFO;
+
+/** A structure that describes the
+    PCI Configuration Space information for the Platform.
+*/
+typedef struct CmArmPciConfigSpaceInfo {
+  /// The physical base address for the PCI segment.
+  UINT64  BaseAddress;
+
+  /// The PCI segment group number.
+  UINT16  PciSegmentGroupNumber;
+
+  /// The start bus number.
+  UINT8   StartBusNumber;
+
+  /// The end bus number.
+  UINT8   EndBusNumber;
+} CM_ARM_PCI_CONFIG_SPACE_INFO;
+
+/** A structure that describes the
+    Hypervisor Vendor ID information for the Platform.
+*/
+typedef struct CmArmHypervisorVendorId {
+  /// The hypervisor Vendor ID.
+  UINT64  HypervisorVendorId;
+} CM_ARM_HYPERVISOR_VENDOR_ID;
+
+#pragma pack()
+
+#endif // ARM_NAMESPACE_OBJECTS_H_
diff --git a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..23edd7c343bd09476692d2fb8af088d95b8ff28d
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
@@ -0,0 +1,112 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef CONFIGURATION_MANAGER_HELPER_H_
+#define CONFIGURATION_MANAGER_HELPER_H_
+
+/** The GET_OBJECT_LIST macro expands to a function that is used to retrieve
+    an object or an object list from the Configuration Manager using the
+    Configuration Manager Protocol interface.
+
+    The macro expands to a function which has the following prototype:
+
+    STATIC
+    EFI_STATUS
+    EFIAPI
+    Get<CmObjectId> (
+      IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+      OUT       Type                              **       List,
+      OUT       UINTN                              *       Count OPTIONAL
+      );
+
+    Generated function parameters:
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
+                                  interface.
+    @param [out] List           Pointer to the Object list.
+    @param [out] Count          Count of the objects returned in the list.
+
+    Macro Parameters:
+    @param [in] CmObjectNameSpace The Object Namespace
+    @param [in] CmObjectId        Object Id.
+    @param [in] Type              Structure used to describe the Object.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object information is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)                      \
+STATIC                                                                            \
+EFI_STATUS                                                                        \
+EFIAPI                                                                            \
+Get##CmObjectId (                                                                 \
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,           \
+  OUT       Type                               **       List,                     \
+  OUT       UINTN                               * CONST Count OPTIONAL            \
+  )                                                                               \
+{                                                                                 \
+  EFI_STATUS         Status;                                                      \
+  CM_OBJ_DESCRIPTOR  CmObjectDesc;                                                \
+  UINTN              ObjCount = 0;                                                \
+  if (List == NULL) {                                                             \
+    Status = EFI_INVALID_PARAMETER;                                               \
+    DEBUG ((                                                                      \
+      DEBUG_ERROR,                                                                \
+      "ERROR: Get" #CmObjectId ": Invalid out parameter for"                      \
+      " object list. Status = %r\n",                                              \
+      Status                                                                      \
+      ));                                                                         \
+    goto error_handler;                                                           \
+  }                                                                               \
+  Status = CfgMgrProtocol->GetObject (                                            \
+                             CfgMgrProtocol,                                      \
+                             CREATE_CM_OBJECT_ID (CmObjectNameSpace, CmObjectId), \
+                             &CmObjectDesc                                        \
+                             );                                                   \
+  if (EFI_ERROR (Status)) {                                                       \
+    DEBUG ((                                                                      \
+      DEBUG_WARN,                                                                 \
+      "WARNING: Get" #CmObjectId ": Platform does not implement "                 \
+      #CmObjectId ". Status = %r\n",                                              \
+      Status                                                                      \
+      ));                                                                         \
+    *List = NULL;                                                                 \
+    goto error_handler;                                                           \
+  }                                                                               \
+  if (CmObjectDesc.Size < sizeof (Type)) {                                        \
+    DEBUG ((                                                                      \
+      DEBUG_ERROR,                                                                \
+      "ERROR: Get" #CmObjectId ": " #CmObjectId                                   \
+      ": Buffer too small, size = 0x%x\n",                                        \
+      CmObjectDesc.Size                                                           \
+      ));                                                                         \
+    ASSERT (CmObjectDesc.Size >= sizeof (Type));                                  \
+    Status = EFI_BAD_BUFFER_SIZE;                                                 \
+    goto error_handler;                                                           \
+  }                                                                               \
+  ObjCount = CmObjectDesc.Size / sizeof (Type);                                   \
+  *List = (Type*)CmObjectDesc.Data;                                               \
+error_handler:                                                                    \
+  if (Count != NULL) {                                                            \
+    *Count = ObjCount;                                                            \
+  }                                                                               \
+  return Status;                                                                  \
+}
+
+#endif // CONFIGURATION_MANAGER_HELPER_H_
diff --git a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
new file mode 100644
index 0000000000000000000000000000000000000000..99afab094328cf830831899011a7f6fca1d6e5f2
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
@@ -0,0 +1,158 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef CONFIGURATION_MANAGER_OBJECT_H_
+#define CONFIGURATION_MANAGER_OBJECT_H_
+
+#pragma pack(1)
+
+/** The CM_OBJECT_ID type is used to identify the Configration Manager objects.
+
+ Description of Configuration Manager Object ID
+________________________________________________________________________________
+|31 |30 |29 |28 || 27 | 26 | 25 | 24 || 23 | 22 | 21 | 20 || 19 | 18 | 17 | 16 |
+--------------------------------------------------------------------------------
+| Name Space ID ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 |
+________________________________________________________________________________
+
+Bits: [31:28] - Name Space ID
+                0000 - Standard
+                0001 - ARM
+                1000 - Custom/OEM
+                All other values are reserved.
+
+Bits: [27:16] - Reserved.
+________________________________________________________________________________
+|15 |14 |13 |12 || 11 | 10 |  9 |  8 ||  7 |  6 |  5 |  4 ||  3 |  2 |  1 |  0 |
+--------------------------------------------------------------------------------
+| 0 | 0 | 0 | 0 ||  0 |  0 |  0 |  0 ||                 Object ID              |
+________________________________________________________________________________
+
+Bits: [15:8] - Are reserved and must be zero.
+
+Bits: [7:0] - Object ID
+
+Object ID's in the Standard Namespace:
+  0 - Configuration Manager Revision
+  1 - ACPI Table List
+  2 - SMBIOS Table List
+
+Object ID's in the ARM Namespace:
+   0 - Reserved
+   1 - Boot Architecture Info
+   2 - CPU Info
+   3 - Power Management Profile Info
+   4 - GICC Info
+   5 - GICD Info
+   6 - GIC MSI Frame Info
+   7 - GIC Redistributor Info
+   8 - GIC ITS Info
+   9 - Serial Console Port Info
+  10 - Serial Debug Port Info
+  12 - Generic Timer Info
+  13 - Platform GT Block Info
+  14 - Platform Generic Watchdog
+  15 - PCI Configuration Space Info
+  16 - Hypervisor Vendor Id
+*/
+typedef UINT32  CM_OBJECT_ID;
+
+/** The EOBJECT_NAMESPACE_ID enum describes the defined namespaces
+    for the Confguration Manager Objects.
+*/
+typedef enum ObjectNameSpaceID {
+  EObjNameSpaceStandard,      ///< Standard Objects Namespace
+  EObjNameSpaceArm,           ///< ARM Objects Namespace
+  EObjNameSpaceOem = 0x8,     ///< OEM Objects Namespace
+  EObjNameSpaceMax
+} EOBJECT_NAMESPACE_ID;
+
+/** The CM_OBJ_DESCRIPTOR structure describes the Configuration
+    Manager Object descriptor. The Configuration Manager Protocol
+    interface uses this descriptor to return the Configuration
+    Manager Objects.
+*/
+typedef struct CmObjDescriptor {
+  /// Size of the Object or Object List
+  /// described by this descriptor.
+  UINT32   Size;
+
+  /// Pointer to the Object or Object List
+  /// described by this descriptor.
+  UINTN  * Data;
+} CM_OBJ_DESCRIPTOR;
+
+#pragma pack()
+
+/** This macro returns the namespace ID from the CmObjectID.
+
+  @param [in] CmObjectId  The Configuration Manager Object ID.
+
+  @retval Returns the Namespace ID corresponding to the CmObjectID.
+*/
+#define GET_CM_NAMESPACE_ID(CmObjectId) (((CmObjectId) >> 28) & 0xF)
+
+/** This macro returns the Object ID from the CmObjectID.
+
+  @param [in] CmObjectId  The Configuration Manager Object ID.
+
+  @retval Returns the Object ID corresponding to the CmObjectID.
+*/
+#define GET_CM_OBJECT_ID(CmObjectId)    ((CmObjectId) & 0xFF)
+
+/** This macro returns a Configuration Manager Object ID
+    from the NameSpace ID and the ObjectID.
+
+  @param [in] NameSpaceId The namespace ID for the Object.
+  @param [in] ObjectId    The Object ID.
+
+  @retval Returns the Configuration Manager Object ID.
+*/
+#define CREATE_CM_OBJECT_ID(NameSpaceId, ObjectId) \
+          ((((NameSpaceId) & 0xF) << 28) | ((ObjectId) & 0xF))
+
+/** This macro returns a Configuration Manager Object ID
+    in the Standard Object Namespace.
+
+  @param [in] ObjectId    The Object ID.
+
+  @retval Returns a Standard Configuration Manager Object ID.
+*/
+#define CREATE_CM_STD_OBJECT_ID(ObjectId) \
+          (CREATE_CM_OBJECT_ID (EObjNameSpaceStandard, ObjectId))
+
+/** This macro returns a Configuration Manager Object ID
+    in the ARM Object Namespace.
+
+  @param [in] ObjectId    The Object ID.
+
+  @retval Returns an ARM Configuration Manager Object ID.
+*/
+#define CREATE_CM_ARM_OBJECT_ID(ObjectId) \
+          (CREATE_CM_OBJECT_ID (EObjNameSpaceArm, ObjectId))
+
+/** This macro returns a Configuration Manager Object ID
+    in the OEM Object Namespace.
+
+  @param [in] ObjectId    The Object ID.
+
+  @retval Returns an OEM Configuration Manager Object ID.
+*/
+#define CREATE_CM_OEM_OBJECT_ID(ObjectId) \
+          (CREATE_CM_OBJECT_ID (EObjNameSpaceOem, ObjectId))
+
+#endif // CONFIGURATION_MANAGER_OBJECT_H_
diff --git a/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..10d29be800a0c126ed32dcfa070f1473a8aee7a9
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
@@ -0,0 +1,235 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef SMBIOS_TABLE_GENERATOR_H_
+#define SMBIOS_TABLE_GENERATOR_H_
+
+#pragma pack(1)
+
+/** The SMBIOS_TABLE_GENERATOR_ID type describes SMBIOS table generator ID.
+*/
+typedef TABLE_GENERATOR_ID SMBIOS_TABLE_GENERATOR_ID;
+
+/** The ESTD_SMBIOS_TABLE_ID enum describes the SMBIOS table IDs reserved for
+  the standard generators.
+
+  NOTE: The SMBIOS Generator IDs do not match the table type numbers!
+          This allows 0 to be used to catch invalid parameters.
+*/
+typedef enum StdSmbiosTableGeneratorId {
+  ESTD_SMBIOS_TABLE_ID_RESERVED = 0x0000,
+  ESTD_SMBIOS_TABLE_ID_RAW,
+  ESTD_SMBIOS_TABLE_ID_TYPE00,
+  ESTD_SMBIOS_TABLE_ID_TYPE01,
+  ESTD_SMBIOS_TABLE_ID_TYPE02,
+  ESTD_SMBIOS_TABLE_ID_TYPE03,
+  ESTD_SMBIOS_TABLE_ID_TYPE04,
+  ESTD_SMBIOS_TABLE_ID_TYPE05,
+  ESTD_SMBIOS_TABLE_ID_TYPE06,
+  ESTD_SMBIOS_TABLE_ID_TYPE07,
+  ESTD_SMBIOS_TABLE_ID_TYPE08,
+  ESTD_SMBIOS_TABLE_ID_TYPE09,
+  ESTD_SMBIOS_TABLE_ID_TYPE10,
+  ESTD_SMBIOS_TABLE_ID_TYPE11,
+  ESTD_SMBIOS_TABLE_ID_TYPE12,
+  ESTD_SMBIOS_TABLE_ID_TYPE13,
+  ESTD_SMBIOS_TABLE_ID_TYPE14,
+  ESTD_SMBIOS_TABLE_ID_TYPE15,
+  ESTD_SMBIOS_TABLE_ID_TYPE16,
+  ESTD_SMBIOS_TABLE_ID_TYPE17,
+  ESTD_SMBIOS_TABLE_ID_TYPE18,
+  ESTD_SMBIOS_TABLE_ID_TYPE19,
+  ESTD_SMBIOS_TABLE_ID_TYPE20,
+  ESTD_SMBIOS_TABLE_ID_TYPE21,
+  ESTD_SMBIOS_TABLE_ID_TYPE22,
+  ESTD_SMBIOS_TABLE_ID_TYPE23,
+  ESTD_SMBIOS_TABLE_ID_TYPE24,
+  ESTD_SMBIOS_TABLE_ID_TYPE25,
+  ESTD_SMBIOS_TABLE_ID_TYPE26,
+  ESTD_SMBIOS_TABLE_ID_TYPE27,
+  ESTD_SMBIOS_TABLE_ID_TYPE28,
+  ESTD_SMBIOS_TABLE_ID_TYPE29,
+  ESTD_SMBIOS_TABLE_ID_TYPE30,
+  ESTD_SMBIOS_TABLE_ID_TYPE31,
+  ESTD_SMBIOS_TABLE_ID_TYPE32,
+  ESTD_SMBIOS_TABLE_ID_TYPE33,
+  ESTD_SMBIOS_TABLE_ID_TYPE34,
+  ESTD_SMBIOS_TABLE_ID_TYPE35,
+  ESTD_SMBIOS_TABLE_ID_TYPE36,
+  ESTD_SMBIOS_TABLE_ID_TYPE37,
+  ESTD_SMBIOS_TABLE_ID_TYPE38,
+  ESTD_SMBIOS_TABLE_ID_TYPE39,
+  ESTD_SMBIOS_TABLE_ID_TYPE40,
+  ESTD_SMBIOS_TABLE_ID_TYPE41,
+  ESTD_SMBIOS_TABLE_ID_TYPE42,
+
+  // IDs 43 - 125 are reserved
+
+  ESTD_SMBIOS_TABLE_ID_TYPE126 = (ESTD_SMBIOS_TABLE_ID_TYPE00 + 126),
+  ESTD_SMBIOS_TABLE_ID_TYPE127,
+  ESTD_SMBIOS_TABLE_ID_MAX
+} ESTD_SMBIOS_TABLE_ID;
+
+/** This macro checks if the Table Generator ID is for an SMBIOS Table
+    Generator.
+    @param [in] TableGeneratorId  The table generator ID.
+
+    @returns  TRUE if the table generator ID is for an SMBIOS Table
+              Generator.
+*/
+#define IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId) \
+          (                                        \
+          GET_TABLE_TYPE (TableGeneratorId) ==     \
+          ETableGeneratorTypeSmbios                \
+          )
+
+/** This macro checks if the Table Generator ID is for a standard SMBIOS
+    Table Generator.
+
+    @param [in] TableGeneratorId  The table generator ID.
+
+    @returns  TRUE if the table generator ID is for a standard SMBIOS
+              Table Generator.
+*/
+#define IS_VALID_STD_SMBIOS_GENERATOR_ID(TableGeneratorId)            \
+          (                                                           \
+          IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) &&             \
+          IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId)   &&             \
+          ((GET_TABLE_ID(GeneratorId) >= ESTD_SMBIOS_TABLE_ID_RAW) && \
+           (GET_TABLE_ID(GeneratorId) < ESTD_SMIOS_TABLE_ID_MAX))     \
+          )
+
+/** This macro creates a standard SMBIOS Table Generator ID.
+
+    @param [in] TableId  The table generator ID.
+
+    @returns a standard SMBIOS table generator ID.
+*/
+#define CREATE_STD_SMBIOS_TABLE_GEN_ID(TableId) \
+          CREATE_TABLE_GEN_ID (                 \
+            ETableGeneratorTypeSmbios,          \
+            ETableGeneratorNameSpaceStd,        \
+            TableId                             \
+            )
+
+/** Forward declarations.
+*/
+typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
+typedef struct CmStdObjSmbiosTableInfo      CM_STD_OBJ_SMBIOS_TABLE_INFO;
+typedef struct SmbiosTableGenerator         SMBIOS_TABLE_GENERATOR;
+
+/** This function pointer describes the interface to SMBIOS table build
+    functions provided by the SMBIOS table generator and called by the
+    Table Manager to build an SMBIOS table.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
+    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
+                                 Protocol interface.
+    @param [out] Table           Pointer to the generated SMBIOS table.
+
+    @returns EFI_SUCCESS  If the table is generated successfully or other
+                          failure codes as returned by the generator.
+*/
+typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLE) (
+  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
+  IN        CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       SMBIOS_STRUCTURE                   **       Table
+  );
+
+/** This function pointer describes the interface to used by the
+    Table Manager to give the generator an opportunity to free
+    any resources allocated for building the SMBIOS table.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
+    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
+                                 Protocol interface.
+    @param [in]  Table           Pointer to the generated SMBIOS table.
+
+    @returns  EFI_SUCCESS If freed successfully or other failure codes
+                          as returned by the generator.
+*/
+typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLE) (
+  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
+  IN  CONST CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        SMBIOS_STRUCTURE                   **       Table
+  );
+
+/** The SMBIOS_TABLE_GENERATOR structure provides an interface that the
+    Table Manager can use to invoke the functions to build SMBIOS tables.
+
+*/
+typedef struct SmbiosTableGenerator {
+  /// The SMBIOS table generator ID.
+  SMBIOS_TABLE_GENERATOR_ID                GeneratorID;
+
+  /// String describing the DT table
+  /// generator.
+  CONST CHAR16*                            Description;
+
+  /// The SMBIOS table type.
+  SMBIOS_TYPE                              Type;
+
+  /// SMBIOS table build function pointer.
+  SMBIOS_TABLE_GENERATOR_BUILD_TABLE       BuildSmbiosTable;
+
+  /// The function to free any resources
+  /// allocated for building the SMBIOS table.
+  SMBIOS_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
+} SMBIOS_TABLE_GENERATOR;
+
+/** Register SMBIOS table factory generator.
+
+    The SMBIOS table factory maintains a list of the Standard and OEM SMBIOS
+    table generators.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+
+    @retval EFI_SUCCESS           The Generator was registered
+                                  successfully.
+    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
+                                  the Generator pointer is NULL.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
+                                  already registered.
+*/
+EFI_STATUS
+EFIAPI
+RegisterSmbiosTableGenerator (
+  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
+  );
+
+/** Unregister SMBIOS generator.
+
+    This function is called by the SMBIOS table generator to unregister itself
+    from the SMBIOS table factory.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The generator is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+UnRegisterSmbiosTableGenerator (
+  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
+  );
+#pragma pack()
+
+#endif // SMBIOS_TABLE_GENERATOR_H_
+
diff --git a/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
new file mode 100644
index 0000000000000000000000000000000000000000..76ae3f2208a5c80f0ca10b75e5df94cbb43e4688
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
@@ -0,0 +1,93 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+    - Std or STD - Standard
+**/
+
+#ifndef STANDARD_NAMESPACE_OBJECTS_H_
+#define STANDARD_NAMESPACE_OBJECTS_H_
+
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+
+#pragma pack(1)
+
+/** The ESTD_OBJECT_ID enum describes the Object IDs
+    in the Standard Namespace.
+*/
+typedef enum StdObjectID {
+  EStdObjCfgMgrInfo = 0x00000000, ///< 0 - Configuration Manager Info
+  EStdObjAcpiTableList,           ///< 1 - ACPI table Info List
+  EStdObjSmbiosTableList,         ///< 2 - SMBIOS table Info List
+  EStdObjMax
+} ESTD_OBJECT_ID;
+
+/** A structure that describes the Configuration Manager Information.
+*/
+typedef struct CmStdObjConfigurationManagerInfo {
+  /// The Configuration Manager Revision.
+  UINT32  Revision;
+
+  /// The OEM ID. This information is used to
+  /// populate the ACPI table header information.
+  UINT8   OemId[6];
+} CM_STD_OBJ_CONFIGURATION_MANAGER_INFO;
+
+/** A structure used to describe the ACPI table generators to be invoked.
+
+    The AcpiTableData member of this structure may be used to directly provide
+    the binary ACPI table data which is required by the following standard
+    generators:
+      - RAW
+      - DSDT
+      - SSDT
+
+    Providing the ACPI table data is optional and depends on the generator
+    that is being invoked. If unused, set AcpiTableData to NULL.
+*/
+typedef struct CmAStdObjAcpiTableInfo {
+  /// The signature of the ACPI Table to be installed.
+  UINT32                         AcpiTableSignature;
+
+  /// The ACPI Table Generator ID.
+  ACPI_TABLE_GENERATOR_ID        TableGeneratorId;
+
+  /// Optional pointer to the ACPI table data.
+  EFI_ACPI_DESCRIPTION_HEADER  * AcpiTableData;
+
+} CM_STD_OBJ_ACPI_TABLE_INFO;
+
+/** A structure used to describe the SMBIOS table generators to be invoked.
+
+    The SmbiosTableData member of this structure is used to provide
+    the SMBIOS table data which is required by the following standard
+    generator(s):
+      - RAW
+
+    Providing the SMBIOS table data is optional and depends on the
+    generator that is being invoked. If unused, set the SmbiosTableData
+    to NULL.
+*/
+typedef struct CmStdObjSmbiosTableInfo {
+  /// The SMBIOS Table Generator ID.
+  SMBIOS_TABLE_GENERATOR_ID   TableGeneratorId;
+
+  /// Optional pointer to the SMBIOS table data.
+  SMBIOS_STRUCTURE           * SmbiosTableData;
+} CM_STD_OBJ_SMBIOS_TABLE_INFO;
+
+#pragma pack()
+
+#endif // STANDARD_NAMESPACE_OBJECTS_H_
diff --git a/MdeModulePkg/Include/DynamicTables/TableGenerator.h b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..93d557273459948f5211e1c26a6028fc12b181fb
--- /dev/null
+++ b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
@@ -0,0 +1,235 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - ACPI   - Advanced Configuration and Power Interface
+    - SMBIOS - System Management BIOS
+    - DT     - Device Tree
+**/
+
+#ifndef TABLE_GENERATOR_H_
+#define TABLE_GENERATOR_H_
+
+/** The TABLE_GENERATOR_ID type describes the Table Generator ID
+
+  Table Generator ID
+
+________________________________________________________________________________
+|  31 | 30 |29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16|
+--------------------------------------------------------------------------------
+|TNSID|  0 |   TT   |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0|  0 |
+________________________________________________________________________________
+
+
+________________________________________________________________________________
+|15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
+--------------------------------------------------------------------------------
+|                                 Table ID                                     |
+________________________________________________________________________________
+
+
+  Bit [31] - Table NameSpace ID (TNSID)
+      0 - Standard
+      1 - Custom/OEM
+
+  Bit [30] - Reserved, Must be Zero
+
+  Bit [29:28] - Table Type (TT)
+       0 - ACPI Table
+       1 - SMBIOS Table
+       2 - DT (Device Tree) Table
+       3 - Reserved (INVALID)
+
+  Bit [27:16] - Reserved, Must Be Zero
+
+  Bit [15:0] - Table ID
+
+    Standard ACPI Table IDs:
+       0 - Reserved
+       1 - RAW
+       2 - FADT
+       3 - DSDT
+       4 - SSDT
+       5 - MADT
+       6 - GTDT
+       7 - DBG2
+       8 - SPCR
+       9 - MCFG
+
+
+    Standard SMBIOS Table IDs:
+       0 - Reserved
+       1 - RAW
+       2 - Table Type00
+       3 - Table Type01
+       4 - Table Type02
+       5 - Table Type03
+       6 - Table Type04
+       7 - Table Type05
+       8 - Table Type06
+       9 - Table Type07
+      10 - Table Type08
+      11 - Table Type09
+      12 - Table Type10
+      13 - Table Type11
+      14 - Table Type12
+      15 - Table Type13
+      16 - Table Type14
+      17 - Table Type15
+      18 - Table Type16
+      19 - Table Type17
+      20 - Table Type18
+      21 - Table Type19
+      22 - Table Type20
+      23 - Table Type21
+      24 - Table Type22
+      25 - Table Type23
+      26 - Table Type24
+      27 - Table Type25
+      28 - Table Type26
+      29 - Table Type27
+      30 - Table Type28
+      31 - Table Type29
+      32 - Table Type30
+      33 - Table Type31
+      34 - Table Type32
+      35 - Table Type33
+      36 - Table Type34
+      37 - Table Type35
+      38 - Table Type36
+      39 - Table Type37
+      40 - Table Type38
+      41 - Table Type39
+      42 - Table Type40
+      43 - Table Type41
+      44 - Table Type42
+  45-127 - Reserved
+     128 - Table Type126
+     129 - Table Type127
+**/
+typedef UINT32  TABLE_GENERATOR_ID;
+
+/** This enum lists the Table Generator Types.
+*/
+typedef enum TableGeneratorType {
+  ETableGeneratorTypeAcpi = 0,  ///< ACPI Table Generator Type.
+  ETableGeneratorTypeSmbios,    ///< SMBIOS Table Generator Type.
+  ETableGeneratorTypeDt,        ///< Device Tree Table Generator Type.
+  ETableGeneratorTypeReserved
+} ETABLE_GENERATOR_TYPE;
+
+/** This enum lists the namespaces for the Table Generators.
+*/
+typedef enum TableGeneratorNameSpace {
+  ETableGeneratorNameSpaceStd = 0,  ///< Standard Namespace.
+  ETableGeneratorNameSpaceOem       ///< OEM Namespace.
+} ETABLE_GENERATOR_NAMESPACE;
+
+/** A mask for the Table ID bits of TABLE_GENERATOR_ID.
+*/
+#define TABLE_ID_MASK             0xFF
+
+/** A mask for the Namespace ID bits of TABLE_GENERATOR_ID.
+*/
+#define TABLE_NAMESPACEID_MASK    (BIT31)
+
+/** A mask for the Table Type bits of TABLE_GENERATOR_ID.
+*/
+#define TABLE_TYPE_MASK           (BIT29 | BIT28)
+
+/** This macro returns the Table ID from the TableGeneratorId.
+
+    @param [in]  TableGeneratorId  The table generator ID.
+
+    @returns the Table ID described by the TableGeneratorId.
+*/
+#define GET_TABLE_ID(TableGeneratorId)                          \
+          ((TableGeneratorId) & TABLE_ID_MASK)
+
+/** This macro returns the Table type from the TableGeneratorId.
+
+    @param [in]  TableGeneratorId  The table generator ID.
+
+    @returns the Table type described by the TableGeneratorId.
+*/
+#define GET_TABLE_TYPE(TableGeneratorId)                        \
+          (((TableGeneratorId) & TABLE_TYPE_MASK) >> 28)
+
+/** This macro returns the Namespace ID from the TableGeneratorId.
+
+    @param [in]  TableGeneratorId  The table generator ID.
+
+    @returns the Namespace described by the TableGeneratorId.
+*/
+#define GET_TABLE_NAMESPACEID(TableGeneratorId)                 \
+          (((TableGeneratorId) & TABLE_NAMESPACEID_MASK) >> 31)
+
+/** This macro checks if the TableGeneratorId is in the Standard Namespace.
+
+    @param [in]  TableGeneratorId  The table generator ID.
+
+    @returns TRUE if the TableGeneratorId is in the Standard Namespace.
+*/
+#define IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) \
+          (                                          \
+          GET_TABLE_NAMESPACEID(TableGeneratorId) == \
+          ETableGeneratorNameSpaceStd                \
+          )
+
+/** This macro creates a TableGeneratorId
+
+    @param [in]  TableType        The table type.
+    @param [in]  TableNameSpaceId The namespace ID for the table.
+    @param [in]  TableId          The table ID.
+
+    @returns a TableGeneratorId calculated from the inputs.
+*/
+#define CREATE_TABLE_GEN_ID(TableType, TableNameSpaceId, TableId)  \
+          (                                                        \
+           (((TableType) << 28) & TABLE_TYPE_MASK)               | \
+           (((TableNameSpaceId) << 31) & TABLE_NAMESPACEID_MASK) | \
+           ((TableId) & TABLE_ID_MASK)                             \
+          )
+
+/** This macro generates a Major.Minor version
+    where the Major and Minor fields are 16 bit.
+
+    @param [in]  Major  The Major Revision.
+    @param [in]  Minor  The Minor Revision.
+
+    @returns a 32 bit representation of the type Major.Minor.
+*/
+#define CREATE_REVISION(Major, Minor)                            \
+          ((((Major) & 0xFFFF) << 16) | ((Minor) & 0xFFFF))
+
+/** This macro returns the Major revison
+
+    Extracts Major from the 32 bit representation of the type Major.Minor
+
+    @param [in]  Revision  The Revision value which is 32 bit.
+
+    @returns the Major part of the revision.
+*/
+#define GET_MAJOR_REVISION(Revision)  (((Revision) >> 16) & 0xFFFF)
+
+/** This macro returns the Minor revison
+
+    Extracts Minor from the 32 bit representation of the type Major.Minor
+
+    @param [in]  Revision  The Revision value which is 32 bit.
+
+    @returns the Minor part of the revision.
+*/
+#define GET_MINOR_REVISION(Revision)  ((Revision) & 0xFFFF)
+
+#endif // TABLE_GENERATOR_H_
+
diff --git a/MdeModulePkg/Include/Library/TableHelperLib.h b/MdeModulePkg/Include/Library/TableHelperLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b22e024dee1a311e4e4b532371ccef94bc02be3
--- /dev/null
+++ b/MdeModulePkg/Include/Library/TableHelperLib.h
@@ -0,0 +1,67 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef TABLE_HELPER_LIB_H_
+#define TABLE_HELPER_LIB_H_
+
+/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
+    object from the Configuration Manager.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
+                                interface.
+    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
+                                object structure.
+
+    @retval EFI_SUCCESS           The object is returned.
+    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
+    @retval EFI_NOT_FOUND         The requested Object is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size.
+*/
+EFI_STATUS
+EFIAPI
+GetCgfMgrInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST  CfgMgrProtocol,
+  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **        CfgMfrInfo
+  );
+
+/** The AddAcpiHeader function updates the ACPI header structure pointed by
+    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
+    Manager protocol to obtain any information required for constructing the
+    header.
+
+    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
+                                   protocol interface.
+    @param [in]     Generator      Pointer to the ACPI table Generator.
+    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
+                                   updated.
+    @param [in]     Length         Length of the ACPI table.
+
+    @retval EFI_SUCCESS           The ACPI table is updated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object information is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+EFI_STATUS
+EFIAPI
+AddAcpiHeader (
+  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
+  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
+  IN      CONST UINT32                                      Length
+  );
+
+#endif // TABLE_HELPER_LIB_H_
diff --git a/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..387935943648654ef095720dec452d1c15b8fc11
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
@@ -0,0 +1,121 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Cm or CM   - Configuration Manager
+    - Obj or OBJ - Object
+**/
+
+#ifndef CONFIGURATION_MANAGER_PROTOCOL_H_
+#define CONFIGURATION_MANAGER_PROTOCOL_H_
+
+/** This macro defines the Configuration Manager Protocol GUID.
+
+  GUID: {D85A4835-5A82-4894-AC02-706F43D5978E}
+*/
+#define EFI_CONFIGURATION_MANAGER_PROTOCOL_GUID         \
+  { 0xd85a4835, 0x5a82, 0x4894,                         \
+    { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e }   \
+  };
+
+/** This macro defines the Configuration Manager Protocol Revision.
+*/
+#define EFI_CONFIGURATION_MANAGER_PROTOCOL_REVISION  CREATE_REVISION (1, 0)
+
+#pragma pack(1)
+
+/**
+  Forward declarations:
+*/
+typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
+typedef struct PlatformRepositoryInfo       EFI_PLATFORM_REPOSITORY_INFO;
+
+
+/** The GetObject function defines the interface implemented by the
+    Configuration Manager Protocol for returning the Configuration
+    Manager Objects.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the requested Object.
+
+    @retval Returns:
+      EFI_SUCCESS           Success.
+      EFI_INVALID_PARAMETER A parameter is invalid.
+      EFI_NOT_FOUND         The required object information is not found.
+      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                            is less than the Object size for the requested
+                            object.
+*/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_CONFIGURATION_MANAGER_GET_OBJECT) (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  );
+
+/** The SetObject function defines the interface implemented by the
+    Configuration Manager Protocol for updating the Configuration
+    Manager Objects.
+
+    @param [in]  This        Poiner to the Configuration Manager Protocol.
+    @param [in]  CmObjectId  The Configuration Manager Object ID.
+    @param [out] CmObject    Pointer to the Configuration Manager Object
+                             descrptor describing the Object.
+
+    @retval Returns:
+      EFI_SUCCESS           The operation completed successfully.
+      EFI_INVALID_PARAMETER A parameter is invalid.
+      EFI_NOT_FOUND         The required object information is not found.
+      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                            is less than the Object size for the requested
+                            object.
+      EFI_UNSUPPORTED       This operation is not supported.
+*/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_CONFIGURATION_MANAGER_SET_OBJECT) (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
+  IN  CONST CM_OBJECT_ID                                CmObjectId,
+  IN        CM_OBJ_DESCRIPTOR                   * CONST CmObject
+  );
+
+/** The EFI_CONFIGURATION_MANAGER_PROTOCOL structure describes the
+    Configuration Manager Protocol interface.
+*/
+typedef struct ConfigurationManagerProtocol {
+  /// The Configuration Manager Protocol revision.
+  UINT32                                Revision;
+
+  /// The interface used to request information about
+  /// the Configuration Manager Objects.
+  EFI_CONFIGURATION_MANAGER_GET_OBJECT  GetObject;
+
+  /// The interface used to update the information stored
+  /// in the Configuration Manager repository.
+  EFI_CONFIGURATION_MANAGER_SET_OBJECT  SetObject;
+
+  /// Pointer to an implementation defined abstract repository
+  /// provisioned by the Configuration Manager.
+  EFI_PLATFORM_REPOSITORY_INFO        * PlatRepoInfo;
+} EFI_CONFIGURATION_MANAGER_PROTOCOL;
+
+/** A global GUID defined in the protocol section of the
+    MdeModulePkg.dec file.
+*/
+extern EFI_GUID gEfiConfigurationManagerProtocolGuid;
+
+#pragma pack()
+
+#endif // CONFIGURATION_MANAGER_PROTOCOL_H_
diff --git a/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ece83bb44ec2d88fbd3b49b0e7bdc6314c332c7
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
@@ -0,0 +1,113 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - ACPI   - Advanced Configuration and Power Interface
+    - SMBIOS - System Management BIOS
+**/
+
+#ifndef DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
+#define DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
+
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+
+/** This macro defines the Dynamic Table Factory Protocol GUID.
+
+  GUID: {91D1E327-FE5A-49B8-AB65-0ECE2DDB45EC}
+*/
+#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_GUID         \
+  { 0x91d1e327, 0xfe5a, 0x49b8,                         \
+    { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec }   \
+  };
+
+/** This macro defines the Configuration Manager Protocol Revision.
+*/
+#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_REVISION  CREATE_REVISION (1, 0)
+
+#pragma pack(1)
+
+/**
+  Forward declarations:
+*/
+typedef struct DynamicTableFactoryProtocol EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
+typedef struct DynamicTableFactoryInfo EFI_DYNAMIC_TABLE_FACTORY_INFO;
+
+/** Return a pointer to the ACPI table generator.
+
+    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  TableId    The ACPI table generator ID for the
+                            requested generator.
+    @param [out] Generator  Pointer to the requested ACPI table
+                            generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A paramter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+typedef
+EFI_STATUS
+EFIAPI
+(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR) (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
+  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
+  );
+
+/** Return a pointer to the SMBIOS table generator.
+
+    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  TableId    The SMBIOS table generator ID for the
+                            requested generator.
+    @param [out] Generator  Pointer to the requested SMBIOS table
+                            generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+typedef
+EFI_STATUS
+EFIAPI
+(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR) (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
+  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
+  );
+
+/** A structure describing the Dynamic Table Factory Protocol interface.
+*/
+typedef struct DynamicTableFactoryProtocol {
+  /// The Dynamic Table Factory Protocol revision.
+  UINT32                                               Revision;
+
+  /// The interface used to request an ACPI Table Generator.
+  EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR   GetAcpiTableGenerator;
+
+  /// The interface used to request a SMBIOS Table Generator.
+  EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR GetSmbiosTableGenerator;
+
+  /// Pointer to the data structure that holds the
+  /// list of registered table generators
+  EFI_DYNAMIC_TABLE_FACTORY_INFO          * TableFactoryInfo;
+} EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
+
+/** A global GUID defined in the protocol section of the
+    MdeModulePkg.dec file.
+*/
+extern EFI_GUID gEfiDynamicTableFactoryProtocolGuid;
+
+#pragma pack()
+
+#endif // DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..88d9e5a4a58307ea26ddbe75579cddc3333ccc34
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
@@ -0,0 +1,91 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Std - Standard
+    - ACPI   - Advanced Configuration and Power Interface
+    - SMBIOS - System Management BIOS
+**/
+
+#ifndef DYNAMIC_TABLE_FACTORY_H_
+#define DYNAMIC_TABLE_FACTORY_H_
+
+#pragma pack(1)
+
+/** A structure that holds the list of registered ACPI and
+    SMBIOS table generators.
+*/
+typedef struct DynamicTableFactoryInfo {
+  /// An array for holding the list of Standard ACPI Table  Generators.
+  CONST ACPI_TABLE_GENERATOR *
+          StdAcpiTableGeneratorList[ESTD_ACPI_TABLE_ID_MAX];
+
+  /// An array for holding the list of Custom ACPI Table Generators.
+  CONST ACPI_TABLE_GENERATOR *
+          CustomAcpiTableGeneratorList[FixedPcdGet16 (
+            PcdMaxCustomACPIGenerators)];
+
+  /// An array for holding the list of Standard SMBIOS Table Generators.
+  CONST SMBIOS_TABLE_GENERATOR *
+          StdSmbiosTableGeneratorList[ESTD_SMBIOS_TABLE_ID_MAX];
+
+  /// An array for holding the list of Custom SMBIOS Table Generators.
+  CONST SMBIOS_TABLE_GENERATOR *
+          CustomSmbiosTableGeneratorList[FixedPcdGet16 (
+            PcdMaxCustomSMBIOSGenerators)];
+} EFI_DYNAMIC_TABLE_FACTORY_INFO;
+
+/** Return a pointer to the ACPI table generator.
+
+    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  GeneratorId  The ACPI table generator ID for the
+                              requested generator.
+    @param [out] Generator    Pointer to the requested ACPI table
+                              generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+GetAcpiTableGenerator (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
+  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
+  );
+
+/** Return a pointer to the SMBIOS table generator.
+
+    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  GeneratorId  The SMBIOS table generator ID for the
+                              requested generator.
+    @param [out] Generator    Pointer to the requested SMBIOS table
+                              generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+GetSmbiosTableGenerator (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
+  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
+  );
+
+#pragma pack()
+
+#endif // DYNAMIC_TABLE_FACTORY_H_
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
new file mode 100644
index 0000000000000000000000000000000000000000..1bf20424b942ac08fe93d157f3869de53577cf0e
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
@@ -0,0 +1,440 @@
+/** @file
+  DBG2 Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+#include <IndustryStandard/DebugPort2Table.h>
+#include <Drivers/PL011Uart.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard DBG2 Table Generator
+
+    Generates the ACPI DBG2 Port Table for ARM UARTs
+    as specified by the Microsoft Debug Port Table 2 (DBG2)
+    Specification - December 10, 2015.
+
+    Constructs the DBG2 table for PL011 or SBSA UART peripherals.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjSerialDebugPortInfo
+*/
+
+#pragma pack(1)
+
+/** Define the number of debug ports represented by the Table.
+*/
+#define DBG2_NUM_DEBUG_PORTS                       1
+
+/** Define the number of Generic Address Registers
+    presented in the debug device information.
+*/
+#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS   1
+
+/** Define the index for the debug port 1.
+*/
+#define DBG_PORT_INDEX_PORT1                       0
+
+/** Define the string representing the debug port 1 name.
+*/
+#define NAME_STR_PORT1                            "COM1"
+
+/** Define the length of the namespace string.
+*/
+#define DBG2_NAMESPACESTRING_FIELD_SIZE            sizeof (NAME_STR_PORT1)
+
+/** Define the PL011 UART address range length.
+*/
+#define PL011_UART_LENGTH                          0x1000
+
+/** This structure provides the OS with the information required for
+    initializing a debugger connection.
+*/
+typedef struct {
+  /// The debug device information for the platform
+  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device;
+
+  /// The base address register for the serial port
+  EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE        BaseAddressRegister;
+
+  /// The address size
+  UINT32 AddressSize;
+
+  /// The debug port name string
+  UINT8  NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
+} DBG2_DEBUG_DEVICE_INFORMATION;
+
+/** This structure represents the information about the debug port(s)
+    available on the platform.
+*/
+typedef struct {
+  /// The DBG2 table header
+  EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description;
+
+  /// Debug port information list
+  DBG2_DEBUG_DEVICE_INFORMATION       Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS];
+} DBG2_TABLE;
+
+/** A helper macro used for initalizing the debug port device
+    information structure.
+
+    @param [in]  NumReg       The number of generic address registers.
+    @param [in]  SubType      The DBG Port SubType.
+    @param [in]  UartBase     The UART port base address.
+    @param [in]  UartAddrLen  The UART port address range length.
+    @param [in]  UartNameStr  The UART port name string.
+*/
+#define DBG2_DEBUG_PORT_DDI(                                          \
+          NumReg,                                                     \
+          SubType,                                                    \
+          UartBase,                                                   \
+          UartAddrLen,                                                \
+          UartNameStr                                                 \
+          ) {                                                         \
+    {                                                                 \
+      /* UINT8     Revision */                                        \
+      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,         \
+      /* UINT16    Length */                                          \
+      sizeof (DBG2_DEBUG_DEVICE_INFORMATION),                         \
+      /* UINT8     NumberofGenericAddressRegisters */                 \
+      NumReg,                                                         \
+      /* UINT16    NameSpaceStringLength */                           \
+      DBG2_NAMESPACESTRING_FIELD_SIZE,                                \
+      /* UINT16    NameSpaceStringOffset */                           \
+      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString),     \
+      /* UINT16    OemDataLength */                                   \
+      0,                                                              \
+      /* UINT16    OemDataOffset */                                   \
+      0,                                                              \
+      /* UINT16    Port Type */                                       \
+      EFI_ACPI_DBG2_PORT_TYPE_SERIAL,                                 \
+      /* UINT16    Port Subtype */                                    \
+      SubType,                                                        \
+      /* UINT8     Reserved[2] */                                     \
+      {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE},               \
+      /* UINT16    BaseAddressRegister Offset */                      \
+      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \
+      /* UINT16    AddressSize Offset */                              \
+      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize)          \
+    },                                                                \
+    /* EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */  \
+    ARM_GAS32 (UartBase),                                             \
+    /* UINT32  AddressSize */                                         \
+    UartAddrLen,                                                      \
+    /* UINT8   NameSpaceString[MAX_DBG2_NAME_LEN] */                  \
+    UartNameStr                                                       \
+  }
+
+/** The DBG2 Table template definition.
+
+    Note: fields marked with "{Template}" will be set dynamically
+*/
+STATIC
+DBG2_TABLE AcpiDbg2 = {
+  {
+    ACPI_HEADER (
+      EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
+      DBG2_TABLE,
+      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
+      ),
+    OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),
+    DBG2_NUM_DEBUG_PORTS
+  },
+  {
+    /*
+     * Debug port 1
+     */
+    DBG2_DEBUG_PORT_DDI (
+      DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS,
+      EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART,
+      0,                    // {Template}: Serial Port Base Address
+      PL011_UART_LENGTH,
+      NAME_STR_PORT1
+      )
+  }
+};
+
+#pragma pack()
+
+/** This macro expands to a function that retrieves the Serial
+    debug port information from the Configuration Manager
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjSerialDebugPortInfo,
+  CM_ARM_SERIAL_PORT_INFO
+  );
+
+/** Initialize the PL011 UART with the parameters obtained from
+    the Configuration Manager.
+
+    @param [in]  SerialPortInfo Pointer to the Serial Port Information.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The parameters for serial port initialization
+                                  are invalid.
+*/
+STATIC
+EFI_STATUS
+SetupDebugUart (
+  IN  CONST CM_ARM_SERIAL_PORT_INFO  * CONST SerialPortInfo
+  )
+{
+  EFI_STATUS          Status;
+  UINT64              BaudRate;
+  UINT32              ReceiveFifoDepth;
+  EFI_PARITY_TYPE     Parity;
+  UINT8               DataBits;
+  EFI_STOP_BITS_TYPE  StopBits;
+
+  ASSERT (SerialPortInfo != NULL);
+
+  // Initialize the Serial Debug UART
+  DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));
+  ReceiveFifoDepth = 0; // Use the default value for FIFO depth
+  Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
+  DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
+  StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
+
+  BaudRate = SerialPortInfo->BaudRate;
+  Status = PL011UartInitializePort (
+             (UINTN)SerialPortInfo->BaseAddress,
+             SerialPortInfo->Clock,
+             &BaudRate,
+             &ReceiveFifoDepth,
+             &Parity,
+             &DataBits,
+             &StopBits
+             );
+
+  DEBUG ((DEBUG_INFO, "Debug UART Configuration:\n"));
+  DEBUG ((DEBUG_INFO, "UART Base  = 0x%lx\n", SerialPortInfo->BaseAddress));
+  DEBUG ((DEBUG_INFO, "Clock      = %d\n", SerialPortInfo->Clock));
+  DEBUG ((DEBUG_INFO, "Baudrate   = %ld\n", BaudRate));
+  DEBUG ((DEBUG_INFO, "Configuring Debug UART. Status = %r\n", Status));
+
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Construct the DBG2 ACPI table
+
+    The BuildDbg2Table function is called by the Dynamic Table Manager
+    to construct the DBG2 ACPI table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildDbg2Table (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                 Status;
+  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+
+  Status = GetEArmObjSerialDebugPortInfo (
+             CfgMgrProtocol,
+             &SerialPortInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = AddAcpiHeader (
+             CfgMgrProtocol,
+             This,
+             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2,
+             sizeof (DBG2_TABLE)
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.Address =
+    SerialPortInfo->BaseAddress;
+
+  Status = SetupDebugUart (SerialPortInfo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2;
+
+error_handler:
+  return Status;
+}
+
+/** Free any resources allocated for constructing the DBG2.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS         The resources were freed successfully.
+*/
+STATIC
+EFI_STATUS
+FreeDbg2TableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the DBG2 Table Generator revision.
+*/
+#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the DBG2 Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR Dbg2Generator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_DBG2),
+  // Generator Description
+  L"ACPI.STD.DBG2.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  DBG2_GENERATOR_REVISION,
+  // Build Table function
+  BuildDbg2Table,
+  // Free Resource function
+  FreeDbg2TableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiDbg2LibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&Dbg2Generator);
+  DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiDbg2LibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&Dbg2Generator);
+  DEBUG ((DEBUG_INFO, "DBG2: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..75e0b7b50ef34a71cc091db50667a19b40b3f1c9
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
@@ -0,0 +1,562 @@
+/** @file
+  FADT Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard FADT Generator
+
+    Generates the ACPI FADT Table as specified by the
+    ACPI 6.1 Specification - January, 2016.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjPowerManagementProfileInfo
+  - EArmObjBootArchInfo
+  - EArmObjHypervisorVendorIdentity (OPTIONAL)
+*/
+
+/** This macro defines the FADT flag options for ARM Platforms.
+*/
+#define FADT_FLAGS  (EFI_ACPI_6_1_HW_REDUCED_ACPI |          \
+                     EFI_ACPI_6_1_LOW_POWER_S0_IDLE_CAPABLE)
+
+#pragma pack(1)
+
+/** The AcpiFadt is a template EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE
+    structure used for generating the FADT Table.
+  Note: fields marked with "{Template}" will be updated dynamically.
+*/
+STATIC
+EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = {
+  ACPI_HEADER (
+    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE,
+    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
+    ),
+  // UINT32     FirmwareCtrl
+  0,
+  // UINT32     Dsdt
+  0,
+  // UINT8      Reserved0
+  EFI_ACPI_RESERVED_BYTE,
+  // UINT8      PreferredPmProfile
+  EFI_ACPI_6_1_PM_PROFILE_UNSPECIFIED,  // {Template}: Power Management Profile
+  // UINT16     SciInt
+  0,
+  // UINT32     SmiCmd
+  0,
+  // UINT8      AcpiEnable
+  0,
+  // UINT8      AcpiDisable
+  0,
+  // UINT8      S4BiosReq
+  0,
+  // UINT8      PstateCnt
+  0,
+  // UINT32     Pm1aEvtBlk
+  0,
+  // UINT32     Pm1bEvtBlk
+  0,
+  // UINT32     Pm1aCntBlk
+  0,
+  // UINT32     Pm1bCntBlk
+  0,
+  // UINT32     Pm2CntBlk
+  0,
+  // UINT32     PmTmrBlk
+  0,
+  // UINT32     Gpe0Blk
+  0,
+  // UINT32     Gpe1Blk
+  0,
+  // UINT8      Pm1EvtLen
+  0,
+  // UINT8      Pm1CntLen
+  0,
+  // UINT8      Pm2CntLen
+  0,
+  // UINT8      PmTmrLen
+  0,
+  // UINT8      Gpe0BlkLen
+  0,
+  // UINT8      Gpe1BlkLen
+  0,
+  // UINT8      Gpe1Base
+  0,
+  // UINT8      CstCnt
+  0,
+  // UINT16     PLvl2Lat
+  0,
+  // UINT16     PLvl3Lat
+  0,
+  // UINT16     FlushSize
+  0,
+  // UINT16     FlushStride
+  0,
+  // UINT8      DutyOffset
+  0,
+  // UINT8      DutyWidth
+  0,
+  // UINT8      DayAlrm
+  0,
+  // UINT8      MonAlrm
+  0,
+  // UINT8      Century
+  0,
+  // UINT16     IaPcBootArch
+  0,
+  // UINT8      Reserved1
+  0,
+  // UINT32     Flags
+  FADT_FLAGS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  ResetReg
+  NULL_GAS,
+  // UINT8      ResetValue
+  0,
+  // UINT16     ArmBootArch
+  EFI_ACPI_6_1_ARM_PSCI_COMPLIANT,  // {Template}: ARM Boot Architecture Flags
+  // UINT8      MinorRevision
+  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION,
+  // UINT64     XFirmwareCtrl
+  0,
+  // UINT64     XDsdt
+  0,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aEvtBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bEvtBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aCntBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bCntBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm2CntBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPmTmrBlk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe0Blk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe1Blk
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepControlReg
+  NULL_GAS,
+  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepStatusReg
+  NULL_GAS,
+  // UINT64     HypervisorVendorIdentity
+  EFI_ACPI_RESERVED_QWORD  // {Template}: Hypervisor Vendor ID
+};
+
+#pragma pack()
+
+/** This macro expands to a function that retrieves the Power
+    Management Profile Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPowerManagementProfileInfo,
+  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
+  );
+
+/** This macro expands to a function that retrieves the Boot
+    Architecture Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjBootArchInfo,
+  CM_ARM_BOOT_ARCH_INFO
+  );
+
+/** This macro expands to a function that retrieves the Hypervisor
+    Vendor ID from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjHypervisorVendorIdentity,
+  CM_ARM_HYPERVISOR_VENDOR_ID
+  );
+
+/** Update the Power Management Profile information in the FADT Table.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                  Protocol Interface.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+FadtAddPmProfileInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
+)
+{
+  EFI_STATUS                              Status;
+  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO  * PmProfile = NULL;
+
+  ASSERT (CfgMgrProtocol != NULL);
+
+  // Get the Power Management Profile from the Platform Configuration Manager
+  Status = GetEArmObjPowerManagementProfileInfo (
+             CfgMgrProtocol,
+             &PmProfile,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: FADT: Failed to get Power Management Profile information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "FADT: PreferredPmProfile = 0x%x\n",
+    PmProfile->PowerManagementProfile
+    ));
+
+  AcpiFadt.PreferredPmProfile = PmProfile->PowerManagementProfile;
+
+error_handler:
+  return Status;
+}
+
+/** Updates the Boot Architecture information in the FADT Table.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+FadtAddBootArchInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
+)
+{
+  EFI_STATUS               Status;
+  CM_ARM_BOOT_ARCH_INFO  * BootArchInfo = NULL;
+
+  ASSERT (CfgMgrProtocol != NULL);
+
+  // Get the Boot Architecture flags from the Platform Configuration Manager
+  Status = GetEArmObjBootArchInfo (
+             CfgMgrProtocol,
+             &BootArchInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "FADT BootArchFlag = 0x%x\n",
+    BootArchInfo->BootArchFlags
+    ));
+
+  AcpiFadt.ArmBootArch = BootArchInfo->BootArchFlags;
+
+error_handler:
+  return Status;
+}
+
+/** Update the Hypervisor Vendor ID in the FADT Table.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+FadtAddHypervisorVendorId (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
+)
+{
+  EFI_STATUS                     Status;
+  CM_ARM_HYPERVISOR_VENDOR_ID  * HypervisorVendorInfo = NULL;
+
+  ASSERT (CfgMgrProtocol != NULL);
+
+  // Get the Hypervisor Vendor ID from the Platform Configuration Manager
+  Status = GetEArmObjHypervisorVendorIdentity (
+             CfgMgrProtocol,
+             &HypervisorVendorInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+      DEBUG ((
+        DEBUG_INFO,
+        "INFO: FADT: Platform does not have a Hypervisor Vendor ID. Status = %r\n",
+        Status
+        ));
+    } else {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n",
+        Status
+        ));
+    }
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "FADT: EArmObjHypervisorVendorIdentity = 0x%lx\n",
+    HypervisorVendorInfo->HypervisorVendorId
+    ));
+
+  AcpiFadt.HypervisorVendorIdentity = HypervisorVendorInfo->HypervisorVendorId;
+
+error_handler:
+  return Status;
+}
+
+/** Construct the FADT table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildFadtTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS  Status;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+
+  Status = AddAcpiHeader (
+             CfgMgrProtocol,
+             This,
+             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt,
+             sizeof (EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE)
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: FADT: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  // Update PmProfile Info
+  Status = FadtAddPmProfileInfo (CfgMgrProtocol);
+  if (EFI_ERROR (Status)) {
+    goto error_handler;
+  }
+
+  // Update BootArch Info
+  Status = FadtAddBootArchInfo (CfgMgrProtocol);
+  if (EFI_ERROR (Status)) {
+    goto error_handler;
+  }
+
+  // Add the Hypervisor Vendor Id if present
+  // Note if no hypervisor is present the zero bytes
+  // will be placed in this field.
+  Status = FadtAddHypervisorVendorId (CfgMgrProtocol);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+      DEBUG ((
+        DEBUG_INFO,
+        "INFO: FADT: No Hypervisor Vendor ID found," \
+        " assuming no Hypervisor is present in the firmware.\n"
+        ));
+    } else {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r",
+        Status
+        ));
+      goto error_handler;
+    }
+  }
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt;
+  Status = EFI_SUCCESS;
+error_handler:
+  return Status;
+}
+
+/** Free any resources allocated for constructing the FADT.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS         The resources were freed successfully.
+*/
+STATIC
+EFI_STATUS
+FreeFadtTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the FADT Table Generator revision.
+*/
+#define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the FADT Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR FadtGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT),
+  // Generator Description
+  L"ACPI.STD.FADT.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  FADT_GENERATOR_REVISION,
+  // Build Table function
+  BuildFadtTable,
+  // Free Resource function
+  FreeFadtTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiFadtLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&FadtGenerator);
+  DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiFadtLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&FadtGenerator);
+  DEBUG ((DEBUG_INFO, "FADT: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..8a243e7d2ef2fa5806116030c74337f1f8e72e8b
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
@@ -0,0 +1,652 @@
+/** @file
+  GTDT Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard GTDT Generator
+
+    Generates the ACPI GTDT Table as specified by the
+    ACPI 6.1 Specification - January, 2016.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjGenericTimerInfo
+  - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)
+  - EArmObjPlatformGTBlockInfo (OPTIONAL)
+*/
+
+/** This macro expands to a function that retrieves the Generic
+    Timer Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGenericTimerInfo,
+  CM_ARM_GENERIC_TIMER_INFO
+  );
+
+/** This macro expands to a function that retrieves the SBSA Generic
+    Watchdog Timer Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPlatformGenericWatchdogInfo,
+  CM_ARM_GENERIC_WATCHDOG_INFO
+  );
+
+/** This macro expands to a function that retrieves the Platform Generic
+    Timer Block Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPlatformGTBlockInfo,
+  CM_ARM_GTBLOCK_INFO
+  );
+
+/** Add the Generic Timer Information to the GTDT table.
+
+    Also update the Platform Timer offset information if the platform
+    implements platform timers.
+
+    @param [in]  CfgMgrProtocol     Pointer to the Configuration Manager
+                                    Protocol Interface.
+    @param [in]  Gtdt               Pointer to the GTDT Table.
+    @param [in]  PlatformTimerCount Platform timer count.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+AddGenericTimerInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,
+  IN  CONST UINT32 PlatformTimerCount
+)
+{
+  EFI_STATUS                   Status;
+  CM_ARM_GENERIC_TIMER_INFO  * GenericTimerInfo = NULL;
+
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Gtdt != NULL);
+
+  Status = GetEArmObjGenericTimerInfo (
+             CfgMgrProtocol,
+             &GenericTimerInfo,
+             NULL
+             );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to get GenericTimerInfo. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  Gtdt->CntControlBasePhysicalAddress =
+    GenericTimerInfo->CounterControlBaseAddress;
+  Gtdt->Reserved = EFI_ACPI_RESERVED_DWORD;
+  Gtdt->CntReadBasePhysicalAddress =
+    GenericTimerInfo->CounterReadBaseAddress;
+  Gtdt->PlatformTimerCount = PlatformTimerCount;
+  Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :
+    sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
+
+  Gtdt->SecurePL1TimerGSIV = GenericTimerInfo->SecurePL1TimerGSIV;
+  Gtdt->SecurePL1TimerFlags = GenericTimerInfo->SecurePL1TimerFlags;
+  Gtdt->NonSecurePL1TimerGSIV = GenericTimerInfo->NonSecurePL1TimerGSIV;
+  Gtdt->NonSecurePL1TimerFlags = GenericTimerInfo->NonSecurePL1TimerFlags;
+  Gtdt->VirtualTimerGSIV = GenericTimerInfo->VirtualTimerGSIV;
+  Gtdt->VirtualTimerFlags = GenericTimerInfo->VirtualTimerFlags;
+  Gtdt->NonSecurePL2TimerGSIV = GenericTimerInfo->NonSecurePL2TimerGSIV;
+  Gtdt->NonSecurePL2TimerFlags = GenericTimerInfo->NonSecurePL2TimerFlags;
+
+  return EFI_SUCCESS;
+}
+
+/** Add the SBSA Generic Watchdog Timers to the GTDT table.
+
+    @param [in]  Gtdt             Pointer to the GTDT Table.
+    @param [in]  WatchdogOffset   Offset to the watchdog information in the
+                                  GTDT Table.
+    @param [in]  WatchdogInfoList Pointer to the watchdog information list.
+    @param [in]  WatchdogCount    Platform timer count.
+*/
+STATIC
+VOID
+AddGenericWatchdogList (
+  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
+  IN CONST UINTN                                           WatchdogOffset,
+  IN CONST CM_ARM_GENERIC_WATCHDOG_INFO            * CONST WatchdogInfoList,
+  IN CONST UINTN                                           WatchdogCount
+  )
+{
+  UINTN                                                idx;
+  EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE  * Watchdog;
+
+  ASSERT (Gtdt != NULL);
+  ASSERT (WatchdogInfoList != NULL);
+
+  Watchdog = (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *)
+             ((UINT8*)Gtdt + WatchdogOffset);
+
+  for (idx = 0; idx < WatchdogCount; idx++) {
+    // Add watchdog entry
+    DEBUG ((DEBUG_INFO, "GTDT: Watchdog[%d] = 0x%p\n", idx, &Watchdog[idx]));
+    Watchdog[idx].Type = EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG;
+    Watchdog[idx].Length =
+      sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);
+    Watchdog[idx].Reserved = EFI_ACPI_RESERVED_BYTE;
+    Watchdog[idx].RefreshFramePhysicalAddress =
+      WatchdogInfoList[idx].RefreshFrameAddress;
+    Watchdog[idx].WatchdogControlFramePhysicalAddress =
+      WatchdogInfoList[idx].ControlFrameAddress;
+    Watchdog[idx].WatchdogTimerGSIV = WatchdogInfoList[idx].TimerGSIV;
+    Watchdog[idx].WatchdogTimerFlags = WatchdogInfoList[idx].Flags;
+
+  } // for
+}
+
+/** Update the GT Block Timer Frame lists in the GTDT Table.
+
+    @param [in]  GtBlockFrame           Pointer to the GT Block Frames
+                                        list to be updated.
+    @param [in]  GTBlockTimerFrameList  Pointer to the GT Block Frame
+                                        Information List.
+    @param [in]  GTBlockFrameCount      Number of GT Block Frames.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+*/
+STATIC
+EFI_STATUS
+AddGTBlockTimerFrames (
+  IN       EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE * CONST GtBlockFrame,
+  IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO * CONST GTBlockTimerFrameList,
+  IN CONST UINTN GTBlockFrameCount
+)
+{
+  UINTN       idx;
+
+  ASSERT (GtBlockFrame != NULL);
+  ASSERT (GTBlockTimerFrameList != NULL);
+
+  if (GTBlockFrameCount > 8) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: GT Block Frame Count %d is greater than 8\n",
+      GTBlockFrameCount
+      ));
+    ASSERT (GTBlockFrameCount <= 8);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  for (idx = 0; idx < GTBlockFrameCount; idx++) {
+    DEBUG ((
+      DEBUG_INFO,
+      "GTDT: GtBlockFrame[%d] = 0x%p\n",
+      idx,
+      GtBlockFrame[idx]
+      ));
+
+    GtBlockFrame[idx].GTFrameNumber = GTBlockTimerFrameList[idx].FrameNumber;
+    GtBlockFrame[idx].Reserved[0] = EFI_ACPI_RESERVED_BYTE;
+    GtBlockFrame[idx].Reserved[1] = EFI_ACPI_RESERVED_BYTE;
+    GtBlockFrame[idx].Reserved[2] = EFI_ACPI_RESERVED_BYTE;
+
+    GtBlockFrame[idx].CntBaseX =
+      GTBlockTimerFrameList[idx].PhysicalAddressCntBase;
+    GtBlockFrame[idx].CntEL0BaseX =
+      GTBlockTimerFrameList[idx].PhysicalAddressCntEL0Base;
+
+    GtBlockFrame[idx].GTxPhysicalTimerGSIV =
+      GTBlockTimerFrameList[idx].PhysicalTimerGSIV;
+    GtBlockFrame[idx].GTxPhysicalTimerFlags =
+      GTBlockTimerFrameList[idx].PhysicalTimerFlags;
+
+    GtBlockFrame[idx].GTxVirtualTimerGSIV =
+      GTBlockTimerFrameList[idx].VirtualTimerGSIV;
+    GtBlockFrame[idx].GTxVirtualTimerFlags =
+      GTBlockTimerFrameList[idx].VirtualTimerFlags;
+
+    GtBlockFrame[idx].GTxCommonFlags = GTBlockTimerFrameList[idx].CommonFlags;
+
+  } // for
+  return EFI_SUCCESS;
+}
+
+/** Add the GT Block Timers in the GTDT Table.
+
+    @param [in]  Gtdt             Pointer to the GTDT Table.
+    @param [in]  GTBlockOffset    Offset of the GT Block
+                                  information in the GTDT Table.
+    @param [in]  GTBlockInfo      Pointer to the GT Block
+                                  Information List.
+    @param [in]  BlockTimerCount  Number of GT Block Timers.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+
+*/
+STATIC
+EFI_STATUS
+AddGTBlockList (
+  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
+  IN CONST UINTN                                           GTBlockOffset,
+  IN CONST CM_ARM_GTBLOCK_INFO                     * CONST GTBlockInfo,
+  IN CONST UINTN                                           BlockTimerCount
+)
+{
+  EFI_STATUS                                    Status;
+  UINTN                                         idx;
+  EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE        * GTBlock;
+  EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE  * GtBlockFrame;
+
+  ASSERT (Gtdt != NULL);
+  ASSERT (GTBlockInfo != NULL);
+
+  GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)Gtdt +
+              GTBlockOffset);
+
+  for (idx = 0; idx < BlockTimerCount; idx++) {
+    DEBUG ((DEBUG_INFO, "GTDT: GTBlock[%d] = 0x%p\n",
+      idx,
+      GTBlock
+      ));
+
+    GTBlock->Type = EFI_ACPI_6_1_GTDT_GT_BLOCK;
+    GTBlock->Length = sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) +
+                        (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
+                          GTBlockInfo[idx].GTBlockTimerFrameCount);
+
+    GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;
+    GTBlock->CntCtlBase = GTBlockInfo[idx].GTBlockPhysicalAddress;
+    GTBlock->GTBlockTimerCount = GTBlockInfo[idx].GTBlockTimerFrameCount;
+    GTBlock->GTBlockTimerOffset =
+      sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE);
+
+    GtBlockFrame = (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE*)
+      ((UINT8*)GTBlock + GTBlock->GTBlockTimerOffset);
+
+    // Add GT Block Timer frames
+    Status = AddGTBlockTimerFrames (
+               GtBlockFrame,
+               GTBlockInfo[idx].GTBlockTimerFrameList,
+               GTBlockInfo[idx].GTBlockTimerFrameCount
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",
+        Status
+        ));
+      return Status;
+    }
+
+    // Next GTBlock
+    GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)GTBlock +
+                GTBlock->Length);
+  }// for
+  return EFI_SUCCESS;
+}
+
+/** Construct the GTDT ACPI table.
+
+    Called by the Dynamic Table Manager, this function invokes the
+    Confguration Manager protocol interface to get the required hardware
+    information for generating the ACPI table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildGtdtTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                                      Status;
+  UINTN                                           TableSize;
+  UINTN                                           PlatformTimerCount = 0;
+  UINTN                                           WatchdogCount;
+  UINTN                                           BlockTimerCount;
+  CM_ARM_GENERIC_WATCHDOG_INFO                  * WatchdogInfoList = NULL;
+  CM_ARM_GTBLOCK_INFO                           * GTBlockInfo = NULL;
+  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * Gtdt;
+  UINTN                                           idx;
+  UINTN                                           GTBlockOffset;
+  UINTN                                           WatchdogOffset = 0;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+  Status = GetEArmObjPlatformGTBlockInfo (
+             CfgMgrProtocol,
+             &GTBlockInfo,
+             &BlockTimerCount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to Get Platform GT Block Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = GetEArmObjPlatformGenericWatchdogInfo (
+             CfgMgrProtocol,
+             &WatchdogInfoList,
+             &WatchdogCount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",
+    BlockTimerCount,
+    WatchdogCount
+    ));
+
+  // Calculate the GTDT Table Size
+  TableSize = sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
+  if (BlockTimerCount != 0) {
+    GTBlockOffset = TableSize;
+    PlatformTimerCount += BlockTimerCount;
+    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) *
+                  BlockTimerCount);
+
+    for (idx = 0; idx < BlockTimerCount; idx++) {
+      if (GTBlockInfo[idx].GTBlockTimerFrameCount > 8) {
+        Status = EFI_INVALID_PARAMETER;
+        DEBUG ((
+          DEBUG_ERROR,
+          "GTDT: GTBockFrameCount cannot be more than 8." \
+          " GTBockFrameCount = %d, Status = %r\n",
+          GTBlockInfo[idx].GTBlockTimerFrameCount,
+          Status
+          ));
+        goto error_handler;
+      }
+      TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
+        GTBlockInfo[idx].GTBlockTimerFrameCount);
+    }
+
+    DEBUG ((
+      DEBUG_INFO,
+      "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
+      GTBlockOffset,
+      PlatformTimerCount
+      ));
+  }
+
+  if (WatchdogCount != 0) {
+    WatchdogOffset = TableSize;
+    PlatformTimerCount += WatchdogCount;
+    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE) *
+                  WatchdogCount);
+    DEBUG ((
+      DEBUG_INFO,
+      "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
+      WatchdogOffset,
+      PlatformTimerCount
+      ));
+  }
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Gtdt = (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE*)*Table;
+  DEBUG ((
+    DEBUG_INFO,
+    "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",
+    Gtdt,
+    TableSize
+    ));
+
+  Status = AddAcpiHeader (CfgMgrProtocol, This, &Gtdt->Header, TableSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = AddGenericTimerInfo (
+             CfgMgrProtocol,
+             Gtdt,
+             PlatformTimerCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  if (BlockTimerCount != 0) {
+    Status = AddGTBlockList (
+               Gtdt,
+               GTBlockOffset,
+               GTBlockInfo,
+               BlockTimerCount
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",
+        Status
+        ));
+      goto error_handler;
+    }
+  }
+
+  if (WatchdogCount != 0) {
+    AddGenericWatchdogList (
+      Gtdt,
+      WatchdogOffset,
+      WatchdogInfoList,
+      WatchdogCount
+      );
+  }
+
+  return Status;
+
+error_handler:
+  if (*Table != NULL) {
+    FreePool (*Table);
+    *Table = NULL;
+  }
+  return Status;
+}
+
+/** Free any resources allocated for constructing the GTDT.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS           The resources were freed successfully.
+    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+
+*/
+STATIC
+EFI_STATUS
+FreeGtdtTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+)
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((Table == NULL) || (*Table == NULL)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));
+    ASSERT ((Table != NULL) && (*Table != NULL));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (*Table);
+  *Table = NULL;
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the GTDT Table Generator revision.
+*/
+#define GTDT_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the GTDT Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR GtdtGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_GTDT),
+  // Generator Description
+  L"ACPI.STD.GTDT.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  GTDT_GENERATOR_REVISION,
+  // Build Table function
+  BuildGtdtTable,
+  // Free Resource function
+  FreeGtdtTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiGtdtLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&GtdtGenerator);
+  DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiGtdtLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&GtdtGenerator);
+  DEBUG ((DEBUG_INFO, "GTDT: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..cce440d91f50d8a7ac429acb6be40d4a6ac4e230
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
@@ -0,0 +1,732 @@
+/** @file
+  MADT Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard MADT Generator
+
+    Generates the ACPI MADT Table as specified by the
+    ACPI 6.1 Specification - January, 2016.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjGicCInfo
+  - EArmObjGicDInfo
+  - EArmObjGicMsiFrameInfo (OPTIONAL)
+  - EArmObjGicRedistributorInfo (OPTIONAL)
+  - EArmObjGicItsInfo (OPTIONAL)
+*/
+
+/** This macro expands to a function that retrieves the GIC
+    CPU interface Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicCInfo,
+  CM_ARM_GICC_INFO
+  );
+
+/** This macro expands to a function that retrieves the GIC
+    Distributor Information from the Configuration Manager.
+*/
+
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicDInfo,
+  CM_ARM_GICD_INFO
+  );
+
+/** This macro expands to a function that retrieves the GIC
+    MSI Frame Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicMsiFrameInfo,
+  CM_ARM_GIC_MSI_FRAME_INFO
+  );
+
+/** This macro expands to a function that retrieves the GIC
+    Redistributor Information from the Configuration Manager.
+*/
+
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicRedistributorInfo,
+  CM_ARM_GIC_REDIST_INFO
+  );
+
+/** This macro expands to a function that retrieves the GIC
+    Interrupt Translation Serice Information from the
+    Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjGicItsInfo,
+  CM_ARM_GIC_ITS_INFO
+  );
+
+/** This function updates the GIC CPU Interface Information in the
+    EFI_ACPI_6_1_GIC_STRUCTURE structure.
+
+    @param [in]  Gicc      Pointer to GIC CPU Interface structure.
+    @param [in]  GicCInfo  Pointer to the GIC CPU Interface Information.
+*/
+STATIC
+VOID
+AddGICC (
+  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * CONST Gicc,
+  IN  CONST CM_ARM_GICC_INFO      * CONST GicCInfo
+  )
+{
+  ASSERT (Gicc != NULL);
+  ASSERT (GicCInfo != NULL);
+
+  /* UINT8 Type */
+  Gicc->Type = EFI_ACPI_6_1_GIC;
+  /* UINT8 Length */
+  Gicc->Length = sizeof (EFI_ACPI_6_1_GIC_STRUCTURE);
+  /* UINT16 Reserved */
+  Gicc->Reserved = EFI_ACPI_RESERVED_WORD;
+
+  /* UINT32 CPUInterfaceNumber */
+  Gicc->CPUInterfaceNumber = GicCInfo->CPUInterfaceNumber;
+  /* UINT32 AcpiProcessorUid */
+  Gicc->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;
+  /* UINT32 Flags */
+  Gicc->Flags = GicCInfo->Flags;
+  /* UINT32 ParkingProtocolVersion */
+  Gicc->ParkingProtocolVersion = GicCInfo->ParkingProtocolVersion;
+  /* UINT32 PerformanceInterruptGsiv */
+  Gicc->PerformanceInterruptGsiv = GicCInfo->PerformanceInterruptGsiv;
+  /* UINT64 ParkedAddress */
+  Gicc->ParkedAddress = GicCInfo->ParkedAddress;
+
+  /* UINT64 PhysicalBaseAddress */
+  Gicc->PhysicalBaseAddress = GicCInfo->PhysicalBaseAddress;
+  /* UINT64 GICV */
+  Gicc->GICV = GicCInfo->GICV;
+  /* UINT64 GICH */
+  Gicc->GICH = GicCInfo->GICH;
+
+  /* UINT32 VGICMaintenanceInterrupt */
+  Gicc->VGICMaintenanceInterrupt = GicCInfo->VGICMaintenanceInterrupt;
+  /* UINT64 GICRBaseAddress */
+  Gicc->GICRBaseAddress = GicCInfo->GICRBaseAddress;
+
+  /* UINT64 MPIDR */
+  Gicc->MPIDR = GicCInfo->MPIDR;
+  /* UINT8 ProcessorPowerEfficiencyClass */
+  Gicc->ProcessorPowerEfficiencyClass =
+    GicCInfo->ProcessorPowerEfficiencyClass;
+  /* UINT8 Reserved2[3] */
+  Gicc->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
+  Gicc->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
+  Gicc->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
+}
+
+/** Add the GIC CPU Interface Information to the MADT Table.
+
+    @param [in]  Gicc      Pointer to GIC CPU Interface
+                            structure list.
+    @param [in]  GicCInfo  Pointer to the GIC CPU
+                            Information list.
+    @param [in]  GicCCount Count of GIC CPU Interfaces.
+*/
+STATIC
+VOID
+AddGICCList (
+  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * Gicc,
+  IN  CONST CM_ARM_GICC_INFO      * GicCInfo,
+  IN  CONST UINTN                   GicCCount
+  )
+{
+  UINTN  idx;
+
+  ASSERT (Gicc != NULL);
+  ASSERT (GicCInfo != NULL);
+
+  for (idx = 0; idx < GicCCount; idx++) {
+    AddGICC (Gicc++, GicCInfo++);
+  }
+}
+
+/** Update the GIC Distributor Information in the MADT Table.
+
+    @param [in]  Gicd      Pointer to GIC Distributor structure.
+    @param [in]  GicDInfo  Pointer to the GIC Distributor Information.
+*/
+STATIC
+VOID
+AddGICD (
+  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * CONST Gicd,
+  CONST CM_ARM_GICD_INFO                  * CONST GicDInfo
+)
+{
+  ASSERT (Gicd != NULL);
+  ASSERT (GicDInfo != NULL);
+
+  /* UINT8 Type */
+  Gicd->Type = EFI_ACPI_6_1_GICD;
+  /* UINT8 Length */
+  Gicd->Length = sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE);
+  /* UINT16 Reserved */
+  Gicd->Reserved1 = EFI_ACPI_RESERVED_WORD;
+  /* UINT32 Identifier */
+  Gicd->GicId = GicDInfo->GicId;
+  /* UINT64 PhysicalBaseAddress */
+  Gicd->PhysicalBaseAddress = GicDInfo->PhysicalBaseAddress;
+  /* UINT32 VectorBase */
+  Gicd->SystemVectorBase = GicDInfo->SystemVectorBase;
+  /* UINT8  GicVersion */
+  Gicd->GicVersion = GicDInfo->GicVersion;
+  /* UINT8  Reserved2[3] */
+  Gicd->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
+  Gicd->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
+  Gicd->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
+}
+
+/** Add the GIC Distributor Information to the MADT Table.
+
+    @param [in]  Gicd      Pointer to GIC Distributor structure list.
+    @param [in]  GicDInfo  Pointer to the GIC Distributor Information list.
+    @param [in]  GicDCount Count of GIC Distributors.
+*/
+STATIC
+VOID
+AddGICDList (
+  IN  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * Gicd,
+  IN  CONST CM_ARM_GICD_INFO                  * GicDInfo,
+  IN  CONST UINTN                               GicDCount
+  )
+{
+  UINTN  idx;
+
+  ASSERT (Gicd != NULL);
+  ASSERT (GicDInfo != NULL);
+
+  for (idx = 0; idx < GicDCount; idx++) {
+    AddGICD (Gicd++, GicDInfo++);
+  }
+}
+
+/** Update the GIC MSI Frame Information.
+
+    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure.
+    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame Information.
+*/
+STATIC
+VOID
+AddGICMsiFrame (
+  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * CONST GicMsiFrame,
+  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * CONST GicMsiFrameInfo
+)
+{
+  ASSERT (GicMsiFrame != NULL);
+  ASSERT (GicMsiFrameInfo != NULL);
+
+  GicMsiFrame->Type = EFI_ACPI_6_1_GIC_MSI_FRAME;
+  GicMsiFrame->Length = sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE);
+  GicMsiFrame->Reserved1 = EFI_ACPI_RESERVED_WORD;
+  GicMsiFrame->GicMsiFrameId = GicMsiFrameInfo->GicMsiFrameId;
+  GicMsiFrame->PhysicalBaseAddress = GicMsiFrameInfo->PhysicalBaseAddress;
+
+  GicMsiFrame->Flags = GicMsiFrameInfo->Flags;
+  GicMsiFrame->SPICount = GicMsiFrameInfo->SPICount;
+  GicMsiFrame->SPIBase = GicMsiFrameInfo->SPIBase;
+}
+
+/** Add the GIC MSI Frame Information to the MADT Table.
+
+    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure list.
+    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame info list.
+    @param [in]  GicMsiFrameCount Count of GIC MSI Frames.
+*/
+STATIC
+VOID
+AddGICMsiFrameInfoList (
+  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * GicMsiFrame,
+  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * GicMsiFrameInfo,
+  IN  CONST UINTN                             GicMsiFrameCount
+)
+{
+  UINTN  idx;
+
+  ASSERT (GicMsiFrame != NULL);
+  ASSERT (GicMsiFrameInfo != NULL);
+
+  for (idx = 0; idx < GicMsiFrameCount; idx++) {
+    AddGICMsiFrame (GicMsiFrame++, GicMsiFrameInfo++);
+  }
+}
+
+/** Update the GIC Redistributor Information.
+
+    @param [in]  Gicr                 Pointer to GIC Redistributor structure.
+    @param [in]  GicRedisributorInfo  Pointer to the GIC Redistributor Info.
+*/
+STATIC
+VOID
+AddGICRedistributor (
+  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * CONST Gicr,
+  IN  CONST CM_ARM_GIC_REDIST_INFO  * CONST GicRedisributorInfo
+  )
+{
+  ASSERT (Gicr != NULL);
+  ASSERT (GicRedisributorInfo != NULL);
+
+  Gicr->Type = EFI_ACPI_6_1_GICR;
+  Gicr->Length = sizeof (EFI_ACPI_6_1_GICR_STRUCTURE);
+  Gicr->Reserved = EFI_ACPI_RESERVED_WORD;
+  Gicr->DiscoveryRangeBaseAddress =
+    GicRedisributorInfo->DiscoveryRangeBaseAddress;
+  Gicr->DiscoveryRangeLength = GicRedisributorInfo->DiscoveryRangeLength;
+}
+
+/** Add the GIC Redistributor Information to the MADT Table.
+
+    @param [in]  Gicr      Pointer to GIC Redistributor structure list.
+    @param [in]  GicRInfo  Pointer to the GIC Distributor info list.
+    @param [in]  GicRCount Count of GIC Distributors.
+*/
+STATIC
+VOID
+AddGICRedistributorList (
+  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * Gicr,
+  IN  CONST CM_ARM_GIC_REDIST_INFO  * GicRInfo,
+  IN  CONST UINTN                     GicRCount
+)
+{
+  UINTN  idx;
+
+  ASSERT (Gicr != NULL);
+  ASSERT (GicRInfo != NULL);
+
+  for (idx = 0; idx < GicRCount; idx++) {
+    AddGICRedistributor (Gicr++, GicRInfo++);
+  }
+}
+
+/** Update the GIC Interrupt Translation Service Information
+
+    @param [in]  GicIts      Pointer to GIC ITS structure.
+    @param [in]  GicItsInfo  Pointer to the GIC ITS Information.
+*/
+STATIC
+VOID
+AddGICInterruptTranslationService (
+  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * CONST GicIts,
+  IN  CONST CM_ARM_GIC_ITS_INFO       * CONST GicItsInfo
+)
+{
+  ASSERT (GicIts != NULL);
+  ASSERT (GicItsInfo != NULL);
+
+  GicIts->Type = EFI_ACPI_6_1_GIC_ITS;
+  GicIts->Length = sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE);
+  GicIts->Reserved = EFI_ACPI_RESERVED_WORD;
+  GicIts->GicItsId = GicItsInfo->GicItsId;
+  GicIts->PhysicalBaseAddress = GicItsInfo->PhysicalBaseAddress;
+  GicIts->Reserved2 = EFI_ACPI_RESERVED_DWORD;
+}
+
+/** Add the GIC Interrupt Translation Service Information
+    to the MADT Table.
+
+    @param [in]  GicIts       Pointer to GIC ITS structure list.
+    @param [in]  GicItsInfo   Pointer to the GIC ITS list.
+    @param [in]  GicItsCount  Count of GIC ITS.
+*/
+STATIC
+VOID
+AddGICItsList (
+  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * GicIts,
+  IN  CONST CM_ARM_GIC_ITS_INFO       * GicItsInfo,
+  IN  CONST UINTN                       GicItsCount
+)
+{
+  UINTN  idx;
+
+  ASSERT (GicIts != NULL);
+  ASSERT (GicItsInfo != NULL);
+
+  for (idx = 0; idx < GicItsCount; idx++) {
+    AddGICInterruptTranslationService (GicIts++, GicItsInfo++);
+  }
+}
+
+/** Construct the MADT ACPI table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildMadtTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                   Status;
+  UINTN                        TableSize;
+  UINTN                        GicCCount;
+  UINTN                        GicDCount;
+  UINTN                        GicMSICount;
+  UINTN                        GicRedistCount;
+  UINTN                        GicItsCount;
+  CM_ARM_GICC_INFO           * GicCInfo = NULL;
+  CM_ARM_GICD_INFO           * GicDInfo = NULL;
+  CM_ARM_GIC_MSI_FRAME_INFO  * GicMSIInfo = NULL;
+  CM_ARM_GIC_REDIST_INFO     * GicRedistInfo = NULL;
+  CM_ARM_GIC_ITS_INFO        * GicItsInfo = NULL;
+  UINTN                        GicCOffset;
+  UINTN                        GicDOffset;
+  UINTN                        GicMSIOffset;
+  UINTN                        GicRedistOffset;
+  UINTN                        GicItsOffset;
+
+  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER  * Madt;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+
+  Status = GetEArmObjGicCInfo (CfgMgrProtocol, &GicCInfo, &GicCCount);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GICC Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  if (GicCCount == 0) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: GIC CPU Interface information not provided.\n"
+      ));
+    ASSERT (GicCCount != 0);
+    Status = EFI_INVALID_PARAMETER;
+    goto error_handler;
+  }
+
+  Status = GetEArmObjGicDInfo (CfgMgrProtocol, &GicDInfo, &GicDCount);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GICD Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  if (GicDCount == 0) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: GIC Distributor information not provided.\n"
+      ));
+    ASSERT (GicDCount != 0);
+    Status = EFI_INVALID_PARAMETER;
+    goto error_handler;
+  }
+
+  Status = GetEArmObjGicMsiFrameInfo (
+             CfgMgrProtocol,
+             &GicMSIInfo,
+             &GicMSICount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GIC MSI Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = GetEArmObjGicRedistributorInfo (
+             CfgMgrProtocol,
+             &GicRedistInfo,
+             &GicRedistCount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GIC Redistributor Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Status = GetEArmObjGicItsInfo (
+             CfgMgrProtocol,
+             &GicItsInfo,
+             &GicItsCount
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to get GIC ITS Info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  TableSize = sizeof (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
+
+  GicCOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GIC_STRUCTURE) * GicCCount);
+
+  GicDOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE) * GicDCount);
+
+  GicMSIOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE) * GicMSICount);
+
+  GicRedistOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GICR_STRUCTURE) * GicRedistCount);
+
+  GicItsOffset = TableSize;
+  TableSize += (sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE) * GicItsCount);
+
+  // Allocate the Buffer for MADT table
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to allocate memory for MADT Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Madt = (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER*)*Table;
+
+  DEBUG ((
+    DEBUG_INFO,
+    "MADT: Madt = 0x%p TableSize = 0x%x\n",
+    Madt,
+    TableSize
+    ));
+
+  Status = AddAcpiHeader (CfgMgrProtocol, This, &Madt->Header, TableSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MADT: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  AddGICCList (
+    (EFI_ACPI_6_1_GIC_STRUCTURE*)((UINT8*)Madt + GicCOffset),
+    GicCInfo,
+    GicCCount
+    );
+
+  AddGICDList (
+    (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE*)((UINT8*)Madt + GicDOffset),
+    GicDInfo,
+    GicDCount
+    );
+
+  if (GicMSICount != 0) {
+    AddGICMsiFrameInfoList (
+      (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE*)((UINT8*)Madt + GicMSIOffset),
+      GicMSIInfo,
+      GicMSICount
+      );
+  }
+
+  if (GicRedistCount != 0) {
+    AddGICRedistributorList (
+      (EFI_ACPI_6_1_GICR_STRUCTURE*)((UINT8*)Madt + GicRedistOffset),
+      GicRedistInfo,
+      GicRedistCount
+      );
+  }
+
+  if (GicItsCount != 0) {
+    AddGICItsList (
+      (EFI_ACPI_6_1_GIC_ITS_STRUCTURE*)((UINT8*)Madt + GicItsOffset),
+      GicItsInfo,
+      GicItsCount
+      );
+  }
+
+  return EFI_SUCCESS;
+
+error_handler:
+  if (*Table != NULL) {
+    FreePool (*Table);
+    *Table = NULL;
+  }
+  return Status;
+}
+
+/** Free any resources allocated for constructing the MADT
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS           The resources were freed successfully.
+    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+*/
+STATIC
+EFI_STATUS
+FreeMadtTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((Table == NULL) || (*Table == NULL)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: MADT: Invalid Table Pointer\n"));
+    ASSERT ((Table != NULL) && (*Table != NULL));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (*Table);
+  *Table = NULL;
+  return EFI_SUCCESS;
+}
+
+/** The MADT Table Generator revision.
+*/
+#define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the MADT Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR MadtGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MADT),
+  // Generator Description
+  L"ACPI.STD.MADT.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  MADT_GENERATOR_REVISION,
+  // Build Table function
+  BuildMadtTable,
+  // Free Resource function
+  FreeMadtTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiMadtLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&MadtGenerator);
+  DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiMadtLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&MadtGenerator);
+  DEBUG ((DEBUG_INFO, "MADT: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..c023b413797379562f20ae97db9e2f2ca6d8758c
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
@@ -0,0 +1,336 @@
+/** @file
+  MCFG Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard MCFG Generator
+
+    Generates the MCFG Table as specified by the PCI Firmware
+    Specification - Revision 3.2, January 26, 2015.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjPciConfigSpaceInfo
+*/
+
+#pragma pack(1)
+
+/** This typedef is used to shorten the name of the MCFG Table
+    header structure.
+*/
+typedef
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER
+  MCFG_TABLE;
+
+/** This typedef is used to shorten the name of the Enhanced
+    Configuration Space address structure.
+*/
+typedef
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE
+  MCFG_CFG_SPACE_ADDR;
+
+#pragma pack()
+
+/** Retrieve the PCI Configuration Space Information.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPciConfigSpaceInfo,
+  CM_ARM_PCI_CONFIG_SPACE_INFO
+  );
+
+/** Add the PCI Enhanced Configuration Space Information to the MCFG Table.
+
+    @param [in]  Mcfg                Pointer to MCFG Table.
+    @param [in]  PciCfgSpaceOffset   Offset for the PCI Configuration Space
+                                     Info structure in the MCFG Table.
+    @param [in]  PciCfgSpaceInfoList Pointer to the PCI Configuration Space
+                                     Info List.
+    @param [in]  PciCfgSpaceCount    Count of PCI Configuration Space Info.
+*/
+STATIC
+VOID
+AddPciConfigurationSpaceList (
+  IN       MCFG_TABLE                   * CONST Mcfg,
+  IN CONST UINTN                                PciCfgSpaceOffset,
+  IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * CONST PciCfgSpaceInfoList,
+  IN CONST UINTN                                PciCfgSpaceCount
+)
+{
+  UINTN                  idx;
+  MCFG_CFG_SPACE_ADDR  * PciCfgSpace;
+
+  ASSERT (Mcfg != NULL);
+  ASSERT (PciCfgSpaceInfoList != NULL);
+
+  PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8*)Mcfg + PciCfgSpaceOffset);
+  for (idx = 0; idx < PciCfgSpaceCount; idx++) {
+    // Add PCI Configuration Space entry
+    PciCfgSpace[idx].BaseAddress = PciCfgSpaceInfoList[idx].BaseAddress;
+    PciCfgSpace[idx].PciSegmentGroupNumber =
+      PciCfgSpaceInfoList[idx].PciSegmentGroupNumber;
+    PciCfgSpace[idx].StartBusNumber = PciCfgSpaceInfoList[idx].StartBusNumber;
+    PciCfgSpace[idx].EndBusNumber = PciCfgSpaceInfoList[idx].EndBusNumber;
+    PciCfgSpace[idx].Reserved = EFI_ACPI_RESERVED_DWORD;
+  }
+}
+
+/** Construct the MCFG ACPI table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildMcfgTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           TableSize;
+  UINTN                           ConfigurationSpaceCount;
+  CM_ARM_PCI_CONFIG_SPACE_INFO  * PciConfigSpaceInfoList = NULL;
+  MCFG_TABLE                    * Mcfg;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+  Status = GetEArmObjPciConfigSpaceInfo (
+              CfgMgrProtocol,
+              &PciConfigSpaceInfoList,
+              &ConfigurationSpaceCount
+              );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "ERROR: MCFG: Failed to get PCI Configuration Space Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+  ASSERT (ConfigurationSpaceCount != 0);
+
+  DEBUG ((
+    DEBUG_INFO,
+    "MCFG: Configuration Space Count = %d\n",
+    ConfigurationSpaceCount
+    ));
+
+  // Calculate the MCFG Table Size
+  TableSize = sizeof (MCFG_TABLE) +
+    ((sizeof (MCFG_CFG_SPACE_ADDR) * ConfigurationSpaceCount));
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Mcfg = (MCFG_TABLE*)*Table;
+  DEBUG ((
+    DEBUG_INFO,
+    "MCFG: Mcfg = 0x%p TableSize = 0x%x\n",
+    Mcfg,
+    TableSize
+    ));
+
+  Status = AddAcpiHeader (CfgMgrProtocol, This, &Mcfg->Header, TableSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: MCFG: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  Mcfg->Reserved = EFI_ACPI_RESERVED_QWORD;
+
+  AddPciConfigurationSpaceList (
+    Mcfg,
+    sizeof (MCFG_TABLE),
+    PciConfigSpaceInfoList,
+    ConfigurationSpaceCount
+    );
+
+  return EFI_SUCCESS;
+
+error_handler:
+  if (*Table != NULL) {
+    FreePool (*Table);
+    *Table = NULL;
+  }
+  return Status;
+}
+
+/** Free any resources allocated for constructing the MCFG
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS           The resources were freed successfully.
+    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+*/
+STATIC
+EFI_STATUS
+FreeMcfgTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((Table == NULL) || (*Table == NULL)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: MCFG: Invalid Table Pointer\n"));
+    ASSERT ((Table != NULL) && (*Table != NULL));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (*Table);
+  *Table = NULL;
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the MCFG Table Generator revision.
+*/
+#define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the MCFG Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR McfgGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MCFG),
+  // Generator Description
+  L"ACPI.STD.MCFG.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  MCFG_GENERATOR_REVISION,
+  // Build Table function
+  BuildMcfgTable,
+  // Free Resource function
+  FreeMcfgTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiMcfgLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&McfgGenerator);
+  DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiMcfgLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&McfgGenerator);
+  DEBUG ((DEBUG_INFO, "MCFG: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..aaca70cba0a1a08c0730bd84134c1b8722edd7af
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
@@ -0,0 +1,177 @@
+/** @file
+  MCFG Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** Construct the ACPI table using the ACPI table data provided.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildRawTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableData != NULL);
+
+  if (AcpiTableInfo->AcpiTableData == NULL) {
+    *Table = NULL;
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Table = AcpiTableInfo->AcpiTableData;
+
+  return EFI_SUCCESS;
+}
+
+/** Free any resources allocated for constructing the ACPI table.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS         The resources were freed successfully.
+
+*/
+STATIC
+EFI_STATUS
+FreeRawTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the Raw Generator revision.
+*/
+#define RAW_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the Raw Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR RawGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RAW),
+  // Generator Description
+  L"ACPI.STD.RAW.GENERATOR",
+  // ACPI Table Signature - Unused
+  0,
+  // ACPI Table Revision - Unused
+  0,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  RAW_GENERATOR_REVISION,
+  // Build Table function
+  BuildRawTable,
+  // Free Resource function
+  FreeRawTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                  is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiRawLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&RawGenerator);
+  DEBUG ((DEBUG_INFO, "RAW: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+
+EFI_STATUS
+EFIAPI
+AcpiRawLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&RawGenerator);
+  DEBUG ((DEBUG_INFO, "RAW: UnRegister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..ccfbcf088cfaec1e4f9f3738f5fe09a65c93bc9e
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
@@ -0,0 +1,323 @@
+/** @file
+  SPCR Table Generator
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/DebugLib.h>
+#include <Library/AcpiLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ArmNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** ARM standard SPCR Table Generator
+
+    Generates the ACPI SPCR Table for ARM UARTs as specified by
+    the Microsoft Serial Port Console Redirection Table
+    Specification - Version 1.03 - August 10, 2015.
+
+    Constructs the SPCR table for PL011 or SBSA UART peripherals.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjSerialConsolePortInfo
+
+NOTE: This implementation ignores the possibility that the Serial settings may
+      be modified from the UEFI Shell.  A more complex handler would be needed
+      to (e.g.) recover serial port settings from the UART, or non-volatile
+      storage.
+*/
+
+#pragma pack(1)
+
+/** This macro defines the no flow control option.
+*/
+#define SPCR_FLOW_CONTROL_NONE           0
+
+/**A template for generating the SPCR Table.
+
+  Note: fields marked "{Template}" will be updated dynamically.
+*/
+STATIC
+EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = {
+  ACPI_HEADER (
+    EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,
+    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
+    ),
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_PL011_UART,
+  {
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE
+  },
+  ARM_GAS32 (0), // {Template}: Serial Port Base Address
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC,
+  0, // Not used on ARM
+  0, // {Template}: Serial Port Interrupt
+  0, // {Template}: Serial Port Baudrate
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
+  SPCR_FLOW_CONTROL_NONE,
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI,
+  EFI_ACPI_RESERVED_BYTE,
+  0xFFFF,
+  0xFFFF,
+  0x00,
+  0x00,
+  0x00,
+  0x00000000,
+  0x00,
+  EFI_ACPI_RESERVED_DWORD
+};
+
+#pragma pack()
+
+/** This macro expands to a function that retrieves the Serial
+    Port Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjSerialConsolePortInfo,
+  CM_ARM_SERIAL_PORT_INFO
+  )
+
+/** Construct the SPCR ACPI table.
+
+    This function invokes the Confguration Manager protocol interface
+    to get the required hardware information for generating the ACPI
+    table.
+
+    If this function allocates any resources then they must be freed
+    in the FreeXXXXTableResources function.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [out] Table          Pointer to the constructed ACPI Table.
+
+    @retval EFI_SUCCESS           Table generated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object was not found.
+    @retval EFI_UNSUPPORTED       An unsupported baudrate was specified by the
+                                  Confguration Manager.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSpcrTable (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  EFI_STATUS                 Status;
+  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *Table = NULL;
+
+  Status = GetEArmObjSerialConsolePortInfo (
+             CfgMgrProtocol,
+             &SerialPortInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));
+  DEBUG ((DEBUG_INFO, "  UART Base  = 0x%lx\n", SerialPortInfo->BaseAddress));
+  DEBUG ((DEBUG_INFO, "  Clock      = %d\n", SerialPortInfo->Clock));
+  DEBUG ((DEBUG_INFO, "  Baudrate   = %ld\n", SerialPortInfo->BaudRate));
+  DEBUG ((DEBUG_INFO, "  Interrupt  = %d\n", SerialPortInfo->Interrupt));
+
+  Status = AddAcpiHeader (
+             CfgMgrProtocol,
+             This,
+             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr,
+             sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE)
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
+  AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;
+
+  switch (SerialPortInfo->BaudRate) {
+    case 9600:
+      AcpiSpcr.BaudRate =
+        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;
+      break;
+    case 19200:
+      AcpiSpcr.BaudRate =
+        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;
+      break;
+    case 57600:
+      AcpiSpcr.BaudRate =
+        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;
+      break;
+    case 115200:
+      AcpiSpcr.BaudRate =
+        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;
+      break;
+    default:
+      Status = EFI_UNSUPPORTED;
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
+        SerialPortInfo->BaudRate,
+        Status
+        ));
+      goto error_handler;
+  } // switch
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
+
+error_handler:
+  return Status;
+}
+
+/** Free any resources allocated for constructing the SPCR.
+
+    @param [in]  This           Pointer to the table generator.
+    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                                Protocol Interface.
+    @param [in]  Table          Pointer to the ACPI Table.
+
+    @retval EFI_SUCCESS         The resources were freed successfully.
+*/
+STATIC
+EFI_STATUS
+FreeSpcrTableResources (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the SPCR Table Generator revision.
+*/
+#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the SPCR Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR SpcrGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_SPCR),
+  // Generator Description
+  L"ACPI.STD.SPCR.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+  // ACPI Table Revision
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID_ARM,
+  // Creator Revision
+  SPCR_GENERATOR_REVISION,
+  // Build Table function
+  BuildSpcrTable,
+  // Free Resource function
+  FreeSpcrTableResources
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                is already registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiSpcrLibConstructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&SpcrGenerator);
+  DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Un-register the Generator from the ACPI Table Factory.
+
+    @param [in]  ImageHandle  The handle to the image.
+    @param [in]  SystemTable  Pointer to the System Table.
+
+    @retval EFI_SUCCESS           The Generator is un-registered.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The Generator is not registered.
+*/
+EFI_STATUS
+EFIAPI
+AcpiSpcrLibDestructor (
+  IN CONST EFI_HANDLE                ImageHandle,
+  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UnRegisterAcpiTableGenerator (&SpcrGenerator);
+  DEBUG ((DEBUG_INFO, "SPCR: Unregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
new file mode 100644
index 0000000000000000000000000000000000000000..8dc1d6b6f7c6eb71bd0ab16b690a9f5b4855dc3d
--- /dev/null
+++ b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
@@ -0,0 +1,165 @@
+/** @file
+  Table Helper
+
+Copyright (c) 2017, ARM Limited. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
+    object from the Configuration Manager.
+
+    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
+                                interface.
+    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
+                                object structure.
+
+    @retval EFI_SUCCESS           The object is returned.
+    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
+    @retval EFI_NOT_FOUND         The requested Object is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size.
+*/
+EFI_STATUS
+EFIAPI
+GetCgfMgrInfo (
+  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST  CfgMgrProtocol,
+  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **        CfgMfrInfo
+  )
+{
+  EFI_STATUS         Status;
+  CM_OBJ_DESCRIPTOR  CmObjectDesc;
+
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (CfgMfrInfo != NULL);
+
+  *CfgMfrInfo = NULL;
+  Status = CfgMgrProtocol->GetObject (
+    CfgMgrProtocol,
+    CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
+    &CmObjectDesc
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to Get Configuration Manager Info. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  ASSERT (CmObjectDesc.Size >= sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO));
+  if (CmObjectDesc.Size < sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: EStdObjCfgMgrInfo: Buffer too small, size  = 0x%x\n",
+      CmObjectDesc.Size
+      ));
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  *CfgMfrInfo = (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO*)CmObjectDesc.Data;
+  return Status;
+}
+
+/** The AddAcpiHeader function updates the ACPI header structure pointed by
+    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
+    Manager protocol to obtain any information required for constructing the
+    header.
+
+    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
+                                   protocol interface.
+    @param [in]     Generator      Pointer to the ACPI table Generator.
+    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
+                                   updated.
+    @param [in]     Length         Length of the ACPI table.
+
+    @retval EFI_SUCCESS           The ACPI table is updated successfully.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The required object information is not found.
+    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+EFI_STATUS
+EFIAPI
+AddAcpiHeader (
+  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
+  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
+  IN      CONST UINT32                                      Length
+  )
+{
+  EFI_STATUS                               Status;
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
+
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Generator != NULL);
+  ASSERT (AcpiHeader != NULL);
+  ASSERT (Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+
+  if ((CfgMgrProtocol == NULL) ||
+      (Generator == NULL) ||
+      (AcpiHeader == NULL) ||
+      (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))
+    ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  /* UINT32  Signature */
+  AcpiHeader->Signature = Generator->AcpiTableSignature;
+  /* UINT32  Length */
+  AcpiHeader->Length = Length;
+  /* UINT8   Revision */
+  AcpiHeader->Revision = Generator->AcpiTableRevision;
+  /* UINT8   Checksum */
+  AcpiHeader->Checksum = 0;
+
+  /* UINT8   OemId[6] */
+  CopyMem (AcpiHeader->OemId, CfgMfrInfo->OemId, sizeof (AcpiHeader->OemId));
+
+  /* UINT64  OemTableId */
+  AcpiHeader->OemTableId = Generator->CreatorId; // Generator->GeneratorID;
+  AcpiHeader->OemTableId <<= 32;
+  AcpiHeader->OemTableId |= Generator->AcpiTableSignature;
+
+  /* UINT32  OemRevision */
+  AcpiHeader->OemRevision = CfgMfrInfo->Revision;
+
+  /* UINT32  CreatorId */
+  AcpiHeader->CreatorId = Generator->CreatorId;
+  /* UINT32  CreatorRevision */
+  AcpiHeader->CreatorRevision = Generator->CreatorRevision;
+
+  Status = EFI_SUCCESS;
+error_handler:
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
new file mode 100644
index 0000000000000000000000000000000000000000..79cf0f290ddb79499c71d6c553b420418dec50f1
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
@@ -0,0 +1,227 @@
+/** @file
+  ACPI Table Factory
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Std - Standard
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include "DynamicTableFactory.h"
+
+extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
+
+/** Return a pointer to the ACPI table generator.
+
+    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  GeneratorId  The ACPI table generator ID for the
+                              requested generator.
+    @param [out] Generator    Pointer to the requested ACPI table
+                              generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+GetAcpiTableGenerator (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
+  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
+  )
+{
+  UINT16                           TableId;
+  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
+
+  ASSERT (This != NULL);
+
+  FactoryInfo = This->TableFactoryInfo;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_ACPI (GeneratorId)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not ACPI\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Generator = NULL;
+  TableId = GET_TABLE_ID (GeneratorId);
+  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
+    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (FactoryInfo->StdAcpiTableGeneratorList[TableId] != NULL) {
+      *Generator = FactoryInfo->StdAcpiTableGeneratorList[TableId];
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (FactoryInfo->CustomAcpiTableGeneratorList[TableId] != NULL) {
+      *Generator = FactoryInfo->CustomAcpiTableGeneratorList[TableId];
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/** Register ACPI table factory generator.
+
+    The ACPI table factory maintains a list of the Standard and OEM ACPI
+    table generators.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+
+    @retval EFI_SUCCESS           The Generator was registered
+                                  successfully.
+    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
+                                  the Generator pointer is NULL.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
+                                  already registered.
+*/
+EFI_STATUS
+EFIAPI
+RegisterAcpiTableGenerator (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
+  )
+{
+  UINT16  TableId;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: ACPI register - Invalid Generator\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: ACPI register - Generator" \
+      " Type is not ACPI\n"
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
+
+  TableId = GET_TABLE_ID (Generator->GeneratorID);
+  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
+    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] == NULL) {
+      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = Generator;
+    } else {
+      return EFI_ALREADY_STARTED;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] == NULL) {
+      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = Generator;
+    } else {
+      return EFI_ALREADY_STARTED;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/** Unregister ACPI generator.
+
+    This function is called by the ACPI table generator to unregister itself
+    from the ACPI table factory.
+
+    @param [in]  Generator       Pointer to the ACPI table generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The generator is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+UnRegisterAcpiTableGenerator (
+  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
+  )
+{
+  UINT16  TableId;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: ACPI un-register - Invalid Generator\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: ACPI un-register - Generator" \
+      " Type is not ACPI\n"
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TableId = GET_TABLE_ID (Generator->GeneratorID);
+  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
+    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] != NULL) {
+      if (Generator != TableFactoryInfo.StdAcpiTableGeneratorList[TableId]) {
+        return EFI_INVALID_PARAMETER;
+      }
+      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = NULL;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] != NULL) {
+      if (Generator !=
+          TableFactoryInfo.CustomAcpiTableGeneratorList[TableId]) {
+        return EFI_INVALID_PARAMETER;
+      }
+      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = NULL;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..64a0390cdd006d8e3222ff19b269d1b4326736c3
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
@@ -0,0 +1,84 @@
+/** @file
+  Dynamic Table Factory Dxe
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include "DynamicTableFactory.h"
+
+/** The Dynamic Table Factory protocol structure that holds the
+    list of registered ACPI and SMBIOS table generators.
+*/
+EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
+
+
+/** A structure describing the Dynamic Table Factory protocol.
+*/
+STATIC
+CONST
+EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL DynamicTableFactoryProtocol = {
+  CREATE_REVISION (1, 0),
+  GetAcpiTableGenerator,
+  GetSmbiosTableGenerator,
+  &TableFactoryInfo
+};
+
+/** Entrypoint for Dynamic Table Factory Dxe.
+
+    @param  ImageHandle
+    @param  SystemTable
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+    @retval EFI_NOT_FOUND         Required interface/object was not found.
+    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
+
+*/
+EFI_STATUS
+EFIAPI
+DynamicTableFactoryDxeInitialize (
+  IN  EFI_HANDLE                 ImageHandle,
+  IN  EFI_SYSTEM_TABLE   * CONST SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->InstallProtocolInterface (
+                  &ImageHandle,
+                  &gEfiDynamicTableFactoryProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID*)&DynamicTableFactoryProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to install the Dynamic Table Factory Protocol." \
+      " Status = %r\n",
+      Status
+      ));
+  }
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
new file mode 100644
index 0000000000000000000000000000000000000000..64b578f30a3413ac2b22ccef4f09368c1af38b67
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
@@ -0,0 +1,227 @@
+/** @file
+  SMBIOS Table Factory
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Glossary:
+    - Std - Standard
+**/
+
+#include <Protocol/Smbios.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include "DynamicTableFactory.h"
+
+extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
+
+/** Return a pointer to the SMBIOS table generator.
+
+    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
+    @param [in]  GeneratorId  The SMBIOS table generator ID for the
+                              requested generator.
+    @param [out] Generator    Pointer to the requested SMBIOS table
+                              generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+GetSmbiosTableGenerator (
+  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
+  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
+  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
+  )
+{
+  UINT16                           TableId;
+  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
+
+  ASSERT (This != NULL);
+
+  FactoryInfo = This->TableFactoryInfo;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_SMBIOS (GeneratorId)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not SMBIOS\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Generator = NULL;
+  TableId = GET_TABLE_ID (GeneratorId);
+  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
+    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (FactoryInfo->StdSmbiosTableGeneratorList[TableId] != NULL) {
+      *Generator = FactoryInfo->StdSmbiosTableGeneratorList[TableId];
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (FactoryInfo->CustomSmbiosTableGeneratorList[TableId] != NULL) {
+      *Generator = FactoryInfo->CustomSmbiosTableGeneratorList[TableId];
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/** Register SMBIOS table factory generator.
+
+    The SMBIOS table factory maintains a list of the Standard and OEM SMBIOS
+    table generators.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+
+    @retval EFI_SUCCESS           The Generator was registered
+                                  successfully.
+    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
+                                  the Generator pointer is NULL.
+    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
+                                  already registered.
+*/
+EFI_STATUS
+EFIAPI
+RegisterSmbiosTableGenerator (
+  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
+  )
+{
+  UINT16  TableId;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS register - Invalid Generator\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SMBIOS register - Generator" \
+      " Type is not SMBIOS\n"
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
+
+  TableId = GET_TABLE_ID (Generator->GeneratorID);
+  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
+    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] == NULL) {
+      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = Generator;
+    } else {
+      return EFI_ALREADY_STARTED;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] == NULL) {
+      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = Generator;
+    } else {
+      return EFI_ALREADY_STARTED;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/** Unregister SMBIOS generator.
+
+    This function is called by the SMBIOS table generator to unregister itself
+    from the SMBIOS table factory.
+
+    @param [in]  Generator       Pointer to the SMBIOS table generator.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER The generator is invalid.
+    @retval EFI_NOT_FOUND         The requested generator is not found
+                                  in the list of registered generators.
+*/
+EFI_STATUS
+EFIAPI
+UnRegisterSmbiosTableGenerator (
+  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
+  )
+{
+  UINT16  TableId;
+
+  if (Generator == NULL) {
+    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS un-register - Invalid Generator\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SMBIOS un-register - Generator" \
+      " Type is not SMBIOS\n"
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TableId = GET_TABLE_ID (Generator->GeneratorID);
+  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
+    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
+      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] != NULL) {
+      if (Generator != TableFactoryInfo.StdSmbiosTableGeneratorList[TableId]) {
+        return EFI_INVALID_PARAMETER;
+      }
+      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = NULL;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
+      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
+      return EFI_INVALID_PARAMETER;
+    }
+    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] != NULL) {
+      if (Generator !=
+          TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId]) {
+        return EFI_INVALID_PARAMETER;
+      }
+      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = NULL;
+    } else {
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..f84bf3bef910ddf86629062d6d1ca1dffafa5a28
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
@@ -0,0 +1,531 @@
+/** @file
+  Dynamic Table Manager Dxe
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+
+#include <DynamicTables/TableGenerator.h>
+#include <DynamicTables/AcpiTableGenerator.h>
+#include <DynamicTables/SmbiosTableGenerator.h>
+#include <DynamicTables/StandardNameSpaceObjects.h>
+#include <DynamicTables/ConfigurationManagerObject.h>
+#include <DynamicTables/ConfigurationManagerHelper.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include <Library/TableHelperLib.h>
+
+/** This macro expands to a function that retrieves the ACPI Table
+    List from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceStandard,
+  EStdObjAcpiTableList,
+  CM_STD_OBJ_ACPI_TABLE_INFO
+  )
+
+/** A helper function to invoke a Table generator
+
+    This is a helper function that invokes the Table generator interface
+    for building an ACPI table. It uses the AcpiTableProtocol to install the
+    table, then frees the resources allocated for generating it.
+
+    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
+                                      interface.
+    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
+                                      Protocol Interface.
+    @param [in]  AcpiTableProtocol    Pointer to the AcpiTable protocol.
+    @param [in]  AcpiTableInfo        Pointer to the ACPI table Info.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_INVALID_PARAMETER A parameter is invalid.
+    @retval EFI_NOT_FOUND         Required object is not found.
+    @retval EFI_BAD_BUFFER_SIZE   Size returned by the Configuration Manager
+                                  is less than the Object size for the requested
+                                  object.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildAndInstallAcpiTable (
+  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST TableFactoryProtocol,
+  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN       EFI_ACPI_TABLE_PROTOCOL             *       AcpiTableProtocol,
+  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo
+  )
+{
+  EFI_STATUS                    Status;
+  CONST ACPI_TABLE_GENERATOR  * Generator = NULL;
+  EFI_ACPI_DESCRIPTION_HEADER * AcpiTable;
+  UINTN                         TableHandle;
+
+  ASSERT (TableFactoryProtocol != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableProtocol != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: EStdObjAcpiTableList: Address = 0x%p," \
+    " TableGeneratorId = 0x%x\n",
+    AcpiTableInfo,
+    AcpiTableInfo->TableGeneratorId
+    ));
+
+  Status = TableFactoryProtocol->GetAcpiTableGenerator (
+                                   TableFactoryProtocol,
+                                   AcpiTableInfo->TableGeneratorId,
+                                   &Generator
+                                   );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Table Generator not found." \
+      " TableGeneratorId = 0x%x. Status = %r\n",
+      AcpiTableInfo->TableGeneratorId,
+      Status
+      ));
+    return Status;
+  }
+
+  ASSERT (Generator != NULL);
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: Generator found : %s\n",
+    Generator->Description
+    ));
+
+  if (Generator->BuildAcpiTable == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Table Generator does not implement the" \
+      " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
+      " TableGeneratorId = 0x%x. Status = %r\n",
+      AcpiTableInfo->TableGeneratorId,
+      Status
+      ));
+    return Status;
+  }
+
+  AcpiTable = NULL;
+  Status = Generator->BuildAcpiTable (
+                        Generator,
+                        AcpiTableInfo,
+                        CfgMgrProtocol,
+                        &AcpiTable
+                        );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to Build Table." \
+      " TableGeneratorId = 0x%x. Status = %r\n",
+      AcpiTableInfo->TableGeneratorId,
+      Status
+      ));
+    // Free any allocated resources.
+    goto error_handler;
+  }
+
+  ASSERT (AcpiTable != NULL);
+
+  // Dump ACPI Table Header
+  DUMP_ACPI_TABLE_HEADER (AcpiTable);
+
+  // Install ACPI table
+  Status = AcpiTableProtocol->InstallAcpiTable (
+                                AcpiTableProtocol,
+                                AcpiTable,
+                                AcpiTable->Length,
+                                &TableHandle
+                                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to Install ACPI Table. Status = %r\n",
+      Status
+      ));
+    // Free any allocated resources.
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: ACPI Table installed. Status = %r\n",
+    Status
+    ));
+
+error_handler:
+  // Free any resources allocated for generating the tables.
+  if ((AcpiTable != NULL) && (Generator->FreeTableResources != NULL)) {
+    Status = Generator->FreeTableResources (
+                          Generator,
+                          AcpiTableInfo,
+                          CfgMgrProtocol,
+                          &AcpiTable
+                          );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: Failed to Free Table Resources." \
+        "TableGeneratorId = 0x%x. Status = %r\n",
+        AcpiTableInfo->TableGeneratorId,
+        Status
+        ));
+    }
+  }
+  return Status;
+}
+
+/** The function checks if the Configuration Manager has provided the
+    mandatory ACPI tables for installation.
+
+    @param [in]  AcpiTableInfo      Pointer to the ACPI Table Info list.
+    @param [in]  AcpiTableCount     Count of ACPI Table Info.
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_NOT_FOUND         If mandatory table is not found.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+VerifyMandatoryTablesArePresent (
+  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO  * CONST AcpiTableInfo,
+  IN CONST UINTN                               AcpiTableCount
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+  BOOLEAN     FadtFound = FALSE;
+  BOOLEAN     MadtFound = FALSE;
+  BOOLEAN     GtdtFound = FALSE;
+  BOOLEAN     DsdtFound = FALSE;
+  BOOLEAN     Dbg2Found = FALSE;
+  BOOLEAN     SpcrFound = FALSE;
+  UINTN       idx;
+
+  ASSERT (AcpiTableInfo != NULL);
+
+  for (idx = 0; idx < AcpiTableCount; idx++) {
+    switch (AcpiTableInfo[idx].AcpiTableSignature) {
+      case EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+        FadtFound = TRUE;
+        break;
+      case EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+        MadtFound = TRUE;
+        break;
+      case EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:
+        GtdtFound = TRUE;
+        break;
+      case EFI_ACPI_6_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+        DsdtFound = TRUE;
+        break;
+      case EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE:
+        Dbg2Found = TRUE;
+        break;
+      case EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
+        SpcrFound = TRUE;
+        break;
+      default:
+        break;
+    }
+  }
+
+  // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
+  if (!FadtFound) {
+    DEBUG ((DEBUG_ERROR,"ERROR: FADT Table not found\n"));
+    Status = EFI_NOT_FOUND;
+  }
+  if (!MadtFound) {
+    DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));
+    Status = EFI_NOT_FOUND;
+  }
+  if (!GtdtFound) {
+    DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));
+    Status = EFI_NOT_FOUND;
+  }
+  if (!DsdtFound) {
+    DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));
+    Status = EFI_NOT_FOUND;
+  }
+  if (!Dbg2Found) {
+    DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));
+  }
+  if (!SpcrFound) {
+    DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));
+  }
+  return Status;
+}
+
+/** Generate and install ACPI tables.
+
+    The function gathers the information necessary for installing the
+    ACPI tables from the Configuration Manager, invokes the generators
+    and installs them (via BuildAndInstallAcpiTable).
+
+    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
+                                      interface.
+    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
+                                      Protocol Interface.
+
+
+    @retval EFI_SUCCESS   Success.
+    @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+ProcessAcpiTables (
+  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST TableFactoryProtocol,
+  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_ACPI_TABLE_PROTOCOL     * AcpiTableProtocol;
+  UINTN                         AcpiTableCount;
+  CM_STD_OBJ_ACPI_TABLE_INFO  * AcpiTableInfo;
+  UINTN                         idx;
+
+  ASSERT (TableFactoryProtocol != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+
+  // Find the AcpiTable protocol
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID**)&AcpiTableProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  Status = GetEStdObjAcpiTableList (
+             CfgMgrProtocol,
+             &AcpiTableInfo,
+             &AcpiTableCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to get ACPI Table List. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  if (0 == AcpiTableCount) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
+      AcpiTableCount
+      ));
+    return EFI_NOT_FOUND;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
+    AcpiTableCount
+    ));
+
+  // Check if mandatory ACPI tables are present.
+  Status = VerifyMandatoryTablesArePresent (
+             AcpiTableInfo,
+             AcpiTableCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to find mandatory ACPI Table(s)."
+      " Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  // Add the FADT Table first.
+  for (idx = 0; idx < AcpiTableCount; idx++) {
+    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
+        AcpiTableInfo[idx].TableGeneratorId) {
+      Status = BuildAndInstallAcpiTable (
+                 TableFactoryProtocol,
+                 CfgMgrProtocol,
+                 AcpiTableProtocol,
+                 &AcpiTableInfo[idx]
+                 );
+      if (EFI_ERROR (Status)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: Failed to find build and install ACPI FADT Table." \
+          " Status = %r\n",
+          Status
+          ));
+        return Status;
+      }
+      break;
+    }
+  } // for
+
+  // Add remaining ACPI Tables
+  for (idx = 0; idx < AcpiTableCount; idx++) {
+    DEBUG ((
+      DEBUG_INFO,
+      "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
+      idx,
+      AcpiTableInfo[idx].TableGeneratorId
+      ));
+
+    // Skip FADT Table since we have already added
+    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
+        AcpiTableInfo[idx].TableGeneratorId) {
+      continue;
+    }
+
+    // Skip the Reserved table Generator ID
+    if ((CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RESERVED) >=
+           AcpiTableInfo[idx].TableGeneratorId)                     ||
+        (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MAX)      <=
+           AcpiTableInfo[idx].TableGeneratorId)) {
+      DEBUG ((
+        DEBUG_WARN,
+        "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
+        AcpiTableInfo[idx].TableGeneratorId
+        ));
+      continue;
+    }
+
+    Status = BuildAndInstallAcpiTable (
+               TableFactoryProtocol,
+               CfgMgrProtocol,
+               AcpiTableProtocol,
+               &AcpiTableInfo[idx]
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: Failed to find, build, and install ACPI Table." \
+        " Status = %r\n",
+        Status
+        ));
+      return Status;
+    }
+  } // for
+
+  return Status;
+}
+
+/** Entrypoint of Dynamic Table Manager Dxe.
+
+  The Dynamic Table Manager uses the Configuration Manager Protocol
+  to get the list of ACPI and SMBIOS tables to install. For each table
+  in the list it requests the corresponding ACPI/SMBIOS table factory for
+  a generator capable of building the ACPI/SMBIOS table.
+  If a suitable table generator is found, it invokes the generator interface
+  to build the table. The Dynamic Table Manager then installs the
+  table and invokes another generator interface to free any resources
+  allocated for building the table.
+
+    @param  ImageHandle
+    @param  SystemTable
+
+    @retval EFI_SUCCESS           Success.
+    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+    @retval EFI_NOT_FOUND         Required interface/object was not found.
+    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
+
+*/
+EFI_STATUS
+EFIAPI
+DynamicTableManagerDxeInitialize (
+  IN CONST EFI_HANDLE                 ImageHandle,
+  IN       EFI_SYSTEM_TABLE   * CONST SystemTable
+  )
+{
+  EFI_STATUS                               Status;
+  EFI_CONFIGURATION_MANAGER_PROTOCOL     * CfgMgrProtocol;
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
+  EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL     * TableFactoryProtocol;
+
+  // Locate the Dynamic Table Factory
+  Status = gBS->LocateProtocol (
+                  &gEfiDynamicTableFactoryProtocolGuid,
+                  NULL,
+                  (VOID**)&TableFactoryProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to find Dynamic Table Factory protocol." \
+      " Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  // Locate the Configuration Manager for the Platform
+  Status = gBS->LocateProtocol (
+                  &gEfiConfigurationManagerProtocolGuid,
+                  NULL,
+                  (VOID**)&CfgMgrProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",
+    CfgMfrInfo->Revision,
+    CfgMfrInfo->OemId[0],
+    CfgMfrInfo->OemId[1],
+    CfgMfrInfo->OemId[2],
+    CfgMfrInfo->OemId[3],
+    CfgMfrInfo->OemId[4],
+    CfgMfrInfo->OemId[5]
+    ));
+
+  Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: ACPI Table processing failure. Status = %r\n",
+      Status
+      ));
+  }
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
new file mode 100644
index 0000000000000000000000000000000000000000..69012cf8242c8ddd13ac4033293ac8a7053dfbd8
--- /dev/null
+++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
@@ -0,0 +1,35 @@
+## @file
+#  fdf include file for Dynamic Tables Framework.
+#
+#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file.  This section also defines order the components and modules are positioned
+# within the image.  The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+
+  #
+  # Dynamic Table Factory Dxe
+  #
+  INF MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
+
+  #
+  # Dynamic Tables Dxe
+  #
+  INF MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
-- 
Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
  2017-10-03 14:34   ` Zeng, Star
@ 2017-10-03 16:03     ` Leif Lindholm
  2017-10-03 18:44       ` Sean Brogan
  2017-10-03 17:03     ` Evan Lloyd
  1 sibling, 1 reply; 14+ messages in thread
From: Leif Lindholm @ 2017-10-03 16:03 UTC (permalink / raw)
  To: Zeng, Star
  Cc: evan.lloyd@arm.com, edk2-devel@lists.01.org, Matteo.Carlini,
	ard.biesheuvel, Kinney, Michael D, thomas.abraham, Arvind.Chauhan,
	Yao, Jiewen, leif.lindholm, Daniil.Egranov

(something funky going on with email addresses on cc, I've adjusted here)

On Tue, Oct 03, 2017 at 02:34:52PM +0000, Zeng, Star wrote:
> May I ask you are proposing
> edk2-platforms(https://github.com/tianocore/edk2-platforms) change
> or edk2 master(https://github.com/tianocore/edk2) change?

MdeModulePkg exists only in edk2, so that is the intended target.
(I expect to be back to patch reviewing again tomorrow.)

Best Regards,

Leif

> Please note, we may have no/occasional email response during PRC holiday (10/1 - 10/8).
> 
> Thanks,
> Star
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of evan.lloyd@arm.com
> Sent: Tuesday, October 3, 2017 3:48 AM
> To: edk2-devel@lists.01.org
> Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com; "ard.biesheuvel@linaro.org"@arm.com; "thomas.abraham@arm.com"@arm.com; "Arvind.Chauhan@arm.com"@arm.com; "leif.lindholm@linaro.org"@arm.com; "Daniil.Egranov@arm.com"@arm.com
> Subject: [edk2] [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
> 
> From: Sami Mujawar <sami.mujawar@arm.com>
> 
> The dynamic tables framework is designed to generate standardised
> firmware tables that describe the hardware information at
> run-time. A goal of standardised firmware is to have a common
> firmware for a platform capable of booting both Windows and Linux
> operating systems.
> 
> Traditionally the firmware tables are handcrafted using ACPI
> Machine Language (AML), Table Definition Language (TDL) and
> C-code. This approach can be error prone and involves time
> consuming debugging. In addition, it may be desirable to configure
> platform hardware at runtime such as: configuring the number of
> cores available for use by the OS, or turning SoC features ON or
> OFF.
> 
> The dynamic tables framework simplifies this by providing a set
> of standard table generators, that are implemented as libraries.
> These generators query a platform specific component, the
> 'Configuration Manager', to collate the information required
> for generating the tables at run-time.
> 
> The framework also provisions the ability to implement custom/OEM
> generators; thereby facilitating support for custom tables. The
> custom generators can also utilize the existing standard generators
> and override any functionality if needed.
> 
> The framework currently implements a set of standard ACPI table
> generators for ARM architecture, that can generate Server Base Boot
> Requirement (SBBR) compliant tables. Support for generating SMBIOS
> tables is planned to be added subsequently. Although, the set
> of standard generators implements the functionality required for ARM
> architecture; the framework is extensible, and support for other
> architectures can be easily added.
> 
> Contributions from the community are invited.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> Signed-off-by: Evan Lloyd <evan.lloyd@arm.com>
> ---
>  MdeModulePkg/MdeModulePkg.dec                                                                       |  13 +
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc                                          |  45 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf                       |  49 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf                       |  47 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf                       |  46 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf                       |  47 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf                       |  47 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf                         |  44 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf                       |  44 ++
>  MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf                         |  39 ++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf              |  57 ++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf              |  47 ++
>  MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h                                             | 280 ++++++++
>  MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h                                            | 367 ++++++++++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h                                     | 112 +++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h                                     | 158 +++++
>  MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h                                           | 235 +++++++
>  MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h                                       |  93 +++
>  MdeModulePkg/Include/DynamicTables/TableGenerator.h                                                 | 235 +++++++
>  MdeModulePkg/Include/Library/TableHelperLib.h                                                       |  67 ++
>  MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h                                        | 121 ++++
>  MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h                                         | 113 +++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h                   |  91 +++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c                          | 440 ++++++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c                          | 562 +++++++++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c                          | 652 +++++++++++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c                          | 732 ++++++++++++++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c                          | 336 +++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c                            | 177 +++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c                          | 323 +++++++++
>  MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c                              | 165 +++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c     | 227 ++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c                |  84 +++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c | 227 ++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c                | 531 ++++++++++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc                                          |  35 +
>  36 files changed, 6888 insertions(+)
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
> index a3c0633ee1ec6ab7540a1b7221850e975f95ad80..de8a658c21d11ab1396bb543b026f94a396a0710 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -7,6 +7,7 @@
>  # Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
>  # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
>  # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +# Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
>  #
>  # This program and the accompanying materials are licensed and made available under
>  # the terms and conditions of the BSD License that accompanies this distribution.
> @@ -556,6 +557,12 @@ [Protocols]
>    ## Include/Protocol/IoMmu.h
>    gEdkiiIoMmuProtocolGuid = { 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed, 0xe6, 0xe1, 0xce, 0x51, 0x7c, 0x1e } }
>  
> +  # Configuration Manager Protocol GUID
> +  gEfiConfigurationManagerProtocolGuid = { 0xd85a4835, 0x5a82, 0x4894, { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } }
> +
> +  # Dynamic Table Factory Protocol GUID
> +  gEfiDynamicTableFactoryProtocolGuid = { 0x91d1e327, 0xfe5a, 0x49b8, { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec } }
> +
>  #
>  # [Error.gEfiMdeModulePkgTokenSpaceGuid]
>  #   0x80000001 | Invalid value provided.
> @@ -867,6 +874,12 @@ [PcdsFixedAtBuild]
>    # @ValidList  0x80000006 | 0x03058002
>    gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UINT32|0x30001040
>  
> +  # Maximum number of Custom ACPI Generators
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators|1|UINT16|0xC0000001
> +
> +  # Maximum number of Custom SMBIOS Generators
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators|1|UINT16|0xC0000002
> +
>  [PcdsFixedAtBuild, PcdsPatchableInModule]
>    ## Dynamic type PCD can be registered callback function for Pcd setting action.
>    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> new file mode 100644
> index 0000000000000000000000000000000000000000..548c77ad971f97c43da8f7ba1b69fa6948430c17
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> @@ -0,0 +1,45 @@
> +## @file
> +#  Dsc include file for Dynamic Tables Framework.
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +
> +[BuildOptions]
> +  *_*_*_ASL_FLAGS          = -th -li
> +
> +[LibraryClasses.common]
> +
> +[Components.common]
> +  #
> +  # Dynamic Table Factory Dxe
> +  #
> +  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf {
> +    <LibraryClasses>
> +      TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
> +  }
> +
> +  #
> +  # Dynamic Tables Manager Dxe
> +  #
> +  MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf {
> +    <LibraryClasses>
> +      TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
> +  }
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..591b6364ae86c885ca4768599d3eadf6d2842eff
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
> @@ -0,0 +1,49 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiDbg2LibArm
> +  FILE_GUID      = A17BA4F0-3DEB-4FE5-BD27-EC008E541B22
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiDbg2LibConstructor
> +  DESTRUCTOR     = AcpiDbg2LibDestructor
> +
> +
> +[Sources]
> +  Dbg2Generator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  SerialPortLib
> +
> +[FixedPcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..ae5239fd2a3e6f00574cf5f3bb4a561031e122be
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiFadtLibArm
> +  FILE_GUID      = 686FE5FE-B944-485F-8B1C-7D60E0056487
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiFadtLibConstructor
> +  DESTRUCTOR     = AcpiFadtLibDestructor
> +
> +
> +[Sources]
> +  FadtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..be38489c2987a81d68effd9c05b731b17cb2819c
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
> @@ -0,0 +1,46 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiGtdtLibArm
> +  FILE_GUID      = 26490F7A-7FA2-423C-8939-C6206329BC37
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiGtdtLibConstructor
> +  DESTRUCTOR     = AcpiGtdtLibDestructor
> +
> +
> +[Sources]
> +  GtdtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[FixedPcd]
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..9807e3fe75bb785c3b400410248e6434532f2147
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiMadtLibArm
> +  FILE_GUID      = AF76C93B-41B5-454D-83CD-D2A80A1C1E38
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiMadtLibConstructor
> +  DESTRUCTOR     = AcpiMadtLibDestructor
> +
> +
> +[Sources]
> +  MadtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..2f879dfee4b93a56a923340c4b416c6df9656618
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiMcfgLibArm
> +  FILE_GUID      = 8C9BDCB2-72D4-4F30-A12D-1145C3807FF7
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiMcfgLibConstructor
> +  DESTRUCTOR     = AcpiMcfgLibDestructor
> +
> +
> +[Sources]
> +  McfgGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..db208bdeb8ffce085367ee865766a0a1bd90cb28
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> @@ -0,0 +1,44 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiRawLibArm
> +  FILE_GUID      = 20F31568-D687-49BA-B326-CCD9D38EDE16
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiRawLibConstructor
> +  DESTRUCTOR     = AcpiRawLibDestructor
> +
> +
> +[Sources]
> +  RawGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..3d47e6ae1f7995f76fe3e93093b0185e48ecae79
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
> @@ -0,0 +1,44 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiSpcrLibArm
> +  FILE_GUID      = 55088136-7B78-4974-B1EE-F630150D0DE7
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiSpcrLibConstructor
> +  DESTRUCTOR     = AcpiSpcrLibDestructor
> +
> +
> +[Sources]
> +  SpcrGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..38952fba1c8056bf0c581975ca974abbef1e8096
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
> @@ -0,0 +1,39 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = DynamicTableHelperLib
> +  FILE_GUID      = E315C738-3A39-4D0D-A0AF-8EDFA770AB39
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = TableHelperLib
> +
> +
> +[Sources]
> +  TableHelper.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..c58ac3a8d6d655e38cb8460a35ce256fc4e5ada6
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
> @@ -0,0 +1,57 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010016
> +  BASE_NAME                      = DynamicTableFactoryDxe
> +  FILE_GUID                      = FE846898-7403-4932-B8AD-A0491F0C2CBA
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DynamicTableFactoryDxeInitialize
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = ARM AARCH64
> +#
> +
> +[Sources]
> +  DynamicTableFactoryDxe.c
> +  AcpiTableFactory/AcpiTableFactory.c
> +  SmbiosTableFactory/SmbiosTableFactory.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  PrintLib
> +  BaseLib
> +  MemoryAllocationLib
> +  TableHelperLib
> +
> +[FixedPcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators
> +
> +[Protocols]
> +  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
> +  gEfiSmbiosProtocolGuid                        # PROTOCOL ALWAYS_CONSUMED
> +  gEfiConfigurationManagerProtocolGuid
> +  gEfiDynamicTableFactoryProtocolGuid
> +
> +[Depex]
> +  TRUE
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..9c5a5f6207687ca90fa11188340d09c304fc34c0
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010016
> +  BASE_NAME                      = DynamicTableManagerDxe
> +  FILE_GUID                      = 89122868-BCFD-49E8-88A3-06635CB7B3CF
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DynamicTableManagerDxeInitialize
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = ARM AARCH64
> +#
> +
> +[Sources]
> +  DynamicTableManagerDxe.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  PrintLib
> +  TableHelperLib
> +
> +[Protocols]
> +  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
> +  gEfiConfigurationManagerProtocolGuid
> +  gEfiDynamicTableFactoryProtocolGuid
> +
> +[Depex]
> +  TRUE
> diff --git a/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..3a07cd6e10217958d22a93060a0f9aa48947f264
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> @@ -0,0 +1,280 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef ACPI_TABLE_GENERATOR_H_
> +#define ACPI_TABLE_GENERATOR_H_
> +
> +#pragma pack(1)
> +
> +/**
> +The Dynamic Tables Framework provisions two classes of ACPI table
> +generators.
> + - Standard generators: The ACPI table generators implemented by the
> +                        Dynamic Tables Framework.
> + - OEM generators:      The ACPI table generatos customized by the OEM.
> +
> +The Dynamic Tables Framework implements the following ACPI table generators:
> +  - RAW   : This is the simplest ACPI table generator. It simply installs
> +            the ACPI table provided in the AcpiTableData member of the
> +            CM_STD_OBJ_ACPI_TABLE_INFO. The ACPI table data is provided by
> +            the Configuration Manager and is generated using an implementation
> +            defined mechanism.
> +  - DSDT  : The DSDT generator is clone of the RAW generator. The difference
> +            is in the way the ACPI Table Data is generated from an AML file.
> +  - SSDT  : The SSDT generator is clone of the RAW generator. The difference
> +            is in the way the ACPI Table Data is generated from an AML file.
> +  - FADT  : The FADT generator collates the required platform information for
> +            building the ACPI FADT table from the Configuration Manager and
> +            generates the FADT table.
> +  - MADT  : The MADT generator collates the GIC information for building the
> +            ACPI MADT table from the Configuration Manager and generates the
> +            MADT table.
> +  - GTDT  : The GTDT generator collates the Timer information for building the
> +            ACPI GTDT table from the Configuration Manager and generates the
> +            GTDT table.
> +  - DBG2  : The DBG2 generator collates the debug serial port information for
> +            building the DBG2 table from the Configuration Manager and
> +            generates the GTDT table.
> +  - SPCR  : The SPCR generator collates the serial port information for
> +            building the SPCR table from the Configuration Manager and
> +            generates the SPCR table.
> +  - MCFG  : The MCFG generator collates the PCI configuration space information
> +            for building the MCFG table from the Configuration Manager and
> +            generates the MCFG table.
> +*/
> +
> +/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
> +*/
> +typedef TABLE_GENERATOR_ID ACPI_TABLE_GENERATOR_ID;
> +
> +/** The ESTD_ACPI_TABLE_ID enum describes the ACPI table IDs reserved for
> +  the standard generators.
> +*/
> +typedef enum StdAcpiTableId {
> +  ESTD_ACPI_TABLE_ID_RESERVED = 0x0000,             ///< Reserved.
> +  ESTD_ACPI_TABLE_ID_RAW,                           ///< RAW Generator.
> +  ESTD_ACPI_TABLE_ID_DSDT = ESTD_ACPI_TABLE_ID_RAW, ///< DSDT Generator.
> +  ESTD_ACPI_TABLE_ID_SSDT = ESTD_ACPI_TABLE_ID_RAW, ///< SSDT Generator.
> +  ESTD_ACPI_TABLE_ID_FADT,                          ///< FADT Generator.
> +  ESTD_ACPI_TABLE_ID_MADT,                          ///< MADT Generator.
> +  ESTD_ACPI_TABLE_ID_GTDT,                          ///< GTDT Generator.
> +  ESTD_ACPI_TABLE_ID_DBG2,                          ///< DBG2 Generator.
> +  ESTD_ACPI_TABLE_ID_SPCR,                          ///< SPCR Generator.
> +  ESTD_ACPI_TABLE_ID_MCFG,                          ///< MCFG Generator.
> +  ESTD_ACPI_TABLE_ID_MAX
> +} ESTD_ACPI_TABLE_ID;
> +
> +/** This macro checks if the Table Generator ID is for an ACPI Table Generator.
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the table generator ID is for an ACPI Table
> +          Generator.
> +*/
> +#define IS_GENERATOR_TYPE_ACPI(TableGeneratorId) \
> +          (GET_TABLE_TYPE (TableGeneratorId) == ETableGeneratorTypeAcpi)
> +
> +/** This macro checks if the Table Generator ID is for a standard ACPI
> +    Table Generator.
> +
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the table generator ID is for a standard ACPI
> +            Table Generator.
> +*/
> +#define IS_VALID_STD_ACPI_GENERATOR_ID(TableGeneratorId)               \
> +          (                                                            \
> +          IS_GENERATOR_NAMESPACE_STD (TableGeneratorId) &&             \
> +          IS_GENERATOR_TYPE_ACPI (TableGeneratorId)     &&             \
> +          ((GET_TABLE_ID (GeneratorId) >= ESTD_ACPI_TABLE_ID_RAW) &&   \
> +           (GET_TABLE_ID (GeneratorId) < ESTD_ACPI_TABLE_ID_MAX))      \
> +          )
> +
> +/** This macro creates a standard ACPI Table Generator ID.
> +
> +    @param [in] TableId  The table generator ID.
> +
> +    @returns a standard ACPI table generator ID.
> +*/
> +#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId) \
> +          CREATE_TABLE_GEN_ID (               \
> +            ETableGeneratorTypeAcpi,          \
> +            ETableGeneratorNameSpaceStd,      \
> +            TableId                           \
> +            )
> +
> +/** The Creator ID for the ACPI tables generated using
> +  the standard ACPI table generators.
> +*/
> +#define TABLE_GENERATOR_CREATOR_ID_ARM  SIGNATURE_32('A', 'R', 'M', 'H')
> +
> +/** A macro to initialise the common header part of EFI ACPI tables as
> +    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
> +
> +    @param [in] Signature The ACPI table signature.
> +    @param [in] Type      The ACPI table structure.
> +    @param [in] Revision  The ACPI table revision.
> +*/
> +#define ACPI_HEADER(Signature, Type, Revision) {              \
> +          Signature,             /* UINT32  Signature */      \
> +          sizeof (Type),         /* UINT32  Length */         \
> +          Revision,              /* UINT8   Revision */       \
> +          0,                     /* UINT8   Checksum */       \
> +          { 0, 0, 0, 0, 0, 0 },  /* UINT8   OemId[6] */       \
> +          0,                     /* UINT64  OemTableId */     \
> +          0,                     /* UINT32  OemRevision */    \
> +          0,                     /* UINT32  CreatorId */      \
> +          0                      /* UINT32  CreatorRevision */\
> +          }
> +
> +/** A macro to dump the common header part of EFI ACPI tables as
> +    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
> +
> +    @param [in] AcpiHeader The pointer to the ACPI table header.
> +*/
> +#define DUMP_ACPI_TABLE_HEADER(AcpiHeader)                        \
> +          DEBUG ((                                                \
> +            DEBUG_INFO,                                           \
> +            "ACPI TABLE %c%c%c%c : Rev 0x%x : Length : 0x%x\n",   \
> +            (AcpiHeader->Signature & 0xFF),                       \
> +            ((AcpiHeader->Signature >> 8) & 0xFF),                \
> +            ((AcpiHeader->Signature >> 16) & 0xFF),               \
> +            ((AcpiHeader->Signature >> 24) & 0xFF),               \
> +            AcpiHeader->Revision,                                 \
> +            AcpiHeader->Length                                    \
> +            ));
> +
> +/** Forward declarations.
> +*/
> +typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct CmAStdObjAcpiTableInfo       CM_STD_OBJ_ACPI_TABLE_INFO;
> +typedef struct AcpiTableGenerator           ACPI_TABLE_GENERATOR;
> +
> +/** This function pointer describes the interface to ACPI table build
> +    functions provided by the ACPI table generator and called by the
> +    Table Manager to build an ACPI table.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [out] Table           Pointer to the generated ACPI table.
> +
> +    @returns  EFI_SUCCESS If the table is generated successfully or other
> +                          failure codes as returned by the generator.
> +*/
> +typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_BUILD_TABLE) (
> +  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        **       Table
> +  );
> +
> +/** This function pointer describes the interface to used by the
> +    Table Manager to give the generator an opportunity to free
> +    any resources allocated for building the ACPI table.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [in]  Table           Pointer to the generated ACPI table.
> +
> +    @returns EFI_SUCCESS  If freed successfully or other failure codes
> +                          as returned by the generator.
> +*/
> +typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_FREE_TABLE) (
> +  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        **       Table
> +  );
> +
> +/** The ACPI_TABLE_GENERATOR structure provides an interface that the
> +    Table Manager can use to invoke the functions to build ACPI tables.
> +
> +*/
> +typedef struct AcpiTableGenerator {
> +  /// The ACPI table generator ID.
> +  ACPI_TABLE_GENERATOR_ID                GeneratorID;
> +
> +  /// String describing the ACPI table
> +  /// generator.
> +  CONST CHAR16                         * Description;
> +
> +  /// The ACPI table signature.
> +  UINT32                                 AcpiTableSignature;
> +
> +  /// The ACPI table revision.
> +  UINT32                                 AcpiTableRevision;
> +
> +  /// The ACPI table creator ID.
> +  UINT32                                 CreatorId;
> +
> +  /// The ACPI table creator revision.
> +  UINT32                                 CreatorRevision;
> +
> +  /// ACPI table build function pointer.
> +  ACPI_TABLE_GENERATOR_BUILD_TABLE       BuildAcpiTable;
> +
> +  /// The function to free any resources
> +  /// allocated for building the ACPI table.
> +  ACPI_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
> +} ACPI_TABLE_GENERATOR;
> +
> +/** Register ACPI table factory generator.
> +
> +    The ACPI table factory maintains a list of the Standard and OEM ACPI
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterAcpiTableGenerator (
> +  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +/** Unregister ACPI generator.
> +
> +    This function is called by the ACPI table generator to unregister itself
> +    from the ACPI table factory.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterAcpiTableGenerator (
> +  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +#pragma pack()
> +
> +#endif // ACPI_TABLE_GENERATOR_H_
> +
> diff --git a/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..dbc909894d17ba9df7a78c2d8be797adabb49a34
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> @@ -0,0 +1,367 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef ARM_NAMESPACE_OBJECTS_H_
> +#define ARM_NAMESPACE_OBJECTS_H_
> +#pragma pack(1)
> +
> +/** The EARM_OBJECT_ID enum describes the Object IDs
> +    in the ARM Namespace
> +*/
> +typedef enum ArmObjectID {
> +  EArmObjReserved,                    ///<  0 - Reserved.
> +  EArmObjBootArchInfo,                ///<  1 - Boot Architecture Info
> +  EArmObjCpuInfo,                     ///<  2 - CPU Info
> +  EArmObjPowerManagementProfileInfo,  ///<  3 - Power Management Profile Info
> +  EArmObjGicCInfo,                    ///<  4 - GIC CPU Interface Info
> +  EArmObjGicDInfo,                    ///<  5 - GIC Distributor Info
> +  EArmObjGicMsiFrameInfo,             ///<  6 - GIC MSI Frame Info
> +  EArmObjGicRedistributorInfo,        ///<  7 - GIC Redistributor Info
> +  EArmObjGicItsInfo,                  ///<  8 - GIC ITS Info
> +  EArmObjSerialConsolePortInfo,       ///<  9 - Serial Console Port Info
> +  EArmObjSerialDebugPortInfo,         ///< 10 - Serial Debug Port Info
> +  EArmObjGenericTimerInfo,            ///< 11 - Generic Timer Info
> +  EArmObjPlatformGTBlockInfo,         ///< 12 - Platform GT Block Info
> +  EArmObjPlatformGenericWatchdogInfo, ///< 13 - Platform Generic Watchdog
> +  EArmObjPciConfigSpaceInfo,          ///< 14 - PCI Configuration Space Info
> +  EArmObjHypervisorVendorIdentity,    ///< 15 - Hypervisor Vendor Id
> +  EArmObjMax
> +} EARM_OBJECT_ID;
> +
> +/** A structure that describes the
> +    ARM Boot Architecture flags.
> +*/
> +typedef struct CmArmBootArchInfo {
> +  /// This is the ARM_BOOT_ARCH flags field of the FADT Table
> +  /// described in the ACPI Table Specification.
> +  UINT32  BootArchFlags;
> +} CM_ARM_BOOT_ARCH_INFO;
> +
> +typedef struct CmArmCpuInfo {
> +  // Reserved for use when SMBIOS tables are implemented.
> +} CM_ARM_CPU_INFO;
> +
> +typedef struct CmArmCpuInfoList {
> +  UINT32             CpuCount;
> +  CM_ARM_CPU_INFO  * CpuInfo;
> +} CM_ARM_CPU_INFO_LIST;
> +
> +/** A structure that describes the
> +    Power Management Profile Information for the Platform.
> +*/
> +typedef struct CmArmPowerManagementProfileInfo {
> +  /// This is the Preferred_PM_Profile field of the FADT Table
> +  /// described in the ACPI Specification
> +  UINT8  PowerManagementProfile;
> +} CM_ARM_POWER_MANAGEMENT_PROFILE_INFO;
> +
> +/** A structure that describes the
> +    GIC CPU Interface for the Platform.
> +*/
> +typedef struct CmArmGicCInfo {
> +  /// The GIC CPU Interface number.
> +  UINT32  CPUInterfaceNumber;
> +
> +  /// The ACPI Processor UID. This must match the
> +  /// _UID of the CPU Device object information described
> +  /// in the DSDT/SSDT for the CPU.
> +  UINT32  AcpiProcessorUid;
> +
> +  /// The flags field as described by the GICC structure
> +  /// in the ACPI Specification.
> +  UINT32  Flags;
> +
> +  /// The parking protocol version field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT32  ParkingProtocolVersion;
> +
> +  /// The Performance Interrupt field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT32  PerformanceInterruptGsiv;
> +
> +  /// The CPU Parked address field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT64  ParkedAddress;
> +
> +  /// The base address for the GIC CPU Interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The base address for GICV interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICV;
> +
> +  /// The base address for GICH interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICH;
> +
> +  /// The GICV maintainence interrupt
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT32  VGICMaintenanceInterrupt;
> +
> +  /// The base address for GICR interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICRBaseAddress;
> +
> +  /// The MPIDR for the CPU
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  MPIDR;
> +
> +  /// The Processor Power Efficiency class
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT8   ProcessorPowerEfficiencyClass;
> +} CM_ARM_GICC_INFO;
> +
> +/** A structure that describes the
> +    GIC Distributor information for the Platform.
> +*/
> +typedef struct CmArmGicDInfo {
> +  /// The GIC Distributor ID.
> +  UINT32  GicId;
> +
> +  /// The Physical Base address
> +  /// for the GIC Distributor.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The global system interrupt
> +  /// number where this GIC Distributor's
> +  /// interrupt inputs start.
> +  UINT32  SystemVectorBase;
> +
> +  /// The GIC version as described
> +  /// by the GICD structure in the
> +  /// ACPI Specification.
> +  UINT8   GicVersion;
> +} CM_ARM_GICD_INFO;
> +
> +/** A structure that describes the
> +    GIC MSI Frame information for the Platform.
> +*/
> +typedef struct CmArmGicMsiFrameInfo {
> +  /// The GIC MSI Frame ID
> +  UINT32  GicMsiFrameId;
> +
> +  /// The Physical base address for the
> +  /// MSI Frame.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The GIC MSI Frame flags
> +  /// as described by the GIC MSI frame
> +  /// structure in the ACPI Specification.
> +  UINT32  Flags;
> +
> +  /// SPI Count used by this frame.
> +  UINT16  SPICount;
> +
> +  /// SPI Base used by this frame.
> +  UINT16  SPIBase;
> +} CM_ARM_GIC_MSI_FRAME_INFO;
> +
> +/** A structure that describes the
> +    GIC Redistributor information for the Platform.
> +*/
> +typedef struct CmArmGicRedistInfo {
> +  /// The physical address of a page range
> +  /// containing all GIC Redistributors.
> +  UINT64  DiscoveryRangeBaseAddress;
> +
> +  /// Length of the GIC Redistributor
> +  /// Discovery page range
> +  UINT32  DiscoveryRangeLength;
> +} CM_ARM_GIC_REDIST_INFO;
> +
> +/** A structure that describes the
> +    GIC Interrupt Translation Service information for the Platform.
> +*/
> +typedef struct CmArmGicItsInfo {
> +  /// The GIC ITS ID.
> +  UINT32  GicItsId;
> +
> +  /// The physical address for the
> +  /// Interrupt Translation Service
> +  UINT64  PhysicalBaseAddress;
> +} CM_ARM_GIC_ITS_INFO;
> +
> +/** A structure that describes the
> +    Serial Port information for the Platform.
> +*/
> +typedef struct CmArmSerialPortInfo {
> +  /// The physical base address for the
> +  /// serial port.
> +  UINT64  BaseAddress;
> +
> +  /// The serial port interrupt.
> +  UINT32  Interrupt;
> +
> +  /// The serial port baud rate.
> +  UINT64  BaudRate;
> +
> +  /// The serial port clock.
> +  UINT32  Clock;
> +} CM_ARM_SERIAL_PORT_INFO;
> +
> +/** A structure that describes the
> +    Generic Timer information for the Platform.
> +*/
> +typedef struct CmArmGenericTimerInfo {
> +  /// The physical base address for the
> +  /// counter control frame.
> +  UINT64  CounterControlBaseAddress;
> +
> +  /// The physical base address for the
> +  /// counter read frame.
> +  UINT64  CounterReadBaseAddress;
> +
> +  /// The secure PL1 timer interrupt.
> +  UINT32  SecurePL1TimerGSIV;
> +
> +  /// The secure PL1 timer flags.
> +  UINT32  SecurePL1TimerFlags;
> +
> +  /// The non-secure PL1 timer interrupt.
> +  UINT32  NonSecurePL1TimerGSIV;
> +
> +  /// The non-secure PL1 timer flags.
> +  UINT32  NonSecurePL1TimerFlags;
> +
> +  /// The virtual timer interrupt.
> +  UINT32  VirtualTimerGSIV;
> +
> +  /// The virtual timer flags.
> +  UINT32  VirtualTimerFlags;
> +
> +  /// The non-secure PL2 timer interrupt.
> +  UINT32  NonSecurePL2TimerGSIV;
> +
> +  /// The non-secure PL2 timer flags.
> +  UINT32  NonSecurePL2TimerFlags;
> +} CM_ARM_GENERIC_TIMER_INFO;
> +
> +/** A structure that describes the
> +    Platform Generic Block Timer Frame information for the Platform.
> +*/
> +typedef struct CmArmGTBlockTimerFrameInfo {
> +  /// The Generic Timer frame number.
> +  UINT8   FrameNumber;
> +
> +  /// The physical base address
> +  /// for the CntBase block.
> +  UINT64  PhysicalAddressCntBase;
> +
> +  /// The physical base address
> +  /// for the CntEL0Base block.
> +  UINT64  PhysicalAddressCntEL0Base;
> +
> +  /// The physical timer interrupt.
> +  UINT32  PhysicalTimerGSIV;
> +
> +  /// The physical timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  PhysicalTimerFlags;
> +
> +  /// The virtual timer interrupt.
> +  UINT32  VirtualTimerGSIV;
> +
> +  /// The virtual timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  VirtualTimerFlags;
> +
> +  /// The common timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  CommonFlags;
> +} CM_ARM_GTBLOCK_TIMER_FRAME_INFO;
> +
> +/** A structure that describes the
> +    Platform Generic Block Timer information for the Platform.
> +*/
> +typedef struct CmArmGTBlockInfo {
> +  /// The physical base address for
> +  /// the GT Block Timer structure.
> +  UINT64                             GTBlockPhysicalAddress;
> +
> +  /// The number of timer frames
> +  /// implemented in the GT Block.
> +  UINT32                             GTBlockTimerFrameCount;
> +
> +  /// Pointer to the GT Block timer
> +  /// frame list.
> +  CM_ARM_GTBLOCK_TIMER_FRAME_INFO  * GTBlockTimerFrameList;
> +} CM_ARM_GTBLOCK_INFO;
> +
> +/** A structure that describes the
> +    SBSA Generic Watchdog information for the Platform.
> +*/
> +typedef struct CmArmGenericWatchdogInfo {
> +  /// The physical base address of the
> +  /// SBSA Watchdog control frame.
> +  UINT64  ControlFrameAddress;
> +
> +  /// The physical base address of the
> +  /// SBSA Watchdog refresh frame.
> +  UINT64  RefreshFrameAddress;
> +
> +  /// The watchdog interrupt.
> +  UINT32  TimerGSIV;
> +
> +  /// The flags for the watchdog
> +  /// as described by the SBSA watchdog
> +  /// structure in the ACPI specification.
> +  UINT32  Flags;
> +} CM_ARM_GENERIC_WATCHDOG_INFO;
> +
> +/** A structure that describes the
> +    PCI Configuration Space information for the Platform.
> +*/
> +typedef struct CmArmPciConfigSpaceInfo {
> +  /// The physical base address for the PCI segment.
> +  UINT64  BaseAddress;
> +
> +  /// The PCI segment group number.
> +  UINT16  PciSegmentGroupNumber;
> +
> +  /// The start bus number.
> +  UINT8   StartBusNumber;
> +
> +  /// The end bus number.
> +  UINT8   EndBusNumber;
> +} CM_ARM_PCI_CONFIG_SPACE_INFO;
> +
> +/** A structure that describes the
> +    Hypervisor Vendor ID information for the Platform.
> +*/
> +typedef struct CmArmHypervisorVendorId {
> +  /// The hypervisor Vendor ID.
> +  UINT64  HypervisorVendorId;
> +} CM_ARM_HYPERVISOR_VENDOR_ID;
> +
> +#pragma pack()
> +
> +#endif // ARM_NAMESPACE_OBJECTS_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..23edd7c343bd09476692d2fb8af088d95b8ff28d
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> @@ -0,0 +1,112 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_HELPER_H_
> +#define CONFIGURATION_MANAGER_HELPER_H_
> +
> +/** The GET_OBJECT_LIST macro expands to a function that is used to retrieve
> +    an object or an object list from the Configuration Manager using the
> +    Configuration Manager Protocol interface.
> +
> +    The macro expands to a function which has the following prototype:
> +
> +    STATIC
> +    EFI_STATUS
> +    EFIAPI
> +    Get<CmObjectId> (
> +      IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
> +      OUT       Type                              **       List,
> +      OUT       UINTN                              *       Count OPTIONAL
> +      );
> +
> +    Generated function parameters:
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
> +                                  interface.
> +    @param [out] List           Pointer to the Object list.
> +    @param [out] Count          Count of the objects returned in the list.
> +
> +    Macro Parameters:
> +    @param [in] CmObjectNameSpace The Object Namespace
> +    @param [in] CmObjectId        Object Id.
> +    @param [in] Type              Structure used to describe the Object.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)                      \
> +STATIC                                                                            \
> +EFI_STATUS                                                                        \
> +EFIAPI                                                                            \
> +Get##CmObjectId (                                                                 \
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,           \
> +  OUT       Type                               **       List,                     \
> +  OUT       UINTN                               * CONST Count OPTIONAL            \
> +  )                                                                               \
> +{                                                                                 \
> +  EFI_STATUS         Status;                                                      \
> +  CM_OBJ_DESCRIPTOR  CmObjectDesc;                                                \
> +  UINTN              ObjCount = 0;                                                \
> +  if (List == NULL) {                                                             \
> +    Status = EFI_INVALID_PARAMETER;                                               \
> +    DEBUG ((                                                                      \
> +      DEBUG_ERROR,                                                                \
> +      "ERROR: Get" #CmObjectId ": Invalid out parameter for"                      \
> +      " object list. Status = %r\n",                                              \
> +      Status                                                                      \
> +      ));                                                                         \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  Status = CfgMgrProtocol->GetObject (                                            \
> +                             CfgMgrProtocol,                                      \
> +                             CREATE_CM_OBJECT_ID (CmObjectNameSpace, CmObjectId), \
> +                             &CmObjectDesc                                        \
> +                             );                                                   \
> +  if (EFI_ERROR (Status)) {                                                       \
> +    DEBUG ((                                                                      \
> +      DEBUG_WARN,                                                                 \
> +      "WARNING: Get" #CmObjectId ": Platform does not implement "                 \
> +      #CmObjectId ". Status = %r\n",                                              \
> +      Status                                                                      \
> +      ));                                                                         \
> +    *List = NULL;                                                                 \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  if (CmObjectDesc.Size < sizeof (Type)) {                                        \
> +    DEBUG ((                                                                      \
> +      DEBUG_ERROR,                                                                \
> +      "ERROR: Get" #CmObjectId ": " #CmObjectId                                   \
> +      ": Buffer too small, size = 0x%x\n",                                        \
> +      CmObjectDesc.Size                                                           \
> +      ));                                                                         \
> +    ASSERT (CmObjectDesc.Size >= sizeof (Type));                                  \
> +    Status = EFI_BAD_BUFFER_SIZE;                                                 \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  ObjCount = CmObjectDesc.Size / sizeof (Type);                                   \
> +  *List = (Type*)CmObjectDesc.Data;                                               \
> +error_handler:                                                                    \
> +  if (Count != NULL) {                                                            \
> +    *Count = ObjCount;                                                            \
> +  }                                                                               \
> +  return Status;                                                                  \
> +}
> +
> +#endif // CONFIGURATION_MANAGER_HELPER_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..99afab094328cf830831899011a7f6fca1d6e5f2
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> @@ -0,0 +1,158 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_OBJECT_H_
> +#define CONFIGURATION_MANAGER_OBJECT_H_
> +
> +#pragma pack(1)
> +
> +/** The CM_OBJECT_ID type is used to identify the Configration Manager objects.
> +
> + Description of Configuration Manager Object ID
> +________________________________________________________________________________
> +|31 |30 |29 |28 || 27 | 26 | 25 | 24 || 23 | 22 | 21 | 20 || 19 | 18 | 17 | 16 |
> +--------------------------------------------------------------------------------
> +| Name Space ID ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 |
> +________________________________________________________________________________
> +
> +Bits: [31:28] - Name Space ID
> +                0000 - Standard
> +                0001 - ARM
> +                1000 - Custom/OEM
> +                All other values are reserved.
> +
> +Bits: [27:16] - Reserved.
> +________________________________________________________________________________
> +|15 |14 |13 |12 || 11 | 10 |  9 |  8 ||  7 |  6 |  5 |  4 ||  3 |  2 |  1 |  0 |
> +--------------------------------------------------------------------------------
> +| 0 | 0 | 0 | 0 ||  0 |  0 |  0 |  0 ||                 Object ID              |
> +________________________________________________________________________________
> +
> +Bits: [15:8] - Are reserved and must be zero.
> +
> +Bits: [7:0] - Object ID
> +
> +Object ID's in the Standard Namespace:
> +  0 - Configuration Manager Revision
> +  1 - ACPI Table List
> +  2 - SMBIOS Table List
> +
> +Object ID's in the ARM Namespace:
> +   0 - Reserved
> +   1 - Boot Architecture Info
> +   2 - CPU Info
> +   3 - Power Management Profile Info
> +   4 - GICC Info
> +   5 - GICD Info
> +   6 - GIC MSI Frame Info
> +   7 - GIC Redistributor Info
> +   8 - GIC ITS Info
> +   9 - Serial Console Port Info
> +  10 - Serial Debug Port Info
> +  12 - Generic Timer Info
> +  13 - Platform GT Block Info
> +  14 - Platform Generic Watchdog
> +  15 - PCI Configuration Space Info
> +  16 - Hypervisor Vendor Id
> +*/
> +typedef UINT32  CM_OBJECT_ID;
> +
> +/** The EOBJECT_NAMESPACE_ID enum describes the defined namespaces
> +    for the Confguration Manager Objects.
> +*/
> +typedef enum ObjectNameSpaceID {
> +  EObjNameSpaceStandard,      ///< Standard Objects Namespace
> +  EObjNameSpaceArm,           ///< ARM Objects Namespace
> +  EObjNameSpaceOem = 0x8,     ///< OEM Objects Namespace
> +  EObjNameSpaceMax
> +} EOBJECT_NAMESPACE_ID;
> +
> +/** The CM_OBJ_DESCRIPTOR structure describes the Configuration
> +    Manager Object descriptor. The Configuration Manager Protocol
> +    interface uses this descriptor to return the Configuration
> +    Manager Objects.
> +*/
> +typedef struct CmObjDescriptor {
> +  /// Size of the Object or Object List
> +  /// described by this descriptor.
> +  UINT32   Size;
> +
> +  /// Pointer to the Object or Object List
> +  /// described by this descriptor.
> +  UINTN  * Data;
> +} CM_OBJ_DESCRIPTOR;
> +
> +#pragma pack()
> +
> +/** This macro returns the namespace ID from the CmObjectID.
> +
> +  @param [in] CmObjectId  The Configuration Manager Object ID.
> +
> +  @retval Returns the Namespace ID corresponding to the CmObjectID.
> +*/
> +#define GET_CM_NAMESPACE_ID(CmObjectId) (((CmObjectId) >> 28) & 0xF)
> +
> +/** This macro returns the Object ID from the CmObjectID.
> +
> +  @param [in] CmObjectId  The Configuration Manager Object ID.
> +
> +  @retval Returns the Object ID corresponding to the CmObjectID.
> +*/
> +#define GET_CM_OBJECT_ID(CmObjectId)    ((CmObjectId) & 0xFF)
> +
> +/** This macro returns a Configuration Manager Object ID
> +    from the NameSpace ID and the ObjectID.
> +
> +  @param [in] NameSpaceId The namespace ID for the Object.
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns the Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_OBJECT_ID(NameSpaceId, ObjectId) \
> +          ((((NameSpaceId) & 0xF) << 28) | ((ObjectId) & 0xF))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the Standard Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns a Standard Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_STD_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceStandard, ObjectId))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the ARM Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns an ARM Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_ARM_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceArm, ObjectId))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the OEM Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns an OEM Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_OEM_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceOem, ObjectId))
> +
> +#endif // CONFIGURATION_MANAGER_OBJECT_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..10d29be800a0c126ed32dcfa070f1473a8aee7a9
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> @@ -0,0 +1,235 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef SMBIOS_TABLE_GENERATOR_H_
> +#define SMBIOS_TABLE_GENERATOR_H_
> +
> +#pragma pack(1)
> +
> +/** The SMBIOS_TABLE_GENERATOR_ID type describes SMBIOS table generator ID.
> +*/
> +typedef TABLE_GENERATOR_ID SMBIOS_TABLE_GENERATOR_ID;
> +
> +/** The ESTD_SMBIOS_TABLE_ID enum describes the SMBIOS table IDs reserved for
> +  the standard generators.
> +
> +  NOTE: The SMBIOS Generator IDs do not match the table type numbers!
> +          This allows 0 to be used to catch invalid parameters.
> +*/
> +typedef enum StdSmbiosTableGeneratorId {
> +  ESTD_SMBIOS_TABLE_ID_RESERVED = 0x0000,
> +  ESTD_SMBIOS_TABLE_ID_RAW,
> +  ESTD_SMBIOS_TABLE_ID_TYPE00,
> +  ESTD_SMBIOS_TABLE_ID_TYPE01,
> +  ESTD_SMBIOS_TABLE_ID_TYPE02,
> +  ESTD_SMBIOS_TABLE_ID_TYPE03,
> +  ESTD_SMBIOS_TABLE_ID_TYPE04,
> +  ESTD_SMBIOS_TABLE_ID_TYPE05,
> +  ESTD_SMBIOS_TABLE_ID_TYPE06,
> +  ESTD_SMBIOS_TABLE_ID_TYPE07,
> +  ESTD_SMBIOS_TABLE_ID_TYPE08,
> +  ESTD_SMBIOS_TABLE_ID_TYPE09,
> +  ESTD_SMBIOS_TABLE_ID_TYPE10,
> +  ESTD_SMBIOS_TABLE_ID_TYPE11,
> +  ESTD_SMBIOS_TABLE_ID_TYPE12,
> +  ESTD_SMBIOS_TABLE_ID_TYPE13,
> +  ESTD_SMBIOS_TABLE_ID_TYPE14,
> +  ESTD_SMBIOS_TABLE_ID_TYPE15,
> +  ESTD_SMBIOS_TABLE_ID_TYPE16,
> +  ESTD_SMBIOS_TABLE_ID_TYPE17,
> +  ESTD_SMBIOS_TABLE_ID_TYPE18,
> +  ESTD_SMBIOS_TABLE_ID_TYPE19,
> +  ESTD_SMBIOS_TABLE_ID_TYPE20,
> +  ESTD_SMBIOS_TABLE_ID_TYPE21,
> +  ESTD_SMBIOS_TABLE_ID_TYPE22,
> +  ESTD_SMBIOS_TABLE_ID_TYPE23,
> +  ESTD_SMBIOS_TABLE_ID_TYPE24,
> +  ESTD_SMBIOS_TABLE_ID_TYPE25,
> +  ESTD_SMBIOS_TABLE_ID_TYPE26,
> +  ESTD_SMBIOS_TABLE_ID_TYPE27,
> +  ESTD_SMBIOS_TABLE_ID_TYPE28,
> +  ESTD_SMBIOS_TABLE_ID_TYPE29,
> +  ESTD_SMBIOS_TABLE_ID_TYPE30,
> +  ESTD_SMBIOS_TABLE_ID_TYPE31,
> +  ESTD_SMBIOS_TABLE_ID_TYPE32,
> +  ESTD_SMBIOS_TABLE_ID_TYPE33,
> +  ESTD_SMBIOS_TABLE_ID_TYPE34,
> +  ESTD_SMBIOS_TABLE_ID_TYPE35,
> +  ESTD_SMBIOS_TABLE_ID_TYPE36,
> +  ESTD_SMBIOS_TABLE_ID_TYPE37,
> +  ESTD_SMBIOS_TABLE_ID_TYPE38,
> +  ESTD_SMBIOS_TABLE_ID_TYPE39,
> +  ESTD_SMBIOS_TABLE_ID_TYPE40,
> +  ESTD_SMBIOS_TABLE_ID_TYPE41,
> +  ESTD_SMBIOS_TABLE_ID_TYPE42,
> +
> +  // IDs 43 - 125 are reserved
> +
> +  ESTD_SMBIOS_TABLE_ID_TYPE126 = (ESTD_SMBIOS_TABLE_ID_TYPE00 + 126),
> +  ESTD_SMBIOS_TABLE_ID_TYPE127,
> +  ESTD_SMBIOS_TABLE_ID_MAX
> +} ESTD_SMBIOS_TABLE_ID;
> +
> +/** This macro checks if the Table Generator ID is for an SMBIOS Table
> +    Generator.
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns  TRUE if the table generator ID is for an SMBIOS Table
> +              Generator.
> +*/
> +#define IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId) \
> +          (                                        \
> +          GET_TABLE_TYPE (TableGeneratorId) ==     \
> +          ETableGeneratorTypeSmbios                \
> +          )
> +
> +/** This macro checks if the Table Generator ID is for a standard SMBIOS
> +    Table Generator.
> +
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns  TRUE if the table generator ID is for a standard SMBIOS
> +              Table Generator.
> +*/
> +#define IS_VALID_STD_SMBIOS_GENERATOR_ID(TableGeneratorId)            \
> +          (                                                           \
> +          IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) &&             \
> +          IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId)   &&             \
> +          ((GET_TABLE_ID(GeneratorId) >= ESTD_SMBIOS_TABLE_ID_RAW) && \
> +           (GET_TABLE_ID(GeneratorId) < ESTD_SMIOS_TABLE_ID_MAX))     \
> +          )
> +
> +/** This macro creates a standard SMBIOS Table Generator ID.
> +
> +    @param [in] TableId  The table generator ID.
> +
> +    @returns a standard SMBIOS table generator ID.
> +*/
> +#define CREATE_STD_SMBIOS_TABLE_GEN_ID(TableId) \
> +          CREATE_TABLE_GEN_ID (                 \
> +            ETableGeneratorTypeSmbios,          \
> +            ETableGeneratorNameSpaceStd,        \
> +            TableId                             \
> +            )
> +
> +/** Forward declarations.
> +*/
> +typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct CmStdObjSmbiosTableInfo      CM_STD_OBJ_SMBIOS_TABLE_INFO;
> +typedef struct SmbiosTableGenerator         SMBIOS_TABLE_GENERATOR;
> +
> +/** This function pointer describes the interface to SMBIOS table build
> +    functions provided by the SMBIOS table generator and called by the
> +    Table Manager to build an SMBIOS table.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [out] Table           Pointer to the generated SMBIOS table.
> +
> +    @returns EFI_SUCCESS  If the table is generated successfully or other
> +                          failure codes as returned by the generator.
> +*/
> +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLE) (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
> +  IN        CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       SMBIOS_STRUCTURE                   **       Table
> +  );
> +
> +/** This function pointer describes the interface to used by the
> +    Table Manager to give the generator an opportunity to free
> +    any resources allocated for building the SMBIOS table.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [in]  Table           Pointer to the generated SMBIOS table.
> +
> +    @returns  EFI_SUCCESS If freed successfully or other failure codes
> +                          as returned by the generator.
> +*/
> +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLE) (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
> +  IN  CONST CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        SMBIOS_STRUCTURE                   **       Table
> +  );
> +
> +/** The SMBIOS_TABLE_GENERATOR structure provides an interface that the
> +    Table Manager can use to invoke the functions to build SMBIOS tables.
> +
> +*/
> +typedef struct SmbiosTableGenerator {
> +  /// The SMBIOS table generator ID.
> +  SMBIOS_TABLE_GENERATOR_ID                GeneratorID;
> +
> +  /// String describing the DT table
> +  /// generator.
> +  CONST CHAR16*                            Description;
> +
> +  /// The SMBIOS table type.
> +  SMBIOS_TYPE                              Type;
> +
> +  /// SMBIOS table build function pointer.
> +  SMBIOS_TABLE_GENERATOR_BUILD_TABLE       BuildSmbiosTable;
> +
> +  /// The function to free any resources
> +  /// allocated for building the SMBIOS table.
> +  SMBIOS_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
> +} SMBIOS_TABLE_GENERATOR;
> +
> +/** Register SMBIOS table factory generator.
> +
> +    The SMBIOS table factory maintains a list of the Standard and OEM SMBIOS
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterSmbiosTableGenerator (
> +  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +/** Unregister SMBIOS generator.
> +
> +    This function is called by the SMBIOS table generator to unregister itself
> +    from the SMBIOS table factory.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterSmbiosTableGenerator (
> +  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
> +  );
> +#pragma pack()
> +
> +#endif // SMBIOS_TABLE_GENERATOR_H_
> +
> diff --git a/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..76ae3f2208a5c80f0ca10b75e5df94cbb43e4688
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> @@ -0,0 +1,93 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef STANDARD_NAMESPACE_OBJECTS_H_
> +#define STANDARD_NAMESPACE_OBJECTS_H_
> +
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +
> +#pragma pack(1)
> +
> +/** The ESTD_OBJECT_ID enum describes the Object IDs
> +    in the Standard Namespace.
> +*/
> +typedef enum StdObjectID {
> +  EStdObjCfgMgrInfo = 0x00000000, ///< 0 - Configuration Manager Info
> +  EStdObjAcpiTableList,           ///< 1 - ACPI table Info List
> +  EStdObjSmbiosTableList,         ///< 2 - SMBIOS table Info List
> +  EStdObjMax
> +} ESTD_OBJECT_ID;
> +
> +/** A structure that describes the Configuration Manager Information.
> +*/
> +typedef struct CmStdObjConfigurationManagerInfo {
> +  /// The Configuration Manager Revision.
> +  UINT32  Revision;
> +
> +  /// The OEM ID. This information is used to
> +  /// populate the ACPI table header information.
> +  UINT8   OemId[6];
> +} CM_STD_OBJ_CONFIGURATION_MANAGER_INFO;
> +
> +/** A structure used to describe the ACPI table generators to be invoked.
> +
> +    The AcpiTableData member of this structure may be used to directly provide
> +    the binary ACPI table data which is required by the following standard
> +    generators:
> +      - RAW
> +      - DSDT
> +      - SSDT
> +
> +    Providing the ACPI table data is optional and depends on the generator
> +    that is being invoked. If unused, set AcpiTableData to NULL.
> +*/
> +typedef struct CmAStdObjAcpiTableInfo {
> +  /// The signature of the ACPI Table to be installed.
> +  UINT32                         AcpiTableSignature;
> +
> +  /// The ACPI Table Generator ID.
> +  ACPI_TABLE_GENERATOR_ID        TableGeneratorId;
> +
> +  /// Optional pointer to the ACPI table data.
> +  EFI_ACPI_DESCRIPTION_HEADER  * AcpiTableData;
> +
> +} CM_STD_OBJ_ACPI_TABLE_INFO;
> +
> +/** A structure used to describe the SMBIOS table generators to be invoked.
> +
> +    The SmbiosTableData member of this structure is used to provide
> +    the SMBIOS table data which is required by the following standard
> +    generator(s):
> +      - RAW
> +
> +    Providing the SMBIOS table data is optional and depends on the
> +    generator that is being invoked. If unused, set the SmbiosTableData
> +    to NULL.
> +*/
> +typedef struct CmStdObjSmbiosTableInfo {
> +  /// The SMBIOS Table Generator ID.
> +  SMBIOS_TABLE_GENERATOR_ID   TableGeneratorId;
> +
> +  /// Optional pointer to the SMBIOS table data.
> +  SMBIOS_STRUCTURE           * SmbiosTableData;
> +} CM_STD_OBJ_SMBIOS_TABLE_INFO;
> +
> +#pragma pack()
> +
> +#endif // STANDARD_NAMESPACE_OBJECTS_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/TableGenerator.h b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..93d557273459948f5211e1c26a6028fc12b181fb
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
> @@ -0,0 +1,235 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +    - DT     - Device Tree
> +**/
> +
> +#ifndef TABLE_GENERATOR_H_
> +#define TABLE_GENERATOR_H_
> +
> +/** The TABLE_GENERATOR_ID type describes the Table Generator ID
> +
> +  Table Generator ID
> +
> +________________________________________________________________________________
> +|  31 | 30 |29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16|
> +--------------------------------------------------------------------------------
> +|TNSID|  0 |   TT   |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0|  0 |
> +________________________________________________________________________________
> +
> +
> +________________________________________________________________________________
> +|15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
> +--------------------------------------------------------------------------------
> +|                                 Table ID                                     |
> +________________________________________________________________________________
> +
> +
> +  Bit [31] - Table NameSpace ID (TNSID)
> +      0 - Standard
> +      1 - Custom/OEM
> +
> +  Bit [30] - Reserved, Must be Zero
> +
> +  Bit [29:28] - Table Type (TT)
> +       0 - ACPI Table
> +       1 - SMBIOS Table
> +       2 - DT (Device Tree) Table
> +       3 - Reserved (INVALID)
> +
> +  Bit [27:16] - Reserved, Must Be Zero
> +
> +  Bit [15:0] - Table ID
> +
> +    Standard ACPI Table IDs:
> +       0 - Reserved
> +       1 - RAW
> +       2 - FADT
> +       3 - DSDT
> +       4 - SSDT
> +       5 - MADT
> +       6 - GTDT
> +       7 - DBG2
> +       8 - SPCR
> +       9 - MCFG
> +
> +
> +    Standard SMBIOS Table IDs:
> +       0 - Reserved
> +       1 - RAW
> +       2 - Table Type00
> +       3 - Table Type01
> +       4 - Table Type02
> +       5 - Table Type03
> +       6 - Table Type04
> +       7 - Table Type05
> +       8 - Table Type06
> +       9 - Table Type07
> +      10 - Table Type08
> +      11 - Table Type09
> +      12 - Table Type10
> +      13 - Table Type11
> +      14 - Table Type12
> +      15 - Table Type13
> +      16 - Table Type14
> +      17 - Table Type15
> +      18 - Table Type16
> +      19 - Table Type17
> +      20 - Table Type18
> +      21 - Table Type19
> +      22 - Table Type20
> +      23 - Table Type21
> +      24 - Table Type22
> +      25 - Table Type23
> +      26 - Table Type24
> +      27 - Table Type25
> +      28 - Table Type26
> +      29 - Table Type27
> +      30 - Table Type28
> +      31 - Table Type29
> +      32 - Table Type30
> +      33 - Table Type31
> +      34 - Table Type32
> +      35 - Table Type33
> +      36 - Table Type34
> +      37 - Table Type35
> +      38 - Table Type36
> +      39 - Table Type37
> +      40 - Table Type38
> +      41 - Table Type39
> +      42 - Table Type40
> +      43 - Table Type41
> +      44 - Table Type42
> +  45-127 - Reserved
> +     128 - Table Type126
> +     129 - Table Type127
> +**/
> +typedef UINT32  TABLE_GENERATOR_ID;
> +
> +/** This enum lists the Table Generator Types.
> +*/
> +typedef enum TableGeneratorType {
> +  ETableGeneratorTypeAcpi = 0,  ///< ACPI Table Generator Type.
> +  ETableGeneratorTypeSmbios,    ///< SMBIOS Table Generator Type.
> +  ETableGeneratorTypeDt,        ///< Device Tree Table Generator Type.
> +  ETableGeneratorTypeReserved
> +} ETABLE_GENERATOR_TYPE;
> +
> +/** This enum lists the namespaces for the Table Generators.
> +*/
> +typedef enum TableGeneratorNameSpace {
> +  ETableGeneratorNameSpaceStd = 0,  ///< Standard Namespace.
> +  ETableGeneratorNameSpaceOem       ///< OEM Namespace.
> +} ETABLE_GENERATOR_NAMESPACE;
> +
> +/** A mask for the Table ID bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_ID_MASK             0xFF
> +
> +/** A mask for the Namespace ID bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_NAMESPACEID_MASK    (BIT31)
> +
> +/** A mask for the Table Type bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_TYPE_MASK           (BIT29 | BIT28)
> +
> +/** This macro returns the Table ID from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Table ID described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_ID(TableGeneratorId)                          \
> +          ((TableGeneratorId) & TABLE_ID_MASK)
> +
> +/** This macro returns the Table type from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Table type described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_TYPE(TableGeneratorId)                        \
> +          (((TableGeneratorId) & TABLE_TYPE_MASK) >> 28)
> +
> +/** This macro returns the Namespace ID from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Namespace described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_NAMESPACEID(TableGeneratorId)                 \
> +          (((TableGeneratorId) & TABLE_NAMESPACEID_MASK) >> 31)
> +
> +/** This macro checks if the TableGeneratorId is in the Standard Namespace.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the TableGeneratorId is in the Standard Namespace.
> +*/
> +#define IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) \
> +          (                                          \
> +          GET_TABLE_NAMESPACEID(TableGeneratorId) == \
> +          ETableGeneratorNameSpaceStd                \
> +          )
> +
> +/** This macro creates a TableGeneratorId
> +
> +    @param [in]  TableType        The table type.
> +    @param [in]  TableNameSpaceId The namespace ID for the table.
> +    @param [in]  TableId          The table ID.
> +
> +    @returns a TableGeneratorId calculated from the inputs.
> +*/
> +#define CREATE_TABLE_GEN_ID(TableType, TableNameSpaceId, TableId)  \
> +          (                                                        \
> +           (((TableType) << 28) & TABLE_TYPE_MASK)               | \
> +           (((TableNameSpaceId) << 31) & TABLE_NAMESPACEID_MASK) | \
> +           ((TableId) & TABLE_ID_MASK)                             \
> +          )
> +
> +/** This macro generates a Major.Minor version
> +    where the Major and Minor fields are 16 bit.
> +
> +    @param [in]  Major  The Major Revision.
> +    @param [in]  Minor  The Minor Revision.
> +
> +    @returns a 32 bit representation of the type Major.Minor.
> +*/
> +#define CREATE_REVISION(Major, Minor)                            \
> +          ((((Major) & 0xFFFF) << 16) | ((Minor) & 0xFFFF))
> +
> +/** This macro returns the Major revison
> +
> +    Extracts Major from the 32 bit representation of the type Major.Minor
> +
> +    @param [in]  Revision  The Revision value which is 32 bit.
> +
> +    @returns the Major part of the revision.
> +*/
> +#define GET_MAJOR_REVISION(Revision)  (((Revision) >> 16) & 0xFFFF)
> +
> +/** This macro returns the Minor revison
> +
> +    Extracts Minor from the 32 bit representation of the type Major.Minor
> +
> +    @param [in]  Revision  The Revision value which is 32 bit.
> +
> +    @returns the Minor part of the revision.
> +*/
> +#define GET_MINOR_REVISION(Revision)  ((Revision) & 0xFFFF)
> +
> +#endif // TABLE_GENERATOR_H_
> +
> diff --git a/MdeModulePkg/Include/Library/TableHelperLib.h b/MdeModulePkg/Include/Library/TableHelperLib.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..4b22e024dee1a311e4e4b532371ccef94bc02be3
> --- /dev/null
> +++ b/MdeModulePkg/Include/Library/TableHelperLib.h
> @@ -0,0 +1,67 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef TABLE_HELPER_LIB_H_
> +#define TABLE_HELPER_LIB_H_
> +
> +/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
> +    object from the Configuration Manager.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
> +                                interface.
> +    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
> +                                object structure.
> +
> +    @retval EFI_SUCCESS           The object is returned.
> +    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
> +    @retval EFI_NOT_FOUND         The requested Object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetCgfMgrInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST  CfgMgrProtocol,
> +  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **        CfgMfrInfo
> +  );
> +
> +/** The AddAcpiHeader function updates the ACPI header structure pointed by
> +    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
> +    Manager protocol to obtain any information required for constructing the
> +    header.
> +
> +    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
> +                                   protocol interface.
> +    @param [in]     Generator      Pointer to the ACPI table Generator.
> +    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
> +                                   updated.
> +    @param [in]     Length         Length of the ACPI table.
> +
> +    @retval EFI_SUCCESS           The ACPI table is updated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AddAcpiHeader (
> +  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
> +  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
> +  IN      CONST UINT32                                      Length
> +  );
> +
> +#endif // TABLE_HELPER_LIB_H_
> diff --git a/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..387935943648654ef095720dec452d1c15b8fc11
> --- /dev/null
> +++ b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> @@ -0,0 +1,121 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_PROTOCOL_H_
> +#define CONFIGURATION_MANAGER_PROTOCOL_H_
> +
> +/** This macro defines the Configuration Manager Protocol GUID.
> +
> +  GUID: {D85A4835-5A82-4894-AC02-706F43D5978E}
> +*/
> +#define EFI_CONFIGURATION_MANAGER_PROTOCOL_GUID         \
> +  { 0xd85a4835, 0x5a82, 0x4894,                         \
> +    { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e }   \
> +  };
> +
> +/** This macro defines the Configuration Manager Protocol Revision.
> +*/
> +#define EFI_CONFIGURATION_MANAGER_PROTOCOL_REVISION  CREATE_REVISION (1, 0)
> +
> +#pragma pack(1)
> +
> +/**
> +  Forward declarations:
> +*/
> +typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct PlatformRepositoryInfo       EFI_PLATFORM_REPOSITORY_INFO;
> +
> +
> +/** The GetObject function defines the interface implemented by the
> +    Configuration Manager Protocol for returning the Configuration
> +    Manager Objects.
> +
> +    @param [in]  This        Poiner to the Configuration Manager Protocol.
> +    @param [in]  CmObjectId  The Configuration Manager Object ID.
> +    @param [out] CmObject    Pointer to the Configuration Manager Object
> +                             descrptor describing the requested Object.
> +
> +    @retval Returns:
> +      EFI_SUCCESS           Success.
> +      EFI_INVALID_PARAMETER A parameter is invalid.
> +      EFI_NOT_FOUND         The required object information is not found.
> +      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                            is less than the Object size for the requested
> +                            object.
> +*/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_CONFIGURATION_MANAGER_GET_OBJECT) (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
> +  IN  CONST CM_OBJECT_ID                                CmObjectId,
> +  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
> +  );
> +
> +/** The SetObject function defines the interface implemented by the
> +    Configuration Manager Protocol for updating the Configuration
> +    Manager Objects.
> +
> +    @param [in]  This        Poiner to the Configuration Manager Protocol.
> +    @param [in]  CmObjectId  The Configuration Manager Object ID.
> +    @param [out] CmObject    Pointer to the Configuration Manager Object
> +                             descrptor describing the Object.
> +
> +    @retval Returns:
> +      EFI_SUCCESS           The operation completed successfully.
> +      EFI_INVALID_PARAMETER A parameter is invalid.
> +      EFI_NOT_FOUND         The required object information is not found.
> +      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                            is less than the Object size for the requested
> +                            object.
> +      EFI_UNSUPPORTED       This operation is not supported.
> +*/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_CONFIGURATION_MANAGER_SET_OBJECT) (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
> +  IN  CONST CM_OBJECT_ID                                CmObjectId,
> +  IN        CM_OBJ_DESCRIPTOR                   * CONST CmObject
> +  );
> +
> +/** The EFI_CONFIGURATION_MANAGER_PROTOCOL structure describes the
> +    Configuration Manager Protocol interface.
> +*/
> +typedef struct ConfigurationManagerProtocol {
> +  /// The Configuration Manager Protocol revision.
> +  UINT32                                Revision;
> +
> +  /// The interface used to request information about
> +  /// the Configuration Manager Objects.
> +  EFI_CONFIGURATION_MANAGER_GET_OBJECT  GetObject;
> +
> +  /// The interface used to update the information stored
> +  /// in the Configuration Manager repository.
> +  EFI_CONFIGURATION_MANAGER_SET_OBJECT  SetObject;
> +
> +  /// Pointer to an implementation defined abstract repository
> +  /// provisioned by the Configuration Manager.
> +  EFI_PLATFORM_REPOSITORY_INFO        * PlatRepoInfo;
> +} EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +
> +/** A global GUID defined in the protocol section of the
> +    MdeModulePkg.dec file.
> +*/
> +extern EFI_GUID gEfiConfigurationManagerProtocolGuid;
> +
> +#pragma pack()
> +
> +#endif // CONFIGURATION_MANAGER_PROTOCOL_H_
> diff --git a/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..5ece83bb44ec2d88fbd3b49b0e7bdc6314c332c7
> --- /dev/null
> +++ b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> @@ -0,0 +1,113 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +**/
> +
> +#ifndef DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> +#define DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> +
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +
> +/** This macro defines the Dynamic Table Factory Protocol GUID.
> +
> +  GUID: {91D1E327-FE5A-49B8-AB65-0ECE2DDB45EC}
> +*/
> +#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_GUID         \
> +  { 0x91d1e327, 0xfe5a, 0x49b8,                         \
> +    { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec }   \
> +  };
> +
> +/** This macro defines the Configuration Manager Protocol Revision.
> +*/
> +#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_REVISION  CREATE_REVISION (1, 0)
> +
> +#pragma pack(1)
> +
> +/**
> +  Forward declarations:
> +*/
> +typedef struct DynamicTableFactoryProtocol EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
> +typedef struct DynamicTableFactoryInfo EFI_DYNAMIC_TABLE_FACTORY_INFO;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  TableId    The ACPI table generator ID for the
> +                            requested generator.
> +    @param [out] Generator  Pointer to the requested ACPI table
> +                            generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A paramter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +typedef
> +EFI_STATUS
> +EFIAPI
> +(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR) (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  );
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  TableId    The SMBIOS table generator ID for the
> +                            requested generator.
> +    @param [out] Generator  Pointer to the requested SMBIOS table
> +                            generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +typedef
> +EFI_STATUS
> +EFIAPI
> +(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR) (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  );
> +
> +/** A structure describing the Dynamic Table Factory Protocol interface.
> +*/
> +typedef struct DynamicTableFactoryProtocol {
> +  /// The Dynamic Table Factory Protocol revision.
> +  UINT32                                               Revision;
> +
> +  /// The interface used to request an ACPI Table Generator.
> +  EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR   GetAcpiTableGenerator;
> +
> +  /// The interface used to request a SMBIOS Table Generator.
> +  EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR GetSmbiosTableGenerator;
> +
> +  /// Pointer to the data structure that holds the
> +  /// list of registered table generators
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO          * TableFactoryInfo;
> +} EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
> +
> +/** A global GUID defined in the protocol section of the
> +    MdeModulePkg.dec file.
> +*/
> +extern EFI_GUID gEfiDynamicTableFactoryProtocolGuid;
> +
> +#pragma pack()
> +
> +#endif // DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..88d9e5a4a58307ea26ddbe75579cddc3333ccc34
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
> @@ -0,0 +1,91 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +**/
> +
> +#ifndef DYNAMIC_TABLE_FACTORY_H_
> +#define DYNAMIC_TABLE_FACTORY_H_
> +
> +#pragma pack(1)
> +
> +/** A structure that holds the list of registered ACPI and
> +    SMBIOS table generators.
> +*/
> +typedef struct DynamicTableFactoryInfo {
> +  /// An array for holding the list of Standard ACPI Table  Generators.
> +  CONST ACPI_TABLE_GENERATOR *
> +          StdAcpiTableGeneratorList[ESTD_ACPI_TABLE_ID_MAX];
> +
> +  /// An array for holding the list of Custom ACPI Table Generators.
> +  CONST ACPI_TABLE_GENERATOR *
> +          CustomAcpiTableGeneratorList[FixedPcdGet16 (
> +            PcdMaxCustomACPIGenerators)];
> +
> +  /// An array for holding the list of Standard SMBIOS Table Generators.
> +  CONST SMBIOS_TABLE_GENERATOR *
> +          StdSmbiosTableGeneratorList[ESTD_SMBIOS_TABLE_ID_MAX];
> +
> +  /// An array for holding the list of Custom SMBIOS Table Generators.
> +  CONST SMBIOS_TABLE_GENERATOR *
> +          CustomSmbiosTableGeneratorList[FixedPcdGet16 (
> +            PcdMaxCustomSMBIOSGenerators)];
> +} EFI_DYNAMIC_TABLE_FACTORY_INFO;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The ACPI table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested ACPI table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetAcpiTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  );
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The SMBIOS table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested SMBIOS table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetSmbiosTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  );
> +
> +#pragma pack()
> +
> +#endif // DYNAMIC_TABLE_FACTORY_H_
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..1bf20424b942ac08fe93d157f3869de53577cf0e
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
> @@ -0,0 +1,440 @@
> +/** @file
> +  DBG2 Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include <IndustryStandard/DebugPort2Table.h>
> +#include <Drivers/PL011Uart.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard DBG2 Table Generator
> +
> +    Generates the ACPI DBG2 Port Table for ARM UARTs
> +    as specified by the Microsoft Debug Port Table 2 (DBG2)
> +    Specification - December 10, 2015.
> +
> +    Constructs the DBG2 table for PL011 or SBSA UART peripherals.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjSerialDebugPortInfo
> +*/
> +
> +#pragma pack(1)
> +
> +/** Define the number of debug ports represented by the Table.
> +*/
> +#define DBG2_NUM_DEBUG_PORTS                       1
> +
> +/** Define the number of Generic Address Registers
> +    presented in the debug device information.
> +*/
> +#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS   1
> +
> +/** Define the index for the debug port 1.
> +*/
> +#define DBG_PORT_INDEX_PORT1                       0
> +
> +/** Define the string representing the debug port 1 name.
> +*/
> +#define NAME_STR_PORT1                            "COM1"
> +
> +/** Define the length of the namespace string.
> +*/
> +#define DBG2_NAMESPACESTRING_FIELD_SIZE            sizeof (NAME_STR_PORT1)
> +
> +/** Define the PL011 UART address range length.
> +*/
> +#define PL011_UART_LENGTH                          0x1000
> +
> +/** This structure provides the OS with the information required for
> +    initializing a debugger connection.
> +*/
> +typedef struct {
> +  /// The debug device information for the platform
> +  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device;
> +
> +  /// The base address register for the serial port
> +  EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE        BaseAddressRegister;
> +
> +  /// The address size
> +  UINT32 AddressSize;
> +
> +  /// The debug port name string
> +  UINT8  NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
> +} DBG2_DEBUG_DEVICE_INFORMATION;
> +
> +/** This structure represents the information about the debug port(s)
> +    available on the platform.
> +*/
> +typedef struct {
> +  /// The DBG2 table header
> +  EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description;
> +
> +  /// Debug port information list
> +  DBG2_DEBUG_DEVICE_INFORMATION       Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS];
> +} DBG2_TABLE;
> +
> +/** A helper macro used for initalizing the debug port device
> +    information structure.
> +
> +    @param [in]  NumReg       The number of generic address registers.
> +    @param [in]  SubType      The DBG Port SubType.
> +    @param [in]  UartBase     The UART port base address.
> +    @param [in]  UartAddrLen  The UART port address range length.
> +    @param [in]  UartNameStr  The UART port name string.
> +*/
> +#define DBG2_DEBUG_PORT_DDI(                                          \
> +          NumReg,                                                     \
> +          SubType,                                                    \
> +          UartBase,                                                   \
> +          UartAddrLen,                                                \
> +          UartNameStr                                                 \
> +          ) {                                                         \
> +    {                                                                 \
> +      /* UINT8     Revision */                                        \
> +      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,         \
> +      /* UINT16    Length */                                          \
> +      sizeof (DBG2_DEBUG_DEVICE_INFORMATION),                         \
> +      /* UINT8     NumberofGenericAddressRegisters */                 \
> +      NumReg,                                                         \
> +      /* UINT16    NameSpaceStringLength */                           \
> +      DBG2_NAMESPACESTRING_FIELD_SIZE,                                \
> +      /* UINT16    NameSpaceStringOffset */                           \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString),     \
> +      /* UINT16    OemDataLength */                                   \
> +      0,                                                              \
> +      /* UINT16    OemDataOffset */                                   \
> +      0,                                                              \
> +      /* UINT16    Port Type */                                       \
> +      EFI_ACPI_DBG2_PORT_TYPE_SERIAL,                                 \
> +      /* UINT16    Port Subtype */                                    \
> +      SubType,                                                        \
> +      /* UINT8     Reserved[2] */                                     \
> +      {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE},               \
> +      /* UINT16    BaseAddressRegister Offset */                      \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \
> +      /* UINT16    AddressSize Offset */                              \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize)          \
> +    },                                                                \
> +    /* EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */  \
> +    ARM_GAS32 (UartBase),                                             \
> +    /* UINT32  AddressSize */                                         \
> +    UartAddrLen,                                                      \
> +    /* UINT8   NameSpaceString[MAX_DBG2_NAME_LEN] */                  \
> +    UartNameStr                                                       \
> +  }
> +
> +/** The DBG2 Table template definition.
> +
> +    Note: fields marked with "{Template}" will be set dynamically
> +*/
> +STATIC
> +DBG2_TABLE AcpiDbg2 = {
> +  {
> +    ACPI_HEADER (
> +      EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
> +      DBG2_TABLE,
> +      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
> +      ),
> +    OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),
> +    DBG2_NUM_DEBUG_PORTS
> +  },
> +  {
> +    /*
> +     * Debug port 1
> +     */
> +    DBG2_DEBUG_PORT_DDI (
> +      DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS,
> +      EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART,
> +      0,                    // {Template}: Serial Port Base Address
> +      PL011_UART_LENGTH,
> +      NAME_STR_PORT1
> +      )
> +  }
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Serial
> +    debug port information from the Configuration Manager
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjSerialDebugPortInfo,
> +  CM_ARM_SERIAL_PORT_INFO
> +  );
> +
> +/** Initialize the PL011 UART with the parameters obtained from
> +    the Configuration Manager.
> +
> +    @param [in]  SerialPortInfo Pointer to the Serial Port Information.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The parameters for serial port initialization
> +                                  are invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +SetupDebugUart (
> +  IN  CONST CM_ARM_SERIAL_PORT_INFO  * CONST SerialPortInfo
> +  )
> +{
> +  EFI_STATUS          Status;
> +  UINT64              BaudRate;
> +  UINT32              ReceiveFifoDepth;
> +  EFI_PARITY_TYPE     Parity;
> +  UINT8               DataBits;
> +  EFI_STOP_BITS_TYPE  StopBits;
> +
> +  ASSERT (SerialPortInfo != NULL);
> +
> +  // Initialize the Serial Debug UART
> +  DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));
> +  ReceiveFifoDepth = 0; // Use the default value for FIFO depth
> +  Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
> +  DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
> +  StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
> +
> +  BaudRate = SerialPortInfo->BaudRate;
> +  Status = PL011UartInitializePort (
> +             (UINTN)SerialPortInfo->BaseAddress,
> +             SerialPortInfo->Clock,
> +             &BaudRate,
> +             &ReceiveFifoDepth,
> +             &Parity,
> +             &DataBits,
> +             &StopBits
> +             );
> +
> +  DEBUG ((DEBUG_INFO, "Debug UART Configuration:\n"));
> +  DEBUG ((DEBUG_INFO, "UART Base  = 0x%lx\n", SerialPortInfo->BaseAddress));
> +  DEBUG ((DEBUG_INFO, "Clock      = %d\n", SerialPortInfo->Clock));
> +  DEBUG ((DEBUG_INFO, "Baudrate   = %ld\n", BaudRate));
> +  DEBUG ((DEBUG_INFO, "Configuring Debug UART. Status = %r\n", Status));
> +
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Construct the DBG2 ACPI table
> +
> +    The BuildDbg2Table function is called by the Dynamic Table Manager
> +    to construct the DBG2 ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildDbg2Table (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjSerialDebugPortInfo (
> +             CfgMgrProtocol,
> +             &SerialPortInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2,
> +             sizeof (DBG2_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.Address =
> +    SerialPortInfo->BaseAddress;
> +
> +  Status = SetupDebugUart (SerialPortInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the DBG2.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeDbg2TableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the DBG2 Table Generator revision.
> +*/
> +#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the DBG2 Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR Dbg2Generator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_DBG2),
> +  // Generator Description
> +  L"ACPI.STD.DBG2.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  DBG2_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildDbg2Table,
> +  // Free Resource function
> +  FreeDbg2TableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiDbg2LibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&Dbg2Generator);
> +  DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiDbg2LibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&Dbg2Generator);
> +  DEBUG ((DEBUG_INFO, "DBG2: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..75e0b7b50ef34a71cc091db50667a19b40b3f1c9
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
> @@ -0,0 +1,562 @@
> +/** @file
> +  FADT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard FADT Generator
> +
> +    Generates the ACPI FADT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjPowerManagementProfileInfo
> +  - EArmObjBootArchInfo
> +  - EArmObjHypervisorVendorIdentity (OPTIONAL)
> +*/
> +
> +/** This macro defines the FADT flag options for ARM Platforms.
> +*/
> +#define FADT_FLAGS  (EFI_ACPI_6_1_HW_REDUCED_ACPI |          \
> +                     EFI_ACPI_6_1_LOW_POWER_S0_IDLE_CAPABLE)
> +
> +#pragma pack(1)
> +
> +/** The AcpiFadt is a template EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE
> +    structure used for generating the FADT Table.
> +  Note: fields marked with "{Template}" will be updated dynamically.
> +*/
> +STATIC
> +EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = {
> +  ACPI_HEADER (
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE,
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
> +    ),
> +  // UINT32     FirmwareCtrl
> +  0,
> +  // UINT32     Dsdt
> +  0,
> +  // UINT8      Reserved0
> +  EFI_ACPI_RESERVED_BYTE,
> +  // UINT8      PreferredPmProfile
> +  EFI_ACPI_6_1_PM_PROFILE_UNSPECIFIED,  // {Template}: Power Management Profile
> +  // UINT16     SciInt
> +  0,
> +  // UINT32     SmiCmd
> +  0,
> +  // UINT8      AcpiEnable
> +  0,
> +  // UINT8      AcpiDisable
> +  0,
> +  // UINT8      S4BiosReq
> +  0,
> +  // UINT8      PstateCnt
> +  0,
> +  // UINT32     Pm1aEvtBlk
> +  0,
> +  // UINT32     Pm1bEvtBlk
> +  0,
> +  // UINT32     Pm1aCntBlk
> +  0,
> +  // UINT32     Pm1bCntBlk
> +  0,
> +  // UINT32     Pm2CntBlk
> +  0,
> +  // UINT32     PmTmrBlk
> +  0,
> +  // UINT32     Gpe0Blk
> +  0,
> +  // UINT32     Gpe1Blk
> +  0,
> +  // UINT8      Pm1EvtLen
> +  0,
> +  // UINT8      Pm1CntLen
> +  0,
> +  // UINT8      Pm2CntLen
> +  0,
> +  // UINT8      PmTmrLen
> +  0,
> +  // UINT8      Gpe0BlkLen
> +  0,
> +  // UINT8      Gpe1BlkLen
> +  0,
> +  // UINT8      Gpe1Base
> +  0,
> +  // UINT8      CstCnt
> +  0,
> +  // UINT16     PLvl2Lat
> +  0,
> +  // UINT16     PLvl3Lat
> +  0,
> +  // UINT16     FlushSize
> +  0,
> +  // UINT16     FlushStride
> +  0,
> +  // UINT8      DutyOffset
> +  0,
> +  // UINT8      DutyWidth
> +  0,
> +  // UINT8      DayAlrm
> +  0,
> +  // UINT8      MonAlrm
> +  0,
> +  // UINT8      Century
> +  0,
> +  // UINT16     IaPcBootArch
> +  0,
> +  // UINT8      Reserved1
> +  0,
> +  // UINT32     Flags
> +  FADT_FLAGS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  ResetReg
> +  NULL_GAS,
> +  // UINT8      ResetValue
> +  0,
> +  // UINT16     ArmBootArch
> +  EFI_ACPI_6_1_ARM_PSCI_COMPLIANT,  // {Template}: ARM Boot Architecture Flags
> +  // UINT8      MinorRevision
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION,
> +  // UINT64     XFirmwareCtrl
> +  0,
> +  // UINT64     XDsdt
> +  0,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aEvtBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bEvtBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aCntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bCntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm2CntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPmTmrBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe0Blk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe1Blk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepControlReg
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepStatusReg
> +  NULL_GAS,
> +  // UINT64     HypervisorVendorIdentity
> +  EFI_ACPI_RESERVED_QWORD  // {Template}: Hypervisor Vendor ID
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Power
> +    Management Profile Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPowerManagementProfileInfo,
> +  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Boot
> +    Architecture Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjBootArchInfo,
> +  CM_ARM_BOOT_ARCH_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Hypervisor
> +    Vendor ID from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjHypervisorVendorIdentity,
> +  CM_ARM_HYPERVISOR_VENDOR_ID
> +  );
> +
> +/** Update the Power Management Profile information in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                  Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddPmProfileInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS                              Status;
> +  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO  * PmProfile = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Power Management Profile from the Platform Configuration Manager
> +  Status = GetEArmObjPowerManagementProfileInfo (
> +             CfgMgrProtocol,
> +             &PmProfile,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to get Power Management Profile information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT: PreferredPmProfile = 0x%x\n",
> +    PmProfile->PowerManagementProfile
> +    ));
> +
> +  AcpiFadt.PreferredPmProfile = PmProfile->PowerManagementProfile;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Updates the Boot Architecture information in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddBootArchInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS               Status;
> +  CM_ARM_BOOT_ARCH_INFO  * BootArchInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Boot Architecture flags from the Platform Configuration Manager
> +  Status = GetEArmObjBootArchInfo (
> +             CfgMgrProtocol,
> +             &BootArchInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT BootArchFlag = 0x%x\n",
> +    BootArchInfo->BootArchFlags
> +    ));
> +
> +  AcpiFadt.ArmBootArch = BootArchInfo->BootArchFlags;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Update the Hypervisor Vendor ID in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddHypervisorVendorId (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS                     Status;
> +  CM_ARM_HYPERVISOR_VENDOR_ID  * HypervisorVendorInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Hypervisor Vendor ID from the Platform Configuration Manager
> +  Status = GetEArmObjHypervisorVendorIdentity (
> +             CfgMgrProtocol,
> +             &HypervisorVendorInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    if (Status == EFI_NOT_FOUND) {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "INFO: FADT: Platform does not have a Hypervisor Vendor ID. Status = %r\n",
> +        Status
> +        ));
> +    } else {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n",
> +        Status
> +        ));
> +    }
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT: EArmObjHypervisorVendorIdentity = 0x%lx\n",
> +    HypervisorVendorInfo->HypervisorVendorId
> +    ));
> +
> +  AcpiFadt.HypervisorVendorIdentity = HypervisorVendorInfo->HypervisorVendorId;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Construct the FADT table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildFadtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt,
> +             sizeof (EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  // Update PmProfile Info
> +  Status = FadtAddPmProfileInfo (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    goto error_handler;
> +  }
> +
> +  // Update BootArch Info
> +  Status = FadtAddBootArchInfo (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    goto error_handler;
> +  }
> +
> +  // Add the Hypervisor Vendor Id if present
> +  // Note if no hypervisor is present the zero bytes
> +  // will be placed in this field.
> +  Status = FadtAddHypervisorVendorId (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    if (Status == EFI_NOT_FOUND) {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "INFO: FADT: No Hypervisor Vendor ID found," \
> +        " assuming no Hypervisor is present in the firmware.\n"
> +        ));
> +    } else {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r",
> +        Status
> +        ));
> +      goto error_handler;
> +    }
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt;
> +  Status = EFI_SUCCESS;
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the FADT.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeFadtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the FADT Table Generator revision.
> +*/
> +#define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the FADT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR FadtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT),
> +  // Generator Description
> +  L"ACPI.STD.FADT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  FADT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildFadtTable,
> +  // Free Resource function
> +  FreeFadtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiFadtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&FadtGenerator);
> +  DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiFadtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&FadtGenerator);
> +  DEBUG ((DEBUG_INFO, "FADT: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..8a243e7d2ef2fa5806116030c74337f1f8e72e8b
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
> @@ -0,0 +1,652 @@
> +/** @file
> +  GTDT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard GTDT Generator
> +
> +    Generates the ACPI GTDT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjGenericTimerInfo
> +  - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)
> +  - EArmObjPlatformGTBlockInfo (OPTIONAL)
> +*/
> +
> +/** This macro expands to a function that retrieves the Generic
> +    Timer Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGenericTimerInfo,
> +  CM_ARM_GENERIC_TIMER_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the SBSA Generic
> +    Watchdog Timer Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPlatformGenericWatchdogInfo,
> +  CM_ARM_GENERIC_WATCHDOG_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Platform Generic
> +    Timer Block Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPlatformGTBlockInfo,
> +  CM_ARM_GTBLOCK_INFO
> +  );
> +
> +/** Add the Generic Timer Information to the GTDT table.
> +
> +    Also update the Platform Timer offset information if the platform
> +    implements platform timers.
> +
> +    @param [in]  CfgMgrProtocol     Pointer to the Configuration Manager
> +                                    Protocol Interface.
> +    @param [in]  Gtdt               Pointer to the GTDT Table.
> +    @param [in]  PlatformTimerCount Platform timer count.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddGenericTimerInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,
> +  IN  CONST UINT32 PlatformTimerCount
> +)
> +{
> +  EFI_STATUS                   Status;
> +  CM_ARM_GENERIC_TIMER_INFO  * GenericTimerInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Gtdt != NULL);
> +
> +  Status = GetEArmObjGenericTimerInfo (
> +             CfgMgrProtocol,
> +             &GenericTimerInfo,
> +             NULL
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to get GenericTimerInfo. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Gtdt->CntControlBasePhysicalAddress =
> +    GenericTimerInfo->CounterControlBaseAddress;
> +  Gtdt->Reserved = EFI_ACPI_RESERVED_DWORD;
> +  Gtdt->CntReadBasePhysicalAddress =
> +    GenericTimerInfo->CounterReadBaseAddress;
> +  Gtdt->PlatformTimerCount = PlatformTimerCount;
> +  Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :
> +    sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
> +
> +  Gtdt->SecurePL1TimerGSIV = GenericTimerInfo->SecurePL1TimerGSIV;
> +  Gtdt->SecurePL1TimerFlags = GenericTimerInfo->SecurePL1TimerFlags;
> +  Gtdt->NonSecurePL1TimerGSIV = GenericTimerInfo->NonSecurePL1TimerGSIV;
> +  Gtdt->NonSecurePL1TimerFlags = GenericTimerInfo->NonSecurePL1TimerFlags;
> +  Gtdt->VirtualTimerGSIV = GenericTimerInfo->VirtualTimerGSIV;
> +  Gtdt->VirtualTimerFlags = GenericTimerInfo->VirtualTimerFlags;
> +  Gtdt->NonSecurePL2TimerGSIV = GenericTimerInfo->NonSecurePL2TimerGSIV;
> +  Gtdt->NonSecurePL2TimerFlags = GenericTimerInfo->NonSecurePL2TimerFlags;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add the SBSA Generic Watchdog Timers to the GTDT table.
> +
> +    @param [in]  Gtdt             Pointer to the GTDT Table.
> +    @param [in]  WatchdogOffset   Offset to the watchdog information in the
> +                                  GTDT Table.
> +    @param [in]  WatchdogInfoList Pointer to the watchdog information list.
> +    @param [in]  WatchdogCount    Platform timer count.
> +*/
> +STATIC
> +VOID
> +AddGenericWatchdogList (
> +  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
> +  IN CONST UINTN                                           WatchdogOffset,
> +  IN CONST CM_ARM_GENERIC_WATCHDOG_INFO            * CONST WatchdogInfoList,
> +  IN CONST UINTN                                           WatchdogCount
> +  )
> +{
> +  UINTN                                                idx;
> +  EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE  * Watchdog;
> +
> +  ASSERT (Gtdt != NULL);
> +  ASSERT (WatchdogInfoList != NULL);
> +
> +  Watchdog = (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *)
> +             ((UINT8*)Gtdt + WatchdogOffset);
> +
> +  for (idx = 0; idx < WatchdogCount; idx++) {
> +    // Add watchdog entry
> +    DEBUG ((DEBUG_INFO, "GTDT: Watchdog[%d] = 0x%p\n", idx, &Watchdog[idx]));
> +    Watchdog[idx].Type = EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG;
> +    Watchdog[idx].Length =
> +      sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);
> +    Watchdog[idx].Reserved = EFI_ACPI_RESERVED_BYTE;
> +    Watchdog[idx].RefreshFramePhysicalAddress =
> +      WatchdogInfoList[idx].RefreshFrameAddress;
> +    Watchdog[idx].WatchdogControlFramePhysicalAddress =
> +      WatchdogInfoList[idx].ControlFrameAddress;
> +    Watchdog[idx].WatchdogTimerGSIV = WatchdogInfoList[idx].TimerGSIV;
> +    Watchdog[idx].WatchdogTimerFlags = WatchdogInfoList[idx].Flags;
> +
> +  } // for
> +}
> +
> +/** Update the GT Block Timer Frame lists in the GTDT Table.
> +
> +    @param [in]  GtBlockFrame           Pointer to the GT Block Frames
> +                                        list to be updated.
> +    @param [in]  GTBlockTimerFrameList  Pointer to the GT Block Frame
> +                                        Information List.
> +    @param [in]  GTBlockFrameCount      Number of GT Block Frames.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +AddGTBlockTimerFrames (
> +  IN       EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE * CONST GtBlockFrame,
> +  IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO * CONST GTBlockTimerFrameList,
> +  IN CONST UINTN GTBlockFrameCount
> +)
> +{
> +  UINTN       idx;
> +
> +  ASSERT (GtBlockFrame != NULL);
> +  ASSERT (GTBlockTimerFrameList != NULL);
> +
> +  if (GTBlockFrameCount > 8) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: GT Block Frame Count %d is greater than 8\n",
> +      GTBlockFrameCount
> +      ));
> +    ASSERT (GTBlockFrameCount <= 8);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  for (idx = 0; idx < GTBlockFrameCount; idx++) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: GtBlockFrame[%d] = 0x%p\n",
> +      idx,
> +      GtBlockFrame[idx]
> +      ));
> +
> +    GtBlockFrame[idx].GTFrameNumber = GTBlockTimerFrameList[idx].FrameNumber;
> +    GtBlockFrame[idx].Reserved[0] = EFI_ACPI_RESERVED_BYTE;
> +    GtBlockFrame[idx].Reserved[1] = EFI_ACPI_RESERVED_BYTE;
> +    GtBlockFrame[idx].Reserved[2] = EFI_ACPI_RESERVED_BYTE;
> +
> +    GtBlockFrame[idx].CntBaseX =
> +      GTBlockTimerFrameList[idx].PhysicalAddressCntBase;
> +    GtBlockFrame[idx].CntEL0BaseX =
> +      GTBlockTimerFrameList[idx].PhysicalAddressCntEL0Base;
> +
> +    GtBlockFrame[idx].GTxPhysicalTimerGSIV =
> +      GTBlockTimerFrameList[idx].PhysicalTimerGSIV;
> +    GtBlockFrame[idx].GTxPhysicalTimerFlags =
> +      GTBlockTimerFrameList[idx].PhysicalTimerFlags;
> +
> +    GtBlockFrame[idx].GTxVirtualTimerGSIV =
> +      GTBlockTimerFrameList[idx].VirtualTimerGSIV;
> +    GtBlockFrame[idx].GTxVirtualTimerFlags =
> +      GTBlockTimerFrameList[idx].VirtualTimerFlags;
> +
> +    GtBlockFrame[idx].GTxCommonFlags = GTBlockTimerFrameList[idx].CommonFlags;
> +
> +  } // for
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add the GT Block Timers in the GTDT Table.
> +
> +    @param [in]  Gtdt             Pointer to the GTDT Table.
> +    @param [in]  GTBlockOffset    Offset of the GT Block
> +                                  information in the GTDT Table.
> +    @param [in]  GTBlockInfo      Pointer to the GT Block
> +                                  Information List.
> +    @param [in]  BlockTimerCount  Number of GT Block Timers.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +AddGTBlockList (
> +  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
> +  IN CONST UINTN                                           GTBlockOffset,
> +  IN CONST CM_ARM_GTBLOCK_INFO                     * CONST GTBlockInfo,
> +  IN CONST UINTN                                           BlockTimerCount
> +)
> +{
> +  EFI_STATUS                                    Status;
> +  UINTN                                         idx;
> +  EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE        * GTBlock;
> +  EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE  * GtBlockFrame;
> +
> +  ASSERT (Gtdt != NULL);
> +  ASSERT (GTBlockInfo != NULL);
> +
> +  GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)Gtdt +
> +              GTBlockOffset);
> +
> +  for (idx = 0; idx < BlockTimerCount; idx++) {
> +    DEBUG ((DEBUG_INFO, "GTDT: GTBlock[%d] = 0x%p\n",
> +      idx,
> +      GTBlock
> +      ));
> +
> +    GTBlock->Type = EFI_ACPI_6_1_GTDT_GT_BLOCK;
> +    GTBlock->Length = sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) +
> +                        (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
> +                          GTBlockInfo[idx].GTBlockTimerFrameCount);
> +
> +    GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;
> +    GTBlock->CntCtlBase = GTBlockInfo[idx].GTBlockPhysicalAddress;
> +    GTBlock->GTBlockTimerCount = GTBlockInfo[idx].GTBlockTimerFrameCount;
> +    GTBlock->GTBlockTimerOffset =
> +      sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE);
> +
> +    GtBlockFrame = (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE*)
> +      ((UINT8*)GTBlock + GTBlock->GTBlockTimerOffset);
> +
> +    // Add GT Block Timer frames
> +    Status = AddGTBlockTimerFrames (
> +               GtBlockFrame,
> +               GTBlockInfo[idx].GTBlockTimerFrameList,
> +               GTBlockInfo[idx].GTBlockTimerFrameCount
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",
> +        Status
> +        ));
> +      return Status;
> +    }
> +
> +    // Next GTBlock
> +    GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)GTBlock +
> +                GTBlock->Length);
> +  }// for
> +  return EFI_SUCCESS;
> +}
> +
> +/** Construct the GTDT ACPI table.
> +
> +    Called by the Dynamic Table Manager, this function invokes the
> +    Confguration Manager protocol interface to get the required hardware
> +    information for generating the ACPI table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildGtdtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                                      Status;
> +  UINTN                                           TableSize;
> +  UINTN                                           PlatformTimerCount = 0;
> +  UINTN                                           WatchdogCount;
> +  UINTN                                           BlockTimerCount;
> +  CM_ARM_GENERIC_WATCHDOG_INFO                  * WatchdogInfoList = NULL;
> +  CM_ARM_GTBLOCK_INFO                           * GTBlockInfo = NULL;
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * Gtdt;
> +  UINTN                                           idx;
> +  UINTN                                           GTBlockOffset;
> +  UINTN                                           WatchdogOffset = 0;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +  Status = GetEArmObjPlatformGTBlockInfo (
> +             CfgMgrProtocol,
> +             &GTBlockInfo,
> +             &BlockTimerCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to Get Platform GT Block Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjPlatformGenericWatchdogInfo (
> +             CfgMgrProtocol,
> +             &WatchdogInfoList,
> +             &WatchdogCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",
> +    BlockTimerCount,
> +    WatchdogCount
> +    ));
> +
> +  // Calculate the GTDT Table Size
> +  TableSize = sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
> +  if (BlockTimerCount != 0) {
> +    GTBlockOffset = TableSize;
> +    PlatformTimerCount += BlockTimerCount;
> +    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) *
> +                  BlockTimerCount);
> +
> +    for (idx = 0; idx < BlockTimerCount; idx++) {
> +      if (GTBlockInfo[idx].GTBlockTimerFrameCount > 8) {
> +        Status = EFI_INVALID_PARAMETER;
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "GTDT: GTBockFrameCount cannot be more than 8." \
> +          " GTBockFrameCount = %d, Status = %r\n",
> +          GTBlockInfo[idx].GTBlockTimerFrameCount,
> +          Status
> +          ));
> +        goto error_handler;
> +      }
> +      TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
> +        GTBlockInfo[idx].GTBlockTimerFrameCount);
> +    }
> +
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
> +      GTBlockOffset,
> +      PlatformTimerCount
> +      ));
> +  }
> +
> +  if (WatchdogCount != 0) {
> +    WatchdogOffset = TableSize;
> +    PlatformTimerCount += WatchdogCount;
> +    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE) *
> +                  WatchdogCount);
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
> +      WatchdogOffset,
> +      PlatformTimerCount
> +      ));
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Gtdt = (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE*)*Table;
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",
> +    Gtdt,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Gtdt->Header, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = AddGenericTimerInfo (
> +             CfgMgrProtocol,
> +             Gtdt,
> +             PlatformTimerCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (BlockTimerCount != 0) {
> +    Status = AddGTBlockList (
> +               Gtdt,
> +               GTBlockOffset,
> +               GTBlockInfo,
> +               BlockTimerCount
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",
> +        Status
> +        ));
> +      goto error_handler;
> +    }
> +  }
> +
> +  if (WatchdogCount != 0) {
> +    AddGenericWatchdogList (
> +      Gtdt,
> +      WatchdogOffset,
> +      WatchdogInfoList,
> +      WatchdogCount
> +      );
> +  }
> +
> +  return Status;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the GTDT.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +FreeGtdtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +)
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the GTDT Table Generator revision.
> +*/
> +#define GTDT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the GTDT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR GtdtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_GTDT),
> +  // Generator Description
> +  L"ACPI.STD.GTDT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  GTDT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildGtdtTable,
> +  // Free Resource function
> +  FreeGtdtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiGtdtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&GtdtGenerator);
> +  DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiGtdtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&GtdtGenerator);
> +  DEBUG ((DEBUG_INFO, "GTDT: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..cce440d91f50d8a7ac429acb6be40d4a6ac4e230
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
> @@ -0,0 +1,732 @@
> +/** @file
> +  MADT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard MADT Generator
> +
> +    Generates the ACPI MADT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjGicCInfo
> +  - EArmObjGicDInfo
> +  - EArmObjGicMsiFrameInfo (OPTIONAL)
> +  - EArmObjGicRedistributorInfo (OPTIONAL)
> +  - EArmObjGicItsInfo (OPTIONAL)
> +*/
> +
> +/** This macro expands to a function that retrieves the GIC
> +    CPU interface Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicCInfo,
> +  CM_ARM_GICC_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Distributor Information from the Configuration Manager.
> +*/
> +
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicDInfo,
> +  CM_ARM_GICD_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    MSI Frame Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicMsiFrameInfo,
> +  CM_ARM_GIC_MSI_FRAME_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Redistributor Information from the Configuration Manager.
> +*/
> +
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicRedistributorInfo,
> +  CM_ARM_GIC_REDIST_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Interrupt Translation Serice Information from the
> +    Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicItsInfo,
> +  CM_ARM_GIC_ITS_INFO
> +  );
> +
> +/** This function updates the GIC CPU Interface Information in the
> +    EFI_ACPI_6_1_GIC_STRUCTURE structure.
> +
> +    @param [in]  Gicc      Pointer to GIC CPU Interface structure.
> +    @param [in]  GicCInfo  Pointer to the GIC CPU Interface Information.
> +*/
> +STATIC
> +VOID
> +AddGICC (
> +  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * CONST Gicc,
> +  IN  CONST CM_ARM_GICC_INFO      * CONST GicCInfo
> +  )
> +{
> +  ASSERT (Gicc != NULL);
> +  ASSERT (GicCInfo != NULL);
> +
> +  /* UINT8 Type */
> +  Gicc->Type = EFI_ACPI_6_1_GIC;
> +  /* UINT8 Length */
> +  Gicc->Length = sizeof (EFI_ACPI_6_1_GIC_STRUCTURE);
> +  /* UINT16 Reserved */
> +  Gicc->Reserved = EFI_ACPI_RESERVED_WORD;
> +
> +  /* UINT32 CPUInterfaceNumber */
> +  Gicc->CPUInterfaceNumber = GicCInfo->CPUInterfaceNumber;
> +  /* UINT32 AcpiProcessorUid */
> +  Gicc->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;
> +  /* UINT32 Flags */
> +  Gicc->Flags = GicCInfo->Flags;
> +  /* UINT32 ParkingProtocolVersion */
> +  Gicc->ParkingProtocolVersion = GicCInfo->ParkingProtocolVersion;
> +  /* UINT32 PerformanceInterruptGsiv */
> +  Gicc->PerformanceInterruptGsiv = GicCInfo->PerformanceInterruptGsiv;
> +  /* UINT64 ParkedAddress */
> +  Gicc->ParkedAddress = GicCInfo->ParkedAddress;
> +
> +  /* UINT64 PhysicalBaseAddress */
> +  Gicc->PhysicalBaseAddress = GicCInfo->PhysicalBaseAddress;
> +  /* UINT64 GICV */
> +  Gicc->GICV = GicCInfo->GICV;
> +  /* UINT64 GICH */
> +  Gicc->GICH = GicCInfo->GICH;
> +
> +  /* UINT32 VGICMaintenanceInterrupt */
> +  Gicc->VGICMaintenanceInterrupt = GicCInfo->VGICMaintenanceInterrupt;
> +  /* UINT64 GICRBaseAddress */
> +  Gicc->GICRBaseAddress = GicCInfo->GICRBaseAddress;
> +
> +  /* UINT64 MPIDR */
> +  Gicc->MPIDR = GicCInfo->MPIDR;
> +  /* UINT8 ProcessorPowerEfficiencyClass */
> +  Gicc->ProcessorPowerEfficiencyClass =
> +    GicCInfo->ProcessorPowerEfficiencyClass;
> +  /* UINT8 Reserved2[3] */
> +  Gicc->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
> +  Gicc->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
> +  Gicc->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
> +}
> +
> +/** Add the GIC CPU Interface Information to the MADT Table.
> +
> +    @param [in]  Gicc      Pointer to GIC CPU Interface
> +                            structure list.
> +    @param [in]  GicCInfo  Pointer to the GIC CPU
> +                            Information list.
> +    @param [in]  GicCCount Count of GIC CPU Interfaces.
> +*/
> +STATIC
> +VOID
> +AddGICCList (
> +  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * Gicc,
> +  IN  CONST CM_ARM_GICC_INFO      * GicCInfo,
> +  IN  CONST UINTN                   GicCCount
> +  )
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicc != NULL);
> +  ASSERT (GicCInfo != NULL);
> +
> +  for (idx = 0; idx < GicCCount; idx++) {
> +    AddGICC (Gicc++, GicCInfo++);
> +  }
> +}
> +
> +/** Update the GIC Distributor Information in the MADT Table.
> +
> +    @param [in]  Gicd      Pointer to GIC Distributor structure.
> +    @param [in]  GicDInfo  Pointer to the GIC Distributor Information.
> +*/
> +STATIC
> +VOID
> +AddGICD (
> +  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * CONST Gicd,
> +  CONST CM_ARM_GICD_INFO                  * CONST GicDInfo
> +)
> +{
> +  ASSERT (Gicd != NULL);
> +  ASSERT (GicDInfo != NULL);
> +
> +  /* UINT8 Type */
> +  Gicd->Type = EFI_ACPI_6_1_GICD;
> +  /* UINT8 Length */
> +  Gicd->Length = sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE);
> +  /* UINT16 Reserved */
> +  Gicd->Reserved1 = EFI_ACPI_RESERVED_WORD;
> +  /* UINT32 Identifier */
> +  Gicd->GicId = GicDInfo->GicId;
> +  /* UINT64 PhysicalBaseAddress */
> +  Gicd->PhysicalBaseAddress = GicDInfo->PhysicalBaseAddress;
> +  /* UINT32 VectorBase */
> +  Gicd->SystemVectorBase = GicDInfo->SystemVectorBase;
> +  /* UINT8  GicVersion */
> +  Gicd->GicVersion = GicDInfo->GicVersion;
> +  /* UINT8  Reserved2[3] */
> +  Gicd->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
> +  Gicd->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
> +  Gicd->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
> +}
> +
> +/** Add the GIC Distributor Information to the MADT Table.
> +
> +    @param [in]  Gicd      Pointer to GIC Distributor structure list.
> +    @param [in]  GicDInfo  Pointer to the GIC Distributor Information list.
> +    @param [in]  GicDCount Count of GIC Distributors.
> +*/
> +STATIC
> +VOID
> +AddGICDList (
> +  IN  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * Gicd,
> +  IN  CONST CM_ARM_GICD_INFO                  * GicDInfo,
> +  IN  CONST UINTN                               GicDCount
> +  )
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicd != NULL);
> +  ASSERT (GicDInfo != NULL);
> +
> +  for (idx = 0; idx < GicDCount; idx++) {
> +    AddGICD (Gicd++, GicDInfo++);
> +  }
> +}
> +
> +/** Update the GIC MSI Frame Information.
> +
> +    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure.
> +    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame Information.
> +*/
> +STATIC
> +VOID
> +AddGICMsiFrame (
> +  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * CONST GicMsiFrame,
> +  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * CONST GicMsiFrameInfo
> +)
> +{
> +  ASSERT (GicMsiFrame != NULL);
> +  ASSERT (GicMsiFrameInfo != NULL);
> +
> +  GicMsiFrame->Type = EFI_ACPI_6_1_GIC_MSI_FRAME;
> +  GicMsiFrame->Length = sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE);
> +  GicMsiFrame->Reserved1 = EFI_ACPI_RESERVED_WORD;
> +  GicMsiFrame->GicMsiFrameId = GicMsiFrameInfo->GicMsiFrameId;
> +  GicMsiFrame->PhysicalBaseAddress = GicMsiFrameInfo->PhysicalBaseAddress;
> +
> +  GicMsiFrame->Flags = GicMsiFrameInfo->Flags;
> +  GicMsiFrame->SPICount = GicMsiFrameInfo->SPICount;
> +  GicMsiFrame->SPIBase = GicMsiFrameInfo->SPIBase;
> +}
> +
> +/** Add the GIC MSI Frame Information to the MADT Table.
> +
> +    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure list.
> +    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame info list.
> +    @param [in]  GicMsiFrameCount Count of GIC MSI Frames.
> +*/
> +STATIC
> +VOID
> +AddGICMsiFrameInfoList (
> +  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * GicMsiFrame,
> +  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * GicMsiFrameInfo,
> +  IN  CONST UINTN                             GicMsiFrameCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (GicMsiFrame != NULL);
> +  ASSERT (GicMsiFrameInfo != NULL);
> +
> +  for (idx = 0; idx < GicMsiFrameCount; idx++) {
> +    AddGICMsiFrame (GicMsiFrame++, GicMsiFrameInfo++);
> +  }
> +}
> +
> +/** Update the GIC Redistributor Information.
> +
> +    @param [in]  Gicr                 Pointer to GIC Redistributor structure.
> +    @param [in]  GicRedisributorInfo  Pointer to the GIC Redistributor Info.
> +*/
> +STATIC
> +VOID
> +AddGICRedistributor (
> +  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * CONST Gicr,
> +  IN  CONST CM_ARM_GIC_REDIST_INFO  * CONST GicRedisributorInfo
> +  )
> +{
> +  ASSERT (Gicr != NULL);
> +  ASSERT (GicRedisributorInfo != NULL);
> +
> +  Gicr->Type = EFI_ACPI_6_1_GICR;
> +  Gicr->Length = sizeof (EFI_ACPI_6_1_GICR_STRUCTURE);
> +  Gicr->Reserved = EFI_ACPI_RESERVED_WORD;
> +  Gicr->DiscoveryRangeBaseAddress =
> +    GicRedisributorInfo->DiscoveryRangeBaseAddress;
> +  Gicr->DiscoveryRangeLength = GicRedisributorInfo->DiscoveryRangeLength;
> +}
> +
> +/** Add the GIC Redistributor Information to the MADT Table.
> +
> +    @param [in]  Gicr      Pointer to GIC Redistributor structure list.
> +    @param [in]  GicRInfo  Pointer to the GIC Distributor info list.
> +    @param [in]  GicRCount Count of GIC Distributors.
> +*/
> +STATIC
> +VOID
> +AddGICRedistributorList (
> +  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * Gicr,
> +  IN  CONST CM_ARM_GIC_REDIST_INFO  * GicRInfo,
> +  IN  CONST UINTN                     GicRCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicr != NULL);
> +  ASSERT (GicRInfo != NULL);
> +
> +  for (idx = 0; idx < GicRCount; idx++) {
> +    AddGICRedistributor (Gicr++, GicRInfo++);
> +  }
> +}
> +
> +/** Update the GIC Interrupt Translation Service Information
> +
> +    @param [in]  GicIts      Pointer to GIC ITS structure.
> +    @param [in]  GicItsInfo  Pointer to the GIC ITS Information.
> +*/
> +STATIC
> +VOID
> +AddGICInterruptTranslationService (
> +  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * CONST GicIts,
> +  IN  CONST CM_ARM_GIC_ITS_INFO       * CONST GicItsInfo
> +)
> +{
> +  ASSERT (GicIts != NULL);
> +  ASSERT (GicItsInfo != NULL);
> +
> +  GicIts->Type = EFI_ACPI_6_1_GIC_ITS;
> +  GicIts->Length = sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE);
> +  GicIts->Reserved = EFI_ACPI_RESERVED_WORD;
> +  GicIts->GicItsId = GicItsInfo->GicItsId;
> +  GicIts->PhysicalBaseAddress = GicItsInfo->PhysicalBaseAddress;
> +  GicIts->Reserved2 = EFI_ACPI_RESERVED_DWORD;
> +}
> +
> +/** Add the GIC Interrupt Translation Service Information
> +    to the MADT Table.
> +
> +    @param [in]  GicIts       Pointer to GIC ITS structure list.
> +    @param [in]  GicItsInfo   Pointer to the GIC ITS list.
> +    @param [in]  GicItsCount  Count of GIC ITS.
> +*/
> +STATIC
> +VOID
> +AddGICItsList (
> +  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * GicIts,
> +  IN  CONST CM_ARM_GIC_ITS_INFO       * GicItsInfo,
> +  IN  CONST UINTN                       GicItsCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (GicIts != NULL);
> +  ASSERT (GicItsInfo != NULL);
> +
> +  for (idx = 0; idx < GicItsCount; idx++) {
> +    AddGICInterruptTranslationService (GicIts++, GicItsInfo++);
> +  }
> +}
> +
> +/** Construct the MADT ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildMadtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  UINTN                        TableSize;
> +  UINTN                        GicCCount;
> +  UINTN                        GicDCount;
> +  UINTN                        GicMSICount;
> +  UINTN                        GicRedistCount;
> +  UINTN                        GicItsCount;
> +  CM_ARM_GICC_INFO           * GicCInfo = NULL;
> +  CM_ARM_GICD_INFO           * GicDInfo = NULL;
> +  CM_ARM_GIC_MSI_FRAME_INFO  * GicMSIInfo = NULL;
> +  CM_ARM_GIC_REDIST_INFO     * GicRedistInfo = NULL;
> +  CM_ARM_GIC_ITS_INFO        * GicItsInfo = NULL;
> +  UINTN                        GicCOffset;
> +  UINTN                        GicDOffset;
> +  UINTN                        GicMSIOffset;
> +  UINTN                        GicRedistOffset;
> +  UINTN                        GicItsOffset;
> +
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER  * Madt;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjGicCInfo (CfgMgrProtocol, &GicCInfo, &GicCCount);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GICC Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (GicCCount == 0) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: GIC CPU Interface information not provided.\n"
> +      ));
> +    ASSERT (GicCCount != 0);
> +    Status = EFI_INVALID_PARAMETER;
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicDInfo (CfgMgrProtocol, &GicDInfo, &GicDCount);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GICD Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (GicDCount == 0) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: GIC Distributor information not provided.\n"
> +      ));
> +    ASSERT (GicDCount != 0);
> +    Status = EFI_INVALID_PARAMETER;
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicMsiFrameInfo (
> +             CfgMgrProtocol,
> +             &GicMSIInfo,
> +             &GicMSICount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC MSI Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicRedistributorInfo (
> +             CfgMgrProtocol,
> +             &GicRedistInfo,
> +             &GicRedistCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC Redistributor Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicItsInfo (
> +             CfgMgrProtocol,
> +             &GicItsInfo,
> +             &GicItsCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC ITS Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  TableSize = sizeof (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
> +
> +  GicCOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_STRUCTURE) * GicCCount);
> +
> +  GicDOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE) * GicDCount);
> +
> +  GicMSIOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE) * GicMSICount);
> +
> +  GicRedistOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GICR_STRUCTURE) * GicRedistCount);
> +
> +  GicItsOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE) * GicItsCount);
> +
> +  // Allocate the Buffer for MADT table
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to allocate memory for MADT Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Madt = (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER*)*Table;
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MADT: Madt = 0x%p TableSize = 0x%x\n",
> +    Madt,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Madt->Header, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  AddGICCList (
> +    (EFI_ACPI_6_1_GIC_STRUCTURE*)((UINT8*)Madt + GicCOffset),
> +    GicCInfo,
> +    GicCCount
> +    );
> +
> +  AddGICDList (
> +    (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE*)((UINT8*)Madt + GicDOffset),
> +    GicDInfo,
> +    GicDCount
> +    );
> +
> +  if (GicMSICount != 0) {
> +    AddGICMsiFrameInfoList (
> +      (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE*)((UINT8*)Madt + GicMSIOffset),
> +      GicMSIInfo,
> +      GicMSICount
> +      );
> +  }
> +
> +  if (GicRedistCount != 0) {
> +    AddGICRedistributorList (
> +      (EFI_ACPI_6_1_GICR_STRUCTURE*)((UINT8*)Madt + GicRedistOffset),
> +      GicRedistInfo,
> +      GicRedistCount
> +      );
> +  }
> +
> +  if (GicItsCount != 0) {
> +    AddGICItsList (
> +      (EFI_ACPI_6_1_GIC_ITS_STRUCTURE*)((UINT8*)Madt + GicItsOffset),
> +      GicItsInfo,
> +      GicItsCount
> +      );
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the MADT
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeMadtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MADT: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** The MADT Table Generator revision.
> +*/
> +#define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the MADT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR MadtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MADT),
> +  // Generator Description
> +  L"ACPI.STD.MADT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  MADT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildMadtTable,
> +  // Free Resource function
> +  FreeMadtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMadtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&MadtGenerator);
> +  DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMadtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&MadtGenerator);
> +  DEBUG ((DEBUG_INFO, "MADT: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..c023b413797379562f20ae97db9e2f2ca6d8758c
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
> @@ -0,0 +1,336 @@
> +/** @file
> +  MCFG Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard MCFG Generator
> +
> +    Generates the MCFG Table as specified by the PCI Firmware
> +    Specification - Revision 3.2, January 26, 2015.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjPciConfigSpaceInfo
> +*/
> +
> +#pragma pack(1)
> +
> +/** This typedef is used to shorten the name of the MCFG Table
> +    header structure.
> +*/
> +typedef
> +  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER
> +  MCFG_TABLE;
> +
> +/** This typedef is used to shorten the name of the Enhanced
> +    Configuration Space address structure.
> +*/
> +typedef
> +  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE
> +  MCFG_CFG_SPACE_ADDR;
> +
> +#pragma pack()
> +
> +/** Retrieve the PCI Configuration Space Information.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPciConfigSpaceInfo,
> +  CM_ARM_PCI_CONFIG_SPACE_INFO
> +  );
> +
> +/** Add the PCI Enhanced Configuration Space Information to the MCFG Table.
> +
> +    @param [in]  Mcfg                Pointer to MCFG Table.
> +    @param [in]  PciCfgSpaceOffset   Offset for the PCI Configuration Space
> +                                     Info structure in the MCFG Table.
> +    @param [in]  PciCfgSpaceInfoList Pointer to the PCI Configuration Space
> +                                     Info List.
> +    @param [in]  PciCfgSpaceCount    Count of PCI Configuration Space Info.
> +*/
> +STATIC
> +VOID
> +AddPciConfigurationSpaceList (
> +  IN       MCFG_TABLE                   * CONST Mcfg,
> +  IN CONST UINTN                                PciCfgSpaceOffset,
> +  IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * CONST PciCfgSpaceInfoList,
> +  IN CONST UINTN                                PciCfgSpaceCount
> +)
> +{
> +  UINTN                  idx;
> +  MCFG_CFG_SPACE_ADDR  * PciCfgSpace;
> +
> +  ASSERT (Mcfg != NULL);
> +  ASSERT (PciCfgSpaceInfoList != NULL);
> +
> +  PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8*)Mcfg + PciCfgSpaceOffset);
> +  for (idx = 0; idx < PciCfgSpaceCount; idx++) {
> +    // Add PCI Configuration Space entry
> +    PciCfgSpace[idx].BaseAddress = PciCfgSpaceInfoList[idx].BaseAddress;
> +    PciCfgSpace[idx].PciSegmentGroupNumber =
> +      PciCfgSpaceInfoList[idx].PciSegmentGroupNumber;
> +    PciCfgSpace[idx].StartBusNumber = PciCfgSpaceInfoList[idx].StartBusNumber;
> +    PciCfgSpace[idx].EndBusNumber = PciCfgSpaceInfoList[idx].EndBusNumber;
> +    PciCfgSpace[idx].Reserved = EFI_ACPI_RESERVED_DWORD;
> +  }
> +}
> +
> +/** Construct the MCFG ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildMcfgTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UINTN                           TableSize;
> +  UINTN                           ConfigurationSpaceCount;
> +  CM_ARM_PCI_CONFIG_SPACE_INFO  * PciConfigSpaceInfoList = NULL;
> +  MCFG_TABLE                    * Mcfg;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +  Status = GetEArmObjPciConfigSpaceInfo (
> +              CfgMgrProtocol,
> +              &PciConfigSpaceInfoList,
> +              &ConfigurationSpaceCount
> +              );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to get PCI Configuration Space Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +  ASSERT (ConfigurationSpaceCount != 0);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MCFG: Configuration Space Count = %d\n",
> +    ConfigurationSpaceCount
> +    ));
> +
> +  // Calculate the MCFG Table Size
> +  TableSize = sizeof (MCFG_TABLE) +
> +    ((sizeof (MCFG_CFG_SPACE_ADDR) * ConfigurationSpaceCount));
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Mcfg = (MCFG_TABLE*)*Table;
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MCFG: Mcfg = 0x%p TableSize = 0x%x\n",
> +    Mcfg,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Mcfg->Header, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Mcfg->Reserved = EFI_ACPI_RESERVED_QWORD;
> +
> +  AddPciConfigurationSpaceList (
> +    Mcfg,
> +    sizeof (MCFG_TABLE),
> +    PciConfigSpaceInfoList,
> +    ConfigurationSpaceCount
> +    );
> +
> +  return EFI_SUCCESS;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the MCFG
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeMcfgTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MCFG: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the MCFG Table Generator revision.
> +*/
> +#define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the MCFG Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR McfgGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MCFG),
> +  // Generator Description
> +  L"ACPI.STD.MCFG.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  MCFG_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildMcfgTable,
> +  // Free Resource function
> +  FreeMcfgTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMcfgLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&McfgGenerator);
> +  DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMcfgLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&McfgGenerator);
> +  DEBUG ((DEBUG_INFO, "MCFG: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..aaca70cba0a1a08c0730bd84134c1b8722edd7af
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
> @@ -0,0 +1,177 @@
> +/** @file
> +  MCFG Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** Construct the ACPI table using the ACPI table data provided.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildRawTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableData != NULL);
> +
> +  if (AcpiTableInfo->AcpiTableData == NULL) {
> +    *Table = NULL;
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Table = AcpiTableInfo->AcpiTableData;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Free any resources allocated for constructing the ACPI table.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +FreeRawTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the Raw Generator revision.
> +*/
> +#define RAW_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the Raw Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR RawGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RAW),
> +  // Generator Description
> +  L"ACPI.STD.RAW.GENERATOR",
> +  // ACPI Table Signature - Unused
> +  0,
> +  // ACPI Table Revision - Unused
> +  0,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  RAW_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildRawTable,
> +  // Free Resource function
> +  FreeRawTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiRawLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&RawGenerator);
> +  DEBUG ((DEBUG_INFO, "RAW: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +
> +EFI_STATUS
> +EFIAPI
> +AcpiRawLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&RawGenerator);
> +  DEBUG ((DEBUG_INFO, "RAW: UnRegister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..ccfbcf088cfaec1e4f9f3738f5fe09a65c93bc9e
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
> @@ -0,0 +1,323 @@
> +/** @file
> +  SPCR Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard SPCR Table Generator
> +
> +    Generates the ACPI SPCR Table for ARM UARTs as specified by
> +    the Microsoft Serial Port Console Redirection Table
> +    Specification - Version 1.03 - August 10, 2015.
> +
> +    Constructs the SPCR table for PL011 or SBSA UART peripherals.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjSerialConsolePortInfo
> +
> +NOTE: This implementation ignores the possibility that the Serial settings may
> +      be modified from the UEFI Shell.  A more complex handler would be needed
> +      to (e.g.) recover serial port settings from the UART, or non-volatile
> +      storage.
> +*/
> +
> +#pragma pack(1)
> +
> +/** This macro defines the no flow control option.
> +*/
> +#define SPCR_FLOW_CONTROL_NONE           0
> +
> +/**A template for generating the SPCR Table.
> +
> +  Note: fields marked "{Template}" will be updated dynamically.
> +*/
> +STATIC
> +EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = {
> +  ACPI_HEADER (
> +    EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> +    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,
> +    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
> +    ),
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_PL011_UART,
> +  {
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE
> +  },
> +  ARM_GAS32 (0), // {Template}: Serial Port Base Address
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC,
> +  0, // Not used on ARM
> +  0, // {Template}: Serial Port Interrupt
> +  0, // {Template}: Serial Port Baudrate
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
> +  SPCR_FLOW_CONTROL_NONE,
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI,
> +  EFI_ACPI_RESERVED_BYTE,
> +  0xFFFF,
> +  0xFFFF,
> +  0x00,
> +  0x00,
> +  0x00,
> +  0x00000000,
> +  0x00,
> +  EFI_ACPI_RESERVED_DWORD
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Serial
> +    Port Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjSerialConsolePortInfo,
> +  CM_ARM_SERIAL_PORT_INFO
> +  )
> +
> +/** Construct the SPCR ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_UNSUPPORTED       An unsupported baudrate was specified by the
> +                                  Confguration Manager.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildSpcrTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjSerialConsolePortInfo (
> +             CfgMgrProtocol,
> +             &SerialPortInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));
> +  DEBUG ((DEBUG_INFO, "  UART Base  = 0x%lx\n", SerialPortInfo->BaseAddress));
> +  DEBUG ((DEBUG_INFO, "  Clock      = %d\n", SerialPortInfo->Clock));
> +  DEBUG ((DEBUG_INFO, "  Baudrate   = %ld\n", SerialPortInfo->BaudRate));
> +  DEBUG ((DEBUG_INFO, "  Interrupt  = %d\n", SerialPortInfo->Interrupt));
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr,
> +             sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
> +  AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;
> +
> +  switch (SerialPortInfo->BaudRate) {
> +    case 9600:
> +      AcpiSpcr.BaudRate =
> +        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;
> +      break;
> +    case 19200:
> +      AcpiSpcr.BaudRate =
> +        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;
> +      break;
> +    case 57600:
> +      AcpiSpcr.BaudRate =
> +        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;
> +      break;
> +    case 115200:
> +      AcpiSpcr.BaudRate =
> +        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;
> +      break;
> +    default:
> +      Status = EFI_UNSUPPORTED;
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
> +        SerialPortInfo->BaudRate,
> +        Status
> +        ));
> +      goto error_handler;
> +  } // switch
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the SPCR.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeSpcrTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the SPCR Table Generator revision.
> +*/
> +#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the SPCR Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR SpcrGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_SPCR),
> +  // Generator Description
> +  L"ACPI.STD.SPCR.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  SPCR_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildSpcrTable,
> +  // Free Resource function
> +  FreeSpcrTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiSpcrLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&SpcrGenerator);
> +  DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiSpcrLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&SpcrGenerator);
> +  DEBUG ((DEBUG_INFO, "SPCR: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..8dc1d6b6f7c6eb71bd0ab16b690a9f5b4855dc3d
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
> @@ -0,0 +1,165 @@
> +/** @file
> +  Table Helper
> +
> +Copyright (c) 2017, ARM Limited. All rights reserved.
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD License
> +which accompanies this distribution.  The full text of the license may be found at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
> +    object from the Configuration Manager.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
> +                                interface.
> +    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
> +                                object structure.
> +
> +    @retval EFI_SUCCESS           The object is returned.
> +    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
> +    @retval EFI_NOT_FOUND         The requested Object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetCgfMgrInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST  CfgMgrProtocol,
> +  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **        CfgMfrInfo
> +  )
> +{
> +  EFI_STATUS         Status;
> +  CM_OBJ_DESCRIPTOR  CmObjectDesc;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (CfgMfrInfo != NULL);
> +
> +  *CfgMfrInfo = NULL;
> +  Status = CfgMgrProtocol->GetObject (
> +    CfgMgrProtocol,
> +    CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
> +    &CmObjectDesc
> +    );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Get Configuration Manager Info. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  ASSERT (CmObjectDesc.Size >= sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO));
> +  if (CmObjectDesc.Size < sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: EStdObjCfgMgrInfo: Buffer too small, size  = 0x%x\n",
> +      CmObjectDesc.Size
> +      ));
> +    return EFI_BAD_BUFFER_SIZE;
> +  }
> +
> +  *CfgMfrInfo = (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO*)CmObjectDesc.Data;
> +  return Status;
> +}
> +
> +/** The AddAcpiHeader function updates the ACPI header structure pointed by
> +    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
> +    Manager protocol to obtain any information required for constructing the
> +    header.
> +
> +    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
> +                                   protocol interface.
> +    @param [in]     Generator      Pointer to the ACPI table Generator.
> +    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
> +                                   updated.
> +    @param [in]     Length         Length of the ACPI table.
> +
> +    @retval EFI_SUCCESS           The ACPI table is updated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AddAcpiHeader (
> +  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
> +  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
> +  IN      CONST UINT32                                      Length
> +  )
> +{
> +  EFI_STATUS                               Status;
> +  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Generator != NULL);
> +  ASSERT (AcpiHeader != NULL);
> +  ASSERT (Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
> +
> +  if ((CfgMgrProtocol == NULL) ||
> +      (Generator == NULL) ||
> +      (AcpiHeader == NULL) ||
> +      (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))
> +    ) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  /* UINT32  Signature */
> +  AcpiHeader->Signature = Generator->AcpiTableSignature;
> +  /* UINT32  Length */
> +  AcpiHeader->Length = Length;
> +  /* UINT8   Revision */
> +  AcpiHeader->Revision = Generator->AcpiTableRevision;
> +  /* UINT8   Checksum */
> +  AcpiHeader->Checksum = 0;
> +
> +  /* UINT8   OemId[6] */
> +  CopyMem (AcpiHeader->OemId, CfgMfrInfo->OemId, sizeof (AcpiHeader->OemId));
> +
> +  /* UINT64  OemTableId */
> +  AcpiHeader->OemTableId = Generator->CreatorId; // Generator->GeneratorID;
> +  AcpiHeader->OemTableId <<= 32;
> +  AcpiHeader->OemTableId |= Generator->AcpiTableSignature;
> +
> +  /* UINT32  OemRevision */
> +  AcpiHeader->OemRevision = CfgMfrInfo->Revision;
> +
> +  /* UINT32  CreatorId */
> +  AcpiHeader->CreatorId = Generator->CreatorId;
> +  /* UINT32  CreatorRevision */
> +  AcpiHeader->CreatorRevision = Generator->CreatorRevision;
> +
> +  Status = EFI_SUCCESS;
> +error_handler:
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..79cf0f290ddb79499c71d6c553b420418dec50f1
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
> @@ -0,0 +1,227 @@
> +/** @file
> +  ACPI Table Factory
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The ACPI table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested ACPI table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetAcpiTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  )
> +{
> +  UINT16                           TableId;
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
> +
> +  ASSERT (This != NULL);
> +
> +  FactoryInfo = This->TableFactoryInfo;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (GeneratorId)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not ACPI\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Generator = NULL;
> +  TableId = GET_TABLE_ID (GeneratorId);
> +  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->StdAcpiTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->StdAcpiTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->CustomAcpiTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->CustomAcpiTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Register ACPI table factory generator.
> +
> +    The ACPI table factory maintains a list of the Standard and OEM ACPI
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterAcpiTableGenerator (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: ACPI register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI register - Generator" \
> +      " Type is not ACPI\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Unregister ACPI generator.
> +
> +    This function is called by the ACPI table generator to unregister itself
> +    from the ACPI table factory.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterAcpiTableGenerator (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: ACPI un-register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI un-register - Generator" \
> +      " Type is not ACPI\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] != NULL) {
> +      if (Generator != TableFactoryInfo.StdAcpiTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] != NULL) {
> +      if (Generator !=
> +          TableFactoryInfo.CustomAcpiTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
> +  return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..64a0390cdd006d8e3222ff19b269d1b4326736c3
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
> @@ -0,0 +1,84 @@
> +/** @file
> +  Dynamic Table Factory Dxe
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +/** The Dynamic Table Factory protocol structure that holds the
> +    list of registered ACPI and SMBIOS table generators.
> +*/
> +EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +
> +/** A structure describing the Dynamic Table Factory protocol.
> +*/
> +STATIC
> +CONST
> +EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL DynamicTableFactoryProtocol = {
> +  CREATE_REVISION (1, 0),
> +  GetAcpiTableGenerator,
> +  GetSmbiosTableGenerator,
> +  &TableFactoryInfo
> +};
> +
> +/** Entrypoint for Dynamic Table Factory Dxe.
> +
> +    @param  ImageHandle
> +    @param  SystemTable
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +    @retval EFI_NOT_FOUND         Required interface/object was not found.
> +    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
> +
> +*/
> +EFI_STATUS
> +EFIAPI
> +DynamicTableFactoryDxeInitialize (
> +  IN  EFI_HANDLE                 ImageHandle,
> +  IN  EFI_SYSTEM_TABLE   * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = gBS->InstallProtocolInterface (
> +                  &ImageHandle,
> +                  &gEfiDynamicTableFactoryProtocolGuid,
> +                  EFI_NATIVE_INTERFACE,
> +                  (VOID*)&DynamicTableFactoryProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to install the Dynamic Table Factory Protocol." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +  }
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..64b578f30a3413ac2b22ccef4f09368c1af38b67
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
> @@ -0,0 +1,227 @@
> +/** @file
> +  SMBIOS Table Factory
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +**/
> +
> +#include <Protocol/Smbios.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The SMBIOS table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested SMBIOS table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetSmbiosTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  )
> +{
> +  UINT16                           TableId;
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
> +
> +  ASSERT (This != NULL);
> +
> +  FactoryInfo = This->TableFactoryInfo;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (GeneratorId)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not SMBIOS\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Generator = NULL;
> +  TableId = GET_TABLE_ID (GeneratorId);
> +  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->StdSmbiosTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->StdSmbiosTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->CustomSmbiosTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->CustomSmbiosTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Register SMBIOS table factory generator.
> +
> +    The SMBIOS table factory maintains a list of the Standard and OEM SMBIOS
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterSmbiosTableGenerator (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SMBIOS register - Generator" \
> +      " Type is not SMBIOS\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Unregister SMBIOS generator.
> +
> +    This function is called by the SMBIOS table generator to unregister itself
> +    from the SMBIOS table factory.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterSmbiosTableGenerator (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS un-register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SMBIOS un-register - Generator" \
> +      " Type is not SMBIOS\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] != NULL) {
> +      if (Generator != TableFactoryInfo.StdSmbiosTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] != NULL) {
> +      if (Generator !=
> +          TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
> +  return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..f84bf3bef910ddf86629062d6d1ca1dffafa5a28
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
> @@ -0,0 +1,531 @@
> +/** @file
> +  Dynamic Table Manager Dxe
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** This macro expands to a function that retrieves the ACPI Table
> +    List from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceStandard,
> +  EStdObjAcpiTableList,
> +  CM_STD_OBJ_ACPI_TABLE_INFO
> +  )
> +
> +/** A helper function to invoke a Table generator
> +
> +    This is a helper function that invokes the Table generator interface
> +    for building an ACPI table. It uses the AcpiTableProtocol to install the
> +    table, then frees the resources allocated for generating it.
> +
> +    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> +                                      interface.
> +    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> +                                      Protocol Interface.
> +    @param [in]  AcpiTableProtocol    Pointer to the AcpiTable protocol.
> +    @param [in]  AcpiTableInfo        Pointer to the ACPI table Info.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         Required object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   Size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildAndInstallAcpiTable (
> +  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST TableFactoryProtocol,
> +  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN       EFI_ACPI_TABLE_PROTOCOL             *       AcpiTableProtocol,
> +  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  CONST ACPI_TABLE_GENERATOR  * Generator = NULL;
> +  EFI_ACPI_DESCRIPTION_HEADER * AcpiTable;
> +  UINTN                         TableHandle;
> +
> +  ASSERT (TableFactoryProtocol != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableProtocol != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: EStdObjAcpiTableList: Address = 0x%p," \
> +    " TableGeneratorId = 0x%x\n",
> +    AcpiTableInfo,
> +    AcpiTableInfo->TableGeneratorId
> +    ));
> +
> +  Status = TableFactoryProtocol->GetAcpiTableGenerator (
> +                                   TableFactoryProtocol,
> +                                   AcpiTableInfo->TableGeneratorId,
> +                                   &Generator
> +                                   );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Table Generator not found." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  ASSERT (Generator != NULL);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: Generator found : %s\n",
> +    Generator->Description
> +    ));
> +
> +  if (Generator->BuildAcpiTable == NULL) {
> +    Status = EFI_INVALID_PARAMETER;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Table Generator does not implement the" \
> +      " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  AcpiTable = NULL;
> +  Status = Generator->BuildAcpiTable (
> +                        Generator,
> +                        AcpiTableInfo,
> +                        CfgMgrProtocol,
> +                        &AcpiTable
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Build Table." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    // Free any allocated resources.
> +    goto error_handler;
> +  }
> +
> +  ASSERT (AcpiTable != NULL);
> +
> +  // Dump ACPI Table Header
> +  DUMP_ACPI_TABLE_HEADER (AcpiTable);
> +
> +  // Install ACPI table
> +  Status = AcpiTableProtocol->InstallAcpiTable (
> +                                AcpiTableProtocol,
> +                                AcpiTable,
> +                                AcpiTable->Length,
> +                                &TableHandle
> +                                );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Install ACPI Table. Status = %r\n",
> +      Status
> +      ));
> +    // Free any allocated resources.
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: ACPI Table installed. Status = %r\n",
> +    Status
> +    ));
> +
> +error_handler:
> +  // Free any resources allocated for generating the tables.
> +  if ((AcpiTable != NULL) && (Generator->FreeTableResources != NULL)) {
> +    Status = Generator->FreeTableResources (
> +                          Generator,
> +                          AcpiTableInfo,
> +                          CfgMgrProtocol,
> +                          &AcpiTable
> +                          );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: Failed to Free Table Resources." \
> +        "TableGeneratorId = 0x%x. Status = %r\n",
> +        AcpiTableInfo->TableGeneratorId,
> +        Status
> +        ));
> +    }
> +  }
> +  return Status;
> +}
> +
> +/** The function checks if the Configuration Manager has provided the
> +    mandatory ACPI tables for installation.
> +
> +    @param [in]  AcpiTableInfo      Pointer to the ACPI Table Info list.
> +    @param [in]  AcpiTableCount     Count of ACPI Table Info.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_NOT_FOUND         If mandatory table is not found.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +VerifyMandatoryTablesArePresent (
> +  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO  * CONST AcpiTableInfo,
> +  IN CONST UINTN                               AcpiTableCount
> +  )
> +{
> +  EFI_STATUS  Status = EFI_SUCCESS;
> +  BOOLEAN     FadtFound = FALSE;
> +  BOOLEAN     MadtFound = FALSE;
> +  BOOLEAN     GtdtFound = FALSE;
> +  BOOLEAN     DsdtFound = FALSE;
> +  BOOLEAN     Dbg2Found = FALSE;
> +  BOOLEAN     SpcrFound = FALSE;
> +  UINTN       idx;
> +
> +  ASSERT (AcpiTableInfo != NULL);
> +
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    switch (AcpiTableInfo[idx].AcpiTableSignature) {
> +      case EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
> +        FadtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
> +        MadtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:
> +        GtdtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
> +        DsdtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE:
> +        Dbg2Found = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
> +        SpcrFound = TRUE;
> +        break;
> +      default:
> +        break;
> +    }
> +  }
> +
> +  // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
> +  if (!FadtFound) {
> +    DEBUG ((DEBUG_ERROR,"ERROR: FADT Table not found\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!MadtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!GtdtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!DsdtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!Dbg2Found) {
> +    DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));
> +  }
> +  if (!SpcrFound) {
> +    DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));
> +  }
> +  return Status;
> +}
> +
> +/** Generate and install ACPI tables.
> +
> +    The function gathers the information necessary for installing the
> +    ACPI tables from the Configuration Manager, invokes the generators
> +    and installs them (via BuildAndInstallAcpiTable).
> +
> +    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> +                                      interface.
> +    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> +                                      Protocol Interface.
> +
> +
> +    @retval EFI_SUCCESS   Success.
> +    @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +ProcessAcpiTables (
> +  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST TableFactoryProtocol,
> +  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_ACPI_TABLE_PROTOCOL     * AcpiTableProtocol;
> +  UINTN                         AcpiTableCount;
> +  CM_STD_OBJ_ACPI_TABLE_INFO  * AcpiTableInfo;
> +  UINTN                         idx;
> +
> +  ASSERT (TableFactoryProtocol != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Find the AcpiTable protocol
> +  Status = gBS->LocateProtocol (
> +                  &gEfiAcpiTableProtocolGuid,
> +                  NULL,
> +                  (VOID**)&AcpiTableProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Status = GetEStdObjAcpiTableList (
> +             CfgMgrProtocol,
> +             &AcpiTableInfo,
> +             &AcpiTableCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get ACPI Table List. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  if (0 == AcpiTableCount) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
> +      AcpiTableCount
> +      ));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
> +    AcpiTableCount
> +    ));
> +
> +  // Check if mandatory ACPI tables are present.
> +  Status = VerifyMandatoryTablesArePresent (
> +             AcpiTableInfo,
> +             AcpiTableCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find mandatory ACPI Table(s)."
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  // Add the FADT Table first.
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
> +        AcpiTableInfo[idx].TableGeneratorId) {
> +      Status = BuildAndInstallAcpiTable (
> +                 TableFactoryProtocol,
> +                 CfgMgrProtocol,
> +                 AcpiTableProtocol,
> +                 &AcpiTableInfo[idx]
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "ERROR: Failed to find build and install ACPI FADT Table." \
> +          " Status = %r\n",
> +          Status
> +          ));
> +        return Status;
> +      }
> +      break;
> +    }
> +  } // for
> +
> +  // Add remaining ACPI Tables
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
> +      idx,
> +      AcpiTableInfo[idx].TableGeneratorId
> +      ));
> +
> +    // Skip FADT Table since we have already added
> +    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
> +        AcpiTableInfo[idx].TableGeneratorId) {
> +      continue;
> +    }
> +
> +    // Skip the Reserved table Generator ID
> +    if ((CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RESERVED) >=
> +           AcpiTableInfo[idx].TableGeneratorId)                     ||
> +        (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MAX)      <=
> +           AcpiTableInfo[idx].TableGeneratorId)) {
> +      DEBUG ((
> +        DEBUG_WARN,
> +        "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
> +        AcpiTableInfo[idx].TableGeneratorId
> +        ));
> +      continue;
> +    }
> +
> +    Status = BuildAndInstallAcpiTable (
> +               TableFactoryProtocol,
> +               CfgMgrProtocol,
> +               AcpiTableProtocol,
> +               &AcpiTableInfo[idx]
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: Failed to find, build, and install ACPI Table." \
> +        " Status = %r\n",
> +        Status
> +        ));
> +      return Status;
> +    }
> +  } // for
> +
> +  return Status;
> +}
> +
> +/** Entrypoint of Dynamic Table Manager Dxe.
> +
> +  The Dynamic Table Manager uses the Configuration Manager Protocol
> +  to get the list of ACPI and SMBIOS tables to install. For each table
> +  in the list it requests the corresponding ACPI/SMBIOS table factory for
> +  a generator capable of building the ACPI/SMBIOS table.
> +  If a suitable table generator is found, it invokes the generator interface
> +  to build the table. The Dynamic Table Manager then installs the
> +  table and invokes another generator interface to free any resources
> +  allocated for building the table.
> +
> +    @param  ImageHandle
> +    @param  SystemTable
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +    @retval EFI_NOT_FOUND         Required interface/object was not found.
> +    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
> +
> +*/
> +EFI_STATUS
> +EFIAPI
> +DynamicTableManagerDxeInitialize (
> +  IN CONST EFI_HANDLE                 ImageHandle,
> +  IN       EFI_SYSTEM_TABLE   * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS                               Status;
> +  EFI_CONFIGURATION_MANAGER_PROTOCOL     * CfgMgrProtocol;
> +  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
> +  EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL     * TableFactoryProtocol;
> +
> +  // Locate the Dynamic Table Factory
> +  Status = gBS->LocateProtocol (
> +                  &gEfiDynamicTableFactoryProtocolGuid,
> +                  NULL,
> +                  (VOID**)&TableFactoryProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find Dynamic Table Factory protocol." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  // Locate the Configuration Manager for the Platform
> +  Status = gBS->LocateProtocol (
> +                  &gEfiConfigurationManagerProtocolGuid,
> +                  NULL,
> +                  (VOID**)&CfgMgrProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",
> +    CfgMfrInfo->Revision,
> +    CfgMfrInfo->OemId[0],
> +    CfgMfrInfo->OemId[1],
> +    CfgMfrInfo->OemId[2],
> +    CfgMfrInfo->OemId[3],
> +    CfgMfrInfo->OemId[4],
> +    CfgMfrInfo->OemId[5]
> +    ));
> +
> +  Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI Table processing failure. Status = %r\n",
> +      Status
> +      ));
> +  }
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> new file mode 100644
> index 0000000000000000000000000000000000000000..69012cf8242c8ddd13ac4033293ac8a7053dfbd8
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> @@ -0,0 +1,35 @@
> +## @file
> +#  fdf include file for Dynamic Tables Framework.
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +################################################################################
> +#
> +# FV Section
> +#
> +# [FV] section is used to define what components or modules are placed within a flash
> +# device file.  This section also defines order the components and modules are positioned
> +# within the image.  The [FV] section consists of define statements, set statements and
> +# module statements.
> +#
> +################################################################################
> +
> +  #
> +  # Dynamic Table Factory Dxe
> +  #
> +  INF MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
> +
> +  #
> +  # Dynamic Tables Dxe
> +  #
> +  INF MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> -- 
> Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
  2017-10-03 14:34   ` Zeng, Star
  2017-10-03 16:03     ` Leif Lindholm
@ 2017-10-03 17:03     ` Evan Lloyd
  1 sibling, 0 replies; 14+ messages in thread
From: Evan Lloyd @ 2017-10-03 17:03 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org
  Cc: "Matteo.Carlini@arm.com"@arm.com,
	"nd@arm.com"@arm.com,
	"ard.biesheuvel@linaro.org"@arm.com,
	"thomas.abraham@arm.com"@arm.com,
	"Arvind.Chauhan@arm.com"@arm.com,
	"leif.lindholm@linaro.org"@arm.com,
	"Daniil.Egranov@arm.com"@arm.com, Kinney, Michael D,
	Yao, Jiewen

Hi Star.
This is a mixed patch set:
"[edk2] [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework" is for edk2
"[edk2] [PATCH 2/2] [edk2-platforms] Platform/ARM: Dynamic Tables support for FVP" is for edk2-platforms
I'm not sure that is the best way to handle it, but I've done it that way because earlier patches I submitted were rejected for not having the related platform build changes linked.

Sorry if that has caused confusion.  I am very willing to take instruction on how this might be better handled.
Regards,
Evan


> -----Original Message-----
> From: Zeng, Star [mailto:star.zeng@intel.com]
> Sent: 03 October 2017 15:35
> To: Evan Lloyd <Evan.Lloyd@arm.com>; edk2-devel@lists.01.org
> Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com;
> "ard.biesheuvel@linaro.org"@arm.com;
> "thomas.abraham@arm.com"@arm.com;
> "Arvind.Chauhan@arm.com"@arm.com;
> "leif.lindholm@linaro.org"@arm.com;
> "Daniil.Egranov@arm.com"@arm.com; Kinney, Michael D
> <michael.d.kinney@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Zeng,
> Star <star.zeng@intel.com>
> Subject: RE: [edk2] [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
>
> Hi Evan,
>
> May I ask you are proposing edk2-
> platforms(https://github.com/tianocore/edk2-platforms) change or edk2
> master(https://github.com/tianocore/edk2) change?
>
> Please note, we may have no/occasional email response during PRC holiday
> (10/1 - 10/8).
>
> Thanks,
> Star
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> evan.lloyd@arm.com
> Sent: Tuesday, October 3, 2017 3:48 AM
> To: edk2-devel@lists.01.org
> Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com;
> "ard.biesheuvel@linaro.org"@arm.com;
> "thomas.abraham@arm.com"@arm.com;
> "Arvind.Chauhan@arm.com"@arm.com;
> "leif.lindholm@linaro.org"@arm.com;
> "Daniil.Egranov@arm.com"@arm.com
> Subject: [edk2] [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
>
> From: Sami Mujawar <sami.mujawar@arm.com>
>
> The dynamic tables framework is designed to generate standardised
> firmware tables that describe the hardware information at
> run-time. A goal of standardised firmware is to have a common
> firmware for a platform capable of booting both Windows and Linux
> operating systems.
>
> Traditionally the firmware tables are handcrafted using ACPI
> Machine Language (AML), Table Definition Language (TDL) and
> C-code. This approach can be error prone and involves time
> consuming debugging. In addition, it may be desirable to configure
> platform hardware at runtime such as: configuring the number of
> cores available for use by the OS, or turning SoC features ON or
> OFF.
>
> The dynamic tables framework simplifies this by providing a set
> of standard table generators, that are implemented as libraries.
> These generators query a platform specific component, the
> 'Configuration Manager', to collate the information required
> for generating the tables at run-time.
>
> The framework also provisions the ability to implement custom/OEM
> generators; thereby facilitating support for custom tables. The
> custom generators can also utilize the existing standard generators
> and override any functionality if needed.
>
> The framework currently implements a set of standard ACPI table
> generators for ARM architecture, that can generate Server Base Boot
> Requirement (SBBR) compliant tables. Support for generating SMBIOS
> tables is planned to be added subsequently. Although, the set
> of standard generators implements the functionality required for ARM
> architecture; the framework is extensible, and support for other
> architectures can be easily added.
>
> Contributions from the community are invited.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> Signed-off-by: Evan Lloyd <evan.lloyd@arm.com>
> ---
>  MdeModulePkg/MdeModulePkg.dec                                                                       |
> 13 +
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> |  45 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg
> 2LibArm.inf                       |  49 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadt
> LibArm.inf                       |  47 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdt
> LibArm.inf                       |  46 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMa
> dtLibArm.inf                       |  47 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcf
> gLibArm.inf                       |  47 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRaw
> LibArm.inf                         |  44 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcr
> LibArm.inf                       |  44 ++
>
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelp
> erLib.inf                         |  39 ++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactoryDxe.inf              |  57 ++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyna
> micTableManagerDxe.inf              |  47 ++
>  MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> | 280 ++++++++
>  MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> | 367 ++++++++++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> | 112 +++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> | 158 +++++
>  MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> | 235 +++++++
>  MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> |  93 +++
>  MdeModulePkg/Include/DynamicTables/TableGenerator.h
> | 235 +++++++
>  MdeModulePkg/Include/Library/TableHelperLib.h
> |  67 ++
>  MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> | 121 ++++
>  MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> | 113 +++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactory.h                   |  91 +++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Ge
> nerator.c                          | 440 ++++++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGen
> erator.c                          | 562 +++++++++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGen
> erator.c                          | 652 +++++++++++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGe
> nerator.c                          | 732 ++++++++++++++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGe
> nerator.c                          | 336 +++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGen
> erator.c                            | 177 +++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGen
> erator.c                          | 323 +++++++++
>
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelp
> er.c                              | 165 +++++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTa
> bleFactory/AcpiTableFactory.c     | 227 ++++++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactoryDxe.c                |  84 +++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Smbios
> TableFactory/SmbiosTableFactory.c | 227 ++++++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyna
> micTableManagerDxe.c                | 531 ++++++++++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> |  35 +
>  36 files changed, 6888 insertions(+)
>
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> index
> a3c0633ee1ec6ab7540a1b7221850e975f95ad80..de8a658c21d11ab1396bb54
> 3b026f94a396a0710 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -7,6 +7,7 @@
>  # Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
>  # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
>  # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +# Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
>  #
>  # This program and the accompanying materials are licensed and made
> available under
>  # the terms and conditions of the BSD License that accompanies this
> distribution.
> @@ -556,6 +557,12 @@ [Protocols]
>    ## Include/Protocol/IoMmu.h
>    gEdkiiIoMmuProtocolGuid = { 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed,
> 0xe6, 0xe1, 0xce, 0x51, 0x7c, 0x1e } }
>
> +  # Configuration Manager Protocol GUID
> +  gEfiConfigurationManagerProtocolGuid = { 0xd85a4835, 0x5a82, 0x4894,
> { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } }
> +
> +  # Dynamic Table Factory Protocol GUID
> +  gEfiDynamicTableFactoryProtocolGuid = { 0x91d1e327, 0xfe5a, 0x49b8,
> { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec } }
> +
>  #
>  # [Error.gEfiMdeModulePkgTokenSpaceGuid]
>  #   0x80000001 | Invalid value provided.
> @@ -867,6 +874,12 @@ [PcdsFixedAtBuild]
>    # @ValidList  0x80000006 | 0x03058002
>
> gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|
> UINT32|0x30001040
>
> +  # Maximum number of Custom ACPI Generators
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators|1|UINT
> 16|0xC0000001
> +
> +  # Maximum number of Custom SMBIOS Generators
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators|1|UI
> NT16|0xC0000002
> +
>  [PcdsFixedAtBuild, PcdsPatchableInModule]
>    ## Dynamic type PCD can be registered callback function for Pcd setting
> action.
>    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum
> number of callback function
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..548c77ad971f97c43da8f7b
> a1b69fa6948430c17
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> @@ -0,0 +1,45 @@
> +## @file
> +#  Dsc include file for Dynamic Tables Framework.
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +
> +[BuildOptions]
> +  *_*_*_ASL_FLAGS          = -th -li
> +
> +[LibraryClasses.common]
> +
> +[Components.common]
> +  #
> +  # Dynamic Table Factory Dxe
> +  #
> +
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactoryDxe.inf {
> +    <LibraryClasses>
> +
> TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelp
> erLib/TableHelperLib.inf
> +
> NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/Ac
> piRawLibArm.inf
> +
> NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/Ac
> piFadtLibArm.inf
> +
> NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/A
> cpiMadtLibArm.inf
> +
> NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/Ac
> piGtdtLibArm.inf
> +
> NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/Ac
> piSpcrLibArm.inf
> +
> NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/A
> cpiDbg2LibArm.inf
> +
> NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/Ac
> piMcfgLibArm.inf
> +  }
> +
> +  #
> +  # Dynamic Tables Manager Dxe
> +  #
> +
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyna
> micTableManagerDxe.inf {
> +    <LibraryClasses>
> +
> TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelp
> erLib/TableHelperLib.inf
> +  }
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiD
> bg2LibArm.inf
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiD
> bg2LibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..591b6364ae86c885ca47685
> 99d3eadf6d2842eff
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiD
> bg2LibArm.inf
> @@ -0,0 +1,49 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiDbg2LibArm
> +  FILE_GUID      = A17BA4F0-3DEB-4FE5-BD27-EC008E541B22
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiDbg2LibConstructor
> +  DESTRUCTOR     = AcpiDbg2LibDestructor
> +
> +
> +[Sources]
> +  Dbg2Generator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  SerialPortLib
> +
> +[FixedPcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFa
> dtLibArm.inf
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFa
> dtLibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..ae5239fd2a3e6f00574cf5f3
> bb4a561031e122be
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFa
> dtLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiFadtLibArm
> +  FILE_GUID      = 686FE5FE-B944-485F-8B1C-7D60E0056487
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiFadtLibConstructor
> +  DESTRUCTOR     = AcpiFadtLibDestructor
> +
> +
> +[Sources]
> +  FadtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGt
> dtLibArm.inf
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGt
> dtLibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..be38489c2987a81d68effd9
> c05b731b17cb2819c
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGt
> dtLibArm.inf
> @@ -0,0 +1,46 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiGtdtLibArm
> +  FILE_GUID      = 26490F7A-7FA2-423C-8939-C6206329BC37
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiGtdtLibConstructor
> +  DESTRUCTOR     = AcpiGtdtLibDestructor
> +
> +
> +[Sources]
> +  GtdtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[FixedPcd]
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/Acpi
> MadtLibArm.inf
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/Acpi
> MadtLibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..9807e3fe75bb785c3b40041
> 0248e6434532f2147
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/Acpi
> MadtLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiMadtLibArm
> +  FILE_GUID      = AF76C93B-41B5-454D-83CD-D2A80A1C1E38
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiMadtLibConstructor
> +  DESTRUCTOR     = AcpiMadtLibDestructor
> +
> +
> +[Sources]
> +  MadtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiM
> cfgLibArm.inf
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiM
> cfgLibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..2f879dfee4b93a56a923340
> c4b416c6df9656618
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiM
> cfgLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiMcfgLibArm
> +  FILE_GUID      = 8C9BDCB2-72D4-4F30-A12D-1145C3807FF7
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiMcfgLibConstructor
> +  DESTRUCTOR     = AcpiMcfgLibDestructor
> +
> +
> +[Sources]
> +  McfgGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRa
> wLibArm.inf
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRa
> wLibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..db208bdeb8ffce085367ee8
> 65766a0a1bd90cb28
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRa
> wLibArm.inf
> @@ -0,0 +1,44 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiRawLibArm
> +  FILE_GUID      = 20F31568-D687-49BA-B326-CCD9D38EDE16
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiRawLibConstructor
> +  DESTRUCTOR     = AcpiRawLibDestructor
> +
> +
> +[Sources]
> +  RawGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSp
> crLibArm.inf
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSp
> crLibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..3d47e6ae1f7995f76fe3e930
> 93b0185e48ecae79
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSp
> crLibArm.inf
> @@ -0,0 +1,44 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiSpcrLibArm
> +  FILE_GUID      = 55088136-7B78-4974-B1EE-F630150D0DE7
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiSpcrLibConstructor
> +  DESTRUCTOR     = AcpiSpcrLibDestructor
> +
> +
> +[Sources]
> +  SpcrGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableH
> elperLib.inf
> b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableH
> elperLib.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..38952fba1c8056bf0c58197
> 5ca974abbef1e8096
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableH
> elperLib.inf
> @@ -0,0 +1,39 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = DynamicTableHelperLib
> +  FILE_GUID      = E315C738-3A39-4D0D-A0AF-8EDFA770AB39
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = TableHelperLib
> +
> +
> +[Sources]
> +  TableHelper.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git
> a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactoryDxe.inf
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactoryDxe.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..c58ac3a8d6d655e38cb8460
> a35ce256fc4e5ada6
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactoryDxe.inf
> @@ -0,0 +1,57 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010016
> +  BASE_NAME                      = DynamicTableFactoryDxe
> +  FILE_GUID                      = FE846898-7403-4932-B8AD-A0491F0C2CBA
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DynamicTableFactoryDxeInitialize
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = ARM AARCH64
> +#
> +
> +[Sources]
> +  DynamicTableFactoryDxe.c
> +  AcpiTableFactory/AcpiTableFactory.c
> +  SmbiosTableFactory/SmbiosTableFactory.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  PrintLib
> +  BaseLib
> +  MemoryAllocationLib
> +  TableHelperLib
> +
> +[FixedPcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators
> +
> +[Protocols]
> +  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
> +  gEfiSmbiosProtocolGuid                        # PROTOCOL ALWAYS_CONSUMED
> +  gEfiConfigurationManagerProtocolGuid
> +  gEfiDynamicTableFactoryProtocolGuid
> +
> +[Depex]
> +  TRUE
> diff --git
> a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyn
> amicTableManagerDxe.inf
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dy
> namicTableManagerDxe.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..9c5a5f6207687ca90fa11188
> 340d09c304fc34c0
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dy
> namicTableManagerDxe.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010016
> +  BASE_NAME                      = DynamicTableManagerDxe
> +  FILE_GUID                      = 89122868-BCFD-49E8-88A3-06635CB7B3CF
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DynamicTableManagerDxeInitialize
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = ARM AARCH64
> +#
> +
> +[Sources]
> +  DynamicTableManagerDxe.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  PrintLib
> +  TableHelperLib
> +
> +[Protocols]
> +  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
> +  gEfiConfigurationManagerProtocolGuid
> +  gEfiDynamicTableFactoryProtocolGuid
> +
> +[Depex]
> +  TRUE
> diff --git a/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..3a07cd6e10217958d22a930
> 60a0f9aa48947f264
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> @@ -0,0 +1,280 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef ACPI_TABLE_GENERATOR_H_
> +#define ACPI_TABLE_GENERATOR_H_
> +
> +#pragma pack(1)
> +
> +/**
> +The Dynamic Tables Framework provisions two classes of ACPI table
> +generators.
> + - Standard generators: The ACPI table generators implemented by the
> +                        Dynamic Tables Framework.
> + - OEM generators:      The ACPI table generatos customized by the OEM.
> +
> +The Dynamic Tables Framework implements the following ACPI table
> generators:
> +  - RAW   : This is the simplest ACPI table generator. It simply installs
> +            the ACPI table provided in the AcpiTableData member of the
> +            CM_STD_OBJ_ACPI_TABLE_INFO. The ACPI table data is provided by
> +            the Configuration Manager and is generated using an
> implementation
> +            defined mechanism.
> +  - DSDT  : The DSDT generator is clone of the RAW generator. The
> difference
> +            is in the way the ACPI Table Data is generated from an AML file.
> +  - SSDT  : The SSDT generator is clone of the RAW generator. The difference
> +            is in the way the ACPI Table Data is generated from an AML file.
> +  - FADT  : The FADT generator collates the required platform information
> for
> +            building the ACPI FADT table from the Configuration Manager and
> +            generates the FADT table.
> +  - MADT  : The MADT generator collates the GIC information for building
> the
> +            ACPI MADT table from the Configuration Manager and generates the
> +            MADT table.
> +  - GTDT  : The GTDT generator collates the Timer information for building
> the
> +            ACPI GTDT table from the Configuration Manager and generates the
> +            GTDT table.
> +  - DBG2  : The DBG2 generator collates the debug serial port information for
> +            building the DBG2 table from the Configuration Manager and
> +            generates the GTDT table.
> +  - SPCR  : The SPCR generator collates the serial port information for
> +            building the SPCR table from the Configuration Manager and
> +            generates the SPCR table.
> +  - MCFG  : The MCFG generator collates the PCI configuration space
> information
> +            for building the MCFG table from the Configuration Manager and
> +            generates the MCFG table.
> +*/
> +
> +/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
> +*/
> +typedef TABLE_GENERATOR_ID ACPI_TABLE_GENERATOR_ID;
> +
> +/** The ESTD_ACPI_TABLE_ID enum describes the ACPI table IDs reserved
> for
> +  the standard generators.
> +*/
> +typedef enum StdAcpiTableId {
> +  ESTD_ACPI_TABLE_ID_RESERVED = 0x0000,             ///< Reserved.
> +  ESTD_ACPI_TABLE_ID_RAW,                           ///< RAW Generator.
> +  ESTD_ACPI_TABLE_ID_DSDT = ESTD_ACPI_TABLE_ID_RAW, ///< DSDT
> Generator.
> +  ESTD_ACPI_TABLE_ID_SSDT = ESTD_ACPI_TABLE_ID_RAW, ///< SSDT
> Generator.
> +  ESTD_ACPI_TABLE_ID_FADT,                          ///< FADT Generator.
> +  ESTD_ACPI_TABLE_ID_MADT,                          ///< MADT Generator.
> +  ESTD_ACPI_TABLE_ID_GTDT,                          ///< GTDT Generator.
> +  ESTD_ACPI_TABLE_ID_DBG2,                          ///< DBG2 Generator.
> +  ESTD_ACPI_TABLE_ID_SPCR,                          ///< SPCR Generator.
> +  ESTD_ACPI_TABLE_ID_MCFG,                          ///< MCFG Generator.
> +  ESTD_ACPI_TABLE_ID_MAX
> +} ESTD_ACPI_TABLE_ID;
> +
> +/** This macro checks if the Table Generator ID is for an ACPI Table
> Generator.
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the table generator ID is for an ACPI Table
> +          Generator.
> +*/
> +#define IS_GENERATOR_TYPE_ACPI(TableGeneratorId) \
> +          (GET_TABLE_TYPE (TableGeneratorId) == ETableGeneratorTypeAcpi)
> +
> +/** This macro checks if the Table Generator ID is for a standard ACPI
> +    Table Generator.
> +
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the table generator ID is for a standard ACPI
> +            Table Generator.
> +*/
> +#define IS_VALID_STD_ACPI_GENERATOR_ID(TableGeneratorId)               \
> +          (                                                            \
> +          IS_GENERATOR_NAMESPACE_STD (TableGeneratorId) &&             \
> +          IS_GENERATOR_TYPE_ACPI (TableGeneratorId)     &&             \
> +          ((GET_TABLE_ID (GeneratorId) >= ESTD_ACPI_TABLE_ID_RAW) &&   \
> +           (GET_TABLE_ID (GeneratorId) < ESTD_ACPI_TABLE_ID_MAX))      \
> +          )
> +
> +/** This macro creates a standard ACPI Table Generator ID.
> +
> +    @param [in] TableId  The table generator ID.
> +
> +    @returns a standard ACPI table generator ID.
> +*/
> +#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId) \
> +          CREATE_TABLE_GEN_ID (               \
> +            ETableGeneratorTypeAcpi,          \
> +            ETableGeneratorNameSpaceStd,      \
> +            TableId                           \
> +            )
> +
> +/** The Creator ID for the ACPI tables generated using
> +  the standard ACPI table generators.
> +*/
> +#define TABLE_GENERATOR_CREATOR_ID_ARM  SIGNATURE_32('A', 'R', 'M',
> 'H')
> +
> +/** A macro to initialise the common header part of EFI ACPI tables as
> +    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
> +
> +    @param [in] Signature The ACPI table signature.
> +    @param [in] Type      The ACPI table structure.
> +    @param [in] Revision  The ACPI table revision.
> +*/
> +#define ACPI_HEADER(Signature, Type, Revision) {              \
> +          Signature,             /* UINT32  Signature */      \
> +          sizeof (Type),         /* UINT32  Length */         \
> +          Revision,              /* UINT8   Revision */       \
> +          0,                     /* UINT8   Checksum */       \
> +          { 0, 0, 0, 0, 0, 0 },  /* UINT8   OemId[6] */       \
> +          0,                     /* UINT64  OemTableId */     \
> +          0,                     /* UINT32  OemRevision */    \
> +          0,                     /* UINT32  CreatorId */      \
> +          0                      /* UINT32  CreatorRevision */\
> +          }
> +
> +/** A macro to dump the common header part of EFI ACPI tables as
> +    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
> +
> +    @param [in] AcpiHeader The pointer to the ACPI table header.
> +*/
> +#define DUMP_ACPI_TABLE_HEADER(AcpiHeader)                        \
> +          DEBUG ((                                                \
> +            DEBUG_INFO,                                           \
> +            "ACPI TABLE %c%c%c%c : Rev 0x%x : Length : 0x%x\n",   \
> +            (AcpiHeader->Signature & 0xFF),                       \
> +            ((AcpiHeader->Signature >> 8) & 0xFF),                \
> +            ((AcpiHeader->Signature >> 16) & 0xFF),               \
> +            ((AcpiHeader->Signature >> 24) & 0xFF),               \
> +            AcpiHeader->Revision,                                 \
> +            AcpiHeader->Length                                    \
> +            ));
> +
> +/** Forward declarations.
> +*/
> +typedef struct ConfigurationManagerProtocol
> EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct CmAStdObjAcpiTableInfo
> CM_STD_OBJ_ACPI_TABLE_INFO;
> +typedef struct AcpiTableGenerator           ACPI_TABLE_GENERATOR;
> +
> +/** This function pointer describes the interface to ACPI table build
> +    functions provided by the ACPI table generator and called by the
> +    Table Manager to build an ACPI table.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [out] Table           Pointer to the generated ACPI table.
> +
> +    @returns  EFI_SUCCESS If the table is generated successfully or other
> +                          failure codes as returned by the generator.
> +*/
> +typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_BUILD_TABLE) (
> +  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        **       Table
> +  );
> +
> +/** This function pointer describes the interface to used by the
> +    Table Manager to give the generator an opportunity to free
> +    any resources allocated for building the ACPI table.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [in]  Table           Pointer to the generated ACPI table.
> +
> +    @returns EFI_SUCCESS  If freed successfully or other failure codes
> +                          as returned by the generator.
> +*/
> +typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_FREE_TABLE) (
> +  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        **       Table
> +  );
> +
> +/** The ACPI_TABLE_GENERATOR structure provides an interface that the
> +    Table Manager can use to invoke the functions to build ACPI tables.
> +
> +*/
> +typedef struct AcpiTableGenerator {
> +  /// The ACPI table generator ID.
> +  ACPI_TABLE_GENERATOR_ID                GeneratorID;
> +
> +  /// String describing the ACPI table
> +  /// generator.
> +  CONST CHAR16                         * Description;
> +
> +  /// The ACPI table signature.
> +  UINT32                                 AcpiTableSignature;
> +
> +  /// The ACPI table revision.
> +  UINT32                                 AcpiTableRevision;
> +
> +  /// The ACPI table creator ID.
> +  UINT32                                 CreatorId;
> +
> +  /// The ACPI table creator revision.
> +  UINT32                                 CreatorRevision;
> +
> +  /// ACPI table build function pointer.
> +  ACPI_TABLE_GENERATOR_BUILD_TABLE       BuildAcpiTable;
> +
> +  /// The function to free any resources
> +  /// allocated for building the ACPI table.
> +  ACPI_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
> +} ACPI_TABLE_GENERATOR;
> +
> +/** Register ACPI table factory generator.
> +
> +    The ACPI table factory maintains a list of the Standard and OEM ACPI
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterAcpiTableGenerator (
> +  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +/** Unregister ACPI generator.
> +
> +    This function is called by the ACPI table generator to unregister itself
> +    from the ACPI table factory.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterAcpiTableGenerator (
> +  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +#pragma pack()
> +
> +#endif // ACPI_TABLE_GENERATOR_H_
> +
> diff --git a/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..dbc909894d17ba9df7a78c2
> d8be797adabb49a34
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> @@ -0,0 +1,367 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef ARM_NAMESPACE_OBJECTS_H_
> +#define ARM_NAMESPACE_OBJECTS_H_
> +#pragma pack(1)
> +
> +/** The EARM_OBJECT_ID enum describes the Object IDs
> +    in the ARM Namespace
> +*/
> +typedef enum ArmObjectID {
> +  EArmObjReserved,                    ///<  0 - Reserved.
> +  EArmObjBootArchInfo,                ///<  1 - Boot Architecture Info
> +  EArmObjCpuInfo,                     ///<  2 - CPU Info
> +  EArmObjPowerManagementProfileInfo,  ///<  3 - Power Management
> Profile Info
> +  EArmObjGicCInfo,                    ///<  4 - GIC CPU Interface Info
> +  EArmObjGicDInfo,                    ///<  5 - GIC Distributor Info
> +  EArmObjGicMsiFrameInfo,             ///<  6 - GIC MSI Frame Info
> +  EArmObjGicRedistributorInfo,        ///<  7 - GIC Redistributor Info
> +  EArmObjGicItsInfo,                  ///<  8 - GIC ITS Info
> +  EArmObjSerialConsolePortInfo,       ///<  9 - Serial Console Port Info
> +  EArmObjSerialDebugPortInfo,         ///< 10 - Serial Debug Port Info
> +  EArmObjGenericTimerInfo,            ///< 11 - Generic Timer Info
> +  EArmObjPlatformGTBlockInfo,         ///< 12 - Platform GT Block Info
> +  EArmObjPlatformGenericWatchdogInfo, ///< 13 - Platform Generic
> Watchdog
> +  EArmObjPciConfigSpaceInfo,          ///< 14 - PCI Configuration Space Info
> +  EArmObjHypervisorVendorIdentity,    ///< 15 - Hypervisor Vendor Id
> +  EArmObjMax
> +} EARM_OBJECT_ID;
> +
> +/** A structure that describes the
> +    ARM Boot Architecture flags.
> +*/
> +typedef struct CmArmBootArchInfo {
> +  /// This is the ARM_BOOT_ARCH flags field of the FADT Table
> +  /// described in the ACPI Table Specification.
> +  UINT32  BootArchFlags;
> +} CM_ARM_BOOT_ARCH_INFO;
> +
> +typedef struct CmArmCpuInfo {
> +  // Reserved for use when SMBIOS tables are implemented.
> +} CM_ARM_CPU_INFO;
> +
> +typedef struct CmArmCpuInfoList {
> +  UINT32             CpuCount;
> +  CM_ARM_CPU_INFO  * CpuInfo;
> +} CM_ARM_CPU_INFO_LIST;
> +
> +/** A structure that describes the
> +    Power Management Profile Information for the Platform.
> +*/
> +typedef struct CmArmPowerManagementProfileInfo {
> +  /// This is the Preferred_PM_Profile field of the FADT Table
> +  /// described in the ACPI Specification
> +  UINT8  PowerManagementProfile;
> +} CM_ARM_POWER_MANAGEMENT_PROFILE_INFO;
> +
> +/** A structure that describes the
> +    GIC CPU Interface for the Platform.
> +*/
> +typedef struct CmArmGicCInfo {
> +  /// The GIC CPU Interface number.
> +  UINT32  CPUInterfaceNumber;
> +
> +  /// The ACPI Processor UID. This must match the
> +  /// _UID of the CPU Device object information described
> +  /// in the DSDT/SSDT for the CPU.
> +  UINT32  AcpiProcessorUid;
> +
> +  /// The flags field as described by the GICC structure
> +  /// in the ACPI Specification.
> +  UINT32  Flags;
> +
> +  /// The parking protocol version field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT32  ParkingProtocolVersion;
> +
> +  /// The Performance Interrupt field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT32  PerformanceInterruptGsiv;
> +
> +  /// The CPU Parked address field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT64  ParkedAddress;
> +
> +  /// The base address for the GIC CPU Interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The base address for GICV interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICV;
> +
> +  /// The base address for GICH interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICH;
> +
> +  /// The GICV maintainence interrupt
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT32  VGICMaintenanceInterrupt;
> +
> +  /// The base address for GICR interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICRBaseAddress;
> +
> +  /// The MPIDR for the CPU
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  MPIDR;
> +
> +  /// The Processor Power Efficiency class
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT8   ProcessorPowerEfficiencyClass;
> +} CM_ARM_GICC_INFO;
> +
> +/** A structure that describes the
> +    GIC Distributor information for the Platform.
> +*/
> +typedef struct CmArmGicDInfo {
> +  /// The GIC Distributor ID.
> +  UINT32  GicId;
> +
> +  /// The Physical Base address
> +  /// for the GIC Distributor.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The global system interrupt
> +  /// number where this GIC Distributor's
> +  /// interrupt inputs start.
> +  UINT32  SystemVectorBase;
> +
> +  /// The GIC version as described
> +  /// by the GICD structure in the
> +  /// ACPI Specification.
> +  UINT8   GicVersion;
> +} CM_ARM_GICD_INFO;
> +
> +/** A structure that describes the
> +    GIC MSI Frame information for the Platform.
> +*/
> +typedef struct CmArmGicMsiFrameInfo {
> +  /// The GIC MSI Frame ID
> +  UINT32  GicMsiFrameId;
> +
> +  /// The Physical base address for the
> +  /// MSI Frame.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The GIC MSI Frame flags
> +  /// as described by the GIC MSI frame
> +  /// structure in the ACPI Specification.
> +  UINT32  Flags;
> +
> +  /// SPI Count used by this frame.
> +  UINT16  SPICount;
> +
> +  /// SPI Base used by this frame.
> +  UINT16  SPIBase;
> +} CM_ARM_GIC_MSI_FRAME_INFO;
> +
> +/** A structure that describes the
> +    GIC Redistributor information for the Platform.
> +*/
> +typedef struct CmArmGicRedistInfo {
> +  /// The physical address of a page range
> +  /// containing all GIC Redistributors.
> +  UINT64  DiscoveryRangeBaseAddress;
> +
> +  /// Length of the GIC Redistributor
> +  /// Discovery page range
> +  UINT32  DiscoveryRangeLength;
> +} CM_ARM_GIC_REDIST_INFO;
> +
> +/** A structure that describes the
> +    GIC Interrupt Translation Service information for the Platform.
> +*/
> +typedef struct CmArmGicItsInfo {
> +  /// The GIC ITS ID.
> +  UINT32  GicItsId;
> +
> +  /// The physical address for the
> +  /// Interrupt Translation Service
> +  UINT64  PhysicalBaseAddress;
> +} CM_ARM_GIC_ITS_INFO;
> +
> +/** A structure that describes the
> +    Serial Port information for the Platform.
> +*/
> +typedef struct CmArmSerialPortInfo {
> +  /// The physical base address for the
> +  /// serial port.
> +  UINT64  BaseAddress;
> +
> +  /// The serial port interrupt.
> +  UINT32  Interrupt;
> +
> +  /// The serial port baud rate.
> +  UINT64  BaudRate;
> +
> +  /// The serial port clock.
> +  UINT32  Clock;
> +} CM_ARM_SERIAL_PORT_INFO;
> +
> +/** A structure that describes the
> +    Generic Timer information for the Platform.
> +*/
> +typedef struct CmArmGenericTimerInfo {
> +  /// The physical base address for the
> +  /// counter control frame.
> +  UINT64  CounterControlBaseAddress;
> +
> +  /// The physical base address for the
> +  /// counter read frame.
> +  UINT64  CounterReadBaseAddress;
> +
> +  /// The secure PL1 timer interrupt.
> +  UINT32  SecurePL1TimerGSIV;
> +
> +  /// The secure PL1 timer flags.
> +  UINT32  SecurePL1TimerFlags;
> +
> +  /// The non-secure PL1 timer interrupt.
> +  UINT32  NonSecurePL1TimerGSIV;
> +
> +  /// The non-secure PL1 timer flags.
> +  UINT32  NonSecurePL1TimerFlags;
> +
> +  /// The virtual timer interrupt.
> +  UINT32  VirtualTimerGSIV;
> +
> +  /// The virtual timer flags.
> +  UINT32  VirtualTimerFlags;
> +
> +  /// The non-secure PL2 timer interrupt.
> +  UINT32  NonSecurePL2TimerGSIV;
> +
> +  /// The non-secure PL2 timer flags.
> +  UINT32  NonSecurePL2TimerFlags;
> +} CM_ARM_GENERIC_TIMER_INFO;
> +
> +/** A structure that describes the
> +    Platform Generic Block Timer Frame information for the Platform.
> +*/
> +typedef struct CmArmGTBlockTimerFrameInfo {
> +  /// The Generic Timer frame number.
> +  UINT8   FrameNumber;
> +
> +  /// The physical base address
> +  /// for the CntBase block.
> +  UINT64  PhysicalAddressCntBase;
> +
> +  /// The physical base address
> +  /// for the CntEL0Base block.
> +  UINT64  PhysicalAddressCntEL0Base;
> +
> +  /// The physical timer interrupt.
> +  UINT32  PhysicalTimerGSIV;
> +
> +  /// The physical timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  PhysicalTimerFlags;
> +
> +  /// The virtual timer interrupt.
> +  UINT32  VirtualTimerGSIV;
> +
> +  /// The virtual timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  VirtualTimerFlags;
> +
> +  /// The common timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  CommonFlags;
> +} CM_ARM_GTBLOCK_TIMER_FRAME_INFO;
> +
> +/** A structure that describes the
> +    Platform Generic Block Timer information for the Platform.
> +*/
> +typedef struct CmArmGTBlockInfo {
> +  /// The physical base address for
> +  /// the GT Block Timer structure.
> +  UINT64                             GTBlockPhysicalAddress;
> +
> +  /// The number of timer frames
> +  /// implemented in the GT Block.
> +  UINT32                             GTBlockTimerFrameCount;
> +
> +  /// Pointer to the GT Block timer
> +  /// frame list.
> +  CM_ARM_GTBLOCK_TIMER_FRAME_INFO  * GTBlockTimerFrameList;
> +} CM_ARM_GTBLOCK_INFO;
> +
> +/** A structure that describes the
> +    SBSA Generic Watchdog information for the Platform.
> +*/
> +typedef struct CmArmGenericWatchdogInfo {
> +  /// The physical base address of the
> +  /// SBSA Watchdog control frame.
> +  UINT64  ControlFrameAddress;
> +
> +  /// The physical base address of the
> +  /// SBSA Watchdog refresh frame.
> +  UINT64  RefreshFrameAddress;
> +
> +  /// The watchdog interrupt.
> +  UINT32  TimerGSIV;
> +
> +  /// The flags for the watchdog
> +  /// as described by the SBSA watchdog
> +  /// structure in the ACPI specification.
> +  UINT32  Flags;
> +} CM_ARM_GENERIC_WATCHDOG_INFO;
> +
> +/** A structure that describes the
> +    PCI Configuration Space information for the Platform.
> +*/
> +typedef struct CmArmPciConfigSpaceInfo {
> +  /// The physical base address for the PCI segment.
> +  UINT64  BaseAddress;
> +
> +  /// The PCI segment group number.
> +  UINT16  PciSegmentGroupNumber;
> +
> +  /// The start bus number.
> +  UINT8   StartBusNumber;
> +
> +  /// The end bus number.
> +  UINT8   EndBusNumber;
> +} CM_ARM_PCI_CONFIG_SPACE_INFO;
> +
> +/** A structure that describes the
> +    Hypervisor Vendor ID information for the Platform.
> +*/
> +typedef struct CmArmHypervisorVendorId {
> +  /// The hypervisor Vendor ID.
> +  UINT64  HypervisorVendorId;
> +} CM_ARM_HYPERVISOR_VENDOR_ID;
> +
> +#pragma pack()
> +
> +#endif // ARM_NAMESPACE_OBJECTS_H_
> diff --git
> a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..23edd7c343bd09476692d2f
> b8af088d95b8ff28d
> --- /dev/null
> +++
> b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> @@ -0,0 +1,112 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_HELPER_H_
> +#define CONFIGURATION_MANAGER_HELPER_H_
> +
> +/** The GET_OBJECT_LIST macro expands to a function that is used to
> retrieve
> +    an object or an object list from the Configuration Manager using the
> +    Configuration Manager Protocol interface.
> +
> +    The macro expands to a function which has the following prototype:
> +
> +    STATIC
> +    EFI_STATUS
> +    EFIAPI
> +    Get<CmObjectId> (
> +      IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> +      OUT       Type                              **       List,
> +      OUT       UINTN                              *       Count OPTIONAL
> +      );
> +
> +    Generated function parameters:
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> protocol
> +                                  interface.
> +    @param [out] List           Pointer to the Object list.
> +    @param [out] Count          Count of the objects returned in the list.
> +
> +    Macro Parameters:
> +    @param [in] CmObjectNameSpace The Object Namespace
> +    @param [in] CmObjectId        Object Id.
> +    @param [in] Type              Structure used to describe the Object.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not
> found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)
> \
> +STATIC                                                                            \
> +EFI_STATUS                                                                        \
> +EFIAPI                                                                            \
> +Get##CmObjectId (                                                                 \
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,           \
> +  OUT       Type                               **       List,                     \
> +  OUT       UINTN                               * CONST Count OPTIONAL            \
> +  )                                                                               \
> +{                                                                                 \
> +  EFI_STATUS         Status;                                                      \
> +  CM_OBJ_DESCRIPTOR  CmObjectDesc;                                                \
> +  UINTN              ObjCount = 0;                                                \
> +  if (List == NULL) {                                                             \
> +    Status = EFI_INVALID_PARAMETER;                                               \
> +    DEBUG ((                                                                      \
> +      DEBUG_ERROR,                                                                \
> +      "ERROR: Get" #CmObjectId ": Invalid out parameter for"                      \
> +      " object list. Status = %r\n",                                              \
> +      Status                                                                      \
> +      ));                                                                         \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  Status = CfgMgrProtocol->GetObject (                                            \
> +                             CfgMgrProtocol,                                      \
> +                             CREATE_CM_OBJECT_ID (CmObjectNameSpace,
> CmObjectId), \
> +                             &CmObjectDesc                                        \
> +                             );                                                   \
> +  if (EFI_ERROR (Status)) {                                                       \
> +    DEBUG ((                                                                      \
> +      DEBUG_WARN,                                                                 \
> +      "WARNING: Get" #CmObjectId ": Platform does not implement "
> \
> +      #CmObjectId ". Status = %r\n",                                              \
> +      Status                                                                      \
> +      ));                                                                         \
> +    *List = NULL;                                                                 \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  if (CmObjectDesc.Size < sizeof (Type)) {                                        \
> +    DEBUG ((                                                                      \
> +      DEBUG_ERROR,                                                                \
> +      "ERROR: Get" #CmObjectId ": " #CmObjectId                                   \
> +      ": Buffer too small, size = 0x%x\n",                                        \
> +      CmObjectDesc.Size                                                           \
> +      ));                                                                         \
> +    ASSERT (CmObjectDesc.Size >= sizeof (Type));                                  \
> +    Status = EFI_BAD_BUFFER_SIZE;                                                 \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  ObjCount = CmObjectDesc.Size / sizeof (Type);                                   \
> +  *List = (Type*)CmObjectDesc.Data;                                               \
> +error_handler:                                                                    \
> +  if (Count != NULL) {                                                            \
> +    *Count = ObjCount;                                                            \
> +  }                                                                               \
> +  return Status;                                                                  \
> +}
> +
> +#endif // CONFIGURATION_MANAGER_HELPER_H_
> diff --git
> a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..99afab094328cf830831899
> 011a7f6fca1d6e5f2
> --- /dev/null
> +++
> b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> @@ -0,0 +1,158 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_OBJECT_H_
> +#define CONFIGURATION_MANAGER_OBJECT_H_
> +
> +#pragma pack(1)
> +
> +/** The CM_OBJECT_ID type is used to identify the Configration Manager
> objects.
> +
> + Description of Configuration Manager Object ID
> +_______________________________________________________________
> _________________
> +|31 |30 |29 |28 || 27 | 26 | 25 | 24 || 23 | 22 | 21 | 20 || 19 | 18 | 17 | 16 |
> +--------------------------------------------------------------------------------
> +| Name Space ID ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 |
> +_______________________________________________________________
> _________________
> +
> +Bits: [31:28] - Name Space ID
> +                0000 - Standard
> +                0001 - ARM
> +                1000 - Custom/OEM
> +                All other values are reserved.
> +
> +Bits: [27:16] - Reserved.
> +_______________________________________________________________
> _________________
> +|15 |14 |13 |12 || 11 | 10 |  9 |  8 ||  7 |  6 |  5 |  4 ||  3 |  2 |  1 |  0 |
> +--------------------------------------------------------------------------------
> +| 0 | 0 | 0 | 0 ||  0 |  0 |  0 |  0 ||                 Object ID              |
> +_______________________________________________________________
> _________________
> +
> +Bits: [15:8] - Are reserved and must be zero.
> +
> +Bits: [7:0] - Object ID
> +
> +Object ID's in the Standard Namespace:
> +  0 - Configuration Manager Revision
> +  1 - ACPI Table List
> +  2 - SMBIOS Table List
> +
> +Object ID's in the ARM Namespace:
> +   0 - Reserved
> +   1 - Boot Architecture Info
> +   2 - CPU Info
> +   3 - Power Management Profile Info
> +   4 - GICC Info
> +   5 - GICD Info
> +   6 - GIC MSI Frame Info
> +   7 - GIC Redistributor Info
> +   8 - GIC ITS Info
> +   9 - Serial Console Port Info
> +  10 - Serial Debug Port Info
> +  12 - Generic Timer Info
> +  13 - Platform GT Block Info
> +  14 - Platform Generic Watchdog
> +  15 - PCI Configuration Space Info
> +  16 - Hypervisor Vendor Id
> +*/
> +typedef UINT32  CM_OBJECT_ID;
> +
> +/** The EOBJECT_NAMESPACE_ID enum describes the defined namespaces
> +    for the Confguration Manager Objects.
> +*/
> +typedef enum ObjectNameSpaceID {
> +  EObjNameSpaceStandard,      ///< Standard Objects Namespace
> +  EObjNameSpaceArm,           ///< ARM Objects Namespace
> +  EObjNameSpaceOem = 0x8,     ///< OEM Objects Namespace
> +  EObjNameSpaceMax
> +} EOBJECT_NAMESPACE_ID;
> +
> +/** The CM_OBJ_DESCRIPTOR structure describes the Configuration
> +    Manager Object descriptor. The Configuration Manager Protocol
> +    interface uses this descriptor to return the Configuration
> +    Manager Objects.
> +*/
> +typedef struct CmObjDescriptor {
> +  /// Size of the Object or Object List
> +  /// described by this descriptor.
> +  UINT32   Size;
> +
> +  /// Pointer to the Object or Object List
> +  /// described by this descriptor.
> +  UINTN  * Data;
> +} CM_OBJ_DESCRIPTOR;
> +
> +#pragma pack()
> +
> +/** This macro returns the namespace ID from the CmObjectID.
> +
> +  @param [in] CmObjectId  The Configuration Manager Object ID.
> +
> +  @retval Returns the Namespace ID corresponding to the CmObjectID.
> +*/
> +#define GET_CM_NAMESPACE_ID(CmObjectId) (((CmObjectId) >> 28) & 0xF)
> +
> +/** This macro returns the Object ID from the CmObjectID.
> +
> +  @param [in] CmObjectId  The Configuration Manager Object ID.
> +
> +  @retval Returns the Object ID corresponding to the CmObjectID.
> +*/
> +#define GET_CM_OBJECT_ID(CmObjectId)    ((CmObjectId) & 0xFF)
> +
> +/** This macro returns a Configuration Manager Object ID
> +    from the NameSpace ID and the ObjectID.
> +
> +  @param [in] NameSpaceId The namespace ID for the Object.
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns the Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_OBJECT_ID(NameSpaceId, ObjectId) \
> +          ((((NameSpaceId) & 0xF) << 28) | ((ObjectId) & 0xF))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the Standard Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns a Standard Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_STD_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceStandard, ObjectId))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the ARM Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns an ARM Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_ARM_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceArm, ObjectId))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the OEM Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns an OEM Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_OEM_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceOem, ObjectId))
> +
> +#endif // CONFIGURATION_MANAGER_OBJECT_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..10d29be800a0c126ed32dcf
> a070f1473a8aee7a9
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> @@ -0,0 +1,235 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef SMBIOS_TABLE_GENERATOR_H_
> +#define SMBIOS_TABLE_GENERATOR_H_
> +
> +#pragma pack(1)
> +
> +/** The SMBIOS_TABLE_GENERATOR_ID type describes SMBIOS table
> generator ID.
> +*/
> +typedef TABLE_GENERATOR_ID SMBIOS_TABLE_GENERATOR_ID;
> +
> +/** The ESTD_SMBIOS_TABLE_ID enum describes the SMBIOS table IDs
> reserved for
> +  the standard generators.
> +
> +  NOTE: The SMBIOS Generator IDs do not match the table type numbers!
> +          This allows 0 to be used to catch invalid parameters.
> +*/
> +typedef enum StdSmbiosTableGeneratorId {
> +  ESTD_SMBIOS_TABLE_ID_RESERVED = 0x0000,
> +  ESTD_SMBIOS_TABLE_ID_RAW,
> +  ESTD_SMBIOS_TABLE_ID_TYPE00,
> +  ESTD_SMBIOS_TABLE_ID_TYPE01,
> +  ESTD_SMBIOS_TABLE_ID_TYPE02,
> +  ESTD_SMBIOS_TABLE_ID_TYPE03,
> +  ESTD_SMBIOS_TABLE_ID_TYPE04,
> +  ESTD_SMBIOS_TABLE_ID_TYPE05,
> +  ESTD_SMBIOS_TABLE_ID_TYPE06,
> +  ESTD_SMBIOS_TABLE_ID_TYPE07,
> +  ESTD_SMBIOS_TABLE_ID_TYPE08,
> +  ESTD_SMBIOS_TABLE_ID_TYPE09,
> +  ESTD_SMBIOS_TABLE_ID_TYPE10,
> +  ESTD_SMBIOS_TABLE_ID_TYPE11,
> +  ESTD_SMBIOS_TABLE_ID_TYPE12,
> +  ESTD_SMBIOS_TABLE_ID_TYPE13,
> +  ESTD_SMBIOS_TABLE_ID_TYPE14,
> +  ESTD_SMBIOS_TABLE_ID_TYPE15,
> +  ESTD_SMBIOS_TABLE_ID_TYPE16,
> +  ESTD_SMBIOS_TABLE_ID_TYPE17,
> +  ESTD_SMBIOS_TABLE_ID_TYPE18,
> +  ESTD_SMBIOS_TABLE_ID_TYPE19,
> +  ESTD_SMBIOS_TABLE_ID_TYPE20,
> +  ESTD_SMBIOS_TABLE_ID_TYPE21,
> +  ESTD_SMBIOS_TABLE_ID_TYPE22,
> +  ESTD_SMBIOS_TABLE_ID_TYPE23,
> +  ESTD_SMBIOS_TABLE_ID_TYPE24,
> +  ESTD_SMBIOS_TABLE_ID_TYPE25,
> +  ESTD_SMBIOS_TABLE_ID_TYPE26,
> +  ESTD_SMBIOS_TABLE_ID_TYPE27,
> +  ESTD_SMBIOS_TABLE_ID_TYPE28,
> +  ESTD_SMBIOS_TABLE_ID_TYPE29,
> +  ESTD_SMBIOS_TABLE_ID_TYPE30,
> +  ESTD_SMBIOS_TABLE_ID_TYPE31,
> +  ESTD_SMBIOS_TABLE_ID_TYPE32,
> +  ESTD_SMBIOS_TABLE_ID_TYPE33,
> +  ESTD_SMBIOS_TABLE_ID_TYPE34,
> +  ESTD_SMBIOS_TABLE_ID_TYPE35,
> +  ESTD_SMBIOS_TABLE_ID_TYPE36,
> +  ESTD_SMBIOS_TABLE_ID_TYPE37,
> +  ESTD_SMBIOS_TABLE_ID_TYPE38,
> +  ESTD_SMBIOS_TABLE_ID_TYPE39,
> +  ESTD_SMBIOS_TABLE_ID_TYPE40,
> +  ESTD_SMBIOS_TABLE_ID_TYPE41,
> +  ESTD_SMBIOS_TABLE_ID_TYPE42,
> +
> +  // IDs 43 - 125 are reserved
> +
> +  ESTD_SMBIOS_TABLE_ID_TYPE126 = (ESTD_SMBIOS_TABLE_ID_TYPE00 +
> 126),
> +  ESTD_SMBIOS_TABLE_ID_TYPE127,
> +  ESTD_SMBIOS_TABLE_ID_MAX
> +} ESTD_SMBIOS_TABLE_ID;
> +
> +/** This macro checks if the Table Generator ID is for an SMBIOS Table
> +    Generator.
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns  TRUE if the table generator ID is for an SMBIOS Table
> +              Generator.
> +*/
> +#define IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId) \
> +          (                                        \
> +          GET_TABLE_TYPE (TableGeneratorId) ==     \
> +          ETableGeneratorTypeSmbios                \
> +          )
> +
> +/** This macro checks if the Table Generator ID is for a standard SMBIOS
> +    Table Generator.
> +
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns  TRUE if the table generator ID is for a standard SMBIOS
> +              Table Generator.
> +*/
> +#define IS_VALID_STD_SMBIOS_GENERATOR_ID(TableGeneratorId)            \
> +          (                                                           \
> +          IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) &&             \
> +          IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId)   &&             \
> +          ((GET_TABLE_ID(GeneratorId) >= ESTD_SMBIOS_TABLE_ID_RAW) &&
> \
> +           (GET_TABLE_ID(GeneratorId) < ESTD_SMIOS_TABLE_ID_MAX))     \
> +          )
> +
> +/** This macro creates a standard SMBIOS Table Generator ID.
> +
> +    @param [in] TableId  The table generator ID.
> +
> +    @returns a standard SMBIOS table generator ID.
> +*/
> +#define CREATE_STD_SMBIOS_TABLE_GEN_ID(TableId) \
> +          CREATE_TABLE_GEN_ID (                 \
> +            ETableGeneratorTypeSmbios,          \
> +            ETableGeneratorNameSpaceStd,        \
> +            TableId                             \
> +            )
> +
> +/** Forward declarations.
> +*/
> +typedef struct ConfigurationManagerProtocol
> EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct CmStdObjSmbiosTableInfo
> CM_STD_OBJ_SMBIOS_TABLE_INFO;
> +typedef struct SmbiosTableGenerator         SMBIOS_TABLE_GENERATOR;
> +
> +/** This function pointer describes the interface to SMBIOS table build
> +    functions provided by the SMBIOS table generator and called by the
> +    Table Manager to build an SMBIOS table.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [out] Table           Pointer to the generated SMBIOS table.
> +
> +    @returns EFI_SUCCESS  If the table is generated successfully or other
> +                          failure codes as returned by the generator.
> +*/
> +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLE) (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
> +  IN        CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       SMBIOS_STRUCTURE                   **       Table
> +  );
> +
> +/** This function pointer describes the interface to used by the
> +    Table Manager to give the generator an opportunity to free
> +    any resources allocated for building the SMBIOS table.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [in]  Table           Pointer to the generated SMBIOS table.
> +
> +    @returns  EFI_SUCCESS If freed successfully or other failure codes
> +                          as returned by the generator.
> +*/
> +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLE) (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
> +  IN  CONST CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST
> SmbiosTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        SMBIOS_STRUCTURE                   **       Table
> +  );
> +
> +/** The SMBIOS_TABLE_GENERATOR structure provides an interface that
> the
> +    Table Manager can use to invoke the functions to build SMBIOS tables.
> +
> +*/
> +typedef struct SmbiosTableGenerator {
> +  /// The SMBIOS table generator ID.
> +  SMBIOS_TABLE_GENERATOR_ID                GeneratorID;
> +
> +  /// String describing the DT table
> +  /// generator.
> +  CONST CHAR16*                            Description;
> +
> +  /// The SMBIOS table type.
> +  SMBIOS_TYPE                              Type;
> +
> +  /// SMBIOS table build function pointer.
> +  SMBIOS_TABLE_GENERATOR_BUILD_TABLE       BuildSmbiosTable;
> +
> +  /// The function to free any resources
> +  /// allocated for building the SMBIOS table.
> +  SMBIOS_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
> +} SMBIOS_TABLE_GENERATOR;
> +
> +/** Register SMBIOS table factory generator.
> +
> +    The SMBIOS table factory maintains a list of the Standard and OEM
> SMBIOS
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterSmbiosTableGenerator (
> +  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +/** Unregister SMBIOS generator.
> +
> +    This function is called by the SMBIOS table generator to unregister itself
> +    from the SMBIOS table factory.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterSmbiosTableGenerator (
> +  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
> +  );
> +#pragma pack()
> +
> +#endif // SMBIOS_TABLE_GENERATOR_H_
> +
> diff --git
> a/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..76ae3f2208a5c80f0ca10b75
> e5df94cbb43e4688
> --- /dev/null
> +++
> b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> @@ -0,0 +1,93 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef STANDARD_NAMESPACE_OBJECTS_H_
> +#define STANDARD_NAMESPACE_OBJECTS_H_
> +
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +
> +#pragma pack(1)
> +
> +/** The ESTD_OBJECT_ID enum describes the Object IDs
> +    in the Standard Namespace.
> +*/
> +typedef enum StdObjectID {
> +  EStdObjCfgMgrInfo = 0x00000000, ///< 0 - Configuration Manager Info
> +  EStdObjAcpiTableList,           ///< 1 - ACPI table Info List
> +  EStdObjSmbiosTableList,         ///< 2 - SMBIOS table Info List
> +  EStdObjMax
> +} ESTD_OBJECT_ID;
> +
> +/** A structure that describes the Configuration Manager Information.
> +*/
> +typedef struct CmStdObjConfigurationManagerInfo {
> +  /// The Configuration Manager Revision.
> +  UINT32  Revision;
> +
> +  /// The OEM ID. This information is used to
> +  /// populate the ACPI table header information.
> +  UINT8   OemId[6];
> +} CM_STD_OBJ_CONFIGURATION_MANAGER_INFO;
> +
> +/** A structure used to describe the ACPI table generators to be invoked.
> +
> +    The AcpiTableData member of this structure may be used to directly
> provide
> +    the binary ACPI table data which is required by the following standard
> +    generators:
> +      - RAW
> +      - DSDT
> +      - SSDT
> +
> +    Providing the ACPI table data is optional and depends on the generator
> +    that is being invoked. If unused, set AcpiTableData to NULL.
> +*/
> +typedef struct CmAStdObjAcpiTableInfo {
> +  /// The signature of the ACPI Table to be installed.
> +  UINT32                         AcpiTableSignature;
> +
> +  /// The ACPI Table Generator ID.
> +  ACPI_TABLE_GENERATOR_ID        TableGeneratorId;
> +
> +  /// Optional pointer to the ACPI table data.
> +  EFI_ACPI_DESCRIPTION_HEADER  * AcpiTableData;
> +
> +} CM_STD_OBJ_ACPI_TABLE_INFO;
> +
> +/** A structure used to describe the SMBIOS table generators to be invoked.
> +
> +    The SmbiosTableData member of this structure is used to provide
> +    the SMBIOS table data which is required by the following standard
> +    generator(s):
> +      - RAW
> +
> +    Providing the SMBIOS table data is optional and depends on the
> +    generator that is being invoked. If unused, set the SmbiosTableData
> +    to NULL.
> +*/
> +typedef struct CmStdObjSmbiosTableInfo {
> +  /// The SMBIOS Table Generator ID.
> +  SMBIOS_TABLE_GENERATOR_ID   TableGeneratorId;
> +
> +  /// Optional pointer to the SMBIOS table data.
> +  SMBIOS_STRUCTURE           * SmbiosTableData;
> +} CM_STD_OBJ_SMBIOS_TABLE_INFO;
> +
> +#pragma pack()
> +
> +#endif // STANDARD_NAMESPACE_OBJECTS_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/TableGenerator.h
> b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..93d557273459948f5211e1c
> 26a6028fc12b181fb
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
> @@ -0,0 +1,235 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +    - DT     - Device Tree
> +**/
> +
> +#ifndef TABLE_GENERATOR_H_
> +#define TABLE_GENERATOR_H_
> +
> +/** The TABLE_GENERATOR_ID type describes the Table Generator ID
> +
> +  Table Generator ID
> +
> +_______________________________________________________________
> _________________
> +|  31 | 30 |29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16|
> +--------------------------------------------------------------------------------
> +|TNSID|  0 |   TT   |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0|  0 |
> +_______________________________________________________________
> _________________
> +
> +
> +_______________________________________________________________
> _________________
> +|15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
> +--------------------------------------------------------------------------------
> +|                                 Table ID                                     |
> +_______________________________________________________________
> _________________
> +
> +
> +  Bit [31] - Table NameSpace ID (TNSID)
> +      0 - Standard
> +      1 - Custom/OEM
> +
> +  Bit [30] - Reserved, Must be Zero
> +
> +  Bit [29:28] - Table Type (TT)
> +       0 - ACPI Table
> +       1 - SMBIOS Table
> +       2 - DT (Device Tree) Table
> +       3 - Reserved (INVALID)
> +
> +  Bit [27:16] - Reserved, Must Be Zero
> +
> +  Bit [15:0] - Table ID
> +
> +    Standard ACPI Table IDs:
> +       0 - Reserved
> +       1 - RAW
> +       2 - FADT
> +       3 - DSDT
> +       4 - SSDT
> +       5 - MADT
> +       6 - GTDT
> +       7 - DBG2
> +       8 - SPCR
> +       9 - MCFG
> +
> +
> +    Standard SMBIOS Table IDs:
> +       0 - Reserved
> +       1 - RAW
> +       2 - Table Type00
> +       3 - Table Type01
> +       4 - Table Type02
> +       5 - Table Type03
> +       6 - Table Type04
> +       7 - Table Type05
> +       8 - Table Type06
> +       9 - Table Type07
> +      10 - Table Type08
> +      11 - Table Type09
> +      12 - Table Type10
> +      13 - Table Type11
> +      14 - Table Type12
> +      15 - Table Type13
> +      16 - Table Type14
> +      17 - Table Type15
> +      18 - Table Type16
> +      19 - Table Type17
> +      20 - Table Type18
> +      21 - Table Type19
> +      22 - Table Type20
> +      23 - Table Type21
> +      24 - Table Type22
> +      25 - Table Type23
> +      26 - Table Type24
> +      27 - Table Type25
> +      28 - Table Type26
> +      29 - Table Type27
> +      30 - Table Type28
> +      31 - Table Type29
> +      32 - Table Type30
> +      33 - Table Type31
> +      34 - Table Type32
> +      35 - Table Type33
> +      36 - Table Type34
> +      37 - Table Type35
> +      38 - Table Type36
> +      39 - Table Type37
> +      40 - Table Type38
> +      41 - Table Type39
> +      42 - Table Type40
> +      43 - Table Type41
> +      44 - Table Type42
> +  45-127 - Reserved
> +     128 - Table Type126
> +     129 - Table Type127
> +**/
> +typedef UINT32  TABLE_GENERATOR_ID;
> +
> +/** This enum lists the Table Generator Types.
> +*/
> +typedef enum TableGeneratorType {
> +  ETableGeneratorTypeAcpi = 0,  ///< ACPI Table Generator Type.
> +  ETableGeneratorTypeSmbios,    ///< SMBIOS Table Generator Type.
> +  ETableGeneratorTypeDt,        ///< Device Tree Table Generator Type.
> +  ETableGeneratorTypeReserved
> +} ETABLE_GENERATOR_TYPE;
> +
> +/** This enum lists the namespaces for the Table Generators.
> +*/
> +typedef enum TableGeneratorNameSpace {
> +  ETableGeneratorNameSpaceStd = 0,  ///< Standard Namespace.
> +  ETableGeneratorNameSpaceOem       ///< OEM Namespace.
> +} ETABLE_GENERATOR_NAMESPACE;
> +
> +/** A mask for the Table ID bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_ID_MASK             0xFF
> +
> +/** A mask for the Namespace ID bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_NAMESPACEID_MASK    (BIT31)
> +
> +/** A mask for the Table Type bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_TYPE_MASK           (BIT29 | BIT28)
> +
> +/** This macro returns the Table ID from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Table ID described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_ID(TableGeneratorId)                          \
> +          ((TableGeneratorId) & TABLE_ID_MASK)
> +
> +/** This macro returns the Table type from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Table type described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_TYPE(TableGeneratorId)                        \
> +          (((TableGeneratorId) & TABLE_TYPE_MASK) >> 28)
> +
> +/** This macro returns the Namespace ID from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Namespace described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_NAMESPACEID(TableGeneratorId)                 \
> +          (((TableGeneratorId) & TABLE_NAMESPACEID_MASK) >> 31)
> +
> +/** This macro checks if the TableGeneratorId is in the Standard
> Namespace.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the TableGeneratorId is in the Standard Namespace.
> +*/
> +#define IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) \
> +          (                                          \
> +          GET_TABLE_NAMESPACEID(TableGeneratorId) == \
> +          ETableGeneratorNameSpaceStd                \
> +          )
> +
> +/** This macro creates a TableGeneratorId
> +
> +    @param [in]  TableType        The table type.
> +    @param [in]  TableNameSpaceId The namespace ID for the table.
> +    @param [in]  TableId          The table ID.
> +
> +    @returns a TableGeneratorId calculated from the inputs.
> +*/
> +#define CREATE_TABLE_GEN_ID(TableType, TableNameSpaceId, TableId)  \
> +          (                                                        \
> +           (((TableType) << 28) & TABLE_TYPE_MASK)               | \
> +           (((TableNameSpaceId) << 31) & TABLE_NAMESPACEID_MASK) | \
> +           ((TableId) & TABLE_ID_MASK)                             \
> +          )
> +
> +/** This macro generates a Major.Minor version
> +    where the Major and Minor fields are 16 bit.
> +
> +    @param [in]  Major  The Major Revision.
> +    @param [in]  Minor  The Minor Revision.
> +
> +    @returns a 32 bit representation of the type Major.Minor.
> +*/
> +#define CREATE_REVISION(Major, Minor)                            \
> +          ((((Major) & 0xFFFF) << 16) | ((Minor) & 0xFFFF))
> +
> +/** This macro returns the Major revison
> +
> +    Extracts Major from the 32 bit representation of the type Major.Minor
> +
> +    @param [in]  Revision  The Revision value which is 32 bit.
> +
> +    @returns the Major part of the revision.
> +*/
> +#define GET_MAJOR_REVISION(Revision)  (((Revision) >> 16) & 0xFFFF)
> +
> +/** This macro returns the Minor revison
> +
> +    Extracts Minor from the 32 bit representation of the type Major.Minor
> +
> +    @param [in]  Revision  The Revision value which is 32 bit.
> +
> +    @returns the Minor part of the revision.
> +*/
> +#define GET_MINOR_REVISION(Revision)  ((Revision) & 0xFFFF)
> +
> +#endif // TABLE_GENERATOR_H_
> +
> diff --git a/MdeModulePkg/Include/Library/TableHelperLib.h
> b/MdeModulePkg/Include/Library/TableHelperLib.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..4b22e024dee1a311e4e4b5
> 32371ccef94bc02be3
> --- /dev/null
> +++ b/MdeModulePkg/Include/Library/TableHelperLib.h
> @@ -0,0 +1,67 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef TABLE_HELPER_LIB_H_
> +#define TABLE_HELPER_LIB_H_
> +
> +/** The GetCgfMgrInfo function gets the
> CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
> +    object from the Configuration Manager.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> protocol
> +                                interface.
> +    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
> +                                object structure.
> +
> +    @retval EFI_SUCCESS           The object is returned.
> +    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
> +    @retval EFI_NOT_FOUND         The requested Object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetCgfMgrInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST
> CfgMgrProtocol,
> +  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **
> CfgMfrInfo
> +  );
> +
> +/** The AddAcpiHeader function updates the ACPI header structure pointed
> by
> +    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
> +    Manager protocol to obtain any information required for constructing the
> +    header.
> +
> +    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
> +                                   protocol interface.
> +    @param [in]     Generator      Pointer to the ACPI table Generator.
> +    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
> +                                   updated.
> +    @param [in]     Length         Length of the ACPI table.
> +
> +    @retval EFI_SUCCESS           The ACPI table is updated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not
> found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AddAcpiHeader (
> +  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
> +  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
> +  IN      CONST UINT32                                      Length
> +  );
> +
> +#endif // TABLE_HELPER_LIB_H_
> diff --git
> a/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..387935943648654ef095720
> dec452d1c15b8fc11
> --- /dev/null
> +++ b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> @@ -0,0 +1,121 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_PROTOCOL_H_
> +#define CONFIGURATION_MANAGER_PROTOCOL_H_
> +
> +/** This macro defines the Configuration Manager Protocol GUID.
> +
> +  GUID: {D85A4835-5A82-4894-AC02-706F43D5978E}
> +*/
> +#define EFI_CONFIGURATION_MANAGER_PROTOCOL_GUID         \
> +  { 0xd85a4835, 0x5a82, 0x4894,                         \
> +    { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e }   \
> +  };
> +
> +/** This macro defines the Configuration Manager Protocol Revision.
> +*/
> +#define EFI_CONFIGURATION_MANAGER_PROTOCOL_REVISION
> CREATE_REVISION (1, 0)
> +
> +#pragma pack(1)
> +
> +/**
> +  Forward declarations:
> +*/
> +typedef struct ConfigurationManagerProtocol
> EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct PlatformRepositoryInfo
> EFI_PLATFORM_REPOSITORY_INFO;
> +
> +
> +/** The GetObject function defines the interface implemented by the
> +    Configuration Manager Protocol for returning the Configuration
> +    Manager Objects.
> +
> +    @param [in]  This        Poiner to the Configuration Manager Protocol.
> +    @param [in]  CmObjectId  The Configuration Manager Object ID.
> +    @param [out] CmObject    Pointer to the Configuration Manager Object
> +                             descrptor describing the requested Object.
> +
> +    @retval Returns:
> +      EFI_SUCCESS           Success.
> +      EFI_INVALID_PARAMETER A parameter is invalid.
> +      EFI_NOT_FOUND         The required object information is not found.
> +      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                            is less than the Object size for the requested
> +                            object.
> +*/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_CONFIGURATION_MANAGER_GET_OBJECT) (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
> +  IN  CONST CM_OBJECT_ID                                CmObjectId,
> +  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
> +  );
> +
> +/** The SetObject function defines the interface implemented by the
> +    Configuration Manager Protocol for updating the Configuration
> +    Manager Objects.
> +
> +    @param [in]  This        Poiner to the Configuration Manager Protocol.
> +    @param [in]  CmObjectId  The Configuration Manager Object ID.
> +    @param [out] CmObject    Pointer to the Configuration Manager Object
> +                             descrptor describing the Object.
> +
> +    @retval Returns:
> +      EFI_SUCCESS           The operation completed successfully.
> +      EFI_INVALID_PARAMETER A parameter is invalid.
> +      EFI_NOT_FOUND         The required object information is not found.
> +      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                            is less than the Object size for the requested
> +                            object.
> +      EFI_UNSUPPORTED       This operation is not supported.
> +*/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_CONFIGURATION_MANAGER_SET_OBJECT) (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
> +  IN  CONST CM_OBJECT_ID                                CmObjectId,
> +  IN        CM_OBJ_DESCRIPTOR                   * CONST CmObject
> +  );
> +
> +/** The EFI_CONFIGURATION_MANAGER_PROTOCOL structure describes
> the
> +    Configuration Manager Protocol interface.
> +*/
> +typedef struct ConfigurationManagerProtocol {
> +  /// The Configuration Manager Protocol revision.
> +  UINT32                                Revision;
> +
> +  /// The interface used to request information about
> +  /// the Configuration Manager Objects.
> +  EFI_CONFIGURATION_MANAGER_GET_OBJECT  GetObject;
> +
> +  /// The interface used to update the information stored
> +  /// in the Configuration Manager repository.
> +  EFI_CONFIGURATION_MANAGER_SET_OBJECT  SetObject;
> +
> +  /// Pointer to an implementation defined abstract repository
> +  /// provisioned by the Configuration Manager.
> +  EFI_PLATFORM_REPOSITORY_INFO        * PlatRepoInfo;
> +} EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +
> +/** A global GUID defined in the protocol section of the
> +    MdeModulePkg.dec file.
> +*/
> +extern EFI_GUID gEfiConfigurationManagerProtocolGuid;
> +
> +#pragma pack()
> +
> +#endif // CONFIGURATION_MANAGER_PROTOCOL_H_
> diff --git a/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..5ece83bb44ec2d88fbd3b49
> b0e7bdc6314c332c7
> --- /dev/null
> +++ b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> @@ -0,0 +1,113 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +**/
> +
> +#ifndef DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> +#define DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> +
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +
> +/** This macro defines the Dynamic Table Factory Protocol GUID.
> +
> +  GUID: {91D1E327-FE5A-49B8-AB65-0ECE2DDB45EC}
> +*/
> +#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_GUID         \
> +  { 0x91d1e327, 0xfe5a, 0x49b8,                         \
> +    { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec }   \
> +  };
> +
> +/** This macro defines the Configuration Manager Protocol Revision.
> +*/
> +#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_REVISION
> CREATE_REVISION (1, 0)
> +
> +#pragma pack(1)
> +
> +/**
> +  Forward declarations:
> +*/
> +typedef struct DynamicTableFactoryProtocol
> EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
> +typedef struct DynamicTableFactoryInfo
> EFI_DYNAMIC_TABLE_FACTORY_INFO;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  TableId    The ACPI table generator ID for the
> +                            requested generator.
> +    @param [out] Generator  Pointer to the requested ACPI table
> +                            generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A paramter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +typedef
> +EFI_STATUS
> +EFIAPI
> +(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR) (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  );
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  TableId    The SMBIOS table generator ID for the
> +                            requested generator.
> +    @param [out] Generator  Pointer to the requested SMBIOS table
> +                            generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +typedef
> +EFI_STATUS
> +EFIAPI
> +(EFIAPI *
> EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR) (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  );
> +
> +/** A structure describing the Dynamic Table Factory Protocol interface.
> +*/
> +typedef struct DynamicTableFactoryProtocol {
> +  /// The Dynamic Table Factory Protocol revision.
> +  UINT32                                               Revision;
> +
> +  /// The interface used to request an ACPI Table Generator.
> +  EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR
> GetAcpiTableGenerator;
> +
> +  /// The interface used to request a SMBIOS Table Generator.
> +  EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR
> GetSmbiosTableGenerator;
> +
> +  /// Pointer to the data structure that holds the
> +  /// list of registered table generators
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO          * TableFactoryInfo;
> +} EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
> +
> +/** A global GUID defined in the protocol section of the
> +    MdeModulePkg.dec file.
> +*/
> +extern EFI_GUID gEfiDynamicTableFactoryProtocolGuid;
> +
> +#pragma pack()
> +
> +#endif // DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> diff --git
> a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactory.h
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactory.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..88d9e5a4a58307ea26ddbe
> 75579cddc3333ccc34
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactory.h
> @@ -0,0 +1,91 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +**/
> +
> +#ifndef DYNAMIC_TABLE_FACTORY_H_
> +#define DYNAMIC_TABLE_FACTORY_H_
> +
> +#pragma pack(1)
> +
> +/** A structure that holds the list of registered ACPI and
> +    SMBIOS table generators.
> +*/
> +typedef struct DynamicTableFactoryInfo {
> +  /// An array for holding the list of Standard ACPI Table  Generators.
> +  CONST ACPI_TABLE_GENERATOR *
> +          StdAcpiTableGeneratorList[ESTD_ACPI_TABLE_ID_MAX];
> +
> +  /// An array for holding the list of Custom ACPI Table Generators.
> +  CONST ACPI_TABLE_GENERATOR *
> +          CustomAcpiTableGeneratorList[FixedPcdGet16 (
> +            PcdMaxCustomACPIGenerators)];
> +
> +  /// An array for holding the list of Standard SMBIOS Table Generators.
> +  CONST SMBIOS_TABLE_GENERATOR *
> +          StdSmbiosTableGeneratorList[ESTD_SMBIOS_TABLE_ID_MAX];
> +
> +  /// An array for holding the list of Custom SMBIOS Table Generators.
> +  CONST SMBIOS_TABLE_GENERATOR *
> +          CustomSmbiosTableGeneratorList[FixedPcdGet16 (
> +            PcdMaxCustomSMBIOSGenerators)];
> +} EFI_DYNAMIC_TABLE_FACTORY_INFO;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The ACPI table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested ACPI table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetAcpiTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  );
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The SMBIOS table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested SMBIOS table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetSmbiosTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  );
> +
> +#pragma pack()
> +
> +#endif // DYNAMIC_TABLE_FACTORY_H_
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2
> Generator.c
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2
> Generator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..1bf20424b942ac08fe93d15
> 7f3869de53577cf0e
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2
> Generator.c
> @@ -0,0 +1,440 @@
> +/** @file
> +  DBG2 Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include <IndustryStandard/DebugPort2Table.h>
> +#include <Drivers/PL011Uart.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard DBG2 Table Generator
> +
> +    Generates the ACPI DBG2 Port Table for ARM UARTs
> +    as specified by the Microsoft Debug Port Table 2 (DBG2)
> +    Specification - December 10, 2015.
> +
> +    Constructs the DBG2 table for PL011 or SBSA UART peripherals.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjSerialDebugPortInfo
> +*/
> +
> +#pragma pack(1)
> +
> +/** Define the number of debug ports represented by the Table.
> +*/
> +#define DBG2_NUM_DEBUG_PORTS                       1
> +
> +/** Define the number of Generic Address Registers
> +    presented in the debug device information.
> +*/
> +#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS   1
> +
> +/** Define the index for the debug port 1.
> +*/
> +#define DBG_PORT_INDEX_PORT1                       0
> +
> +/** Define the string representing the debug port 1 name.
> +*/
> +#define NAME_STR_PORT1                            "COM1"
> +
> +/** Define the length of the namespace string.
> +*/
> +#define DBG2_NAMESPACESTRING_FIELD_SIZE            sizeof
> (NAME_STR_PORT1)
> +
> +/** Define the PL011 UART address range length.
> +*/
> +#define PL011_UART_LENGTH                          0x1000
> +
> +/** This structure provides the OS with the information required for
> +    initializing a debugger connection.
> +*/
> +typedef struct {
> +  /// The debug device information for the platform
> +  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device;
> +
> +  /// The base address register for the serial port
> +  EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE        BaseAddressRegister;
> +
> +  /// The address size
> +  UINT32 AddressSize;
> +
> +  /// The debug port name string
> +  UINT8  NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
> +} DBG2_DEBUG_DEVICE_INFORMATION;
> +
> +/** This structure represents the information about the debug port(s)
> +    available on the platform.
> +*/
> +typedef struct {
> +  /// The DBG2 table header
> +  EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description;
> +
> +  /// Debug port information list
> +  DBG2_DEBUG_DEVICE_INFORMATION
> Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS];
> +} DBG2_TABLE;
> +
> +/** A helper macro used for initalizing the debug port device
> +    information structure.
> +
> +    @param [in]  NumReg       The number of generic address registers.
> +    @param [in]  SubType      The DBG Port SubType.
> +    @param [in]  UartBase     The UART port base address.
> +    @param [in]  UartAddrLen  The UART port address range length.
> +    @param [in]  UartNameStr  The UART port name string.
> +*/
> +#define DBG2_DEBUG_PORT_DDI(                                          \
> +          NumReg,                                                     \
> +          SubType,                                                    \
> +          UartBase,                                                   \
> +          UartAddrLen,                                                \
> +          UartNameStr                                                 \
> +          ) {                                                         \
> +    {                                                                 \
> +      /* UINT8     Revision */                                        \
> +      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
> \
> +      /* UINT16    Length */                                          \
> +      sizeof (DBG2_DEBUG_DEVICE_INFORMATION),                         \
> +      /* UINT8     NumberofGenericAddressRegisters */                 \
> +      NumReg,                                                         \
> +      /* UINT16    NameSpaceStringLength */                           \
> +      DBG2_NAMESPACESTRING_FIELD_SIZE,                                \
> +      /* UINT16    NameSpaceStringOffset */                           \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString),
> \
> +      /* UINT16    OemDataLength */                                   \
> +      0,                                                              \
> +      /* UINT16    OemDataOffset */                                   \
> +      0,                                                              \
> +      /* UINT16    Port Type */                                       \
> +      EFI_ACPI_DBG2_PORT_TYPE_SERIAL,                                 \
> +      /* UINT16    Port Subtype */                                    \
> +      SubType,                                                        \
> +      /* UINT8     Reserved[2] */                                     \
> +      {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE},               \
> +      /* UINT16    BaseAddressRegister Offset */                      \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION,
> BaseAddressRegister), \
> +      /* UINT16    AddressSize Offset */                              \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize)          \
> +    },                                                                \
> +    /* EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */
> \
> +    ARM_GAS32 (UartBase),                                             \
> +    /* UINT32  AddressSize */                                         \
> +    UartAddrLen,                                                      \
> +    /* UINT8   NameSpaceString[MAX_DBG2_NAME_LEN] */                  \
> +    UartNameStr                                                       \
> +  }
> +
> +/** The DBG2 Table template definition.
> +
> +    Note: fields marked with "{Template}" will be set dynamically
> +*/
> +STATIC
> +DBG2_TABLE AcpiDbg2 = {
> +  {
> +    ACPI_HEADER (
> +      EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
> +      DBG2_TABLE,
> +      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
> +      ),
> +    OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),
> +    DBG2_NUM_DEBUG_PORTS
> +  },
> +  {
> +    /*
> +     * Debug port 1
> +     */
> +    DBG2_DEBUG_PORT_DDI (
> +      DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS,
> +      EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART,
> +      0,                    // {Template}: Serial Port Base Address
> +      PL011_UART_LENGTH,
> +      NAME_STR_PORT1
> +      )
> +  }
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Serial
> +    debug port information from the Configuration Manager
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjSerialDebugPortInfo,
> +  CM_ARM_SERIAL_PORT_INFO
> +  );
> +
> +/** Initialize the PL011 UART with the parameters obtained from
> +    the Configuration Manager.
> +
> +    @param [in]  SerialPortInfo Pointer to the Serial Port Information.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The parameters for serial port
> initialization
> +                                  are invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +SetupDebugUart (
> +  IN  CONST CM_ARM_SERIAL_PORT_INFO  * CONST SerialPortInfo
> +  )
> +{
> +  EFI_STATUS          Status;
> +  UINT64              BaudRate;
> +  UINT32              ReceiveFifoDepth;
> +  EFI_PARITY_TYPE     Parity;
> +  UINT8               DataBits;
> +  EFI_STOP_BITS_TYPE  StopBits;
> +
> +  ASSERT (SerialPortInfo != NULL);
> +
> +  // Initialize the Serial Debug UART
> +  DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));
> +  ReceiveFifoDepth = 0; // Use the default value for FIFO depth
> +  Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
> +  DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
> +  StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
> +
> +  BaudRate = SerialPortInfo->BaudRate;
> +  Status = PL011UartInitializePort (
> +             (UINTN)SerialPortInfo->BaseAddress,
> +             SerialPortInfo->Clock,
> +             &BaudRate,
> +             &ReceiveFifoDepth,
> +             &Parity,
> +             &DataBits,
> +             &StopBits
> +             );
> +
> +  DEBUG ((DEBUG_INFO, "Debug UART Configuration:\n"));
> +  DEBUG ((DEBUG_INFO, "UART Base  = 0x%lx\n", SerialPortInfo-
> >BaseAddress));
> +  DEBUG ((DEBUG_INFO, "Clock      = %d\n", SerialPortInfo->Clock));
> +  DEBUG ((DEBUG_INFO, "Baudrate   = %ld\n", BaudRate));
> +  DEBUG ((DEBUG_INFO, "Configuring Debug UART. Status = %r\n", Status));
> +
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Construct the DBG2 ACPI table
> +
> +    The BuildDbg2Table function is called by the Dynamic Table Manager
> +    to construct the DBG2 ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildDbg2Table (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjSerialDebugPortInfo (
> +             CfgMgrProtocol,
> +             &SerialPortInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2,
> +             sizeof (DBG2_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +
> AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.A
> ddress =
> +    SerialPortInfo->BaseAddress;
> +
> +  Status = SetupDebugUart (SerialPortInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the DBG2.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeDbg2TableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the DBG2 Table Generator revision.
> +*/
> +#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the DBG2 Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR Dbg2Generator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_DBG2),
> +  // Generator Description
> +  L"ACPI.STD.DBG2.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  DBG2_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildDbg2Table,
> +  // Free Resource function
> +  FreeDbg2TableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiDbg2LibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&Dbg2Generator);
> +  DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiDbg2LibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&Dbg2Generator);
> +  DEBUG ((DEBUG_INFO, "DBG2: Unregister Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtG
> enerator.c
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtG
> enerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..75e0b7b50ef34a71cc091db
> 50667a19b40b3f1c9
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtG
> enerator.c
> @@ -0,0 +1,562 @@
> +/** @file
> +  FADT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard FADT Generator
> +
> +    Generates the ACPI FADT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjPowerManagementProfileInfo
> +  - EArmObjBootArchInfo
> +  - EArmObjHypervisorVendorIdentity (OPTIONAL)
> +*/
> +
> +/** This macro defines the FADT flag options for ARM Platforms.
> +*/
> +#define FADT_FLAGS  (EFI_ACPI_6_1_HW_REDUCED_ACPI |          \
> +                     EFI_ACPI_6_1_LOW_POWER_S0_IDLE_CAPABLE)
> +
> +#pragma pack(1)
> +
> +/** The AcpiFadt is a template
> EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE
> +    structure used for generating the FADT Table.
> +  Note: fields marked with "{Template}" will be updated dynamically.
> +*/
> +STATIC
> +EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = {
> +  ACPI_HEADER (
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE,
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
> +    ),
> +  // UINT32     FirmwareCtrl
> +  0,
> +  // UINT32     Dsdt
> +  0,
> +  // UINT8      Reserved0
> +  EFI_ACPI_RESERVED_BYTE,
> +  // UINT8      PreferredPmProfile
> +  EFI_ACPI_6_1_PM_PROFILE_UNSPECIFIED,  // {Template}: Power
> Management Profile
> +  // UINT16     SciInt
> +  0,
> +  // UINT32     SmiCmd
> +  0,
> +  // UINT8      AcpiEnable
> +  0,
> +  // UINT8      AcpiDisable
> +  0,
> +  // UINT8      S4BiosReq
> +  0,
> +  // UINT8      PstateCnt
> +  0,
> +  // UINT32     Pm1aEvtBlk
> +  0,
> +  // UINT32     Pm1bEvtBlk
> +  0,
> +  // UINT32     Pm1aCntBlk
> +  0,
> +  // UINT32     Pm1bCntBlk
> +  0,
> +  // UINT32     Pm2CntBlk
> +  0,
> +  // UINT32     PmTmrBlk
> +  0,
> +  // UINT32     Gpe0Blk
> +  0,
> +  // UINT32     Gpe1Blk
> +  0,
> +  // UINT8      Pm1EvtLen
> +  0,
> +  // UINT8      Pm1CntLen
> +  0,
> +  // UINT8      Pm2CntLen
> +  0,
> +  // UINT8      PmTmrLen
> +  0,
> +  // UINT8      Gpe0BlkLen
> +  0,
> +  // UINT8      Gpe1BlkLen
> +  0,
> +  // UINT8      Gpe1Base
> +  0,
> +  // UINT8      CstCnt
> +  0,
> +  // UINT16     PLvl2Lat
> +  0,
> +  // UINT16     PLvl3Lat
> +  0,
> +  // UINT16     FlushSize
> +  0,
> +  // UINT16     FlushStride
> +  0,
> +  // UINT8      DutyOffset
> +  0,
> +  // UINT8      DutyWidth
> +  0,
> +  // UINT8      DayAlrm
> +  0,
> +  // UINT8      MonAlrm
> +  0,
> +  // UINT8      Century
> +  0,
> +  // UINT16     IaPcBootArch
> +  0,
> +  // UINT8      Reserved1
> +  0,
> +  // UINT32     Flags
> +  FADT_FLAGS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  ResetReg
> +  NULL_GAS,
> +  // UINT8      ResetValue
> +  0,
> +  // UINT16     ArmBootArch
> +  EFI_ACPI_6_1_ARM_PSCI_COMPLIANT,  // {Template}: ARM Boot
> Architecture Flags
> +  // UINT8      MinorRevision
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION,
> +  // UINT64     XFirmwareCtrl
> +  0,
> +  // UINT64     XDsdt
> +  0,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aEvtBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bEvtBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aCntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bCntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm2CntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPmTmrBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe0Blk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe1Blk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepControlReg
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepStatusReg
> +  NULL_GAS,
> +  // UINT64     HypervisorVendorIdentity
> +  EFI_ACPI_RESERVED_QWORD  // {Template}: Hypervisor Vendor ID
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Power
> +    Management Profile Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPowerManagementProfileInfo,
> +  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Boot
> +    Architecture Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjBootArchInfo,
> +  CM_ARM_BOOT_ARCH_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Hypervisor
> +    Vendor ID from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjHypervisorVendorIdentity,
> +  CM_ARM_HYPERVISOR_VENDOR_ID
> +  );
> +
> +/** Update the Power Management Profile information in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                  Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddPmProfileInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS                              Status;
> +  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO  * PmProfile = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Power Management Profile from the Platform Configuration
> Manager
> +  Status = GetEArmObjPowerManagementProfileInfo (
> +             CfgMgrProtocol,
> +             &PmProfile,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to get Power Management Profile information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT: PreferredPmProfile = 0x%x\n",
> +    PmProfile->PowerManagementProfile
> +    ));
> +
> +  AcpiFadt.PreferredPmProfile = PmProfile->PowerManagementProfile;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Updates the Boot Architecture information in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddBootArchInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS               Status;
> +  CM_ARM_BOOT_ARCH_INFO  * BootArchInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Boot Architecture flags from the Platform Configuration
> Manager
> +  Status = GetEArmObjBootArchInfo (
> +             CfgMgrProtocol,
> +             &BootArchInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT BootArchFlag = 0x%x\n",
> +    BootArchInfo->BootArchFlags
> +    ));
> +
> +  AcpiFadt.ArmBootArch = BootArchInfo->BootArchFlags;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Update the Hypervisor Vendor ID in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddHypervisorVendorId (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS                     Status;
> +  CM_ARM_HYPERVISOR_VENDOR_ID  * HypervisorVendorInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Hypervisor Vendor ID from the Platform Configuration Manager
> +  Status = GetEArmObjHypervisorVendorIdentity (
> +             CfgMgrProtocol,
> +             &HypervisorVendorInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    if (Status == EFI_NOT_FOUND) {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "INFO: FADT: Platform does not have a Hypervisor Vendor ID. Status
> = %r\n",
> +        Status
> +        ));
> +    } else {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n",
> +        Status
> +        ));
> +    }
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT: EArmObjHypervisorVendorIdentity = 0x%lx\n",
> +    HypervisorVendorInfo->HypervisorVendorId
> +    ));
> +
> +  AcpiFadt.HypervisorVendorIdentity = HypervisorVendorInfo-
> >HypervisorVendorId;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Construct the FADT table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildFadtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt,
> +             sizeof (EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  // Update PmProfile Info
> +  Status = FadtAddPmProfileInfo (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    goto error_handler;
> +  }
> +
> +  // Update BootArch Info
> +  Status = FadtAddBootArchInfo (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    goto error_handler;
> +  }
> +
> +  // Add the Hypervisor Vendor Id if present
> +  // Note if no hypervisor is present the zero bytes
> +  // will be placed in this field.
> +  Status = FadtAddHypervisorVendorId (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    if (Status == EFI_NOT_FOUND) {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "INFO: FADT: No Hypervisor Vendor ID found," \
> +        " assuming no Hypervisor is present in the firmware.\n"
> +        ));
> +    } else {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r",
> +        Status
> +        ));
> +      goto error_handler;
> +    }
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt;
> +  Status = EFI_SUCCESS;
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the FADT.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeFadtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the FADT Table Generator revision.
> +*/
> +#define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the FADT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR FadtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT),
> +  // Generator Description
> +  L"ACPI.STD.FADT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  FADT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildFadtTable,
> +  // Free Resource function
> +  FreeFadtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiFadtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&FadtGenerator);
> +  DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiFadtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&FadtGenerator);
> +  DEBUG ((DEBUG_INFO, "FADT: Unregister Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtG
> enerator.c
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtG
> enerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..8a243e7d2ef2fa580611603
> 0c74337f1f8e72e8b
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtG
> enerator.c
> @@ -0,0 +1,652 @@
> +/** @file
> +  GTDT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard GTDT Generator
> +
> +    Generates the ACPI GTDT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjGenericTimerInfo
> +  - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)
> +  - EArmObjPlatformGTBlockInfo (OPTIONAL)
> +*/
> +
> +/** This macro expands to a function that retrieves the Generic
> +    Timer Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGenericTimerInfo,
> +  CM_ARM_GENERIC_TIMER_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the SBSA Generic
> +    Watchdog Timer Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPlatformGenericWatchdogInfo,
> +  CM_ARM_GENERIC_WATCHDOG_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Platform Generic
> +    Timer Block Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPlatformGTBlockInfo,
> +  CM_ARM_GTBLOCK_INFO
> +  );
> +
> +/** Add the Generic Timer Information to the GTDT table.
> +
> +    Also update the Platform Timer offset information if the platform
> +    implements platform timers.
> +
> +    @param [in]  CfgMgrProtocol     Pointer to the Configuration Manager
> +                                    Protocol Interface.
> +    @param [in]  Gtdt               Pointer to the GTDT Table.
> +    @param [in]  PlatformTimerCount Platform timer count.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddGenericTimerInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,
> +  IN  CONST UINT32 PlatformTimerCount
> +)
> +{
> +  EFI_STATUS                   Status;
> +  CM_ARM_GENERIC_TIMER_INFO  * GenericTimerInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Gtdt != NULL);
> +
> +  Status = GetEArmObjGenericTimerInfo (
> +             CfgMgrProtocol,
> +             &GenericTimerInfo,
> +             NULL
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to get GenericTimerInfo. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Gtdt->CntControlBasePhysicalAddress =
> +    GenericTimerInfo->CounterControlBaseAddress;
> +  Gtdt->Reserved = EFI_ACPI_RESERVED_DWORD;
> +  Gtdt->CntReadBasePhysicalAddress =
> +    GenericTimerInfo->CounterReadBaseAddress;
> +  Gtdt->PlatformTimerCount = PlatformTimerCount;
> +  Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :
> +    sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
> +
> +  Gtdt->SecurePL1TimerGSIV = GenericTimerInfo->SecurePL1TimerGSIV;
> +  Gtdt->SecurePL1TimerFlags = GenericTimerInfo->SecurePL1TimerFlags;
> +  Gtdt->NonSecurePL1TimerGSIV = GenericTimerInfo-
> >NonSecurePL1TimerGSIV;
> +  Gtdt->NonSecurePL1TimerFlags = GenericTimerInfo-
> >NonSecurePL1TimerFlags;
> +  Gtdt->VirtualTimerGSIV = GenericTimerInfo->VirtualTimerGSIV;
> +  Gtdt->VirtualTimerFlags = GenericTimerInfo->VirtualTimerFlags;
> +  Gtdt->NonSecurePL2TimerGSIV = GenericTimerInfo-
> >NonSecurePL2TimerGSIV;
> +  Gtdt->NonSecurePL2TimerFlags = GenericTimerInfo-
> >NonSecurePL2TimerFlags;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add the SBSA Generic Watchdog Timers to the GTDT table.
> +
> +    @param [in]  Gtdt             Pointer to the GTDT Table.
> +    @param [in]  WatchdogOffset   Offset to the watchdog information in the
> +                                  GTDT Table.
> +    @param [in]  WatchdogInfoList Pointer to the watchdog information list.
> +    @param [in]  WatchdogCount    Platform timer count.
> +*/
> +STATIC
> +VOID
> +AddGenericWatchdogList (
> +  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
> +  IN CONST UINTN                                           WatchdogOffset,
> +  IN CONST CM_ARM_GENERIC_WATCHDOG_INFO            * CONST
> WatchdogInfoList,
> +  IN CONST UINTN                                           WatchdogCount
> +  )
> +{
> +  UINTN                                                idx;
> +  EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE  *
> Watchdog;
> +
> +  ASSERT (Gtdt != NULL);
> +  ASSERT (WatchdogInfoList != NULL);
> +
> +  Watchdog =
> (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *)
> +             ((UINT8*)Gtdt + WatchdogOffset);
> +
> +  for (idx = 0; idx < WatchdogCount; idx++) {
> +    // Add watchdog entry
> +    DEBUG ((DEBUG_INFO, "GTDT: Watchdog[%d] = 0x%p\n", idx,
> &Watchdog[idx]));
> +    Watchdog[idx].Type = EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG;
> +    Watchdog[idx].Length =
> +      sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);
> +    Watchdog[idx].Reserved = EFI_ACPI_RESERVED_BYTE;
> +    Watchdog[idx].RefreshFramePhysicalAddress =
> +      WatchdogInfoList[idx].RefreshFrameAddress;
> +    Watchdog[idx].WatchdogControlFramePhysicalAddress =
> +      WatchdogInfoList[idx].ControlFrameAddress;
> +    Watchdog[idx].WatchdogTimerGSIV = WatchdogInfoList[idx].TimerGSIV;
> +    Watchdog[idx].WatchdogTimerFlags = WatchdogInfoList[idx].Flags;
> +
> +  } // for
> +}
> +
> +/** Update the GT Block Timer Frame lists in the GTDT Table.
> +
> +    @param [in]  GtBlockFrame           Pointer to the GT Block Frames
> +                                        list to be updated.
> +    @param [in]  GTBlockTimerFrameList  Pointer to the GT Block Frame
> +                                        Information List.
> +    @param [in]  GTBlockFrameCount      Number of GT Block Frames.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +AddGTBlockTimerFrames (
> +  IN       EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE * CONST
> GtBlockFrame,
> +  IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO * CONST
> GTBlockTimerFrameList,
> +  IN CONST UINTN GTBlockFrameCount
> +)
> +{
> +  UINTN       idx;
> +
> +  ASSERT (GtBlockFrame != NULL);
> +  ASSERT (GTBlockTimerFrameList != NULL);
> +
> +  if (GTBlockFrameCount > 8) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: GT Block Frame Count %d is greater than 8\n",
> +      GTBlockFrameCount
> +      ));
> +    ASSERT (GTBlockFrameCount <= 8);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  for (idx = 0; idx < GTBlockFrameCount; idx++) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: GtBlockFrame[%d] = 0x%p\n",
> +      idx,
> +      GtBlockFrame[idx]
> +      ));
> +
> +    GtBlockFrame[idx].GTFrameNumber =
> GTBlockTimerFrameList[idx].FrameNumber;
> +    GtBlockFrame[idx].Reserved[0] = EFI_ACPI_RESERVED_BYTE;
> +    GtBlockFrame[idx].Reserved[1] = EFI_ACPI_RESERVED_BYTE;
> +    GtBlockFrame[idx].Reserved[2] = EFI_ACPI_RESERVED_BYTE;
> +
> +    GtBlockFrame[idx].CntBaseX =
> +      GTBlockTimerFrameList[idx].PhysicalAddressCntBase;
> +    GtBlockFrame[idx].CntEL0BaseX =
> +      GTBlockTimerFrameList[idx].PhysicalAddressCntEL0Base;
> +
> +    GtBlockFrame[idx].GTxPhysicalTimerGSIV =
> +      GTBlockTimerFrameList[idx].PhysicalTimerGSIV;
> +    GtBlockFrame[idx].GTxPhysicalTimerFlags =
> +      GTBlockTimerFrameList[idx].PhysicalTimerFlags;
> +
> +    GtBlockFrame[idx].GTxVirtualTimerGSIV =
> +      GTBlockTimerFrameList[idx].VirtualTimerGSIV;
> +    GtBlockFrame[idx].GTxVirtualTimerFlags =
> +      GTBlockTimerFrameList[idx].VirtualTimerFlags;
> +
> +    GtBlockFrame[idx].GTxCommonFlags =
> GTBlockTimerFrameList[idx].CommonFlags;
> +
> +  } // for
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add the GT Block Timers in the GTDT Table.
> +
> +    @param [in]  Gtdt             Pointer to the GTDT Table.
> +    @param [in]  GTBlockOffset    Offset of the GT Block
> +                                  information in the GTDT Table.
> +    @param [in]  GTBlockInfo      Pointer to the GT Block
> +                                  Information List.
> +    @param [in]  BlockTimerCount  Number of GT Block Timers.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +AddGTBlockList (
> +  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
> +  IN CONST UINTN                                           GTBlockOffset,
> +  IN CONST CM_ARM_GTBLOCK_INFO                     * CONST GTBlockInfo,
> +  IN CONST UINTN                                           BlockTimerCount
> +)
> +{
> +  EFI_STATUS                                    Status;
> +  UINTN                                         idx;
> +  EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE        * GTBlock;
> +  EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE  * GtBlockFrame;
> +
> +  ASSERT (Gtdt != NULL);
> +  ASSERT (GTBlockInfo != NULL);
> +
> +  GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)Gtdt +
> +              GTBlockOffset);
> +
> +  for (idx = 0; idx < BlockTimerCount; idx++) {
> +    DEBUG ((DEBUG_INFO, "GTDT: GTBlock[%d] = 0x%p\n",
> +      idx,
> +      GTBlock
> +      ));
> +
> +    GTBlock->Type = EFI_ACPI_6_1_GTDT_GT_BLOCK;
> +    GTBlock->Length = sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) +
> +                        (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
> +                          GTBlockInfo[idx].GTBlockTimerFrameCount);
> +
> +    GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;
> +    GTBlock->CntCtlBase = GTBlockInfo[idx].GTBlockPhysicalAddress;
> +    GTBlock->GTBlockTimerCount =
> GTBlockInfo[idx].GTBlockTimerFrameCount;
> +    GTBlock->GTBlockTimerOffset =
> +      sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE);
> +
> +    GtBlockFrame = (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE*)
> +      ((UINT8*)GTBlock + GTBlock->GTBlockTimerOffset);
> +
> +    // Add GT Block Timer frames
> +    Status = AddGTBlockTimerFrames (
> +               GtBlockFrame,
> +               GTBlockInfo[idx].GTBlockTimerFrameList,
> +               GTBlockInfo[idx].GTBlockTimerFrameCount
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",
> +        Status
> +        ));
> +      return Status;
> +    }
> +
> +    // Next GTBlock
> +    GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE
> *)((UINT8*)GTBlock +
> +                GTBlock->Length);
> +  }// for
> +  return EFI_SUCCESS;
> +}
> +
> +/** Construct the GTDT ACPI table.
> +
> +    Called by the Dynamic Table Manager, this function invokes the
> +    Confguration Manager protocol interface to get the required hardware
> +    information for generating the ACPI table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildGtdtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                                      Status;
> +  UINTN                                           TableSize;
> +  UINTN                                           PlatformTimerCount = 0;
> +  UINTN                                           WatchdogCount;
> +  UINTN                                           BlockTimerCount;
> +  CM_ARM_GENERIC_WATCHDOG_INFO                  * WatchdogInfoList =
> NULL;
> +  CM_ARM_GTBLOCK_INFO                           * GTBlockInfo = NULL;
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * Gtdt;
> +  UINTN                                           idx;
> +  UINTN                                           GTBlockOffset;
> +  UINTN                                           WatchdogOffset = 0;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +  Status = GetEArmObjPlatformGTBlockInfo (
> +             CfgMgrProtocol,
> +             &GTBlockInfo,
> +             &BlockTimerCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to Get Platform GT Block Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjPlatformGenericWatchdogInfo (
> +             CfgMgrProtocol,
> +             &WatchdogInfoList,
> +             &WatchdogCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",
> +    BlockTimerCount,
> +    WatchdogCount
> +    ));
> +
> +  // Calculate the GTDT Table Size
> +  TableSize = sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
> +  if (BlockTimerCount != 0) {
> +    GTBlockOffset = TableSize;
> +    PlatformTimerCount += BlockTimerCount;
> +    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) *
> +                  BlockTimerCount);
> +
> +    for (idx = 0; idx < BlockTimerCount; idx++) {
> +      if (GTBlockInfo[idx].GTBlockTimerFrameCount > 8) {
> +        Status = EFI_INVALID_PARAMETER;
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "GTDT: GTBockFrameCount cannot be more than 8." \
> +          " GTBockFrameCount = %d, Status = %r\n",
> +          GTBlockInfo[idx].GTBlockTimerFrameCount,
> +          Status
> +          ));
> +        goto error_handler;
> +      }
> +      TableSize += (sizeof
> (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
> +        GTBlockInfo[idx].GTBlockTimerFrameCount);
> +    }
> +
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
> +      GTBlockOffset,
> +      PlatformTimerCount
> +      ));
> +  }
> +
> +  if (WatchdogCount != 0) {
> +    WatchdogOffset = TableSize;
> +    PlatformTimerCount += WatchdogCount;
> +    TableSize += (sizeof
> (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE) *
> +                  WatchdogCount);
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
> +      WatchdogOffset,
> +      PlatformTimerCount
> +      ));
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Gtdt = (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE*)*Table;
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",
> +    Gtdt,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Gtdt->Header, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = AddGenericTimerInfo (
> +             CfgMgrProtocol,
> +             Gtdt,
> +             PlatformTimerCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (BlockTimerCount != 0) {
> +    Status = AddGTBlockList (
> +               Gtdt,
> +               GTBlockOffset,
> +               GTBlockInfo,
> +               BlockTimerCount
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",
> +        Status
> +        ));
> +      goto error_handler;
> +    }
> +  }
> +
> +  if (WatchdogCount != 0) {
> +    AddGenericWatchdogList (
> +      Gtdt,
> +      WatchdogOffset,
> +      WatchdogInfoList,
> +      WatchdogCount
> +      );
> +  }
> +
> +  return Status;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the GTDT.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +FreeGtdtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +)
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the GTDT Table Generator revision.
> +*/
> +#define GTDT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the GTDT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR GtdtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_GTDT),
> +  // Generator Description
> +  L"ACPI.STD.GTDT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  GTDT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildGtdtTable,
> +  // Free Resource function
> +  FreeGtdtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiGtdtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&GtdtGenerator);
> +  DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiGtdtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&GtdtGenerator);
> +  DEBUG ((DEBUG_INFO, "GTDT: Unregister Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/Madt
> Generator.c
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/Madt
> Generator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..cce440d91f50d8a7ac429ac
> b6be40d4a6ac4e230
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/Madt
> Generator.c
> @@ -0,0 +1,732 @@
> +/** @file
> +  MADT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard MADT Generator
> +
> +    Generates the ACPI MADT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjGicCInfo
> +  - EArmObjGicDInfo
> +  - EArmObjGicMsiFrameInfo (OPTIONAL)
> +  - EArmObjGicRedistributorInfo (OPTIONAL)
> +  - EArmObjGicItsInfo (OPTIONAL)
> +*/
> +
> +/** This macro expands to a function that retrieves the GIC
> +    CPU interface Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicCInfo,
> +  CM_ARM_GICC_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Distributor Information from the Configuration Manager.
> +*/
> +
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicDInfo,
> +  CM_ARM_GICD_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    MSI Frame Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicMsiFrameInfo,
> +  CM_ARM_GIC_MSI_FRAME_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Redistributor Information from the Configuration Manager.
> +*/
> +
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicRedistributorInfo,
> +  CM_ARM_GIC_REDIST_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Interrupt Translation Serice Information from the
> +    Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicItsInfo,
> +  CM_ARM_GIC_ITS_INFO
> +  );
> +
> +/** This function updates the GIC CPU Interface Information in the
> +    EFI_ACPI_6_1_GIC_STRUCTURE structure.
> +
> +    @param [in]  Gicc      Pointer to GIC CPU Interface structure.
> +    @param [in]  GicCInfo  Pointer to the GIC CPU Interface Information.
> +*/
> +STATIC
> +VOID
> +AddGICC (
> +  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * CONST Gicc,
> +  IN  CONST CM_ARM_GICC_INFO      * CONST GicCInfo
> +  )
> +{
> +  ASSERT (Gicc != NULL);
> +  ASSERT (GicCInfo != NULL);
> +
> +  /* UINT8 Type */
> +  Gicc->Type = EFI_ACPI_6_1_GIC;
> +  /* UINT8 Length */
> +  Gicc->Length = sizeof (EFI_ACPI_6_1_GIC_STRUCTURE);
> +  /* UINT16 Reserved */
> +  Gicc->Reserved = EFI_ACPI_RESERVED_WORD;
> +
> +  /* UINT32 CPUInterfaceNumber */
> +  Gicc->CPUInterfaceNumber = GicCInfo->CPUInterfaceNumber;
> +  /* UINT32 AcpiProcessorUid */
> +  Gicc->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;
> +  /* UINT32 Flags */
> +  Gicc->Flags = GicCInfo->Flags;
> +  /* UINT32 ParkingProtocolVersion */
> +  Gicc->ParkingProtocolVersion = GicCInfo->ParkingProtocolVersion;
> +  /* UINT32 PerformanceInterruptGsiv */
> +  Gicc->PerformanceInterruptGsiv = GicCInfo->PerformanceInterruptGsiv;
> +  /* UINT64 ParkedAddress */
> +  Gicc->ParkedAddress = GicCInfo->ParkedAddress;
> +
> +  /* UINT64 PhysicalBaseAddress */
> +  Gicc->PhysicalBaseAddress = GicCInfo->PhysicalBaseAddress;
> +  /* UINT64 GICV */
> +  Gicc->GICV = GicCInfo->GICV;
> +  /* UINT64 GICH */
> +  Gicc->GICH = GicCInfo->GICH;
> +
> +  /* UINT32 VGICMaintenanceInterrupt */
> +  Gicc->VGICMaintenanceInterrupt = GicCInfo->VGICMaintenanceInterrupt;
> +  /* UINT64 GICRBaseAddress */
> +  Gicc->GICRBaseAddress = GicCInfo->GICRBaseAddress;
> +
> +  /* UINT64 MPIDR */
> +  Gicc->MPIDR = GicCInfo->MPIDR;
> +  /* UINT8 ProcessorPowerEfficiencyClass */
> +  Gicc->ProcessorPowerEfficiencyClass =
> +    GicCInfo->ProcessorPowerEfficiencyClass;
> +  /* UINT8 Reserved2[3] */
> +  Gicc->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
> +  Gicc->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
> +  Gicc->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
> +}
> +
> +/** Add the GIC CPU Interface Information to the MADT Table.
> +
> +    @param [in]  Gicc      Pointer to GIC CPU Interface
> +                            structure list.
> +    @param [in]  GicCInfo  Pointer to the GIC CPU
> +                            Information list.
> +    @param [in]  GicCCount Count of GIC CPU Interfaces.
> +*/
> +STATIC
> +VOID
> +AddGICCList (
> +  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * Gicc,
> +  IN  CONST CM_ARM_GICC_INFO      * GicCInfo,
> +  IN  CONST UINTN                   GicCCount
> +  )
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicc != NULL);
> +  ASSERT (GicCInfo != NULL);
> +
> +  for (idx = 0; idx < GicCCount; idx++) {
> +    AddGICC (Gicc++, GicCInfo++);
> +  }
> +}
> +
> +/** Update the GIC Distributor Information in the MADT Table.
> +
> +    @param [in]  Gicd      Pointer to GIC Distributor structure.
> +    @param [in]  GicDInfo  Pointer to the GIC Distributor Information.
> +*/
> +STATIC
> +VOID
> +AddGICD (
> +  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * CONST Gicd,
> +  CONST CM_ARM_GICD_INFO                  * CONST GicDInfo
> +)
> +{
> +  ASSERT (Gicd != NULL);
> +  ASSERT (GicDInfo != NULL);
> +
> +  /* UINT8 Type */
> +  Gicd->Type = EFI_ACPI_6_1_GICD;
> +  /* UINT8 Length */
> +  Gicd->Length = sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE);
> +  /* UINT16 Reserved */
> +  Gicd->Reserved1 = EFI_ACPI_RESERVED_WORD;
> +  /* UINT32 Identifier */
> +  Gicd->GicId = GicDInfo->GicId;
> +  /* UINT64 PhysicalBaseAddress */
> +  Gicd->PhysicalBaseAddress = GicDInfo->PhysicalBaseAddress;
> +  /* UINT32 VectorBase */
> +  Gicd->SystemVectorBase = GicDInfo->SystemVectorBase;
> +  /* UINT8  GicVersion */
> +  Gicd->GicVersion = GicDInfo->GicVersion;
> +  /* UINT8  Reserved2[3] */
> +  Gicd->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
> +  Gicd->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
> +  Gicd->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
> +}
> +
> +/** Add the GIC Distributor Information to the MADT Table.
> +
> +    @param [in]  Gicd      Pointer to GIC Distributor structure list.
> +    @param [in]  GicDInfo  Pointer to the GIC Distributor Information list.
> +    @param [in]  GicDCount Count of GIC Distributors.
> +*/
> +STATIC
> +VOID
> +AddGICDList (
> +  IN  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * Gicd,
> +  IN  CONST CM_ARM_GICD_INFO                  * GicDInfo,
> +  IN  CONST UINTN                               GicDCount
> +  )
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicd != NULL);
> +  ASSERT (GicDInfo != NULL);
> +
> +  for (idx = 0; idx < GicDCount; idx++) {
> +    AddGICD (Gicd++, GicDInfo++);
> +  }
> +}
> +
> +/** Update the GIC MSI Frame Information.
> +
> +    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure.
> +    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame Information.
> +*/
> +STATIC
> +VOID
> +AddGICMsiFrame (
> +  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * CONST GicMsiFrame,
> +  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * CONST GicMsiFrameInfo
> +)
> +{
> +  ASSERT (GicMsiFrame != NULL);
> +  ASSERT (GicMsiFrameInfo != NULL);
> +
> +  GicMsiFrame->Type = EFI_ACPI_6_1_GIC_MSI_FRAME;
> +  GicMsiFrame->Length = sizeof
> (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE);
> +  GicMsiFrame->Reserved1 = EFI_ACPI_RESERVED_WORD;
> +  GicMsiFrame->GicMsiFrameId = GicMsiFrameInfo->GicMsiFrameId;
> +  GicMsiFrame->PhysicalBaseAddress = GicMsiFrameInfo-
> >PhysicalBaseAddress;
> +
> +  GicMsiFrame->Flags = GicMsiFrameInfo->Flags;
> +  GicMsiFrame->SPICount = GicMsiFrameInfo->SPICount;
> +  GicMsiFrame->SPIBase = GicMsiFrameInfo->SPIBase;
> +}
> +
> +/** Add the GIC MSI Frame Information to the MADT Table.
> +
> +    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure list.
> +    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame info list.
> +    @param [in]  GicMsiFrameCount Count of GIC MSI Frames.
> +*/
> +STATIC
> +VOID
> +AddGICMsiFrameInfoList (
> +  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * GicMsiFrame,
> +  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * GicMsiFrameInfo,
> +  IN  CONST UINTN                             GicMsiFrameCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (GicMsiFrame != NULL);
> +  ASSERT (GicMsiFrameInfo != NULL);
> +
> +  for (idx = 0; idx < GicMsiFrameCount; idx++) {
> +    AddGICMsiFrame (GicMsiFrame++, GicMsiFrameInfo++);
> +  }
> +}
> +
> +/** Update the GIC Redistributor Information.
> +
> +    @param [in]  Gicr                 Pointer to GIC Redistributor structure.
> +    @param [in]  GicRedisributorInfo  Pointer to the GIC Redistributor Info.
> +*/
> +STATIC
> +VOID
> +AddGICRedistributor (
> +  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * CONST Gicr,
> +  IN  CONST CM_ARM_GIC_REDIST_INFO  * CONST GicRedisributorInfo
> +  )
> +{
> +  ASSERT (Gicr != NULL);
> +  ASSERT (GicRedisributorInfo != NULL);
> +
> +  Gicr->Type = EFI_ACPI_6_1_GICR;
> +  Gicr->Length = sizeof (EFI_ACPI_6_1_GICR_STRUCTURE);
> +  Gicr->Reserved = EFI_ACPI_RESERVED_WORD;
> +  Gicr->DiscoveryRangeBaseAddress =
> +    GicRedisributorInfo->DiscoveryRangeBaseAddress;
> +  Gicr->DiscoveryRangeLength = GicRedisributorInfo->DiscoveryRangeLength;
> +}
> +
> +/** Add the GIC Redistributor Information to the MADT Table.
> +
> +    @param [in]  Gicr      Pointer to GIC Redistributor structure list.
> +    @param [in]  GicRInfo  Pointer to the GIC Distributor info list.
> +    @param [in]  GicRCount Count of GIC Distributors.
> +*/
> +STATIC
> +VOID
> +AddGICRedistributorList (
> +  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * Gicr,
> +  IN  CONST CM_ARM_GIC_REDIST_INFO  * GicRInfo,
> +  IN  CONST UINTN                     GicRCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicr != NULL);
> +  ASSERT (GicRInfo != NULL);
> +
> +  for (idx = 0; idx < GicRCount; idx++) {
> +    AddGICRedistributor (Gicr++, GicRInfo++);
> +  }
> +}
> +
> +/** Update the GIC Interrupt Translation Service Information
> +
> +    @param [in]  GicIts      Pointer to GIC ITS structure.
> +    @param [in]  GicItsInfo  Pointer to the GIC ITS Information.
> +*/
> +STATIC
> +VOID
> +AddGICInterruptTranslationService (
> +  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * CONST GicIts,
> +  IN  CONST CM_ARM_GIC_ITS_INFO       * CONST GicItsInfo
> +)
> +{
> +  ASSERT (GicIts != NULL);
> +  ASSERT (GicItsInfo != NULL);
> +
> +  GicIts->Type = EFI_ACPI_6_1_GIC_ITS;
> +  GicIts->Length = sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE);
> +  GicIts->Reserved = EFI_ACPI_RESERVED_WORD;
> +  GicIts->GicItsId = GicItsInfo->GicItsId;
> +  GicIts->PhysicalBaseAddress = GicItsInfo->PhysicalBaseAddress;
> +  GicIts->Reserved2 = EFI_ACPI_RESERVED_DWORD;
> +}
> +
> +/** Add the GIC Interrupt Translation Service Information
> +    to the MADT Table.
> +
> +    @param [in]  GicIts       Pointer to GIC ITS structure list.
> +    @param [in]  GicItsInfo   Pointer to the GIC ITS list.
> +    @param [in]  GicItsCount  Count of GIC ITS.
> +*/
> +STATIC
> +VOID
> +AddGICItsList (
> +  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * GicIts,
> +  IN  CONST CM_ARM_GIC_ITS_INFO       * GicItsInfo,
> +  IN  CONST UINTN                       GicItsCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (GicIts != NULL);
> +  ASSERT (GicItsInfo != NULL);
> +
> +  for (idx = 0; idx < GicItsCount; idx++) {
> +    AddGICInterruptTranslationService (GicIts++, GicItsInfo++);
> +  }
> +}
> +
> +/** Construct the MADT ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildMadtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  UINTN                        TableSize;
> +  UINTN                        GicCCount;
> +  UINTN                        GicDCount;
> +  UINTN                        GicMSICount;
> +  UINTN                        GicRedistCount;
> +  UINTN                        GicItsCount;
> +  CM_ARM_GICC_INFO           * GicCInfo = NULL;
> +  CM_ARM_GICD_INFO           * GicDInfo = NULL;
> +  CM_ARM_GIC_MSI_FRAME_INFO  * GicMSIInfo = NULL;
> +  CM_ARM_GIC_REDIST_INFO     * GicRedistInfo = NULL;
> +  CM_ARM_GIC_ITS_INFO        * GicItsInfo = NULL;
> +  UINTN                        GicCOffset;
> +  UINTN                        GicDOffset;
> +  UINTN                        GicMSIOffset;
> +  UINTN                        GicRedistOffset;
> +  UINTN                        GicItsOffset;
> +
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER  * Madt;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjGicCInfo (CfgMgrProtocol, &GicCInfo, &GicCCount);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GICC Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (GicCCount == 0) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: GIC CPU Interface information not provided.\n"
> +      ));
> +    ASSERT (GicCCount != 0);
> +    Status = EFI_INVALID_PARAMETER;
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicDInfo (CfgMgrProtocol, &GicDInfo, &GicDCount);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GICD Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (GicDCount == 0) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: GIC Distributor information not provided.\n"
> +      ));
> +    ASSERT (GicDCount != 0);
> +    Status = EFI_INVALID_PARAMETER;
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicMsiFrameInfo (
> +             CfgMgrProtocol,
> +             &GicMSIInfo,
> +             &GicMSICount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC MSI Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicRedistributorInfo (
> +             CfgMgrProtocol,
> +             &GicRedistInfo,
> +             &GicRedistCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC Redistributor Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicItsInfo (
> +             CfgMgrProtocol,
> +             &GicItsInfo,
> +             &GicItsCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC ITS Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  TableSize = sizeof
> (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
> +
> +  GicCOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_STRUCTURE) * GicCCount);
> +
> +  GicDOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE) *
> GicDCount);
> +
> +  GicMSIOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE) *
> GicMSICount);
> +
> +  GicRedistOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GICR_STRUCTURE) * GicRedistCount);
> +
> +  GicItsOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE) * GicItsCount);
> +
> +  // Allocate the Buffer for MADT table
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to allocate memory for MADT Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Madt =
> (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER*)*Table;
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MADT: Madt = 0x%p TableSize = 0x%x\n",
> +    Madt,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Madt->Header,
> TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  AddGICCList (
> +    (EFI_ACPI_6_1_GIC_STRUCTURE*)((UINT8*)Madt + GicCOffset),
> +    GicCInfo,
> +    GicCCount
> +    );
> +
> +  AddGICDList (
> +    (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE*)((UINT8*)Madt +
> GicDOffset),
> +    GicDInfo,
> +    GicDCount
> +    );
> +
> +  if (GicMSICount != 0) {
> +    AddGICMsiFrameInfoList (
> +      (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE*)((UINT8*)Madt +
> GicMSIOffset),
> +      GicMSIInfo,
> +      GicMSICount
> +      );
> +  }
> +
> +  if (GicRedistCount != 0) {
> +    AddGICRedistributorList (
> +      (EFI_ACPI_6_1_GICR_STRUCTURE*)((UINT8*)Madt + GicRedistOffset),
> +      GicRedistInfo,
> +      GicRedistCount
> +      );
> +  }
> +
> +  if (GicItsCount != 0) {
> +    AddGICItsList (
> +      (EFI_ACPI_6_1_GIC_ITS_STRUCTURE*)((UINT8*)Madt + GicItsOffset),
> +      GicItsInfo,
> +      GicItsCount
> +      );
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the MADT
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeMadtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MADT: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** The MADT Table Generator revision.
> +*/
> +#define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the MADT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR MadtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MADT),
> +  // Generator Description
> +  L"ACPI.STD.MADT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  MADT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildMadtTable,
> +  // Free Resource function
> +  FreeMadtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMadtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&MadtGenerator);
> +  DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMadtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&MadtGenerator);
> +  DEBUG ((DEBUG_INFO, "MADT: Unregister Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgG
> enerator.c
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/Mcfg
> Generator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..c023b413797379562f20ae9
> 7db9e2f2ca6d8758c
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/Mcfg
> Generator.c
> @@ -0,0 +1,336 @@
> +/** @file
> +  MCFG Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include
> <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard MCFG Generator
> +
> +    Generates the MCFG Table as specified by the PCI Firmware
> +    Specification - Revision 3.2, January 26, 2015.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjPciConfigSpaceInfo
> +*/
> +
> +#pragma pack(1)
> +
> +/** This typedef is used to shorten the name of the MCFG Table
> +    header structure.
> +*/
> +typedef
> +
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEA
> DER
> +  MCFG_TABLE;
> +
> +/** This typedef is used to shorten the name of the Enhanced
> +    Configuration Space address structure.
> +*/
> +typedef
> +
> EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_A
> DDRESS_ALLOCATION_STRUCTURE
> +  MCFG_CFG_SPACE_ADDR;
> +
> +#pragma pack()
> +
> +/** Retrieve the PCI Configuration Space Information.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPciConfigSpaceInfo,
> +  CM_ARM_PCI_CONFIG_SPACE_INFO
> +  );
> +
> +/** Add the PCI Enhanced Configuration Space Information to the MCFG
> Table.
> +
> +    @param [in]  Mcfg                Pointer to MCFG Table.
> +    @param [in]  PciCfgSpaceOffset   Offset for the PCI Configuration Space
> +                                     Info structure in the MCFG Table.
> +    @param [in]  PciCfgSpaceInfoList Pointer to the PCI Configuration Space
> +                                     Info List.
> +    @param [in]  PciCfgSpaceCount    Count of PCI Configuration Space Info.
> +*/
> +STATIC
> +VOID
> +AddPciConfigurationSpaceList (
> +  IN       MCFG_TABLE                   * CONST Mcfg,
> +  IN CONST UINTN                                PciCfgSpaceOffset,
> +  IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * CONST
> PciCfgSpaceInfoList,
> +  IN CONST UINTN                                PciCfgSpaceCount
> +)
> +{
> +  UINTN                  idx;
> +  MCFG_CFG_SPACE_ADDR  * PciCfgSpace;
> +
> +  ASSERT (Mcfg != NULL);
> +  ASSERT (PciCfgSpaceInfoList != NULL);
> +
> +  PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8*)Mcfg +
> PciCfgSpaceOffset);
> +  for (idx = 0; idx < PciCfgSpaceCount; idx++) {
> +    // Add PCI Configuration Space entry
> +    PciCfgSpace[idx].BaseAddress = PciCfgSpaceInfoList[idx].BaseAddress;
> +    PciCfgSpace[idx].PciSegmentGroupNumber =
> +      PciCfgSpaceInfoList[idx].PciSegmentGroupNumber;
> +    PciCfgSpace[idx].StartBusNumber =
> PciCfgSpaceInfoList[idx].StartBusNumber;
> +    PciCfgSpace[idx].EndBusNumber =
> PciCfgSpaceInfoList[idx].EndBusNumber;
> +    PciCfgSpace[idx].Reserved = EFI_ACPI_RESERVED_DWORD;
> +  }
> +}
> +
> +/** Construct the MCFG ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildMcfgTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UINTN                           TableSize;
> +  UINTN                           ConfigurationSpaceCount;
> +  CM_ARM_PCI_CONFIG_SPACE_INFO  * PciConfigSpaceInfoList = NULL;
> +  MCFG_TABLE                    * Mcfg;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +  Status = GetEArmObjPciConfigSpaceInfo (
> +              CfgMgrProtocol,
> +              &PciConfigSpaceInfoList,
> +              &ConfigurationSpaceCount
> +              );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to get PCI Configuration Space Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +  ASSERT (ConfigurationSpaceCount != 0);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MCFG: Configuration Space Count = %d\n",
> +    ConfigurationSpaceCount
> +    ));
> +
> +  // Calculate the MCFG Table Size
> +  TableSize = sizeof (MCFG_TABLE) +
> +    ((sizeof (MCFG_CFG_SPACE_ADDR) * ConfigurationSpaceCount));
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Mcfg = (MCFG_TABLE*)*Table;
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MCFG: Mcfg = 0x%p TableSize = 0x%x\n",
> +    Mcfg,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Mcfg->Header, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Mcfg->Reserved = EFI_ACPI_RESERVED_QWORD;
> +
> +  AddPciConfigurationSpaceList (
> +    Mcfg,
> +    sizeof (MCFG_TABLE),
> +    PciConfigSpaceInfoList,
> +    ConfigurationSpaceCount
> +    );
> +
> +  return EFI_SUCCESS;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the MCFG
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeMcfgTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MCFG: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the MCFG Table Generator revision.
> +*/
> +#define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the MCFG Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR McfgGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MCFG),
> +  // Generator Description
> +  L"ACPI.STD.MCFG.GENERATOR",
> +  // ACPI Table Signature
> +
> EFI_ACPI_6_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_B
> ASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVI
> SION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  MCFG_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildMcfgTable,
> +  // Free Resource function
> +  FreeMcfgTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMcfgLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&McfgGenerator);
> +  DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMcfgLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&McfgGenerator);
> +  DEBUG ((DEBUG_INFO, "MCFG: Unregister Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGe
> nerator.c
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGe
> nerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..aaca70cba0a1a08c0730bd8
> 4134c1b8722edd7af
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGe
> nerator.c
> @@ -0,0 +1,177 @@
> +/** @file
> +  MCFG Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** Construct the ACPI table using the ACPI table data provided.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildRawTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableData != NULL);
> +
> +  if (AcpiTableInfo->AcpiTableData == NULL) {
> +    *Table = NULL;
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Table = AcpiTableInfo->AcpiTableData;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Free any resources allocated for constructing the ACPI table.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +FreeRawTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the Raw Generator revision.
> +*/
> +#define RAW_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the Raw Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR RawGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RAW),
> +  // Generator Description
> +  L"ACPI.STD.RAW.GENERATOR",
> +  // ACPI Table Signature - Unused
> +  0,
> +  // ACPI Table Revision - Unused
> +  0,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  RAW_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildRawTable,
> +  // Free Resource function
> +  FreeRawTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiRawLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&RawGenerator);
> +  DEBUG ((DEBUG_INFO, "RAW: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +
> +EFI_STATUS
> +EFIAPI
> +AcpiRawLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&RawGenerator);
> +  DEBUG ((DEBUG_INFO, "RAW: UnRegister Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGe
> nerator.c
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGe
> nerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..ccfbcf088cfaec1e4f9f3738f5
> fe09a65c93bc9e
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGe
> nerator.c
> @@ -0,0 +1,323 @@
> +/** @file
> +  SPCR Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard SPCR Table Generator
> +
> +    Generates the ACPI SPCR Table for ARM UARTs as specified by
> +    the Microsoft Serial Port Console Redirection Table
> +    Specification - Version 1.03 - August 10, 2015.
> +
> +    Constructs the SPCR table for PL011 or SBSA UART peripherals.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjSerialConsolePortInfo
> +
> +NOTE: This implementation ignores the possibility that the Serial settings
> may
> +      be modified from the UEFI Shell.  A more complex handler would be
> needed
> +      to (e.g.) recover serial port settings from the UART, or non-volatile
> +      storage.
> +*/
> +
> +#pragma pack(1)
> +
> +/** This macro defines the no flow control option.
> +*/
> +#define SPCR_FLOW_CONTROL_NONE           0
> +
> +/**A template for generating the SPCR Table.
> +
> +  Note: fields marked "{Template}" will be updated dynamically.
> +*/
> +STATIC
> +EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = {
> +  ACPI_HEADER (
> +    EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> +    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,
> +    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
> +    ),
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_A
> RM_PL011_UART,
> +  {
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE
> +  },
> +  ARM_GAS32 (0), // {Template}: Serial Port Base Address
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_G
> IC,
> +  0, // Not used on ARM
> +  0, // {Template}: Serial Port Interrupt
> +  0, // {Template}: Serial Port Baudrate
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
> +  SPCR_FLOW_CONTROL_NONE,
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_A
> NSI,
> +  EFI_ACPI_RESERVED_BYTE,
> +  0xFFFF,
> +  0xFFFF,
> +  0x00,
> +  0x00,
> +  0x00,
> +  0x00000000,
> +  0x00,
> +  EFI_ACPI_RESERVED_DWORD
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Serial
> +    Port Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjSerialConsolePortInfo,
> +  CM_ARM_SERIAL_PORT_INFO
> +  )
> +
> +/** Construct the SPCR ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_UNSUPPORTED       An unsupported baudrate was specified
> by the
> +                                  Confguration Manager.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildSpcrTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjSerialConsolePortInfo (
> +             CfgMgrProtocol,
> +             &SerialPortInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));
> +  DEBUG ((DEBUG_INFO, "  UART Base  = 0x%lx\n", SerialPortInfo-
> >BaseAddress));
> +  DEBUG ((DEBUG_INFO, "  Clock      = %d\n", SerialPortInfo->Clock));
> +  DEBUG ((DEBUG_INFO, "  Baudrate   = %ld\n", SerialPortInfo->BaudRate));
> +  DEBUG ((DEBUG_INFO, "  Interrupt  = %d\n", SerialPortInfo->Interrupt));
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr,
> +             sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
> +  AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;
> +
> +  switch (SerialPortInfo->BaudRate) {
> +    case 9600:
> +      AcpiSpcr.BaudRate =
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;
> +      break;
> +    case 19200:
> +      AcpiSpcr.BaudRate =
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;
> +      break;
> +    case 57600:
> +      AcpiSpcr.BaudRate =
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;
> +      break;
> +    case 115200:
> +      AcpiSpcr.BaudRate =
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_11520
> 0;
> +      break;
> +    default:
> +      Status = EFI_UNSUPPORTED;
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
> +        SerialPortInfo->BaudRate,
> +        Status
> +        ));
> +      goto error_handler;
> +  } // switch
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the SPCR.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeSpcrTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the SPCR Table Generator revision.
> +*/
> +#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the SPCR Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR SpcrGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_SPCR),
> +  // Generator Description
> +  L"ACPI.STD.SPCR.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  SPCR_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildSpcrTable,
> +  // Free Resource function
> +  FreeSpcrTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiSpcrLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&SpcrGenerator);
> +  DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiSpcrLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&SpcrGenerator);
> +  DEBUG ((DEBUG_INFO, "SPCR: Unregister Generator. Status = %r\n",
> Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableH
> elper.c
> b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableH
> elper.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..8dc1d6b6f7c6eb71bd0ab16
> b690a9f5b4855dc3d
> --- /dev/null
> +++
> b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableH
> elper.c
> @@ -0,0 +1,165 @@
> +/** @file
> +  Table Helper
> +
> +Copyright (c) 2017, ARM Limited. All rights reserved.
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be
> found at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** The GetCgfMgrInfo function gets the
> CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
> +    object from the Configuration Manager.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> protocol
> +                                interface.
> +    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
> +                                object structure.
> +
> +    @retval EFI_SUCCESS           The object is returned.
> +    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
> +    @retval EFI_NOT_FOUND         The requested Object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetCgfMgrInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST
> CfgMgrProtocol,
> +  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **
> CfgMfrInfo
> +  )
> +{
> +  EFI_STATUS         Status;
> +  CM_OBJ_DESCRIPTOR  CmObjectDesc;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (CfgMfrInfo != NULL);
> +
> +  *CfgMfrInfo = NULL;
> +  Status = CfgMgrProtocol->GetObject (
> +    CfgMgrProtocol,
> +    CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
> +    &CmObjectDesc
> +    );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Get Configuration Manager Info. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  ASSERT (CmObjectDesc.Size >= sizeof
> (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO));
> +  if (CmObjectDesc.Size < sizeof
> (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: EStdObjCfgMgrInfo: Buffer too small, size  = 0x%x\n",
> +      CmObjectDesc.Size
> +      ));
> +    return EFI_BAD_BUFFER_SIZE;
> +  }
> +
> +  *CfgMfrInfo =
> (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO*)CmObjectDesc.Data;
> +  return Status;
> +}
> +
> +/** The AddAcpiHeader function updates the ACPI header structure pointed
> by
> +    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
> +    Manager protocol to obtain any information required for constructing the
> +    header.
> +
> +    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
> +                                   protocol interface.
> +    @param [in]     Generator      Pointer to the ACPI table Generator.
> +    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
> +                                   updated.
> +    @param [in]     Length         Length of the ACPI table.
> +
> +    @retval EFI_SUCCESS           The ACPI table is updated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not
> found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AddAcpiHeader (
> +  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
> +  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
> +  IN      CONST UINT32                                      Length
> +  )
> +{
> +  EFI_STATUS                               Status;
> +  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Generator != NULL);
> +  ASSERT (AcpiHeader != NULL);
> +  ASSERT (Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
> +
> +  if ((CfgMgrProtocol == NULL) ||
> +      (Generator == NULL) ||
> +      (AcpiHeader == NULL) ||
> +      (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))
> +    ) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  /* UINT32  Signature */
> +  AcpiHeader->Signature = Generator->AcpiTableSignature;
> +  /* UINT32  Length */
> +  AcpiHeader->Length = Length;
> +  /* UINT8   Revision */
> +  AcpiHeader->Revision = Generator->AcpiTableRevision;
> +  /* UINT8   Checksum */
> +  AcpiHeader->Checksum = 0;
> +
> +  /* UINT8   OemId[6] */
> +  CopyMem (AcpiHeader->OemId, CfgMfrInfo->OemId, sizeof (AcpiHeader-
> >OemId));
> +
> +  /* UINT64  OemTableId */
> +  AcpiHeader->OemTableId = Generator->CreatorId; // Generator-
> >GeneratorID;
> +  AcpiHeader->OemTableId <<= 32;
> +  AcpiHeader->OemTableId |= Generator->AcpiTableSignature;
> +
> +  /* UINT32  OemRevision */
> +  AcpiHeader->OemRevision = CfgMfrInfo->Revision;
> +
> +  /* UINT32  CreatorId */
> +  AcpiHeader->CreatorId = Generator->CreatorId;
> +  /* UINT32  CreatorRevision */
> +  AcpiHeader->CreatorRevision = Generator->CreatorRevision;
> +
> +  Status = EFI_SUCCESS;
> +error_handler:
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiT
> ableFactory/AcpiTableFactory.c
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiT
> ableFactory/AcpiTableFactory.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..79cf0f290ddb79499c71d6c
> 553b420418dec50f1
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiT
> ableFactory/AcpiTableFactory.c
> @@ -0,0 +1,227 @@
> +/** @file
> +  ACPI Table Factory
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The ACPI table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested ACPI table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetAcpiTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  )
> +{
> +  UINT16                           TableId;
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
> +
> +  ASSERT (This != NULL);
> +
> +  FactoryInfo = This->TableFactoryInfo;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (GeneratorId)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not ACPI\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Generator = NULL;
> +  TableId = GET_TABLE_ID (GeneratorId);
> +  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->StdAcpiTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->StdAcpiTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->CustomAcpiTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->CustomAcpiTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Register ACPI table factory generator.
> +
> +    The ACPI table factory maintains a list of the Standard and OEM ACPI
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterAcpiTableGenerator (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: ACPI register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI register - Generator" \
> +      " Type is not ACPI\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Unregister ACPI generator.
> +
> +    This function is called by the ACPI table generator to unregister itself
> +    from the ACPI table factory.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterAcpiTableGenerator (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: ACPI un-register - Invalid
> Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI un-register - Generator" \
> +      " Type is not ACPI\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] != NULL) {
> +      if (Generator != TableFactoryInfo.StdAcpiTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] != NULL) {
> +      if (Generator !=
> +          TableFactoryInfo.CustomAcpiTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactoryDxe.c
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactoryDxe.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..64a0390cdd006d8e3222ff1
> 9b269d1b4326736c3
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dyna
> micTableFactoryDxe.c
> @@ -0,0 +1,84 @@
> +/** @file
> +  Dynamic Table Factory Dxe
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +/** The Dynamic Table Factory protocol structure that holds the
> +    list of registered ACPI and SMBIOS table generators.
> +*/
> +EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +
> +/** A structure describing the Dynamic Table Factory protocol.
> +*/
> +STATIC
> +CONST
> +EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL DynamicTableFactoryProtocol =
> {
> +  CREATE_REVISION (1, 0),
> +  GetAcpiTableGenerator,
> +  GetSmbiosTableGenerator,
> +  &TableFactoryInfo
> +};
> +
> +/** Entrypoint for Dynamic Table Factory Dxe.
> +
> +    @param  ImageHandle
> +    @param  SystemTable
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +    @retval EFI_NOT_FOUND         Required interface/object was not found.
> +    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
> +
> +*/
> +EFI_STATUS
> +EFIAPI
> +DynamicTableFactoryDxeInitialize (
> +  IN  EFI_HANDLE                 ImageHandle,
> +  IN  EFI_SYSTEM_TABLE   * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = gBS->InstallProtocolInterface (
> +                  &ImageHandle,
> +                  &gEfiDynamicTableFactoryProtocolGuid,
> +                  EFI_NATIVE_INTERFACE,
> +                  (VOID*)&DynamicTableFactoryProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to install the Dynamic Table Factory Protocol." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +  }
> +  return Status;
> +}
> diff --git
> a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Smbi
> osTableFactory/SmbiosTableFactory.c
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Smbi
> osTableFactory/SmbiosTableFactory.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..64b578f30a3413ac2b22ccef
> 4f09368c1af38b67
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Smbi
> osTableFactory/SmbiosTableFactory.c
> @@ -0,0 +1,227 @@
> +/** @file
> +  SMBIOS Table Factory
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +**/
> +
> +#include <Protocol/Smbios.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The SMBIOS table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested SMBIOS table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetSmbiosTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  )
> +{
> +  UINT16                           TableId;
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
> +
> +  ASSERT (This != NULL);
> +
> +  FactoryInfo = This->TableFactoryInfo;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (GeneratorId)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not SMBIOS\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Generator = NULL;
> +  TableId = GET_TABLE_ID (GeneratorId);
> +  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->StdSmbiosTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->StdSmbiosTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->CustomSmbiosTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->CustomSmbiosTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Register SMBIOS table factory generator.
> +
> +    The SMBIOS table factory maintains a list of the Standard and OEM
> SMBIOS
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterSmbiosTableGenerator (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS register - Invalid
> Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SMBIOS register - Generator" \
> +      " Type is not SMBIOS\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] =
> Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Unregister SMBIOS generator.
> +
> +    This function is called by the SMBIOS table generator to unregister itself
> +    from the SMBIOS table factory.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterSmbiosTableGenerator (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS un-register - Invalid
> Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SMBIOS un-register - Generator" \
> +      " Type is not SMBIOS\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] != NULL) {
> +      if (Generator != TableFactoryInfo.StdSmbiosTableGeneratorList[TableId])
> {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] != NULL) {
> +      if (Generator !=
> +          TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyn
> amicTableManagerDxe.c
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dy
> namicTableManagerDxe.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..f84bf3bef910ddf86629062d
> 6d1ca1dffafa5a28
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dy
> namicTableManagerDxe.c
> @@ -0,0 +1,531 @@
> +/** @file
> +  Dynamic Table Manager Dxe
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the
> BSD License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** This macro expands to a function that retrieves the ACPI Table
> +    List from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceStandard,
> +  EStdObjAcpiTableList,
> +  CM_STD_OBJ_ACPI_TABLE_INFO
> +  )
> +
> +/** A helper function to invoke a Table generator
> +
> +    This is a helper function that invokes the Table generator interface
> +    for building an ACPI table. It uses the AcpiTableProtocol to install the
> +    table, then frees the resources allocated for generating it.
> +
> +    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> +                                      interface.
> +    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> +                                      Protocol Interface.
> +    @param [in]  AcpiTableProtocol    Pointer to the AcpiTable protocol.
> +    @param [in]  AcpiTableInfo        Pointer to the ACPI table Info.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         Required object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   Size returned by the Configuration
> Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildAndInstallAcpiTable (
> +  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST
> TableFactoryProtocol,
> +  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol,
> +  IN       EFI_ACPI_TABLE_PROTOCOL             *       AcpiTableProtocol,
> +  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  CONST ACPI_TABLE_GENERATOR  * Generator = NULL;
> +  EFI_ACPI_DESCRIPTION_HEADER * AcpiTable;
> +  UINTN                         TableHandle;
> +
> +  ASSERT (TableFactoryProtocol != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableProtocol != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: EStdObjAcpiTableList: Address = 0x%p," \
> +    " TableGeneratorId = 0x%x\n",
> +    AcpiTableInfo,
> +    AcpiTableInfo->TableGeneratorId
> +    ));
> +
> +  Status = TableFactoryProtocol->GetAcpiTableGenerator (
> +                                   TableFactoryProtocol,
> +                                   AcpiTableInfo->TableGeneratorId,
> +                                   &Generator
> +                                   );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Table Generator not found." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  ASSERT (Generator != NULL);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: Generator found : %s\n",
> +    Generator->Description
> +    ));
> +
> +  if (Generator->BuildAcpiTable == NULL) {
> +    Status = EFI_INVALID_PARAMETER;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Table Generator does not implement the" \
> +      " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  AcpiTable = NULL;
> +  Status = Generator->BuildAcpiTable (
> +                        Generator,
> +                        AcpiTableInfo,
> +                        CfgMgrProtocol,
> +                        &AcpiTable
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Build Table." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    // Free any allocated resources.
> +    goto error_handler;
> +  }
> +
> +  ASSERT (AcpiTable != NULL);
> +
> +  // Dump ACPI Table Header
> +  DUMP_ACPI_TABLE_HEADER (AcpiTable);
> +
> +  // Install ACPI table
> +  Status = AcpiTableProtocol->InstallAcpiTable (
> +                                AcpiTableProtocol,
> +                                AcpiTable,
> +                                AcpiTable->Length,
> +                                &TableHandle
> +                                );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Install ACPI Table. Status = %r\n",
> +      Status
> +      ));
> +    // Free any allocated resources.
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: ACPI Table installed. Status = %r\n",
> +    Status
> +    ));
> +
> +error_handler:
> +  // Free any resources allocated for generating the tables.
> +  if ((AcpiTable != NULL) && (Generator->FreeTableResources != NULL)) {
> +    Status = Generator->FreeTableResources (
> +                          Generator,
> +                          AcpiTableInfo,
> +                          CfgMgrProtocol,
> +                          &AcpiTable
> +                          );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: Failed to Free Table Resources." \
> +        "TableGeneratorId = 0x%x. Status = %r\n",
> +        AcpiTableInfo->TableGeneratorId,
> +        Status
> +        ));
> +    }
> +  }
> +  return Status;
> +}
> +
> +/** The function checks if the Configuration Manager has provided the
> +    mandatory ACPI tables for installation.
> +
> +    @param [in]  AcpiTableInfo      Pointer to the ACPI Table Info list.
> +    @param [in]  AcpiTableCount     Count of ACPI Table Info.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_NOT_FOUND         If mandatory table is not found.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +VerifyMandatoryTablesArePresent (
> +  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO  * CONST AcpiTableInfo,
> +  IN CONST UINTN                               AcpiTableCount
> +  )
> +{
> +  EFI_STATUS  Status = EFI_SUCCESS;
> +  BOOLEAN     FadtFound = FALSE;
> +  BOOLEAN     MadtFound = FALSE;
> +  BOOLEAN     GtdtFound = FALSE;
> +  BOOLEAN     DsdtFound = FALSE;
> +  BOOLEAN     Dbg2Found = FALSE;
> +  BOOLEAN     SpcrFound = FALSE;
> +  UINTN       idx;
> +
> +  ASSERT (AcpiTableInfo != NULL);
> +
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    switch (AcpiTableInfo[idx].AcpiTableSignature) {
> +      case EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
> +        FadtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
> +        MadtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:
> +        GtdtFound = TRUE;
> +        break;
> +      case
> EFI_ACPI_6_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
> +        DsdtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE:
> +        Dbg2Found = TRUE;
> +        break;
> +      case
> EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
> +        SpcrFound = TRUE;
> +        break;
> +      default:
> +        break;
> +    }
> +  }
> +
> +  // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
> +  if (!FadtFound) {
> +    DEBUG ((DEBUG_ERROR,"ERROR: FADT Table not found\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!MadtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!GtdtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!DsdtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!Dbg2Found) {
> +    DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));
> +  }
> +  if (!SpcrFound) {
> +    DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));
> +  }
> +  return Status;
> +}
> +
> +/** Generate and install ACPI tables.
> +
> +    The function gathers the information necessary for installing the
> +    ACPI tables from the Configuration Manager, invokes the generators
> +    and installs them (via BuildAndInstallAcpiTable).
> +
> +    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> +                                      interface.
> +    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> +                                      Protocol Interface.
> +
> +
> +    @retval EFI_SUCCESS   Success.
> +    @retval EFI_NOT_FOUND If a mandatory table or a generator is not
> found.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +ProcessAcpiTables (
> +  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST
> TableFactoryProtocol,
> +  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST
> CfgMgrProtocol
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_ACPI_TABLE_PROTOCOL     * AcpiTableProtocol;
> +  UINTN                         AcpiTableCount;
> +  CM_STD_OBJ_ACPI_TABLE_INFO  * AcpiTableInfo;
> +  UINTN                         idx;
> +
> +  ASSERT (TableFactoryProtocol != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Find the AcpiTable protocol
> +  Status = gBS->LocateProtocol (
> +                  &gEfiAcpiTableProtocolGuid,
> +                  NULL,
> +                  (VOID**)&AcpiTableProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Status = GetEStdObjAcpiTableList (
> +             CfgMgrProtocol,
> +             &AcpiTableInfo,
> +             &AcpiTableCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get ACPI Table List. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  if (0 == AcpiTableCount) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
> +      AcpiTableCount
> +      ));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
> +    AcpiTableCount
> +    ));
> +
> +  // Check if mandatory ACPI tables are present.
> +  Status = VerifyMandatoryTablesArePresent (
> +             AcpiTableInfo,
> +             AcpiTableCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find mandatory ACPI Table(s)."
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  // Add the FADT Table first.
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
> +        AcpiTableInfo[idx].TableGeneratorId) {
> +      Status = BuildAndInstallAcpiTable (
> +                 TableFactoryProtocol,
> +                 CfgMgrProtocol,
> +                 AcpiTableProtocol,
> +                 &AcpiTableInfo[idx]
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "ERROR: Failed to find build and install ACPI FADT Table." \
> +          " Status = %r\n",
> +          Status
> +          ));
> +        return Status;
> +      }
> +      break;
> +    }
> +  } // for
> +
> +  // Add remaining ACPI Tables
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
> +      idx,
> +      AcpiTableInfo[idx].TableGeneratorId
> +      ));
> +
> +    // Skip FADT Table since we have already added
> +    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
> +        AcpiTableInfo[idx].TableGeneratorId) {
> +      continue;
> +    }
> +
> +    // Skip the Reserved table Generator ID
> +    if ((CREATE_STD_ACPI_TABLE_GEN_ID
> (ESTD_ACPI_TABLE_ID_RESERVED) >=
> +           AcpiTableInfo[idx].TableGeneratorId)                     ||
> +        (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MAX)      <=
> +           AcpiTableInfo[idx].TableGeneratorId)) {
> +      DEBUG ((
> +        DEBUG_WARN,
> +        "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
> +        AcpiTableInfo[idx].TableGeneratorId
> +        ));
> +      continue;
> +    }
> +
> +    Status = BuildAndInstallAcpiTable (
> +               TableFactoryProtocol,
> +               CfgMgrProtocol,
> +               AcpiTableProtocol,
> +               &AcpiTableInfo[idx]
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: Failed to find, build, and install ACPI Table." \
> +        " Status = %r\n",
> +        Status
> +        ));
> +      return Status;
> +    }
> +  } // for
> +
> +  return Status;
> +}
> +
> +/** Entrypoint of Dynamic Table Manager Dxe.
> +
> +  The Dynamic Table Manager uses the Configuration Manager Protocol
> +  to get the list of ACPI and SMBIOS tables to install. For each table
> +  in the list it requests the corresponding ACPI/SMBIOS table factory for
> +  a generator capable of building the ACPI/SMBIOS table.
> +  If a suitable table generator is found, it invokes the generator interface
> +  to build the table. The Dynamic Table Manager then installs the
> +  table and invokes another generator interface to free any resources
> +  allocated for building the table.
> +
> +    @param  ImageHandle
> +    @param  SystemTable
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +    @retval EFI_NOT_FOUND         Required interface/object was not found.
> +    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
> +
> +*/
> +EFI_STATUS
> +EFIAPI
> +DynamicTableManagerDxeInitialize (
> +  IN CONST EFI_HANDLE                 ImageHandle,
> +  IN       EFI_SYSTEM_TABLE   * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS                               Status;
> +  EFI_CONFIGURATION_MANAGER_PROTOCOL     * CfgMgrProtocol;
> +  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
> +  EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL     * TableFactoryProtocol;
> +
> +  // Locate the Dynamic Table Factory
> +  Status = gBS->LocateProtocol (
> +                  &gEfiDynamicTableFactoryProtocolGuid,
> +                  NULL,
> +                  (VOID**)&TableFactoryProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find Dynamic Table Factory protocol." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  // Locate the Configuration Manager for the Platform
> +  Status = gBS->LocateProtocol (
> +                  &gEfiConfigurationManagerProtocolGuid,
> +                  NULL,
> +                  (VOID**)&CfgMgrProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: Configuration Manager Version = 0x%x, OemID
> = %c%c%c%c%c%c\n",
> +    CfgMfrInfo->Revision,
> +    CfgMfrInfo->OemId[0],
> +    CfgMfrInfo->OemId[1],
> +    CfgMfrInfo->OemId[2],
> +    CfgMfrInfo->OemId[3],
> +    CfgMfrInfo->OemId[4],
> +    CfgMfrInfo->OemId[5]
> +    ));
> +
> +  Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI Table processing failure. Status = %r\n",
> +      Status
> +      ));
> +  }
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..69012cf8242c8ddd13ac403
> 3293ac8a7053dfbd8
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> @@ -0,0 +1,35 @@
> +## @file
> +#  fdf include file for Dynamic Tables Framework.
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution.  The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +
> +###############################################################
> #################
> +#
> +# FV Section
> +#
> +# [FV] section is used to define what components or modules are placed
> within a flash
> +# device file.  This section also defines order the components and modules
> are positioned
> +# within the image.  The [FV] section consists of define statements, set
> statements and
> +# module statements.
> +#
> +###############################################################
> #################
> +
> +  #
> +  # Dynamic Table Factory Dxe
> +  #
> +  INF
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactoryDxe.inf
> +
> +  #
> +  # Dynamic Tables Dxe
> +  #
> +  INF
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyna
> micTableManagerDxe.inf
> --
> Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Dynamic Tables
  2017-10-02 19:47 [PATCH 0/2] Dynamic Tables evan.lloyd
  2017-10-02 19:47 ` [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework evan.lloyd
  2017-10-02 19:47 ` [PATCH 2/2] [edk2-platforms] Platform/ARM: Dynamic Tables support for FVP evan.lloyd
@ 2017-10-03 17:12 ` Evan Lloyd
  2017-10-10  2:29 ` Yao, Jiewen
  3 siblings, 0 replies; 14+ messages in thread
From: Evan Lloyd @ 2017-10-03 17:12 UTC (permalink / raw)
  To: Evan Lloyd, edk2-devel@lists.01.org
  Cc: "Matteo.Carlini@arm.com"@arm.com,
	"nd@arm.com"@arm.com,
	"ard.biesheuvel@linaro.org"@arm.com,
	"thomas.abraham@arm.com"@arm.com,
	"Arvind.Chauhan@arm.com"@arm.com,
	"leif.lindholm@linaro.org"@arm.com,
	"Daniil.Egranov@arm.com"@arm.com

I omitted some info here.
The code can be examined at:
https://github.com/EvanLloyd/tianocore/tree/139_dynamic_tables_v1
and
https://github.com/EvanLloyd/edk2-platforms/tree/139_dynamic_tables_v1

Evan

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> evan.lloyd@arm.com
> Sent: 02 October 2017 20:48
> To: edk2-devel@lists.01.org
> Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com;
> "ard.biesheuvel@linaro.org"@arm.com; "Stephanie.Hughes-
> Fitt@arm.com"@arm.com; "thomas.abraham@arm.com"@arm.com;
> "Arvind.Chauhan@arm.com"@arm.com;
> "leif.lindholm@linaro.org"@arm.com;
> "Daniil.Egranov@arm.com"@arm.com
> Subject: [edk2] [PATCH 0/2] Dynamic Tables
>
> From: EvanLloyd <evan.lloyd@arm.com>
>
> Historically, ACPI code, SMBIOS tables, and UEFI firmware were often
> developed in isolation from each other.  This introduced several problems,
> not least of which was duplication of platform information between the
> various source trees.
> In addition, variants of platforms introduced a plethora of alternative builds
> of ACPI, SMBIOS and EDK2, with the concomitant risk of getting the mixture
> wrong in a build.
>
> In the effort to resolve these problems, the solution prototyped here was
> devised.  The basic idea is to obtain the "variant"
> information from a management node.  That means the firmware image can
> be platform independent, with ACPI, SMBIOS (and potentially
> other) tables generated with information from the management node.  This
> example has the framework for that, but the configuration information is
> supplied directly, as an interim solution until a suitable management node
> implementation exists yet.

[[Evan Lloyd]] Oops, sorry about the superfluous yet.
>
>
> Sami Mujawar (1):
>   MdeModulePkg: Dynamic Tables Framework
>
>  MdeModulePkg/MdeModulePkg.dec                                                                       |
> 13 +
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> |  45 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg
> 2LibArm.inf                       |  49 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadt
> LibArm.inf                       |  47 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdt
> LibArm.inf                       |  46 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMa
> dtLibArm.inf                       |  47 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcf
> gLibArm.inf                       |  47 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRaw
> LibArm.inf                         |  44 ++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcr
> LibArm.inf                       |  44 ++
>
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelp
> erLib.inf                         |  39 ++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactoryDxe.inf              |  57 ++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyna
> micTableManagerDxe.inf              |  47 ++
>  MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> | 280 ++++++++
>  MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> | 367 ++++++++++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> | 112 +++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> | 158 +++++
>  MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> | 235 +++++++
>  MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> |  93 +++
>  MdeModulePkg/Include/DynamicTables/TableGenerator.h
> | 235 +++++++
>  MdeModulePkg/Include/Library/TableHelperLib.h
> |  67 ++
>  MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> | 121 ++++
>  MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> | 113 +++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactory.h                   |  91 +++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Ge
> nerator.c                          | 440 ++++++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGen
> erator.c                          | 562 +++++++++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGen
> erator.c                          | 652 +++++++++++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGe
> nerator.c                          | 732 ++++++++++++++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGe
> nerator.c                          | 336 +++++++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGen
> erator.c                            | 177 +++++
>
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGen
> erator.c                          | 323 +++++++++
>
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelp
> er.c                              | 165 +++++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTa
> bleFactory/AcpiTableFactory.c     | 227 ++++++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactoryDxe.c                |  84 +++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Smbios
> TableFactory/SmbiosTableFactory.c | 227 ++++++
>
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyna
> micTableManagerDxe.c                | 531 ++++++++++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> |  35 +
>  36 files changed, 6888 insertions(+)
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg
> 2LibArm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadt
> LibArm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdt
> LibArm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMa
> dtLibArm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcf
> gLibArm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRaw
> LibArm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcr
> LibArm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelp
> erLib.inf
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactoryDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyna
> micTableManagerDxe.inf
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/TableGenerator.h
>  create mode 100644 MdeModulePkg/Include/Library/TableHelperLib.h
>  create mode 100644
> MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
>  create mode 100644
> MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactory.h
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Ge
> nerator.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGen
> erator.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGen
> erator.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGe
> nerator.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGe
> nerator.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGen
> erator.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGen
> erator.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelp
> er.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTa
> bleFactory/AcpiTableFactory.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Dynami
> cTableFactoryDxe.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/Smbios
> TableFactory/SmbiosTableFactory.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/Dyna
> micTableManagerDxe.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
>
> --
> Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
  2017-10-03 16:03     ` Leif Lindholm
@ 2017-10-03 18:44       ` Sean Brogan
  0 siblings, 0 replies; 14+ messages in thread
From: Sean Brogan @ 2017-10-03 18:44 UTC (permalink / raw)
  To: Leif Lindholm, Zeng, Star
  Cc: thomas.abraham@arm.com, ard.biesheuvel@linaro.org,
	edk2-devel@lists.01.org, Arvind.Chauhan@arm.com, Yao, Jiewen,
	Kinney, Michael D

This looks like an interesting proposal but I would like to see it created in a new package rather than continuing to encourage the monolithic MdeModulePkg.  Could this be a candidate for a new "feature" package?   It seems to have enough content and growth potential to warrant a package of its own.  

Thanks
Sean

 

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Leif Lindholm
Sent: Tuesday, October 3, 2017 9:04 AM
To: Zeng, Star <star.zeng@intel.com>
Cc: thomas.abraham@arm.com; ard.biesheuvel@linaro.org; edk2-devel@lists.01.org; leif.lindholm@linaro.org; Arvind.Chauhan@arm.com; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Subject: Re: [edk2] [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework

(something funky going on with email addresses on cc, I've adjusted here)

On Tue, Oct 03, 2017 at 02:34:52PM +0000, Zeng, Star wrote:
> May I ask you are proposing
> edk2-platforms(https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Fedk2-platforms&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347135677&sdata=7e3uXgai8UowRlEh8eakX%2FJvo35fO6q5z5n31qgr1X0%3D&reserved=0) change
> or edk2 master(https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Fedk2&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347135677&sdata=EIpLHlZrsJpCZOBMhVDqz9Tf739WyAHc8NqwaTOHZRM%3D&reserved=0) change?

MdeModulePkg exists only in edk2, so that is the intended target.
(I expect to be back to patch reviewing again tomorrow.)

Best Regards,

Leif

> Please note, we may have no/occasional email response during PRC holiday (10/1 - 10/8).
> 
> Thanks,
> Star
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of evan.lloyd@arm.com
> Sent: Tuesday, October 3, 2017 3:48 AM
> To: edk2-devel@lists.01.org
> Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com; "ard.biesheuvel@linaro.org"@arm.com; "thomas.abraham@arm.com"@arm.com; "Arvind.Chauhan@arm.com"@arm.com; "leif.lindholm@linaro.org"@arm.com; "Daniil.Egranov@arm.com"@arm.com
> Subject: [edk2] [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
> 
> From: Sami Mujawar <sami.mujawar@arm.com>
> 
> The dynamic tables framework is designed to generate standardised
> firmware tables that describe the hardware information at
> run-time. A goal of standardised firmware is to have a common
> firmware for a platform capable of booting both Windows and Linux
> operating systems.
> 
> Traditionally the firmware tables are handcrafted using ACPI
> Machine Language (AML), Table Definition Language (TDL) and
> C-code. This approach can be error prone and involves time
> consuming debugging. In addition, it may be desirable to configure
> platform hardware at runtime such as: configuring the number of
> cores available for use by the OS, or turning SoC features ON or
> OFF.
> 
> The dynamic tables framework simplifies this by providing a set
> of standard table generators, that are implemented as libraries.
> These generators query a platform specific component, the
> 'Configuration Manager', to collate the information required
> for generating the tables at run-time.
> 
> The framework also provisions the ability to implement custom/OEM
> generators; thereby facilitating support for custom tables. The
> custom generators can also utilize the existing standard generators
> and override any functionality if needed.
> 
> The framework currently implements a set of standard ACPI table
> generators for ARM architecture, that can generate Server Base Boot
> Requirement (SBBR) compliant tables. Support for generating SMBIOS
> tables is planned to be added subsequently. Although, the set
> of standard generators implements the functionality required for ARM
> architecture; the framework is extensible, and support for other
> architectures can be easily added.
> 
> Contributions from the community are invited.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> Signed-off-by: Evan Lloyd <evan.lloyd@arm.com>
> ---
>  MdeModulePkg/MdeModulePkg.dec                                                                       |  13 +
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc                                          |  45 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf                       |  49 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf                       |  47 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf                       |  46 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf                       |  47 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf                       |  47 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf                         |  44 ++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf                       |  44 ++
>  MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf                         |  39 ++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf              |  57 ++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf              |  47 ++
>  MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h                                             | 280 ++++++++
>  MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h                                            | 367 ++++++++++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h                                     | 112 +++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h                                     | 158 +++++
>  MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h                                           | 235 +++++++
>  MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h                                       |  93 +++
>  MdeModulePkg/Include/DynamicTables/TableGenerator.h                                                 | 235 +++++++
>  MdeModulePkg/Include/Library/TableHelperLib.h                                                       |  67 ++
>  MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h                                        | 121 ++++
>  MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h                                         | 113 +++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h                   |  91 +++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c                          | 440 ++++++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c                          | 562 +++++++++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c                          | 652 +++++++++++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c                          | 732 ++++++++++++++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c                          | 336 +++++++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c                            | 177 +++++
>  MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c                          | 323 +++++++++
>  MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c                              | 165 +++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c     | 227 ++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c                |  84 +++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c | 227 ++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c                | 531 ++++++++++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc                                          |  35 +
>  36 files changed, 6888 insertions(+)
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
> index a3c0633ee1ec6ab7540a1b7221850e975f95ad80..de8a658c21d11ab1396bb543b026f94a396a0710 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -7,6 +7,7 @@
>  # Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
>  # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
>  # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +# Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
>  #
>  # This program and the accompanying materials are licensed and made available under
>  # the terms and conditions of the BSD License that accompanies this distribution.
> @@ -556,6 +557,12 @@ [Protocols]
>    ## Include/Protocol/IoMmu.h
>    gEdkiiIoMmuProtocolGuid = { 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed, 0xe6, 0xe1, 0xce, 0x51, 0x7c, 0x1e } }
>  
> +  # Configuration Manager Protocol GUID
> +  gEfiConfigurationManagerProtocolGuid = { 0xd85a4835, 0x5a82, 0x4894, { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } }
> +
> +  # Dynamic Table Factory Protocol GUID
> +  gEfiDynamicTableFactoryProtocolGuid = { 0x91d1e327, 0xfe5a, 0x49b8, { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec } }
> +
>  #
>  # [Error.gEfiMdeModulePkgTokenSpaceGuid]
>  #   0x80000001 | Invalid value provided.
> @@ -867,6 +874,12 @@ [PcdsFixedAtBuild]
>    # @ValidList  0x80000006 | 0x03058002
>    gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UINT32|0x30001040
>  
> +  # Maximum number of Custom ACPI Generators
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators|1|UINT16|0xC0000001
> +
> +  # Maximum number of Custom SMBIOS Generators
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators|1|UINT16|0xC0000002
> +
>  [PcdsFixedAtBuild, PcdsPatchableInModule]
>    ## Dynamic type PCD can be registered callback function for Pcd setting action.
>    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> new file mode 100644
> index 0000000000000000000000000000000000000000..548c77ad971f97c43da8f7ba1b69fa6948430c17
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> @@ -0,0 +1,45 @@
> +## @file
> +#  Dsc include file for Dynamic Tables Framework.
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +
> +[BuildOptions]
> +  *_*_*_ASL_FLAGS          = -th -li
> +
> +[LibraryClasses.common]
> +
> +[Components.common]
> +  #
> +  # Dynamic Table Factory Dxe
> +  #
> +  MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf {
> +    <LibraryClasses>
> +      TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
> +      NULL|MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
> +  }
> +
> +  #
> +  # Dynamic Tables Manager Dxe
> +  #
> +  MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf {
> +    <LibraryClasses>
> +      TableHelperLib|MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
> +  }
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..591b6364ae86c885ca4768599d3eadf6d2842eff
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
> @@ -0,0 +1,49 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiDbg2LibArm
> +  FILE_GUID      = A17BA4F0-3DEB-4FE5-BD27-EC008E541B22
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiDbg2LibConstructor
> +  DESTRUCTOR     = AcpiDbg2LibDestructor
> +
> +
> +[Sources]
> +  Dbg2Generator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  SerialPortLib
> +
> +[FixedPcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
> +  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..ae5239fd2a3e6f00574cf5f3bb4a561031e122be
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiFadtLibArm
> +  FILE_GUID      = 686FE5FE-B944-485F-8B1C-7D60E0056487
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiFadtLibConstructor
> +  DESTRUCTOR     = AcpiFadtLibDestructor
> +
> +
> +[Sources]
> +  FadtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..be38489c2987a81d68effd9c05b731b17cb2819c
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
> @@ -0,0 +1,46 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiGtdtLibArm
> +  FILE_GUID      = 26490F7A-7FA2-423C-8939-C6206329BC37
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiGtdtLibConstructor
> +  DESTRUCTOR     = AcpiGtdtLibDestructor
> +
> +
> +[Sources]
> +  GtdtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[FixedPcd]
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..9807e3fe75bb785c3b400410248e6434532f2147
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiMadtLibArm
> +  FILE_GUID      = AF76C93B-41B5-454D-83CD-D2A80A1C1E38
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiMadtLibConstructor
> +  DESTRUCTOR     = AcpiMadtLibDestructor
> +
> +
> +[Sources]
> +  MadtGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..2f879dfee4b93a56a923340c4b416c6df9656618
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiMcfgLibArm
> +  FILE_GUID      = 8C9BDCB2-72D4-4F30-A12D-1145C3807FF7
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiMcfgLibConstructor
> +  DESTRUCTOR     = AcpiMcfgLibDestructor
> +
> +
> +[Sources]
> +  McfgGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> +
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..db208bdeb8ffce085367ee865766a0a1bd90cb28
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> @@ -0,0 +1,44 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiRawLibArm
> +  FILE_GUID      = 20F31568-D687-49BA-B326-CCD9D38EDE16
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiRawLibConstructor
> +  DESTRUCTOR     = AcpiRawLibDestructor
> +
> +
> +[Sources]
> +  RawGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..3d47e6ae1f7995f76fe3e93093b0185e48ecae79
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
> @@ -0,0 +1,44 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = AcpiSpcrLibArm
> +  FILE_GUID      = 55088136-7B78-4974-B1EE-F630150D0DE7
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiSpcrLibConstructor
> +  DESTRUCTOR     = AcpiSpcrLibDestructor
> +
> +
> +[Sources]
> +  SpcrGenerator.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Pcd]
> +
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..38952fba1c8056bf0c581975ca974abbef1e8096
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLib.inf
> @@ -0,0 +1,39 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010019
> +  BASE_NAME      = DynamicTableHelperLib
> +  FILE_GUID      = E315C738-3A39-4D0D-A0AF-8EDFA770AB39
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = TableHelperLib
> +
> +
> +[Sources]
> +  TableHelper.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> +[Protocols]
> +
> +
> +[Guids]
> +
> +
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..c58ac3a8d6d655e38cb8460a35ce256fc4e5ada6
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
> @@ -0,0 +1,57 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010016
> +  BASE_NAME                      = DynamicTableFactoryDxe
> +  FILE_GUID                      = FE846898-7403-4932-B8AD-A0491F0C2CBA
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DynamicTableFactoryDxeInitialize
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = ARM AARCH64
> +#
> +
> +[Sources]
> +  DynamicTableFactoryDxe.c
> +  AcpiTableFactory/AcpiTableFactory.c
> +  SmbiosTableFactory/SmbiosTableFactory.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  PrintLib
> +  BaseLib
> +  MemoryAllocationLib
> +  TableHelperLib
> +
> +[FixedPcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators
> +
> +[Protocols]
> +  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
> +  gEfiSmbiosProtocolGuid                        # PROTOCOL ALWAYS_CONSUMED
> +  gEfiConfigurationManagerProtocolGuid
> +  gEfiDynamicTableFactoryProtocolGuid
> +
> +[Depex]
> +  TRUE
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..9c5a5f6207687ca90fa11188340d09c304fc34c0
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010016
> +  BASE_NAME                      = DynamicTableManagerDxe
> +  FILE_GUID                      = 89122868-BCFD-49E8-88A3-06635CB7B3CF
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DynamicTableManagerDxeInitialize
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = ARM AARCH64
> +#
> +
> +[Sources]
> +  DynamicTableManagerDxe.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  PrintLib
> +  TableHelperLib
> +
> +[Protocols]
> +  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
> +  gEfiConfigurationManagerProtocolGuid
> +  gEfiDynamicTableFactoryProtocolGuid
> +
> +[Depex]
> +  TRUE
> diff --git a/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..3a07cd6e10217958d22a93060a0f9aa48947f264
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> @@ -0,0 +1,280 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef ACPI_TABLE_GENERATOR_H_
> +#define ACPI_TABLE_GENERATOR_H_
> +
> +#pragma pack(1)
> +
> +/**
> +The Dynamic Tables Framework provisions two classes of ACPI table
> +generators.
> + - Standard generators: The ACPI table generators implemented by the
> +                        Dynamic Tables Framework.
> + - OEM generators:      The ACPI table generatos customized by the OEM.
> +
> +The Dynamic Tables Framework implements the following ACPI table generators:
> +  - RAW   : This is the simplest ACPI table generator. It simply installs
> +            the ACPI table provided in the AcpiTableData member of the
> +            CM_STD_OBJ_ACPI_TABLE_INFO. The ACPI table data is provided by
> +            the Configuration Manager and is generated using an implementation
> +            defined mechanism.
> +  - DSDT  : The DSDT generator is clone of the RAW generator. The difference
> +            is in the way the ACPI Table Data is generated from an AML file.
> +  - SSDT  : The SSDT generator is clone of the RAW generator. The difference
> +            is in the way the ACPI Table Data is generated from an AML file.
> +  - FADT  : The FADT generator collates the required platform information for
> +            building the ACPI FADT table from the Configuration Manager and
> +            generates the FADT table.
> +  - MADT  : The MADT generator collates the GIC information for building the
> +            ACPI MADT table from the Configuration Manager and generates the
> +            MADT table.
> +  - GTDT  : The GTDT generator collates the Timer information for building the
> +            ACPI GTDT table from the Configuration Manager and generates the
> +            GTDT table.
> +  - DBG2  : The DBG2 generator collates the debug serial port information for
> +            building the DBG2 table from the Configuration Manager and
> +            generates the GTDT table.
> +  - SPCR  : The SPCR generator collates the serial port information for
> +            building the SPCR table from the Configuration Manager and
> +            generates the SPCR table.
> +  - MCFG  : The MCFG generator collates the PCI configuration space information
> +            for building the MCFG table from the Configuration Manager and
> +            generates the MCFG table.
> +*/
> +
> +/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
> +*/
> +typedef TABLE_GENERATOR_ID ACPI_TABLE_GENERATOR_ID;
> +
> +/** The ESTD_ACPI_TABLE_ID enum describes the ACPI table IDs reserved for
> +  the standard generators.
> +*/
> +typedef enum StdAcpiTableId {
> +  ESTD_ACPI_TABLE_ID_RESERVED = 0x0000,             ///< Reserved.
> +  ESTD_ACPI_TABLE_ID_RAW,                           ///< RAW Generator.
> +  ESTD_ACPI_TABLE_ID_DSDT = ESTD_ACPI_TABLE_ID_RAW, ///< DSDT Generator.
> +  ESTD_ACPI_TABLE_ID_SSDT = ESTD_ACPI_TABLE_ID_RAW, ///< SSDT Generator.
> +  ESTD_ACPI_TABLE_ID_FADT,                          ///< FADT Generator.
> +  ESTD_ACPI_TABLE_ID_MADT,                          ///< MADT Generator.
> +  ESTD_ACPI_TABLE_ID_GTDT,                          ///< GTDT Generator.
> +  ESTD_ACPI_TABLE_ID_DBG2,                          ///< DBG2 Generator.
> +  ESTD_ACPI_TABLE_ID_SPCR,                          ///< SPCR Generator.
> +  ESTD_ACPI_TABLE_ID_MCFG,                          ///< MCFG Generator.
> +  ESTD_ACPI_TABLE_ID_MAX
> +} ESTD_ACPI_TABLE_ID;
> +
> +/** This macro checks if the Table Generator ID is for an ACPI Table Generator.
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the table generator ID is for an ACPI Table
> +          Generator.
> +*/
> +#define IS_GENERATOR_TYPE_ACPI(TableGeneratorId) \
> +          (GET_TABLE_TYPE (TableGeneratorId) == ETableGeneratorTypeAcpi)
> +
> +/** This macro checks if the Table Generator ID is for a standard ACPI
> +    Table Generator.
> +
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the table generator ID is for a standard ACPI
> +            Table Generator.
> +*/
> +#define IS_VALID_STD_ACPI_GENERATOR_ID(TableGeneratorId)               \
> +          (                                                            \
> +          IS_GENERATOR_NAMESPACE_STD (TableGeneratorId) &&             \
> +          IS_GENERATOR_TYPE_ACPI (TableGeneratorId)     &&             \
> +          ((GET_TABLE_ID (GeneratorId) >= ESTD_ACPI_TABLE_ID_RAW) &&   \
> +           (GET_TABLE_ID (GeneratorId) < ESTD_ACPI_TABLE_ID_MAX))      \
> +          )
> +
> +/** This macro creates a standard ACPI Table Generator ID.
> +
> +    @param [in] TableId  The table generator ID.
> +
> +    @returns a standard ACPI table generator ID.
> +*/
> +#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId) \
> +          CREATE_TABLE_GEN_ID (               \
> +            ETableGeneratorTypeAcpi,          \
> +            ETableGeneratorNameSpaceStd,      \
> +            TableId                           \
> +            )
> +
> +/** The Creator ID for the ACPI tables generated using
> +  the standard ACPI table generators.
> +*/
> +#define TABLE_GENERATOR_CREATOR_ID_ARM  SIGNATURE_32('A', 'R', 'M', 'H')
> +
> +/** A macro to initialise the common header part of EFI ACPI tables as
> +    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
> +
> +    @param [in] Signature The ACPI table signature.
> +    @param [in] Type      The ACPI table structure.
> +    @param [in] Revision  The ACPI table revision.
> +*/
> +#define ACPI_HEADER(Signature, Type, Revision) {              \
> +          Signature,             /* UINT32  Signature */      \
> +          sizeof (Type),         /* UINT32  Length */         \
> +          Revision,              /* UINT8   Revision */       \
> +          0,                     /* UINT8   Checksum */       \
> +          { 0, 0, 0, 0, 0, 0 },  /* UINT8   OemId[6] */       \
> +          0,                     /* UINT64  OemTableId */     \
> +          0,                     /* UINT32  OemRevision */    \
> +          0,                     /* UINT32  CreatorId */      \
> +          0                      /* UINT32  CreatorRevision */\
> +          }
> +
> +/** A macro to dump the common header part of EFI ACPI tables as
> +    defined by the EFI_ACPI_DESCRIPTION_HEADER structure.
> +
> +    @param [in] AcpiHeader The pointer to the ACPI table header.
> +*/
> +#define DUMP_ACPI_TABLE_HEADER(AcpiHeader)                        \
> +          DEBUG ((                                                \
> +            DEBUG_INFO,                                           \
> +            "ACPI TABLE %c%c%c%c : Rev 0x%x : Length : 0x%x\n",   \
> +            (AcpiHeader->Signature & 0xFF),                       \
> +            ((AcpiHeader->Signature >> 8) & 0xFF),                \
> +            ((AcpiHeader->Signature >> 16) & 0xFF),               \
> +            ((AcpiHeader->Signature >> 24) & 0xFF),               \
> +            AcpiHeader->Revision,                                 \
> +            AcpiHeader->Length                                    \
> +            ));
> +
> +/** Forward declarations.
> +*/
> +typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct CmAStdObjAcpiTableInfo       CM_STD_OBJ_ACPI_TABLE_INFO;
> +typedef struct AcpiTableGenerator           ACPI_TABLE_GENERATOR;
> +
> +/** This function pointer describes the interface to ACPI table build
> +    functions provided by the ACPI table generator and called by the
> +    Table Manager to build an ACPI table.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [out] Table           Pointer to the generated ACPI table.
> +
> +    @returns  EFI_SUCCESS If the table is generated successfully or other
> +                          failure codes as returned by the generator.
> +*/
> +typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_BUILD_TABLE) (
> +  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        **       Table
> +  );
> +
> +/** This function pointer describes the interface to used by the
> +    Table Manager to give the generator an opportunity to free
> +    any resources allocated for building the ACPI table.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +    @param [in]  AcpiTableInfo   Pointer to the ACPI table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [in]  Table           Pointer to the generated ACPI table.
> +
> +    @returns EFI_SUCCESS  If freed successfully or other failure codes
> +                          as returned by the generator.
> +*/
> +typedef EFI_STATUS (*ACPI_TABLE_GENERATOR_FREE_TABLE) (
> +  IN  CONST ACPI_TABLE_GENERATOR                *       Generator,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        **       Table
> +  );
> +
> +/** The ACPI_TABLE_GENERATOR structure provides an interface that the
> +    Table Manager can use to invoke the functions to build ACPI tables.
> +
> +*/
> +typedef struct AcpiTableGenerator {
> +  /// The ACPI table generator ID.
> +  ACPI_TABLE_GENERATOR_ID                GeneratorID;
> +
> +  /// String describing the ACPI table
> +  /// generator.
> +  CONST CHAR16                         * Description;
> +
> +  /// The ACPI table signature.
> +  UINT32                                 AcpiTableSignature;
> +
> +  /// The ACPI table revision.
> +  UINT32                                 AcpiTableRevision;
> +
> +  /// The ACPI table creator ID.
> +  UINT32                                 CreatorId;
> +
> +  /// The ACPI table creator revision.
> +  UINT32                                 CreatorRevision;
> +
> +  /// ACPI table build function pointer.
> +  ACPI_TABLE_GENERATOR_BUILD_TABLE       BuildAcpiTable;
> +
> +  /// The function to free any resources
> +  /// allocated for building the ACPI table.
> +  ACPI_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
> +} ACPI_TABLE_GENERATOR;
> +
> +/** Register ACPI table factory generator.
> +
> +    The ACPI table factory maintains a list of the Standard and OEM ACPI
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterAcpiTableGenerator (
> +  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +/** Unregister ACPI generator.
> +
> +    This function is called by the ACPI table generator to unregister itself
> +    from the ACPI table factory.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterAcpiTableGenerator (
> +  IN CONST ACPI_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +#pragma pack()
> +
> +#endif // ACPI_TABLE_GENERATOR_H_
> +
> diff --git a/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..dbc909894d17ba9df7a78c2d8be797adabb49a34
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> @@ -0,0 +1,367 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef ARM_NAMESPACE_OBJECTS_H_
> +#define ARM_NAMESPACE_OBJECTS_H_
> +#pragma pack(1)
> +
> +/** The EARM_OBJECT_ID enum describes the Object IDs
> +    in the ARM Namespace
> +*/
> +typedef enum ArmObjectID {
> +  EArmObjReserved,                    ///<  0 - Reserved.
> +  EArmObjBootArchInfo,                ///<  1 - Boot Architecture Info
> +  EArmObjCpuInfo,                     ///<  2 - CPU Info
> +  EArmObjPowerManagementProfileInfo,  ///<  3 - Power Management Profile Info
> +  EArmObjGicCInfo,                    ///<  4 - GIC CPU Interface Info
> +  EArmObjGicDInfo,                    ///<  5 - GIC Distributor Info
> +  EArmObjGicMsiFrameInfo,             ///<  6 - GIC MSI Frame Info
> +  EArmObjGicRedistributorInfo,        ///<  7 - GIC Redistributor Info
> +  EArmObjGicItsInfo,                  ///<  8 - GIC ITS Info
> +  EArmObjSerialConsolePortInfo,       ///<  9 - Serial Console Port Info
> +  EArmObjSerialDebugPortInfo,         ///< 10 - Serial Debug Port Info
> +  EArmObjGenericTimerInfo,            ///< 11 - Generic Timer Info
> +  EArmObjPlatformGTBlockInfo,         ///< 12 - Platform GT Block Info
> +  EArmObjPlatformGenericWatchdogInfo, ///< 13 - Platform Generic Watchdog
> +  EArmObjPciConfigSpaceInfo,          ///< 14 - PCI Configuration Space Info
> +  EArmObjHypervisorVendorIdentity,    ///< 15 - Hypervisor Vendor Id
> +  EArmObjMax
> +} EARM_OBJECT_ID;
> +
> +/** A structure that describes the
> +    ARM Boot Architecture flags.
> +*/
> +typedef struct CmArmBootArchInfo {
> +  /// This is the ARM_BOOT_ARCH flags field of the FADT Table
> +  /// described in the ACPI Table Specification.
> +  UINT32  BootArchFlags;
> +} CM_ARM_BOOT_ARCH_INFO;
> +
> +typedef struct CmArmCpuInfo {
> +  // Reserved for use when SMBIOS tables are implemented.
> +} CM_ARM_CPU_INFO;
> +
> +typedef struct CmArmCpuInfoList {
> +  UINT32             CpuCount;
> +  CM_ARM_CPU_INFO  * CpuInfo;
> +} CM_ARM_CPU_INFO_LIST;
> +
> +/** A structure that describes the
> +    Power Management Profile Information for the Platform.
> +*/
> +typedef struct CmArmPowerManagementProfileInfo {
> +  /// This is the Preferred_PM_Profile field of the FADT Table
> +  /// described in the ACPI Specification
> +  UINT8  PowerManagementProfile;
> +} CM_ARM_POWER_MANAGEMENT_PROFILE_INFO;
> +
> +/** A structure that describes the
> +    GIC CPU Interface for the Platform.
> +*/
> +typedef struct CmArmGicCInfo {
> +  /// The GIC CPU Interface number.
> +  UINT32  CPUInterfaceNumber;
> +
> +  /// The ACPI Processor UID. This must match the
> +  /// _UID of the CPU Device object information described
> +  /// in the DSDT/SSDT for the CPU.
> +  UINT32  AcpiProcessorUid;
> +
> +  /// The flags field as described by the GICC structure
> +  /// in the ACPI Specification.
> +  UINT32  Flags;
> +
> +  /// The parking protocol version field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT32  ParkingProtocolVersion;
> +
> +  /// The Performance Interrupt field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT32  PerformanceInterruptGsiv;
> +
> +  /// The CPU Parked address field as described by
> +  /// the GICC structure in the ACPI Specification.
> +  UINT64  ParkedAddress;
> +
> +  /// The base address for the GIC CPU Interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The base address for GICV interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICV;
> +
> +  /// The base address for GICH interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICH;
> +
> +  /// The GICV maintainence interrupt
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT32  VGICMaintenanceInterrupt;
> +
> +  /// The base address for GICR interface
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  GICRBaseAddress;
> +
> +  /// The MPIDR for the CPU
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT64  MPIDR;
> +
> +  /// The Processor Power Efficiency class
> +  /// as described by the GICC structure in the
> +  /// ACPI Specification.
> +  UINT8   ProcessorPowerEfficiencyClass;
> +} CM_ARM_GICC_INFO;
> +
> +/** A structure that describes the
> +    GIC Distributor information for the Platform.
> +*/
> +typedef struct CmArmGicDInfo {
> +  /// The GIC Distributor ID.
> +  UINT32  GicId;
> +
> +  /// The Physical Base address
> +  /// for the GIC Distributor.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The global system interrupt
> +  /// number where this GIC Distributor's
> +  /// interrupt inputs start.
> +  UINT32  SystemVectorBase;
> +
> +  /// The GIC version as described
> +  /// by the GICD structure in the
> +  /// ACPI Specification.
> +  UINT8   GicVersion;
> +} CM_ARM_GICD_INFO;
> +
> +/** A structure that describes the
> +    GIC MSI Frame information for the Platform.
> +*/
> +typedef struct CmArmGicMsiFrameInfo {
> +  /// The GIC MSI Frame ID
> +  UINT32  GicMsiFrameId;
> +
> +  /// The Physical base address for the
> +  /// MSI Frame.
> +  UINT64  PhysicalBaseAddress;
> +
> +  /// The GIC MSI Frame flags
> +  /// as described by the GIC MSI frame
> +  /// structure in the ACPI Specification.
> +  UINT32  Flags;
> +
> +  /// SPI Count used by this frame.
> +  UINT16  SPICount;
> +
> +  /// SPI Base used by this frame.
> +  UINT16  SPIBase;
> +} CM_ARM_GIC_MSI_FRAME_INFO;
> +
> +/** A structure that describes the
> +    GIC Redistributor information for the Platform.
> +*/
> +typedef struct CmArmGicRedistInfo {
> +  /// The physical address of a page range
> +  /// containing all GIC Redistributors.
> +  UINT64  DiscoveryRangeBaseAddress;
> +
> +  /// Length of the GIC Redistributor
> +  /// Discovery page range
> +  UINT32  DiscoveryRangeLength;
> +} CM_ARM_GIC_REDIST_INFO;
> +
> +/** A structure that describes the
> +    GIC Interrupt Translation Service information for the Platform.
> +*/
> +typedef struct CmArmGicItsInfo {
> +  /// The GIC ITS ID.
> +  UINT32  GicItsId;
> +
> +  /// The physical address for the
> +  /// Interrupt Translation Service
> +  UINT64  PhysicalBaseAddress;
> +} CM_ARM_GIC_ITS_INFO;
> +
> +/** A structure that describes the
> +    Serial Port information for the Platform.
> +*/
> +typedef struct CmArmSerialPortInfo {
> +  /// The physical base address for the
> +  /// serial port.
> +  UINT64  BaseAddress;
> +
> +  /// The serial port interrupt.
> +  UINT32  Interrupt;
> +
> +  /// The serial port baud rate.
> +  UINT64  BaudRate;
> +
> +  /// The serial port clock.
> +  UINT32  Clock;
> +} CM_ARM_SERIAL_PORT_INFO;
> +
> +/** A structure that describes the
> +    Generic Timer information for the Platform.
> +*/
> +typedef struct CmArmGenericTimerInfo {
> +  /// The physical base address for the
> +  /// counter control frame.
> +  UINT64  CounterControlBaseAddress;
> +
> +  /// The physical base address for the
> +  /// counter read frame.
> +  UINT64  CounterReadBaseAddress;
> +
> +  /// The secure PL1 timer interrupt.
> +  UINT32  SecurePL1TimerGSIV;
> +
> +  /// The secure PL1 timer flags.
> +  UINT32  SecurePL1TimerFlags;
> +
> +  /// The non-secure PL1 timer interrupt.
> +  UINT32  NonSecurePL1TimerGSIV;
> +
> +  /// The non-secure PL1 timer flags.
> +  UINT32  NonSecurePL1TimerFlags;
> +
> +  /// The virtual timer interrupt.
> +  UINT32  VirtualTimerGSIV;
> +
> +  /// The virtual timer flags.
> +  UINT32  VirtualTimerFlags;
> +
> +  /// The non-secure PL2 timer interrupt.
> +  UINT32  NonSecurePL2TimerGSIV;
> +
> +  /// The non-secure PL2 timer flags.
> +  UINT32  NonSecurePL2TimerFlags;
> +} CM_ARM_GENERIC_TIMER_INFO;
> +
> +/** A structure that describes the
> +    Platform Generic Block Timer Frame information for the Platform.
> +*/
> +typedef struct CmArmGTBlockTimerFrameInfo {
> +  /// The Generic Timer frame number.
> +  UINT8   FrameNumber;
> +
> +  /// The physical base address
> +  /// for the CntBase block.
> +  UINT64  PhysicalAddressCntBase;
> +
> +  /// The physical base address
> +  /// for the CntEL0Base block.
> +  UINT64  PhysicalAddressCntEL0Base;
> +
> +  /// The physical timer interrupt.
> +  UINT32  PhysicalTimerGSIV;
> +
> +  /// The physical timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  PhysicalTimerFlags;
> +
> +  /// The virtual timer interrupt.
> +  UINT32  VirtualTimerGSIV;
> +
> +  /// The virtual timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  VirtualTimerFlags;
> +
> +  /// The common timer flags
> +  /// as described by the GT Block
> +  /// Timer frame Structure in the
> +  /// ACPI Specification.
> +  UINT32  CommonFlags;
> +} CM_ARM_GTBLOCK_TIMER_FRAME_INFO;
> +
> +/** A structure that describes the
> +    Platform Generic Block Timer information for the Platform.
> +*/
> +typedef struct CmArmGTBlockInfo {
> +  /// The physical base address for
> +  /// the GT Block Timer structure.
> +  UINT64                             GTBlockPhysicalAddress;
> +
> +  /// The number of timer frames
> +  /// implemented in the GT Block.
> +  UINT32                             GTBlockTimerFrameCount;
> +
> +  /// Pointer to the GT Block timer
> +  /// frame list.
> +  CM_ARM_GTBLOCK_TIMER_FRAME_INFO  * GTBlockTimerFrameList;
> +} CM_ARM_GTBLOCK_INFO;
> +
> +/** A structure that describes the
> +    SBSA Generic Watchdog information for the Platform.
> +*/
> +typedef struct CmArmGenericWatchdogInfo {
> +  /// The physical base address of the
> +  /// SBSA Watchdog control frame.
> +  UINT64  ControlFrameAddress;
> +
> +  /// The physical base address of the
> +  /// SBSA Watchdog refresh frame.
> +  UINT64  RefreshFrameAddress;
> +
> +  /// The watchdog interrupt.
> +  UINT32  TimerGSIV;
> +
> +  /// The flags for the watchdog
> +  /// as described by the SBSA watchdog
> +  /// structure in the ACPI specification.
> +  UINT32  Flags;
> +} CM_ARM_GENERIC_WATCHDOG_INFO;
> +
> +/** A structure that describes the
> +    PCI Configuration Space information for the Platform.
> +*/
> +typedef struct CmArmPciConfigSpaceInfo {
> +  /// The physical base address for the PCI segment.
> +  UINT64  BaseAddress;
> +
> +  /// The PCI segment group number.
> +  UINT16  PciSegmentGroupNumber;
> +
> +  /// The start bus number.
> +  UINT8   StartBusNumber;
> +
> +  /// The end bus number.
> +  UINT8   EndBusNumber;
> +} CM_ARM_PCI_CONFIG_SPACE_INFO;
> +
> +/** A structure that describes the
> +    Hypervisor Vendor ID information for the Platform.
> +*/
> +typedef struct CmArmHypervisorVendorId {
> +  /// The hypervisor Vendor ID.
> +  UINT64  HypervisorVendorId;
> +} CM_ARM_HYPERVISOR_VENDOR_ID;
> +
> +#pragma pack()
> +
> +#endif // ARM_NAMESPACE_OBJECTS_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..23edd7c343bd09476692d2fb8af088d95b8ff28d
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> @@ -0,0 +1,112 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_HELPER_H_
> +#define CONFIGURATION_MANAGER_HELPER_H_
> +
> +/** The GET_OBJECT_LIST macro expands to a function that is used to retrieve
> +    an object or an object list from the Configuration Manager using the
> +    Configuration Manager Protocol interface.
> +
> +    The macro expands to a function which has the following prototype:
> +
> +    STATIC
> +    EFI_STATUS
> +    EFIAPI
> +    Get<CmObjectId> (
> +      IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
> +      OUT       Type                              **       List,
> +      OUT       UINTN                              *       Count OPTIONAL
> +      );
> +
> +    Generated function parameters:
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
> +                                  interface.
> +    @param [out] List           Pointer to the Object list.
> +    @param [out] Count          Count of the objects returned in the list.
> +
> +    Macro Parameters:
> +    @param [in] CmObjectNameSpace The Object Namespace
> +    @param [in] CmObjectId        Object Id.
> +    @param [in] Type              Structure used to describe the Object.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)                      \
> +STATIC                                                                            \
> +EFI_STATUS                                                                        \
> +EFIAPI                                                                            \
> +Get##CmObjectId (                                                                 \
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,           \
> +  OUT       Type                               **       List,                     \
> +  OUT       UINTN                               * CONST Count OPTIONAL            \
> +  )                                                                               \
> +{                                                                                 \
> +  EFI_STATUS         Status;                                                      \
> +  CM_OBJ_DESCRIPTOR  CmObjectDesc;                                                \
> +  UINTN              ObjCount = 0;                                                \
> +  if (List == NULL) {                                                             \
> +    Status = EFI_INVALID_PARAMETER;                                               \
> +    DEBUG ((                                                                      \
> +      DEBUG_ERROR,                                                                \
> +      "ERROR: Get" #CmObjectId ": Invalid out parameter for"                      \
> +      " object list. Status = %r\n",                                              \
> +      Status                                                                      \
> +      ));                                                                         \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  Status = CfgMgrProtocol->GetObject (                                            \
> +                             CfgMgrProtocol,                                      \
> +                             CREATE_CM_OBJECT_ID (CmObjectNameSpace, CmObjectId), \
> +                             &CmObjectDesc                                        \
> +                             );                                                   \
> +  if (EFI_ERROR (Status)) {                                                       \
> +    DEBUG ((                                                                      \
> +      DEBUG_WARN,                                                                 \
> +      "WARNING: Get" #CmObjectId ": Platform does not implement "                 \
> +      #CmObjectId ". Status = %r\n",                                              \
> +      Status                                                                      \
> +      ));                                                                         \
> +    *List = NULL;                                                                 \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  if (CmObjectDesc.Size < sizeof (Type)) {                                        \
> +    DEBUG ((                                                                      \
> +      DEBUG_ERROR,                                                                \
> +      "ERROR: Get" #CmObjectId ": " #CmObjectId                                   \
> +      ": Buffer too small, size = 0x%x\n",                                        \
> +      CmObjectDesc.Size                                                           \
> +      ));                                                                         \
> +    ASSERT (CmObjectDesc.Size >= sizeof (Type));                                  \
> +    Status = EFI_BAD_BUFFER_SIZE;                                                 \
> +    goto error_handler;                                                           \
> +  }                                                                               \
> +  ObjCount = CmObjectDesc.Size / sizeof (Type);                                   \
> +  *List = (Type*)CmObjectDesc.Data;                                               \
> +error_handler:                                                                    \
> +  if (Count != NULL) {                                                            \
> +    *Count = ObjCount;                                                            \
> +  }                                                                               \
> +  return Status;                                                                  \
> +}
> +
> +#endif // CONFIGURATION_MANAGER_HELPER_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..99afab094328cf830831899011a7f6fca1d6e5f2
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> @@ -0,0 +1,158 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_OBJECT_H_
> +#define CONFIGURATION_MANAGER_OBJECT_H_
> +
> +#pragma pack(1)
> +
> +/** The CM_OBJECT_ID type is used to identify the Configration Manager objects.
> +
> + Description of Configuration Manager Object ID
> +________________________________________________________________________________
> +|31 |30 |29 |28 || 27 | 26 | 25 | 24 || 23 | 22 | 21 | 20 || 19 | 18 | 17 | 16 |
> +--------------------------------------------------------------------------------
> +| Name Space ID ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 ||  0 |  0 |  0 |  0 |
> +________________________________________________________________________________
> +
> +Bits: [31:28] - Name Space ID
> +                0000 - Standard
> +                0001 - ARM
> +                1000 - Custom/OEM
> +                All other values are reserved.
> +
> +Bits: [27:16] - Reserved.
> +________________________________________________________________________________
> +|15 |14 |13 |12 || 11 | 10 |  9 |  8 ||  7 |  6 |  5 |  4 ||  3 |  2 |  1 |  0 |
> +--------------------------------------------------------------------------------
> +| 0 | 0 | 0 | 0 ||  0 |  0 |  0 |  0 ||                 Object ID              |
> +________________________________________________________________________________
> +
> +Bits: [15:8] - Are reserved and must be zero.
> +
> +Bits: [7:0] - Object ID
> +
> +Object ID's in the Standard Namespace:
> +  0 - Configuration Manager Revision
> +  1 - ACPI Table List
> +  2 - SMBIOS Table List
> +
> +Object ID's in the ARM Namespace:
> +   0 - Reserved
> +   1 - Boot Architecture Info
> +   2 - CPU Info
> +   3 - Power Management Profile Info
> +   4 - GICC Info
> +   5 - GICD Info
> +   6 - GIC MSI Frame Info
> +   7 - GIC Redistributor Info
> +   8 - GIC ITS Info
> +   9 - Serial Console Port Info
> +  10 - Serial Debug Port Info
> +  12 - Generic Timer Info
> +  13 - Platform GT Block Info
> +  14 - Platform Generic Watchdog
> +  15 - PCI Configuration Space Info
> +  16 - Hypervisor Vendor Id
> +*/
> +typedef UINT32  CM_OBJECT_ID;
> +
> +/** The EOBJECT_NAMESPACE_ID enum describes the defined namespaces
> +    for the Confguration Manager Objects.
> +*/
> +typedef enum ObjectNameSpaceID {
> +  EObjNameSpaceStandard,      ///< Standard Objects Namespace
> +  EObjNameSpaceArm,           ///< ARM Objects Namespace
> +  EObjNameSpaceOem = 0x8,     ///< OEM Objects Namespace
> +  EObjNameSpaceMax
> +} EOBJECT_NAMESPACE_ID;
> +
> +/** The CM_OBJ_DESCRIPTOR structure describes the Configuration
> +    Manager Object descriptor. The Configuration Manager Protocol
> +    interface uses this descriptor to return the Configuration
> +    Manager Objects.
> +*/
> +typedef struct CmObjDescriptor {
> +  /// Size of the Object or Object List
> +  /// described by this descriptor.
> +  UINT32   Size;
> +
> +  /// Pointer to the Object or Object List
> +  /// described by this descriptor.
> +  UINTN  * Data;
> +} CM_OBJ_DESCRIPTOR;
> +
> +#pragma pack()
> +
> +/** This macro returns the namespace ID from the CmObjectID.
> +
> +  @param [in] CmObjectId  The Configuration Manager Object ID.
> +
> +  @retval Returns the Namespace ID corresponding to the CmObjectID.
> +*/
> +#define GET_CM_NAMESPACE_ID(CmObjectId) (((CmObjectId) >> 28) & 0xF)
> +
> +/** This macro returns the Object ID from the CmObjectID.
> +
> +  @param [in] CmObjectId  The Configuration Manager Object ID.
> +
> +  @retval Returns the Object ID corresponding to the CmObjectID.
> +*/
> +#define GET_CM_OBJECT_ID(CmObjectId)    ((CmObjectId) & 0xFF)
> +
> +/** This macro returns a Configuration Manager Object ID
> +    from the NameSpace ID and the ObjectID.
> +
> +  @param [in] NameSpaceId The namespace ID for the Object.
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns the Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_OBJECT_ID(NameSpaceId, ObjectId) \
> +          ((((NameSpaceId) & 0xF) << 28) | ((ObjectId) & 0xF))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the Standard Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns a Standard Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_STD_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceStandard, ObjectId))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the ARM Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns an ARM Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_ARM_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceArm, ObjectId))
> +
> +/** This macro returns a Configuration Manager Object ID
> +    in the OEM Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns an OEM Configuration Manager Object ID.
> +*/
> +#define CREATE_CM_OEM_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceOem, ObjectId))
> +
> +#endif // CONFIGURATION_MANAGER_OBJECT_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..10d29be800a0c126ed32dcfa070f1473a8aee7a9
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> @@ -0,0 +1,235 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347145681&sdata=K9HVTSZ3%2BqOcifbd30%2BzzcZScxiQpjLjxwz5caD25z4%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef SMBIOS_TABLE_GENERATOR_H_
> +#define SMBIOS_TABLE_GENERATOR_H_
> +
> +#pragma pack(1)
> +
> +/** The SMBIOS_TABLE_GENERATOR_ID type describes SMBIOS table generator ID.
> +*/
> +typedef TABLE_GENERATOR_ID SMBIOS_TABLE_GENERATOR_ID;
> +
> +/** The ESTD_SMBIOS_TABLE_ID enum describes the SMBIOS table IDs reserved for
> +  the standard generators.
> +
> +  NOTE: The SMBIOS Generator IDs do not match the table type numbers!
> +          This allows 0 to be used to catch invalid parameters.
> +*/
> +typedef enum StdSmbiosTableGeneratorId {
> +  ESTD_SMBIOS_TABLE_ID_RESERVED = 0x0000,
> +  ESTD_SMBIOS_TABLE_ID_RAW,
> +  ESTD_SMBIOS_TABLE_ID_TYPE00,
> +  ESTD_SMBIOS_TABLE_ID_TYPE01,
> +  ESTD_SMBIOS_TABLE_ID_TYPE02,
> +  ESTD_SMBIOS_TABLE_ID_TYPE03,
> +  ESTD_SMBIOS_TABLE_ID_TYPE04,
> +  ESTD_SMBIOS_TABLE_ID_TYPE05,
> +  ESTD_SMBIOS_TABLE_ID_TYPE06,
> +  ESTD_SMBIOS_TABLE_ID_TYPE07,
> +  ESTD_SMBIOS_TABLE_ID_TYPE08,
> +  ESTD_SMBIOS_TABLE_ID_TYPE09,
> +  ESTD_SMBIOS_TABLE_ID_TYPE10,
> +  ESTD_SMBIOS_TABLE_ID_TYPE11,
> +  ESTD_SMBIOS_TABLE_ID_TYPE12,
> +  ESTD_SMBIOS_TABLE_ID_TYPE13,
> +  ESTD_SMBIOS_TABLE_ID_TYPE14,
> +  ESTD_SMBIOS_TABLE_ID_TYPE15,
> +  ESTD_SMBIOS_TABLE_ID_TYPE16,
> +  ESTD_SMBIOS_TABLE_ID_TYPE17,
> +  ESTD_SMBIOS_TABLE_ID_TYPE18,
> +  ESTD_SMBIOS_TABLE_ID_TYPE19,
> +  ESTD_SMBIOS_TABLE_ID_TYPE20,
> +  ESTD_SMBIOS_TABLE_ID_TYPE21,
> +  ESTD_SMBIOS_TABLE_ID_TYPE22,
> +  ESTD_SMBIOS_TABLE_ID_TYPE23,
> +  ESTD_SMBIOS_TABLE_ID_TYPE24,
> +  ESTD_SMBIOS_TABLE_ID_TYPE25,
> +  ESTD_SMBIOS_TABLE_ID_TYPE26,
> +  ESTD_SMBIOS_TABLE_ID_TYPE27,
> +  ESTD_SMBIOS_TABLE_ID_TYPE28,
> +  ESTD_SMBIOS_TABLE_ID_TYPE29,
> +  ESTD_SMBIOS_TABLE_ID_TYPE30,
> +  ESTD_SMBIOS_TABLE_ID_TYPE31,
> +  ESTD_SMBIOS_TABLE_ID_TYPE32,
> +  ESTD_SMBIOS_TABLE_ID_TYPE33,
> +  ESTD_SMBIOS_TABLE_ID_TYPE34,
> +  ESTD_SMBIOS_TABLE_ID_TYPE35,
> +  ESTD_SMBIOS_TABLE_ID_TYPE36,
> +  ESTD_SMBIOS_TABLE_ID_TYPE37,
> +  ESTD_SMBIOS_TABLE_ID_TYPE38,
> +  ESTD_SMBIOS_TABLE_ID_TYPE39,
> +  ESTD_SMBIOS_TABLE_ID_TYPE40,
> +  ESTD_SMBIOS_TABLE_ID_TYPE41,
> +  ESTD_SMBIOS_TABLE_ID_TYPE42,
> +
> +  // IDs 43 - 125 are reserved
> +
> +  ESTD_SMBIOS_TABLE_ID_TYPE126 = (ESTD_SMBIOS_TABLE_ID_TYPE00 + 126),
> +  ESTD_SMBIOS_TABLE_ID_TYPE127,
> +  ESTD_SMBIOS_TABLE_ID_MAX
> +} ESTD_SMBIOS_TABLE_ID;
> +
> +/** This macro checks if the Table Generator ID is for an SMBIOS Table
> +    Generator.
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns  TRUE if the table generator ID is for an SMBIOS Table
> +              Generator.
> +*/
> +#define IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId) \
> +          (                                        \
> +          GET_TABLE_TYPE (TableGeneratorId) ==     \
> +          ETableGeneratorTypeSmbios                \
> +          )
> +
> +/** This macro checks if the Table Generator ID is for a standard SMBIOS
> +    Table Generator.
> +
> +    @param [in] TableGeneratorId  The table generator ID.
> +
> +    @returns  TRUE if the table generator ID is for a standard SMBIOS
> +              Table Generator.
> +*/
> +#define IS_VALID_STD_SMBIOS_GENERATOR_ID(TableGeneratorId)            \
> +          (                                                           \
> +          IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) &&             \
> +          IS_GENERATOR_TYPE_SMBIOS(TableGeneratorId)   &&             \
> +          ((GET_TABLE_ID(GeneratorId) >= ESTD_SMBIOS_TABLE_ID_RAW) && \
> +           (GET_TABLE_ID(GeneratorId) < ESTD_SMIOS_TABLE_ID_MAX))     \
> +          )
> +
> +/** This macro creates a standard SMBIOS Table Generator ID.
> +
> +    @param [in] TableId  The table generator ID.
> +
> +    @returns a standard SMBIOS table generator ID.
> +*/
> +#define CREATE_STD_SMBIOS_TABLE_GEN_ID(TableId) \
> +          CREATE_TABLE_GEN_ID (                 \
> +            ETableGeneratorTypeSmbios,          \
> +            ETableGeneratorNameSpaceStd,        \
> +            TableId                             \
> +            )
> +
> +/** Forward declarations.
> +*/
> +typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct CmStdObjSmbiosTableInfo      CM_STD_OBJ_SMBIOS_TABLE_INFO;
> +typedef struct SmbiosTableGenerator         SMBIOS_TABLE_GENERATOR;
> +
> +/** This function pointer describes the interface to SMBIOS table build
> +    functions provided by the SMBIOS table generator and called by the
> +    Table Manager to build an SMBIOS table.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [out] Table           Pointer to the generated SMBIOS table.
> +
> +    @returns EFI_SUCCESS  If the table is generated successfully or other
> +                          failure codes as returned by the generator.
> +*/
> +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLE) (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
> +  IN        CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       SMBIOS_STRUCTURE                   **       Table
> +  );
> +
> +/** This function pointer describes the interface to used by the
> +    Table Manager to give the generator an opportunity to free
> +    any resources allocated for building the SMBIOS table.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +    @param [in]  SmbiosTableInfo Pointer to the SMBIOS table information.
> +    @param [in]  CfgMgrProtocol  Pointer to the Configuration Manager
> +                                 Protocol interface.
> +    @param [in]  Table           Pointer to the generated SMBIOS table.
> +
> +    @returns  EFI_SUCCESS If freed successfully or other failure codes
> +                          as returned by the generator.
> +*/
> +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLE) (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              *       Generator,
> +  IN  CONST CM_STD_OBJ_SMBIOS_TABLE_INFO        * CONST SmbiosTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        SMBIOS_STRUCTURE                   **       Table
> +  );
> +
> +/** The SMBIOS_TABLE_GENERATOR structure provides an interface that the
> +    Table Manager can use to invoke the functions to build SMBIOS tables.
> +
> +*/
> +typedef struct SmbiosTableGenerator {
> +  /// The SMBIOS table generator ID.
> +  SMBIOS_TABLE_GENERATOR_ID                GeneratorID;
> +
> +  /// String describing the DT table
> +  /// generator.
> +  CONST CHAR16*                            Description;
> +
> +  /// The SMBIOS table type.
> +  SMBIOS_TYPE                              Type;
> +
> +  /// SMBIOS table build function pointer.
> +  SMBIOS_TABLE_GENERATOR_BUILD_TABLE       BuildSmbiosTable;
> +
> +  /// The function to free any resources
> +  /// allocated for building the SMBIOS table.
> +  SMBIOS_TABLE_GENERATOR_FREE_TABLE        FreeTableResources;
> +} SMBIOS_TABLE_GENERATOR;
> +
> +/** Register SMBIOS table factory generator.
> +
> +    The SMBIOS table factory maintains a list of the Standard and OEM SMBIOS
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterSmbiosTableGenerator (
> +  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
> +  );
> +
> +/** Unregister SMBIOS generator.
> +
> +    This function is called by the SMBIOS table generator to unregister itself
> +    from the SMBIOS table factory.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterSmbiosTableGenerator (
> +  IN CONST SMBIOS_TABLE_GENERATOR                 * CONST Generator
> +  );
> +#pragma pack()
> +
> +#endif // SMBIOS_TABLE_GENERATOR_H_
> +
> diff --git a/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..76ae3f2208a5c80f0ca10b75e5df94cbb43e4688
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> @@ -0,0 +1,93 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +    - Std or STD - Standard
> +**/
> +
> +#ifndef STANDARD_NAMESPACE_OBJECTS_H_
> +#define STANDARD_NAMESPACE_OBJECTS_H_
> +
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +
> +#pragma pack(1)
> +
> +/** The ESTD_OBJECT_ID enum describes the Object IDs
> +    in the Standard Namespace.
> +*/
> +typedef enum StdObjectID {
> +  EStdObjCfgMgrInfo = 0x00000000, ///< 0 - Configuration Manager Info
> +  EStdObjAcpiTableList,           ///< 1 - ACPI table Info List
> +  EStdObjSmbiosTableList,         ///< 2 - SMBIOS table Info List
> +  EStdObjMax
> +} ESTD_OBJECT_ID;
> +
> +/** A structure that describes the Configuration Manager Information.
> +*/
> +typedef struct CmStdObjConfigurationManagerInfo {
> +  /// The Configuration Manager Revision.
> +  UINT32  Revision;
> +
> +  /// The OEM ID. This information is used to
> +  /// populate the ACPI table header information.
> +  UINT8   OemId[6];
> +} CM_STD_OBJ_CONFIGURATION_MANAGER_INFO;
> +
> +/** A structure used to describe the ACPI table generators to be invoked.
> +
> +    The AcpiTableData member of this structure may be used to directly provide
> +    the binary ACPI table data which is required by the following standard
> +    generators:
> +      - RAW
> +      - DSDT
> +      - SSDT
> +
> +    Providing the ACPI table data is optional and depends on the generator
> +    that is being invoked. If unused, set AcpiTableData to NULL.
> +*/
> +typedef struct CmAStdObjAcpiTableInfo {
> +  /// The signature of the ACPI Table to be installed.
> +  UINT32                         AcpiTableSignature;
> +
> +  /// The ACPI Table Generator ID.
> +  ACPI_TABLE_GENERATOR_ID        TableGeneratorId;
> +
> +  /// Optional pointer to the ACPI table data.
> +  EFI_ACPI_DESCRIPTION_HEADER  * AcpiTableData;
> +
> +} CM_STD_OBJ_ACPI_TABLE_INFO;
> +
> +/** A structure used to describe the SMBIOS table generators to be invoked.
> +
> +    The SmbiosTableData member of this structure is used to provide
> +    the SMBIOS table data which is required by the following standard
> +    generator(s):
> +      - RAW
> +
> +    Providing the SMBIOS table data is optional and depends on the
> +    generator that is being invoked. If unused, set the SmbiosTableData
> +    to NULL.
> +*/
> +typedef struct CmStdObjSmbiosTableInfo {
> +  /// The SMBIOS Table Generator ID.
> +  SMBIOS_TABLE_GENERATOR_ID   TableGeneratorId;
> +
> +  /// Optional pointer to the SMBIOS table data.
> +  SMBIOS_STRUCTURE           * SmbiosTableData;
> +} CM_STD_OBJ_SMBIOS_TABLE_INFO;
> +
> +#pragma pack()
> +
> +#endif // STANDARD_NAMESPACE_OBJECTS_H_
> diff --git a/MdeModulePkg/Include/DynamicTables/TableGenerator.h b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..93d557273459948f5211e1c26a6028fc12b181fb
> --- /dev/null
> +++ b/MdeModulePkg/Include/DynamicTables/TableGenerator.h
> @@ -0,0 +1,235 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +    - DT     - Device Tree
> +**/
> +
> +#ifndef TABLE_GENERATOR_H_
> +#define TABLE_GENERATOR_H_
> +
> +/** The TABLE_GENERATOR_ID type describes the Table Generator ID
> +
> +  Table Generator ID
> +
> +________________________________________________________________________________
> +|  31 | 30 |29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16|
> +--------------------------------------------------------------------------------
> +|TNSID|  0 |   TT   |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0|  0 |
> +________________________________________________________________________________
> +
> +
> +________________________________________________________________________________
> +|15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
> +--------------------------------------------------------------------------------
> +|                                 Table ID                                     |
> +________________________________________________________________________________
> +
> +
> +  Bit [31] - Table NameSpace ID (TNSID)
> +      0 - Standard
> +      1 - Custom/OEM
> +
> +  Bit [30] - Reserved, Must be Zero
> +
> +  Bit [29:28] - Table Type (TT)
> +       0 - ACPI Table
> +       1 - SMBIOS Table
> +       2 - DT (Device Tree) Table
> +       3 - Reserved (INVALID)
> +
> +  Bit [27:16] - Reserved, Must Be Zero
> +
> +  Bit [15:0] - Table ID
> +
> +    Standard ACPI Table IDs:
> +       0 - Reserved
> +       1 - RAW
> +       2 - FADT
> +       3 - DSDT
> +       4 - SSDT
> +       5 - MADT
> +       6 - GTDT
> +       7 - DBG2
> +       8 - SPCR
> +       9 - MCFG
> +
> +
> +    Standard SMBIOS Table IDs:
> +       0 - Reserved
> +       1 - RAW
> +       2 - Table Type00
> +       3 - Table Type01
> +       4 - Table Type02
> +       5 - Table Type03
> +       6 - Table Type04
> +       7 - Table Type05
> +       8 - Table Type06
> +       9 - Table Type07
> +      10 - Table Type08
> +      11 - Table Type09
> +      12 - Table Type10
> +      13 - Table Type11
> +      14 - Table Type12
> +      15 - Table Type13
> +      16 - Table Type14
> +      17 - Table Type15
> +      18 - Table Type16
> +      19 - Table Type17
> +      20 - Table Type18
> +      21 - Table Type19
> +      22 - Table Type20
> +      23 - Table Type21
> +      24 - Table Type22
> +      25 - Table Type23
> +      26 - Table Type24
> +      27 - Table Type25
> +      28 - Table Type26
> +      29 - Table Type27
> +      30 - Table Type28
> +      31 - Table Type29
> +      32 - Table Type30
> +      33 - Table Type31
> +      34 - Table Type32
> +      35 - Table Type33
> +      36 - Table Type34
> +      37 - Table Type35
> +      38 - Table Type36
> +      39 - Table Type37
> +      40 - Table Type38
> +      41 - Table Type39
> +      42 - Table Type40
> +      43 - Table Type41
> +      44 - Table Type42
> +  45-127 - Reserved
> +     128 - Table Type126
> +     129 - Table Type127
> +**/
> +typedef UINT32  TABLE_GENERATOR_ID;
> +
> +/** This enum lists the Table Generator Types.
> +*/
> +typedef enum TableGeneratorType {
> +  ETableGeneratorTypeAcpi = 0,  ///< ACPI Table Generator Type.
> +  ETableGeneratorTypeSmbios,    ///< SMBIOS Table Generator Type.
> +  ETableGeneratorTypeDt,        ///< Device Tree Table Generator Type.
> +  ETableGeneratorTypeReserved
> +} ETABLE_GENERATOR_TYPE;
> +
> +/** This enum lists the namespaces for the Table Generators.
> +*/
> +typedef enum TableGeneratorNameSpace {
> +  ETableGeneratorNameSpaceStd = 0,  ///< Standard Namespace.
> +  ETableGeneratorNameSpaceOem       ///< OEM Namespace.
> +} ETABLE_GENERATOR_NAMESPACE;
> +
> +/** A mask for the Table ID bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_ID_MASK             0xFF
> +
> +/** A mask for the Namespace ID bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_NAMESPACEID_MASK    (BIT31)
> +
> +/** A mask for the Table Type bits of TABLE_GENERATOR_ID.
> +*/
> +#define TABLE_TYPE_MASK           (BIT29 | BIT28)
> +
> +/** This macro returns the Table ID from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Table ID described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_ID(TableGeneratorId)                          \
> +          ((TableGeneratorId) & TABLE_ID_MASK)
> +
> +/** This macro returns the Table type from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Table type described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_TYPE(TableGeneratorId)                        \
> +          (((TableGeneratorId) & TABLE_TYPE_MASK) >> 28)
> +
> +/** This macro returns the Namespace ID from the TableGeneratorId.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns the Namespace described by the TableGeneratorId.
> +*/
> +#define GET_TABLE_NAMESPACEID(TableGeneratorId)                 \
> +          (((TableGeneratorId) & TABLE_NAMESPACEID_MASK) >> 31)
> +
> +/** This macro checks if the TableGeneratorId is in the Standard Namespace.
> +
> +    @param [in]  TableGeneratorId  The table generator ID.
> +
> +    @returns TRUE if the TableGeneratorId is in the Standard Namespace.
> +*/
> +#define IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) \
> +          (                                          \
> +          GET_TABLE_NAMESPACEID(TableGeneratorId) == \
> +          ETableGeneratorNameSpaceStd                \
> +          )
> +
> +/** This macro creates a TableGeneratorId
> +
> +    @param [in]  TableType        The table type.
> +    @param [in]  TableNameSpaceId The namespace ID for the table.
> +    @param [in]  TableId          The table ID.
> +
> +    @returns a TableGeneratorId calculated from the inputs.
> +*/
> +#define CREATE_TABLE_GEN_ID(TableType, TableNameSpaceId, TableId)  \
> +          (                                                        \
> +           (((TableType) << 28) & TABLE_TYPE_MASK)               | \
> +           (((TableNameSpaceId) << 31) & TABLE_NAMESPACEID_MASK) | \
> +           ((TableId) & TABLE_ID_MASK)                             \
> +          )
> +
> +/** This macro generates a Major.Minor version
> +    where the Major and Minor fields are 16 bit.
> +
> +    @param [in]  Major  The Major Revision.
> +    @param [in]  Minor  The Minor Revision.
> +
> +    @returns a 32 bit representation of the type Major.Minor.
> +*/
> +#define CREATE_REVISION(Major, Minor)                            \
> +          ((((Major) & 0xFFFF) << 16) | ((Minor) & 0xFFFF))
> +
> +/** This macro returns the Major revison
> +
> +    Extracts Major from the 32 bit representation of the type Major.Minor
> +
> +    @param [in]  Revision  The Revision value which is 32 bit.
> +
> +    @returns the Major part of the revision.
> +*/
> +#define GET_MAJOR_REVISION(Revision)  (((Revision) >> 16) & 0xFFFF)
> +
> +/** This macro returns the Minor revison
> +
> +    Extracts Minor from the 32 bit representation of the type Major.Minor
> +
> +    @param [in]  Revision  The Revision value which is 32 bit.
> +
> +    @returns the Minor part of the revision.
> +*/
> +#define GET_MINOR_REVISION(Revision)  ((Revision) & 0xFFFF)
> +
> +#endif // TABLE_GENERATOR_H_
> +
> diff --git a/MdeModulePkg/Include/Library/TableHelperLib.h b/MdeModulePkg/Include/Library/TableHelperLib.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..4b22e024dee1a311e4e4b532371ccef94bc02be3
> --- /dev/null
> +++ b/MdeModulePkg/Include/Library/TableHelperLib.h
> @@ -0,0 +1,67 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef TABLE_HELPER_LIB_H_
> +#define TABLE_HELPER_LIB_H_
> +
> +/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
> +    object from the Configuration Manager.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
> +                                interface.
> +    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
> +                                object structure.
> +
> +    @retval EFI_SUCCESS           The object is returned.
> +    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
> +    @retval EFI_NOT_FOUND         The requested Object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetCgfMgrInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST  CfgMgrProtocol,
> +  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **        CfgMfrInfo
> +  );
> +
> +/** The AddAcpiHeader function updates the ACPI header structure pointed by
> +    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
> +    Manager protocol to obtain any information required for constructing the
> +    header.
> +
> +    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
> +                                   protocol interface.
> +    @param [in]     Generator      Pointer to the ACPI table Generator.
> +    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
> +                                   updated.
> +    @param [in]     Length         Length of the ACPI table.
> +
> +    @retval EFI_SUCCESS           The ACPI table is updated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AddAcpiHeader (
> +  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
> +  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
> +  IN      CONST UINT32                                      Length
> +  );
> +
> +#endif // TABLE_HELPER_LIB_H_
> diff --git a/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..387935943648654ef095720dec452d1c15b8fc11
> --- /dev/null
> +++ b/MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> @@ -0,0 +1,121 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Cm or CM   - Configuration Manager
> +    - Obj or OBJ - Object
> +**/
> +
> +#ifndef CONFIGURATION_MANAGER_PROTOCOL_H_
> +#define CONFIGURATION_MANAGER_PROTOCOL_H_
> +
> +/** This macro defines the Configuration Manager Protocol GUID.
> +
> +  GUID: {D85A4835-5A82-4894-AC02-706F43D5978E}
> +*/
> +#define EFI_CONFIGURATION_MANAGER_PROTOCOL_GUID         \
> +  { 0xd85a4835, 0x5a82, 0x4894,                         \
> +    { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e }   \
> +  };
> +
> +/** This macro defines the Configuration Manager Protocol Revision.
> +*/
> +#define EFI_CONFIGURATION_MANAGER_PROTOCOL_REVISION  CREATE_REVISION (1, 0)
> +
> +#pragma pack(1)
> +
> +/**
> +  Forward declarations:
> +*/
> +typedef struct ConfigurationManagerProtocol EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct PlatformRepositoryInfo       EFI_PLATFORM_REPOSITORY_INFO;
> +
> +
> +/** The GetObject function defines the interface implemented by the
> +    Configuration Manager Protocol for returning the Configuration
> +    Manager Objects.
> +
> +    @param [in]  This        Poiner to the Configuration Manager Protocol.
> +    @param [in]  CmObjectId  The Configuration Manager Object ID.
> +    @param [out] CmObject    Pointer to the Configuration Manager Object
> +                             descrptor describing the requested Object.
> +
> +    @retval Returns:
> +      EFI_SUCCESS           Success.
> +      EFI_INVALID_PARAMETER A parameter is invalid.
> +      EFI_NOT_FOUND         The required object information is not found.
> +      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                            is less than the Object size for the requested
> +                            object.
> +*/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_CONFIGURATION_MANAGER_GET_OBJECT) (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
> +  IN  CONST CM_OBJECT_ID                                CmObjectId,
> +  IN  OUT   CM_OBJ_DESCRIPTOR                   * CONST CmObject
> +  );
> +
> +/** The SetObject function defines the interface implemented by the
> +    Configuration Manager Protocol for updating the Configuration
> +    Manager Objects.
> +
> +    @param [in]  This        Poiner to the Configuration Manager Protocol.
> +    @param [in]  CmObjectId  The Configuration Manager Object ID.
> +    @param [out] CmObject    Pointer to the Configuration Manager Object
> +                             descrptor describing the Object.
> +
> +    @retval Returns:
> +      EFI_SUCCESS           The operation completed successfully.
> +      EFI_INVALID_PARAMETER A parameter is invalid.
> +      EFI_NOT_FOUND         The required object information is not found.
> +      EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                            is less than the Object size for the requested
> +                            object.
> +      EFI_UNSUPPORTED       This operation is not supported.
> +*/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_CONFIGURATION_MANAGER_SET_OBJECT) (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST This,
> +  IN  CONST CM_OBJECT_ID                                CmObjectId,
> +  IN        CM_OBJ_DESCRIPTOR                   * CONST CmObject
> +  );
> +
> +/** The EFI_CONFIGURATION_MANAGER_PROTOCOL structure describes the
> +    Configuration Manager Protocol interface.
> +*/
> +typedef struct ConfigurationManagerProtocol {
> +  /// The Configuration Manager Protocol revision.
> +  UINT32                                Revision;
> +
> +  /// The interface used to request information about
> +  /// the Configuration Manager Objects.
> +  EFI_CONFIGURATION_MANAGER_GET_OBJECT  GetObject;
> +
> +  /// The interface used to update the information stored
> +  /// in the Configuration Manager repository.
> +  EFI_CONFIGURATION_MANAGER_SET_OBJECT  SetObject;
> +
> +  /// Pointer to an implementation defined abstract repository
> +  /// provisioned by the Configuration Manager.
> +  EFI_PLATFORM_REPOSITORY_INFO        * PlatRepoInfo;
> +} EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +
> +/** A global GUID defined in the protocol section of the
> +    MdeModulePkg.dec file.
> +*/
> +extern EFI_GUID gEfiConfigurationManagerProtocolGuid;
> +
> +#pragma pack()
> +
> +#endif // CONFIGURATION_MANAGER_PROTOCOL_H_
> diff --git a/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..5ece83bb44ec2d88fbd3b49b0e7bdc6314c332c7
> --- /dev/null
> +++ b/MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> @@ -0,0 +1,113 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +**/
> +
> +#ifndef DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> +#define DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> +
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +
> +/** This macro defines the Dynamic Table Factory Protocol GUID.
> +
> +  GUID: {91D1E327-FE5A-49B8-AB65-0ECE2DDB45EC}
> +*/
> +#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_GUID         \
> +  { 0x91d1e327, 0xfe5a, 0x49b8,                         \
> +    { 0xab, 0x65, 0xe, 0xce, 0x2d, 0xdb, 0x45, 0xec }   \
> +  };
> +
> +/** This macro defines the Configuration Manager Protocol Revision.
> +*/
> +#define EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL_REVISION  CREATE_REVISION (1, 0)
> +
> +#pragma pack(1)
> +
> +/**
> +  Forward declarations:
> +*/
> +typedef struct DynamicTableFactoryProtocol EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
> +typedef struct DynamicTableFactoryInfo EFI_DYNAMIC_TABLE_FACTORY_INFO;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  TableId    The ACPI table generator ID for the
> +                            requested generator.
> +    @param [out] Generator  Pointer to the requested ACPI table
> +                            generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A paramter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +typedef
> +EFI_STATUS
> +EFIAPI
> +(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR) (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  );
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This       Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  TableId    The SMBIOS table generator ID for the
> +                            requested generator.
> +    @param [out] Generator  Pointer to the requested SMBIOS table
> +                            generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +typedef
> +EFI_STATUS
> +EFIAPI
> +(EFIAPI * EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR) (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  );
> +
> +/** A structure describing the Dynamic Table Factory Protocol interface.
> +*/
> +typedef struct DynamicTableFactoryProtocol {
> +  /// The Dynamic Table Factory Protocol revision.
> +  UINT32                                               Revision;
> +
> +  /// The interface used to request an ACPI Table Generator.
> +  EFI_DYNAMIC_TABLE_FACTORY_GET_ACPI_TABLE_GENERATOR   GetAcpiTableGenerator;
> +
> +  /// The interface used to request a SMBIOS Table Generator.
> +  EFI_DYNAMIC_TABLE_FACTORY_GET_SMBIOS_TABLE_GENERATOR GetSmbiosTableGenerator;
> +
> +  /// Pointer to the data structure that holds the
> +  /// list of registered table generators
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO          * TableFactoryInfo;
> +} EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
> +
> +/** A global GUID defined in the protocol section of the
> +    MdeModulePkg.dec file.
> +*/
> +extern EFI_GUID gEfiDynamicTableFactoryProtocolGuid;
> +
> +#pragma pack()
> +
> +#endif // DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..88d9e5a4a58307ea26ddbe75579cddc3333ccc34
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactory.h
> @@ -0,0 +1,91 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +    - ACPI   - Advanced Configuration and Power Interface
> +    - SMBIOS - System Management BIOS
> +**/
> +
> +#ifndef DYNAMIC_TABLE_FACTORY_H_
> +#define DYNAMIC_TABLE_FACTORY_H_
> +
> +#pragma pack(1)
> +
> +/** A structure that holds the list of registered ACPI and
> +    SMBIOS table generators.
> +*/
> +typedef struct DynamicTableFactoryInfo {
> +  /// An array for holding the list of Standard ACPI Table  Generators.
> +  CONST ACPI_TABLE_GENERATOR *
> +          StdAcpiTableGeneratorList[ESTD_ACPI_TABLE_ID_MAX];
> +
> +  /// An array for holding the list of Custom ACPI Table Generators.
> +  CONST ACPI_TABLE_GENERATOR *
> +          CustomAcpiTableGeneratorList[FixedPcdGet16 (
> +            PcdMaxCustomACPIGenerators)];
> +
> +  /// An array for holding the list of Standard SMBIOS Table Generators.
> +  CONST SMBIOS_TABLE_GENERATOR *
> +          StdSmbiosTableGeneratorList[ESTD_SMBIOS_TABLE_ID_MAX];
> +
> +  /// An array for holding the list of Custom SMBIOS Table Generators.
> +  CONST SMBIOS_TABLE_GENERATOR *
> +          CustomSmbiosTableGeneratorList[FixedPcdGet16 (
> +            PcdMaxCustomSMBIOSGenerators)];
> +} EFI_DYNAMIC_TABLE_FACTORY_INFO;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The ACPI table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested ACPI table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetAcpiTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  );
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The SMBIOS table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested SMBIOS table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetSmbiosTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  );
> +
> +#pragma pack()
> +
> +#endif // DYNAMIC_TABLE_FACTORY_H_
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..1bf20424b942ac08fe93d157f3869de53577cf0e
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
> @@ -0,0 +1,440 @@
> +/** @file
> +  DBG2 Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include <IndustryStandard/DebugPort2Table.h>
> +#include <Drivers/PL011Uart.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard DBG2 Table Generator
> +
> +    Generates the ACPI DBG2 Port Table for ARM UARTs
> +    as specified by the Microsoft Debug Port Table 2 (DBG2)
> +    Specification - December 10, 2015.
> +
> +    Constructs the DBG2 table for PL011 or SBSA UART peripherals.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjSerialDebugPortInfo
> +*/
> +
> +#pragma pack(1)
> +
> +/** Define the number of debug ports represented by the Table.
> +*/
> +#define DBG2_NUM_DEBUG_PORTS                       1
> +
> +/** Define the number of Generic Address Registers
> +    presented in the debug device information.
> +*/
> +#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS   1
> +
> +/** Define the index for the debug port 1.
> +*/
> +#define DBG_PORT_INDEX_PORT1                       0
> +
> +/** Define the string representing the debug port 1 name.
> +*/
> +#define NAME_STR_PORT1                            "COM1"
> +
> +/** Define the length of the namespace string.
> +*/
> +#define DBG2_NAMESPACESTRING_FIELD_SIZE            sizeof (NAME_STR_PORT1)
> +
> +/** Define the PL011 UART address range length.
> +*/
> +#define PL011_UART_LENGTH                          0x1000
> +
> +/** This structure provides the OS with the information required for
> +    initializing a debugger connection.
> +*/
> +typedef struct {
> +  /// The debug device information for the platform
> +  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device;
> +
> +  /// The base address register for the serial port
> +  EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE        BaseAddressRegister;
> +
> +  /// The address size
> +  UINT32 AddressSize;
> +
> +  /// The debug port name string
> +  UINT8  NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
> +} DBG2_DEBUG_DEVICE_INFORMATION;
> +
> +/** This structure represents the information about the debug port(s)
> +    available on the platform.
> +*/
> +typedef struct {
> +  /// The DBG2 table header
> +  EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description;
> +
> +  /// Debug port information list
> +  DBG2_DEBUG_DEVICE_INFORMATION       Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS];
> +} DBG2_TABLE;
> +
> +/** A helper macro used for initalizing the debug port device
> +    information structure.
> +
> +    @param [in]  NumReg       The number of generic address registers.
> +    @param [in]  SubType      The DBG Port SubType.
> +    @param [in]  UartBase     The UART port base address.
> +    @param [in]  UartAddrLen  The UART port address range length.
> +    @param [in]  UartNameStr  The UART port name string.
> +*/
> +#define DBG2_DEBUG_PORT_DDI(                                          \
> +          NumReg,                                                     \
> +          SubType,                                                    \
> +          UartBase,                                                   \
> +          UartAddrLen,                                                \
> +          UartNameStr                                                 \
> +          ) {                                                         \
> +    {                                                                 \
> +      /* UINT8     Revision */                                        \
> +      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,         \
> +      /* UINT16    Length */                                          \
> +      sizeof (DBG2_DEBUG_DEVICE_INFORMATION),                         \
> +      /* UINT8     NumberofGenericAddressRegisters */                 \
> +      NumReg,                                                         \
> +      /* UINT16    NameSpaceStringLength */                           \
> +      DBG2_NAMESPACESTRING_FIELD_SIZE,                                \
> +      /* UINT16    NameSpaceStringOffset */                           \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString),     \
> +      /* UINT16    OemDataLength */                                   \
> +      0,                                                              \
> +      /* UINT16    OemDataOffset */                                   \
> +      0,                                                              \
> +      /* UINT16    Port Type */                                       \
> +      EFI_ACPI_DBG2_PORT_TYPE_SERIAL,                                 \
> +      /* UINT16    Port Subtype */                                    \
> +      SubType,                                                        \
> +      /* UINT8     Reserved[2] */                                     \
> +      {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE},               \
> +      /* UINT16    BaseAddressRegister Offset */                      \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \
> +      /* UINT16    AddressSize Offset */                              \
> +      OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize)          \
> +    },                                                                \
> +    /* EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */  \
> +    ARM_GAS32 (UartBase),                                             \
> +    /* UINT32  AddressSize */                                         \
> +    UartAddrLen,                                                      \
> +    /* UINT8   NameSpaceString[MAX_DBG2_NAME_LEN] */                  \
> +    UartNameStr                                                       \
> +  }
> +
> +/** The DBG2 Table template definition.
> +
> +    Note: fields marked with "{Template}" will be set dynamically
> +*/
> +STATIC
> +DBG2_TABLE AcpiDbg2 = {
> +  {
> +    ACPI_HEADER (
> +      EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
> +      DBG2_TABLE,
> +      EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
> +      ),
> +    OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),
> +    DBG2_NUM_DEBUG_PORTS
> +  },
> +  {
> +    /*
> +     * Debug port 1
> +     */
> +    DBG2_DEBUG_PORT_DDI (
> +      DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS,
> +      EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART,
> +      0,                    // {Template}: Serial Port Base Address
> +      PL011_UART_LENGTH,
> +      NAME_STR_PORT1
> +      )
> +  }
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Serial
> +    debug port information from the Configuration Manager
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjSerialDebugPortInfo,
> +  CM_ARM_SERIAL_PORT_INFO
> +  );
> +
> +/** Initialize the PL011 UART with the parameters obtained from
> +    the Configuration Manager.
> +
> +    @param [in]  SerialPortInfo Pointer to the Serial Port Information.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The parameters for serial port initialization
> +                                  are invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +SetupDebugUart (
> +  IN  CONST CM_ARM_SERIAL_PORT_INFO  * CONST SerialPortInfo
> +  )
> +{
> +  EFI_STATUS          Status;
> +  UINT64              BaudRate;
> +  UINT32              ReceiveFifoDepth;
> +  EFI_PARITY_TYPE     Parity;
> +  UINT8               DataBits;
> +  EFI_STOP_BITS_TYPE  StopBits;
> +
> +  ASSERT (SerialPortInfo != NULL);
> +
> +  // Initialize the Serial Debug UART
> +  DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));
> +  ReceiveFifoDepth = 0; // Use the default value for FIFO depth
> +  Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
> +  DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
> +  StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
> +
> +  BaudRate = SerialPortInfo->BaudRate;
> +  Status = PL011UartInitializePort (
> +             (UINTN)SerialPortInfo->BaseAddress,
> +             SerialPortInfo->Clock,
> +             &BaudRate,
> +             &ReceiveFifoDepth,
> +             &Parity,
> +             &DataBits,
> +             &StopBits
> +             );
> +
> +  DEBUG ((DEBUG_INFO, "Debug UART Configuration:\n"));
> +  DEBUG ((DEBUG_INFO, "UART Base  = 0x%lx\n", SerialPortInfo->BaseAddress));
> +  DEBUG ((DEBUG_INFO, "Clock      = %d\n", SerialPortInfo->Clock));
> +  DEBUG ((DEBUG_INFO, "Baudrate   = %ld\n", BaudRate));
> +  DEBUG ((DEBUG_INFO, "Configuring Debug UART. Status = %r\n", Status));
> +
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Construct the DBG2 ACPI table
> +
> +    The BuildDbg2Table function is called by the Dynamic Table Manager
> +    to construct the DBG2 ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildDbg2Table (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjSerialDebugPortInfo (
> +             CfgMgrProtocol,
> +             &SerialPortInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2,
> +             sizeof (DBG2_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.Address =
> +    SerialPortInfo->BaseAddress;
> +
> +  Status = SetupDebugUart (SerialPortInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the DBG2.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeDbg2TableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the DBG2 Table Generator revision.
> +*/
> +#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the DBG2 Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR Dbg2Generator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_DBG2),
> +  // Generator Description
> +  L"ACPI.STD.DBG2.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  DBG2_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildDbg2Table,
> +  // Free Resource function
> +  FreeDbg2TableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiDbg2LibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&Dbg2Generator);
> +  DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiDbg2LibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&Dbg2Generator);
> +  DEBUG ((DEBUG_INFO, "DBG2: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..75e0b7b50ef34a71cc091db50667a19b40b3f1c9
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
> @@ -0,0 +1,562 @@
> +/** @file
> +  FADT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard FADT Generator
> +
> +    Generates the ACPI FADT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjPowerManagementProfileInfo
> +  - EArmObjBootArchInfo
> +  - EArmObjHypervisorVendorIdentity (OPTIONAL)
> +*/
> +
> +/** This macro defines the FADT flag options for ARM Platforms.
> +*/
> +#define FADT_FLAGS  (EFI_ACPI_6_1_HW_REDUCED_ACPI |          \
> +                     EFI_ACPI_6_1_LOW_POWER_S0_IDLE_CAPABLE)
> +
> +#pragma pack(1)
> +
> +/** The AcpiFadt is a template EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE
> +    structure used for generating the FADT Table.
> +  Note: fields marked with "{Template}" will be updated dynamically.
> +*/
> +STATIC
> +EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = {
> +  ACPI_HEADER (
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE,
> +    EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
> +    ),
> +  // UINT32     FirmwareCtrl
> +  0,
> +  // UINT32     Dsdt
> +  0,
> +  // UINT8      Reserved0
> +  EFI_ACPI_RESERVED_BYTE,
> +  // UINT8      PreferredPmProfile
> +  EFI_ACPI_6_1_PM_PROFILE_UNSPECIFIED,  // {Template}: Power Management Profile
> +  // UINT16     SciInt
> +  0,
> +  // UINT32     SmiCmd
> +  0,
> +  // UINT8      AcpiEnable
> +  0,
> +  // UINT8      AcpiDisable
> +  0,
> +  // UINT8      S4BiosReq
> +  0,
> +  // UINT8      PstateCnt
> +  0,
> +  // UINT32     Pm1aEvtBlk
> +  0,
> +  // UINT32     Pm1bEvtBlk
> +  0,
> +  // UINT32     Pm1aCntBlk
> +  0,
> +  // UINT32     Pm1bCntBlk
> +  0,
> +  // UINT32     Pm2CntBlk
> +  0,
> +  // UINT32     PmTmrBlk
> +  0,
> +  // UINT32     Gpe0Blk
> +  0,
> +  // UINT32     Gpe1Blk
> +  0,
> +  // UINT8      Pm1EvtLen
> +  0,
> +  // UINT8      Pm1CntLen
> +  0,
> +  // UINT8      Pm2CntLen
> +  0,
> +  // UINT8      PmTmrLen
> +  0,
> +  // UINT8      Gpe0BlkLen
> +  0,
> +  // UINT8      Gpe1BlkLen
> +  0,
> +  // UINT8      Gpe1Base
> +  0,
> +  // UINT8      CstCnt
> +  0,
> +  // UINT16     PLvl2Lat
> +  0,
> +  // UINT16     PLvl3Lat
> +  0,
> +  // UINT16     FlushSize
> +  0,
> +  // UINT16     FlushStride
> +  0,
> +  // UINT8      DutyOffset
> +  0,
> +  // UINT8      DutyWidth
> +  0,
> +  // UINT8      DayAlrm
> +  0,
> +  // UINT8      MonAlrm
> +  0,
> +  // UINT8      Century
> +  0,
> +  // UINT16     IaPcBootArch
> +  0,
> +  // UINT8      Reserved1
> +  0,
> +  // UINT32     Flags
> +  FADT_FLAGS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  ResetReg
> +  NULL_GAS,
> +  // UINT8      ResetValue
> +  0,
> +  // UINT16     ArmBootArch
> +  EFI_ACPI_6_1_ARM_PSCI_COMPLIANT,  // {Template}: ARM Boot Architecture Flags
> +  // UINT8      MinorRevision
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION,
> +  // UINT64     XFirmwareCtrl
> +  0,
> +  // UINT64     XDsdt
> +  0,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aEvtBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bEvtBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1aCntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm1bCntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPm2CntBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XPmTmrBlk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe0Blk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  XGpe1Blk
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepControlReg
> +  NULL_GAS,
> +  // EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE  SleepStatusReg
> +  NULL_GAS,
> +  // UINT64     HypervisorVendorIdentity
> +  EFI_ACPI_RESERVED_QWORD  // {Template}: Hypervisor Vendor ID
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Power
> +    Management Profile Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPowerManagementProfileInfo,
> +  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Boot
> +    Architecture Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjBootArchInfo,
> +  CM_ARM_BOOT_ARCH_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Hypervisor
> +    Vendor ID from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjHypervisorVendorIdentity,
> +  CM_ARM_HYPERVISOR_VENDOR_ID
> +  );
> +
> +/** Update the Power Management Profile information in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                  Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddPmProfileInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS                              Status;
> +  CM_ARM_POWER_MANAGEMENT_PROFILE_INFO  * PmProfile = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Power Management Profile from the Platform Configuration Manager
> +  Status = GetEArmObjPowerManagementProfileInfo (
> +             CfgMgrProtocol,
> +             &PmProfile,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to get Power Management Profile information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT: PreferredPmProfile = 0x%x\n",
> +    PmProfile->PowerManagementProfile
> +    ));
> +
> +  AcpiFadt.PreferredPmProfile = PmProfile->PowerManagementProfile;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Updates the Boot Architecture information in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddBootArchInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS               Status;
> +  CM_ARM_BOOT_ARCH_INFO  * BootArchInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Boot Architecture flags from the Platform Configuration Manager
> +  Status = GetEArmObjBootArchInfo (
> +             CfgMgrProtocol,
> +             &BootArchInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT BootArchFlag = 0x%x\n",
> +    BootArchInfo->BootArchFlags
> +    ));
> +
> +  AcpiFadt.ArmBootArch = BootArchInfo->BootArchFlags;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Update the Hypervisor Vendor ID in the FADT Table.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FadtAddHypervisorVendorId (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
> +)
> +{
> +  EFI_STATUS                     Status;
> +  CM_ARM_HYPERVISOR_VENDOR_ID  * HypervisorVendorInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Get the Hypervisor Vendor ID from the Platform Configuration Manager
> +  Status = GetEArmObjHypervisorVendorIdentity (
> +             CfgMgrProtocol,
> +             &HypervisorVendorInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    if (Status == EFI_NOT_FOUND) {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "INFO: FADT: Platform does not have a Hypervisor Vendor ID. Status = %r\n",
> +        Status
> +        ));
> +    } else {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n",
> +        Status
> +        ));
> +    }
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "FADT: EArmObjHypervisorVendorIdentity = 0x%lx\n",
> +    HypervisorVendorInfo->HypervisorVendorId
> +    ));
> +
> +  AcpiFadt.HypervisorVendorIdentity = HypervisorVendorInfo->HypervisorVendorId;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Construct the FADT table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildFadtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt,
> +             sizeof (EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: FADT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  // Update PmProfile Info
> +  Status = FadtAddPmProfileInfo (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    goto error_handler;
> +  }
> +
> +  // Update BootArch Info
> +  Status = FadtAddBootArchInfo (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    goto error_handler;
> +  }
> +
> +  // Add the Hypervisor Vendor Id if present
> +  // Note if no hypervisor is present the zero bytes
> +  // will be placed in this field.
> +  Status = FadtAddHypervisorVendorId (CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    if (Status == EFI_NOT_FOUND) {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "INFO: FADT: No Hypervisor Vendor ID found," \
> +        " assuming no Hypervisor is present in the firmware.\n"
> +        ));
> +    } else {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r",
> +        Status
> +        ));
> +      goto error_handler;
> +    }
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt;
> +  Status = EFI_SUCCESS;
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the FADT.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeFadtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the FADT Table Generator revision.
> +*/
> +#define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the FADT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR FadtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT),
> +  // Generator Description
> +  L"ACPI.STD.FADT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  FADT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildFadtTable,
> +  // Free Resource function
> +  FreeFadtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiFadtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&FadtGenerator);
> +  DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiFadtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&FadtGenerator);
> +  DEBUG ((DEBUG_INFO, "FADT: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..8a243e7d2ef2fa5806116030c74337f1f8e72e8b
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
> @@ -0,0 +1,652 @@
> +/** @file
> +  GTDT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard GTDT Generator
> +
> +    Generates the ACPI GTDT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjGenericTimerInfo
> +  - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)
> +  - EArmObjPlatformGTBlockInfo (OPTIONAL)
> +*/
> +
> +/** This macro expands to a function that retrieves the Generic
> +    Timer Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGenericTimerInfo,
> +  CM_ARM_GENERIC_TIMER_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the SBSA Generic
> +    Watchdog Timer Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPlatformGenericWatchdogInfo,
> +  CM_ARM_GENERIC_WATCHDOG_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Platform Generic
> +    Timer Block Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPlatformGTBlockInfo,
> +  CM_ARM_GTBLOCK_INFO
> +  );
> +
> +/** Add the Generic Timer Information to the GTDT table.
> +
> +    Also update the Platform Timer offset information if the platform
> +    implements platform timers.
> +
> +    @param [in]  CfgMgrProtocol     Pointer to the Configuration Manager
> +                                    Protocol Interface.
> +    @param [in]  Gtdt               Pointer to the GTDT Table.
> +    @param [in]  PlatformTimerCount Platform timer count.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddGenericTimerInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,
> +  IN  CONST UINT32 PlatformTimerCount
> +)
> +{
> +  EFI_STATUS                   Status;
> +  CM_ARM_GENERIC_TIMER_INFO  * GenericTimerInfo = NULL;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Gtdt != NULL);
> +
> +  Status = GetEArmObjGenericTimerInfo (
> +             CfgMgrProtocol,
> +             &GenericTimerInfo,
> +             NULL
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to get GenericTimerInfo. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Gtdt->CntControlBasePhysicalAddress =
> +    GenericTimerInfo->CounterControlBaseAddress;
> +  Gtdt->Reserved = EFI_ACPI_RESERVED_DWORD;
> +  Gtdt->CntReadBasePhysicalAddress =
> +    GenericTimerInfo->CounterReadBaseAddress;
> +  Gtdt->PlatformTimerCount = PlatformTimerCount;
> +  Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :
> +    sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
> +
> +  Gtdt->SecurePL1TimerGSIV = GenericTimerInfo->SecurePL1TimerGSIV;
> +  Gtdt->SecurePL1TimerFlags = GenericTimerInfo->SecurePL1TimerFlags;
> +  Gtdt->NonSecurePL1TimerGSIV = GenericTimerInfo->NonSecurePL1TimerGSIV;
> +  Gtdt->NonSecurePL1TimerFlags = GenericTimerInfo->NonSecurePL1TimerFlags;
> +  Gtdt->VirtualTimerGSIV = GenericTimerInfo->VirtualTimerGSIV;
> +  Gtdt->VirtualTimerFlags = GenericTimerInfo->VirtualTimerFlags;
> +  Gtdt->NonSecurePL2TimerGSIV = GenericTimerInfo->NonSecurePL2TimerGSIV;
> +  Gtdt->NonSecurePL2TimerFlags = GenericTimerInfo->NonSecurePL2TimerFlags;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add the SBSA Generic Watchdog Timers to the GTDT table.
> +
> +    @param [in]  Gtdt             Pointer to the GTDT Table.
> +    @param [in]  WatchdogOffset   Offset to the watchdog information in the
> +                                  GTDT Table.
> +    @param [in]  WatchdogInfoList Pointer to the watchdog information list.
> +    @param [in]  WatchdogCount    Platform timer count.
> +*/
> +STATIC
> +VOID
> +AddGenericWatchdogList (
> +  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
> +  IN CONST UINTN                                           WatchdogOffset,
> +  IN CONST CM_ARM_GENERIC_WATCHDOG_INFO            * CONST WatchdogInfoList,
> +  IN CONST UINTN                                           WatchdogCount
> +  )
> +{
> +  UINTN                                                idx;
> +  EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE  * Watchdog;
> +
> +  ASSERT (Gtdt != NULL);
> +  ASSERT (WatchdogInfoList != NULL);
> +
> +  Watchdog = (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *)
> +             ((UINT8*)Gtdt + WatchdogOffset);
> +
> +  for (idx = 0; idx < WatchdogCount; idx++) {
> +    // Add watchdog entry
> +    DEBUG ((DEBUG_INFO, "GTDT: Watchdog[%d] = 0x%p\n", idx, &Watchdog[idx]));
> +    Watchdog[idx].Type = EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG;
> +    Watchdog[idx].Length =
> +      sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);
> +    Watchdog[idx].Reserved = EFI_ACPI_RESERVED_BYTE;
> +    Watchdog[idx].RefreshFramePhysicalAddress =
> +      WatchdogInfoList[idx].RefreshFrameAddress;
> +    Watchdog[idx].WatchdogControlFramePhysicalAddress =
> +      WatchdogInfoList[idx].ControlFrameAddress;
> +    Watchdog[idx].WatchdogTimerGSIV = WatchdogInfoList[idx].TimerGSIV;
> +    Watchdog[idx].WatchdogTimerFlags = WatchdogInfoList[idx].Flags;
> +
> +  } // for
> +}
> +
> +/** Update the GT Block Timer Frame lists in the GTDT Table.
> +
> +    @param [in]  GtBlockFrame           Pointer to the GT Block Frames
> +                                        list to be updated.
> +    @param [in]  GTBlockTimerFrameList  Pointer to the GT Block Frame
> +                                        Information List.
> +    @param [in]  GTBlockFrameCount      Number of GT Block Frames.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +AddGTBlockTimerFrames (
> +  IN       EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE * CONST GtBlockFrame,
> +  IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO * CONST GTBlockTimerFrameList,
> +  IN CONST UINTN GTBlockFrameCount
> +)
> +{
> +  UINTN       idx;
> +
> +  ASSERT (GtBlockFrame != NULL);
> +  ASSERT (GTBlockTimerFrameList != NULL);
> +
> +  if (GTBlockFrameCount > 8) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: GT Block Frame Count %d is greater than 8\n",
> +      GTBlockFrameCount
> +      ));
> +    ASSERT (GTBlockFrameCount <= 8);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  for (idx = 0; idx < GTBlockFrameCount; idx++) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: GtBlockFrame[%d] = 0x%p\n",
> +      idx,
> +      GtBlockFrame[idx]
> +      ));
> +
> +    GtBlockFrame[idx].GTFrameNumber = GTBlockTimerFrameList[idx].FrameNumber;
> +    GtBlockFrame[idx].Reserved[0] = EFI_ACPI_RESERVED_BYTE;
> +    GtBlockFrame[idx].Reserved[1] = EFI_ACPI_RESERVED_BYTE;
> +    GtBlockFrame[idx].Reserved[2] = EFI_ACPI_RESERVED_BYTE;
> +
> +    GtBlockFrame[idx].CntBaseX =
> +      GTBlockTimerFrameList[idx].PhysicalAddressCntBase;
> +    GtBlockFrame[idx].CntEL0BaseX =
> +      GTBlockTimerFrameList[idx].PhysicalAddressCntEL0Base;
> +
> +    GtBlockFrame[idx].GTxPhysicalTimerGSIV =
> +      GTBlockTimerFrameList[idx].PhysicalTimerGSIV;
> +    GtBlockFrame[idx].GTxPhysicalTimerFlags =
> +      GTBlockTimerFrameList[idx].PhysicalTimerFlags;
> +
> +    GtBlockFrame[idx].GTxVirtualTimerGSIV =
> +      GTBlockTimerFrameList[idx].VirtualTimerGSIV;
> +    GtBlockFrame[idx].GTxVirtualTimerFlags =
> +      GTBlockTimerFrameList[idx].VirtualTimerFlags;
> +
> +    GtBlockFrame[idx].GTxCommonFlags = GTBlockTimerFrameList[idx].CommonFlags;
> +
> +  } // for
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add the GT Block Timers in the GTDT Table.
> +
> +    @param [in]  Gtdt             Pointer to the GTDT Table.
> +    @param [in]  GTBlockOffset    Offset of the GT Block
> +                                  information in the GTDT Table.
> +    @param [in]  GTBlockInfo      Pointer to the GT Block
> +                                  Information List.
> +    @param [in]  BlockTimerCount  Number of GT Block Timers.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +AddGTBlockList (
> +  IN EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * CONST Gtdt,
> +  IN CONST UINTN                                           GTBlockOffset,
> +  IN CONST CM_ARM_GTBLOCK_INFO                     * CONST GTBlockInfo,
> +  IN CONST UINTN                                           BlockTimerCount
> +)
> +{
> +  EFI_STATUS                                    Status;
> +  UINTN                                         idx;
> +  EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE        * GTBlock;
> +  EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE  * GtBlockFrame;
> +
> +  ASSERT (Gtdt != NULL);
> +  ASSERT (GTBlockInfo != NULL);
> +
> +  GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)Gtdt +
> +              GTBlockOffset);
> +
> +  for (idx = 0; idx < BlockTimerCount; idx++) {
> +    DEBUG ((DEBUG_INFO, "GTDT: GTBlock[%d] = 0x%p\n",
> +      idx,
> +      GTBlock
> +      ));
> +
> +    GTBlock->Type = EFI_ACPI_6_1_GTDT_GT_BLOCK;
> +    GTBlock->Length = sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) +
> +                        (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
> +                          GTBlockInfo[idx].GTBlockTimerFrameCount);
> +
> +    GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;
> +    GTBlock->CntCtlBase = GTBlockInfo[idx].GTBlockPhysicalAddress;
> +    GTBlock->GTBlockTimerCount = GTBlockInfo[idx].GTBlockTimerFrameCount;
> +    GTBlock->GTBlockTimerOffset =
> +      sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE);
> +
> +    GtBlockFrame = (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE*)
> +      ((UINT8*)GTBlock + GTBlock->GTBlockTimerOffset);
> +
> +    // Add GT Block Timer frames
> +    Status = AddGTBlockTimerFrames (
> +               GtBlockFrame,
> +               GTBlockInfo[idx].GTBlockTimerFrameList,
> +               GTBlockInfo[idx].GTBlockTimerFrameCount
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",
> +        Status
> +        ));
> +      return Status;
> +    }
> +
> +    // Next GTBlock
> +    GTBlock = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)GTBlock +
> +                GTBlock->Length);
> +  }// for
> +  return EFI_SUCCESS;
> +}
> +
> +/** Construct the GTDT ACPI table.
> +
> +    Called by the Dynamic Table Manager, this function invokes the
> +    Confguration Manager protocol interface to get the required hardware
> +    information for generating the ACPI table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildGtdtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                                      Status;
> +  UINTN                                           TableSize;
> +  UINTN                                           PlatformTimerCount = 0;
> +  UINTN                                           WatchdogCount;
> +  UINTN                                           BlockTimerCount;
> +  CM_ARM_GENERIC_WATCHDOG_INFO                  * WatchdogInfoList = NULL;
> +  CM_ARM_GTBLOCK_INFO                           * GTBlockInfo = NULL;
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE  * Gtdt;
> +  UINTN                                           idx;
> +  UINTN                                           GTBlockOffset;
> +  UINTN                                           WatchdogOffset = 0;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +  Status = GetEArmObjPlatformGTBlockInfo (
> +             CfgMgrProtocol,
> +             &GTBlockInfo,
> +             &BlockTimerCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to Get Platform GT Block Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjPlatformGenericWatchdogInfo (
> +             CfgMgrProtocol,
> +             &WatchdogInfoList,
> +             &WatchdogCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",
> +    BlockTimerCount,
> +    WatchdogCount
> +    ));
> +
> +  // Calculate the GTDT Table Size
> +  TableSize = sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE);
> +  if (BlockTimerCount != 0) {
> +    GTBlockOffset = TableSize;
> +    PlatformTimerCount += BlockTimerCount;
> +    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE) *
> +                  BlockTimerCount);
> +
> +    for (idx = 0; idx < BlockTimerCount; idx++) {
> +      if (GTBlockInfo[idx].GTBlockTimerFrameCount > 8) {
> +        Status = EFI_INVALID_PARAMETER;
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "GTDT: GTBockFrameCount cannot be more than 8." \
> +          " GTBockFrameCount = %d, Status = %r\n",
> +          GTBlockInfo[idx].GTBlockTimerFrameCount,
> +          Status
> +          ));
> +        goto error_handler;
> +      }
> +      TableSize += (sizeof (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
> +        GTBlockInfo[idx].GTBlockTimerFrameCount);
> +    }
> +
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
> +      GTBlockOffset,
> +      PlatformTimerCount
> +      ));
> +  }
> +
> +  if (WatchdogCount != 0) {
> +    WatchdogOffset = TableSize;
> +    PlatformTimerCount += WatchdogCount;
> +    TableSize += (sizeof (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE) *
> +                  WatchdogCount);
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
> +      WatchdogOffset,
> +      PlatformTimerCount
> +      ));
> +  }
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Gtdt = (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE*)*Table;
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",
> +    Gtdt,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Gtdt->Header, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = AddGenericTimerInfo (
> +             CfgMgrProtocol,
> +             Gtdt,
> +             PlatformTimerCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (BlockTimerCount != 0) {
> +    Status = AddGTBlockList (
> +               Gtdt,
> +               GTBlockOffset,
> +               GTBlockInfo,
> +               BlockTimerCount
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",
> +        Status
> +        ));
> +      goto error_handler;
> +    }
> +  }
> +
> +  if (WatchdogCount != 0) {
> +    AddGenericWatchdogList (
> +      Gtdt,
> +      WatchdogOffset,
> +      WatchdogInfoList,
> +      WatchdogCount
> +      );
> +  }
> +
> +  return Status;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the GTDT.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +FreeGtdtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +)
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the GTDT Table Generator revision.
> +*/
> +#define GTDT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the GTDT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR GtdtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_GTDT),
> +  // Generator Description
> +  L"ACPI.STD.GTDT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  GTDT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildGtdtTable,
> +  // Free Resource function
> +  FreeGtdtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiGtdtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&GtdtGenerator);
> +  DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiGtdtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&GtdtGenerator);
> +  DEBUG ((DEBUG_INFO, "GTDT: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..cce440d91f50d8a7ac429acb6be40d4a6ac4e230
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
> @@ -0,0 +1,732 @@
> +/** @file
> +  MADT Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard MADT Generator
> +
> +    Generates the ACPI MADT Table as specified by the
> +    ACPI 6.1 Specification - January, 2016.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjGicCInfo
> +  - EArmObjGicDInfo
> +  - EArmObjGicMsiFrameInfo (OPTIONAL)
> +  - EArmObjGicRedistributorInfo (OPTIONAL)
> +  - EArmObjGicItsInfo (OPTIONAL)
> +*/
> +
> +/** This macro expands to a function that retrieves the GIC
> +    CPU interface Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicCInfo,
> +  CM_ARM_GICC_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Distributor Information from the Configuration Manager.
> +*/
> +
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicDInfo,
> +  CM_ARM_GICD_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    MSI Frame Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicMsiFrameInfo,
> +  CM_ARM_GIC_MSI_FRAME_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Redistributor Information from the Configuration Manager.
> +*/
> +
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicRedistributorInfo,
> +  CM_ARM_GIC_REDIST_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the GIC
> +    Interrupt Translation Serice Information from the
> +    Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjGicItsInfo,
> +  CM_ARM_GIC_ITS_INFO
> +  );
> +
> +/** This function updates the GIC CPU Interface Information in the
> +    EFI_ACPI_6_1_GIC_STRUCTURE structure.
> +
> +    @param [in]  Gicc      Pointer to GIC CPU Interface structure.
> +    @param [in]  GicCInfo  Pointer to the GIC CPU Interface Information.
> +*/
> +STATIC
> +VOID
> +AddGICC (
> +  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * CONST Gicc,
> +  IN  CONST CM_ARM_GICC_INFO      * CONST GicCInfo
> +  )
> +{
> +  ASSERT (Gicc != NULL);
> +  ASSERT (GicCInfo != NULL);
> +
> +  /* UINT8 Type */
> +  Gicc->Type = EFI_ACPI_6_1_GIC;
> +  /* UINT8 Length */
> +  Gicc->Length = sizeof (EFI_ACPI_6_1_GIC_STRUCTURE);
> +  /* UINT16 Reserved */
> +  Gicc->Reserved = EFI_ACPI_RESERVED_WORD;
> +
> +  /* UINT32 CPUInterfaceNumber */
> +  Gicc->CPUInterfaceNumber = GicCInfo->CPUInterfaceNumber;
> +  /* UINT32 AcpiProcessorUid */
> +  Gicc->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;
> +  /* UINT32 Flags */
> +  Gicc->Flags = GicCInfo->Flags;
> +  /* UINT32 ParkingProtocolVersion */
> +  Gicc->ParkingProtocolVersion = GicCInfo->ParkingProtocolVersion;
> +  /* UINT32 PerformanceInterruptGsiv */
> +  Gicc->PerformanceInterruptGsiv = GicCInfo->PerformanceInterruptGsiv;
> +  /* UINT64 ParkedAddress */
> +  Gicc->ParkedAddress = GicCInfo->ParkedAddress;
> +
> +  /* UINT64 PhysicalBaseAddress */
> +  Gicc->PhysicalBaseAddress = GicCInfo->PhysicalBaseAddress;
> +  /* UINT64 GICV */
> +  Gicc->GICV = GicCInfo->GICV;
> +  /* UINT64 GICH */
> +  Gicc->GICH = GicCInfo->GICH;
> +
> +  /* UINT32 VGICMaintenanceInterrupt */
> +  Gicc->VGICMaintenanceInterrupt = GicCInfo->VGICMaintenanceInterrupt;
> +  /* UINT64 GICRBaseAddress */
> +  Gicc->GICRBaseAddress = GicCInfo->GICRBaseAddress;
> +
> +  /* UINT64 MPIDR */
> +  Gicc->MPIDR = GicCInfo->MPIDR;
> +  /* UINT8 ProcessorPowerEfficiencyClass */
> +  Gicc->ProcessorPowerEfficiencyClass =
> +    GicCInfo->ProcessorPowerEfficiencyClass;
> +  /* UINT8 Reserved2[3] */
> +  Gicc->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
> +  Gicc->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
> +  Gicc->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
> +}
> +
> +/** Add the GIC CPU Interface Information to the MADT Table.
> +
> +    @param [in]  Gicc      Pointer to GIC CPU Interface
> +                            structure list.
> +    @param [in]  GicCInfo  Pointer to the GIC CPU
> +                            Information list.
> +    @param [in]  GicCCount Count of GIC CPU Interfaces.
> +*/
> +STATIC
> +VOID
> +AddGICCList (
> +  IN  EFI_ACPI_6_1_GIC_STRUCTURE  * Gicc,
> +  IN  CONST CM_ARM_GICC_INFO      * GicCInfo,
> +  IN  CONST UINTN                   GicCCount
> +  )
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicc != NULL);
> +  ASSERT (GicCInfo != NULL);
> +
> +  for (idx = 0; idx < GicCCount; idx++) {
> +    AddGICC (Gicc++, GicCInfo++);
> +  }
> +}
> +
> +/** Update the GIC Distributor Information in the MADT Table.
> +
> +    @param [in]  Gicd      Pointer to GIC Distributor structure.
> +    @param [in]  GicDInfo  Pointer to the GIC Distributor Information.
> +*/
> +STATIC
> +VOID
> +AddGICD (
> +  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * CONST Gicd,
> +  CONST CM_ARM_GICD_INFO                  * CONST GicDInfo
> +)
> +{
> +  ASSERT (Gicd != NULL);
> +  ASSERT (GicDInfo != NULL);
> +
> +  /* UINT8 Type */
> +  Gicd->Type = EFI_ACPI_6_1_GICD;
> +  /* UINT8 Length */
> +  Gicd->Length = sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE);
> +  /* UINT16 Reserved */
> +  Gicd->Reserved1 = EFI_ACPI_RESERVED_WORD;
> +  /* UINT32 Identifier */
> +  Gicd->GicId = GicDInfo->GicId;
> +  /* UINT64 PhysicalBaseAddress */
> +  Gicd->PhysicalBaseAddress = GicDInfo->PhysicalBaseAddress;
> +  /* UINT32 VectorBase */
> +  Gicd->SystemVectorBase = GicDInfo->SystemVectorBase;
> +  /* UINT8  GicVersion */
> +  Gicd->GicVersion = GicDInfo->GicVersion;
> +  /* UINT8  Reserved2[3] */
> +  Gicd->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
> +  Gicd->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
> +  Gicd->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
> +}
> +
> +/** Add the GIC Distributor Information to the MADT Table.
> +
> +    @param [in]  Gicd      Pointer to GIC Distributor structure list.
> +    @param [in]  GicDInfo  Pointer to the GIC Distributor Information list.
> +    @param [in]  GicDCount Count of GIC Distributors.
> +*/
> +STATIC
> +VOID
> +AddGICDList (
> +  IN  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE  * Gicd,
> +  IN  CONST CM_ARM_GICD_INFO                  * GicDInfo,
> +  IN  CONST UINTN                               GicDCount
> +  )
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicd != NULL);
> +  ASSERT (GicDInfo != NULL);
> +
> +  for (idx = 0; idx < GicDCount; idx++) {
> +    AddGICD (Gicd++, GicDInfo++);
> +  }
> +}
> +
> +/** Update the GIC MSI Frame Information.
> +
> +    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure.
> +    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame Information.
> +*/
> +STATIC
> +VOID
> +AddGICMsiFrame (
> +  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * CONST GicMsiFrame,
> +  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * CONST GicMsiFrameInfo
> +)
> +{
> +  ASSERT (GicMsiFrame != NULL);
> +  ASSERT (GicMsiFrameInfo != NULL);
> +
> +  GicMsiFrame->Type = EFI_ACPI_6_1_GIC_MSI_FRAME;
> +  GicMsiFrame->Length = sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE);
> +  GicMsiFrame->Reserved1 = EFI_ACPI_RESERVED_WORD;
> +  GicMsiFrame->GicMsiFrameId = GicMsiFrameInfo->GicMsiFrameId;
> +  GicMsiFrame->PhysicalBaseAddress = GicMsiFrameInfo->PhysicalBaseAddress;
> +
> +  GicMsiFrame->Flags = GicMsiFrameInfo->Flags;
> +  GicMsiFrame->SPICount = GicMsiFrameInfo->SPICount;
> +  GicMsiFrame->SPIBase = GicMsiFrameInfo->SPIBase;
> +}
> +
> +/** Add the GIC MSI Frame Information to the MADT Table.
> +
> +    @param [in]  GicMsiFrame      Pointer to GIC MSI Frame structure list.
> +    @param [in]  GicMsiFrameInfo  Pointer to the GIC MSI Frame info list.
> +    @param [in]  GicMsiFrameCount Count of GIC MSI Frames.
> +*/
> +STATIC
> +VOID
> +AddGICMsiFrameInfoList (
> +  IN  EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE  * GicMsiFrame,
> +  IN  CONST CM_ARM_GIC_MSI_FRAME_INFO       * GicMsiFrameInfo,
> +  IN  CONST UINTN                             GicMsiFrameCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (GicMsiFrame != NULL);
> +  ASSERT (GicMsiFrameInfo != NULL);
> +
> +  for (idx = 0; idx < GicMsiFrameCount; idx++) {
> +    AddGICMsiFrame (GicMsiFrame++, GicMsiFrameInfo++);
> +  }
> +}
> +
> +/** Update the GIC Redistributor Information.
> +
> +    @param [in]  Gicr                 Pointer to GIC Redistributor structure.
> +    @param [in]  GicRedisributorInfo  Pointer to the GIC Redistributor Info.
> +*/
> +STATIC
> +VOID
> +AddGICRedistributor (
> +  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * CONST Gicr,
> +  IN  CONST CM_ARM_GIC_REDIST_INFO  * CONST GicRedisributorInfo
> +  )
> +{
> +  ASSERT (Gicr != NULL);
> +  ASSERT (GicRedisributorInfo != NULL);
> +
> +  Gicr->Type = EFI_ACPI_6_1_GICR;
> +  Gicr->Length = sizeof (EFI_ACPI_6_1_GICR_STRUCTURE);
> +  Gicr->Reserved = EFI_ACPI_RESERVED_WORD;
> +  Gicr->DiscoveryRangeBaseAddress =
> +    GicRedisributorInfo->DiscoveryRangeBaseAddress;
> +  Gicr->DiscoveryRangeLength = GicRedisributorInfo->DiscoveryRangeLength;
> +}
> +
> +/** Add the GIC Redistributor Information to the MADT Table.
> +
> +    @param [in]  Gicr      Pointer to GIC Redistributor structure list.
> +    @param [in]  GicRInfo  Pointer to the GIC Distributor info list.
> +    @param [in]  GicRCount Count of GIC Distributors.
> +*/
> +STATIC
> +VOID
> +AddGICRedistributorList (
> +  IN  EFI_ACPI_6_1_GICR_STRUCTURE   * Gicr,
> +  IN  CONST CM_ARM_GIC_REDIST_INFO  * GicRInfo,
> +  IN  CONST UINTN                     GicRCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (Gicr != NULL);
> +  ASSERT (GicRInfo != NULL);
> +
> +  for (idx = 0; idx < GicRCount; idx++) {
> +    AddGICRedistributor (Gicr++, GicRInfo++);
> +  }
> +}
> +
> +/** Update the GIC Interrupt Translation Service Information
> +
> +    @param [in]  GicIts      Pointer to GIC ITS structure.
> +    @param [in]  GicItsInfo  Pointer to the GIC ITS Information.
> +*/
> +STATIC
> +VOID
> +AddGICInterruptTranslationService (
> +  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * CONST GicIts,
> +  IN  CONST CM_ARM_GIC_ITS_INFO       * CONST GicItsInfo
> +)
> +{
> +  ASSERT (GicIts != NULL);
> +  ASSERT (GicItsInfo != NULL);
> +
> +  GicIts->Type = EFI_ACPI_6_1_GIC_ITS;
> +  GicIts->Length = sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE);
> +  GicIts->Reserved = EFI_ACPI_RESERVED_WORD;
> +  GicIts->GicItsId = GicItsInfo->GicItsId;
> +  GicIts->PhysicalBaseAddress = GicItsInfo->PhysicalBaseAddress;
> +  GicIts->Reserved2 = EFI_ACPI_RESERVED_DWORD;
> +}
> +
> +/** Add the GIC Interrupt Translation Service Information
> +    to the MADT Table.
> +
> +    @param [in]  GicIts       Pointer to GIC ITS structure list.
> +    @param [in]  GicItsInfo   Pointer to the GIC ITS list.
> +    @param [in]  GicItsCount  Count of GIC ITS.
> +*/
> +STATIC
> +VOID
> +AddGICItsList (
> +  IN  EFI_ACPI_6_1_GIC_ITS_STRUCTURE  * GicIts,
> +  IN  CONST CM_ARM_GIC_ITS_INFO       * GicItsInfo,
> +  IN  CONST UINTN                       GicItsCount
> +)
> +{
> +  UINTN  idx;
> +
> +  ASSERT (GicIts != NULL);
> +  ASSERT (GicItsInfo != NULL);
> +
> +  for (idx = 0; idx < GicItsCount; idx++) {
> +    AddGICInterruptTranslationService (GicIts++, GicItsInfo++);
> +  }
> +}
> +
> +/** Construct the MADT ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildMadtTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  UINTN                        TableSize;
> +  UINTN                        GicCCount;
> +  UINTN                        GicDCount;
> +  UINTN                        GicMSICount;
> +  UINTN                        GicRedistCount;
> +  UINTN                        GicItsCount;
> +  CM_ARM_GICC_INFO           * GicCInfo = NULL;
> +  CM_ARM_GICD_INFO           * GicDInfo = NULL;
> +  CM_ARM_GIC_MSI_FRAME_INFO  * GicMSIInfo = NULL;
> +  CM_ARM_GIC_REDIST_INFO     * GicRedistInfo = NULL;
> +  CM_ARM_GIC_ITS_INFO        * GicItsInfo = NULL;
> +  UINTN                        GicCOffset;
> +  UINTN                        GicDOffset;
> +  UINTN                        GicMSIOffset;
> +  UINTN                        GicRedistOffset;
> +  UINTN                        GicItsOffset;
> +
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER  * Madt;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjGicCInfo (CfgMgrProtocol, &GicCInfo, &GicCCount);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GICC Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (GicCCount == 0) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: GIC CPU Interface information not provided.\n"
> +      ));
> +    ASSERT (GicCCount != 0);
> +    Status = EFI_INVALID_PARAMETER;
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicDInfo (CfgMgrProtocol, &GicDInfo, &GicDCount);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GICD Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  if (GicDCount == 0) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: GIC Distributor information not provided.\n"
> +      ));
> +    ASSERT (GicDCount != 0);
> +    Status = EFI_INVALID_PARAMETER;
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicMsiFrameInfo (
> +             CfgMgrProtocol,
> +             &GicMSIInfo,
> +             &GicMSICount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC MSI Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicRedistributorInfo (
> +             CfgMgrProtocol,
> +             &GicRedistInfo,
> +             &GicRedistCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC Redistributor Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjGicItsInfo (
> +             CfgMgrProtocol,
> +             &GicItsInfo,
> +             &GicItsCount
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to get GIC ITS Info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  TableSize = sizeof (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
> +
> +  GicCOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_STRUCTURE) * GicCCount);
> +
> +  GicDOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE) * GicDCount);
> +
> +  GicMSIOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE) * GicMSICount);
> +
> +  GicRedistOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GICR_STRUCTURE) * GicRedistCount);
> +
> +  GicItsOffset = TableSize;
> +  TableSize += (sizeof (EFI_ACPI_6_1_GIC_ITS_STRUCTURE) * GicItsCount);
> +
> +  // Allocate the Buffer for MADT table
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to allocate memory for MADT Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Madt = (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER*)*Table;
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MADT: Madt = 0x%p TableSize = 0x%x\n",
> +    Madt,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Madt->Header, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MADT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  AddGICCList (
> +    (EFI_ACPI_6_1_GIC_STRUCTURE*)((UINT8*)Madt + GicCOffset),
> +    GicCInfo,
> +    GicCCount
> +    );
> +
> +  AddGICDList (
> +    (EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE*)((UINT8*)Madt + GicDOffset),
> +    GicDInfo,
> +    GicDCount
> +    );
> +
> +  if (GicMSICount != 0) {
> +    AddGICMsiFrameInfoList (
> +      (EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE*)((UINT8*)Madt + GicMSIOffset),
> +      GicMSIInfo,
> +      GicMSICount
> +      );
> +  }
> +
> +  if (GicRedistCount != 0) {
> +    AddGICRedistributorList (
> +      (EFI_ACPI_6_1_GICR_STRUCTURE*)((UINT8*)Madt + GicRedistOffset),
> +      GicRedistInfo,
> +      GicRedistCount
> +      );
> +  }
> +
> +  if (GicItsCount != 0) {
> +    AddGICItsList (
> +      (EFI_ACPI_6_1_GIC_ITS_STRUCTURE*)((UINT8*)Madt + GicItsOffset),
> +      GicItsInfo,
> +      GicItsCount
> +      );
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the MADT
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeMadtTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MADT: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** The MADT Table Generator revision.
> +*/
> +#define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the MADT Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR MadtGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MADT),
> +  // Generator Description
> +  L"ACPI.STD.MADT.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  MADT_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildMadtTable,
> +  // Free Resource function
> +  FreeMadtTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMadtLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&MadtGenerator);
> +  DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMadtLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&MadtGenerator);
> +  DEBUG ((DEBUG_INFO, "MADT: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..c023b413797379562f20ae97db9e2f2ca6d8758c
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
> @@ -0,0 +1,336 @@
> +/** @file
> +  MCFG Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard MCFG Generator
> +
> +    Generates the MCFG Table as specified by the PCI Firmware
> +    Specification - Revision 3.2, January 26, 2015.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjPciConfigSpaceInfo
> +*/
> +
> +#pragma pack(1)
> +
> +/** This typedef is used to shorten the name of the MCFG Table
> +    header structure.
> +*/
> +typedef
> +  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER
> +  MCFG_TABLE;
> +
> +/** This typedef is used to shorten the name of the Enhanced
> +    Configuration Space address structure.
> +*/
> +typedef
> +  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE
> +  MCFG_CFG_SPACE_ADDR;
> +
> +#pragma pack()
> +
> +/** Retrieve the PCI Configuration Space Information.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPciConfigSpaceInfo,
> +  CM_ARM_PCI_CONFIG_SPACE_INFO
> +  );
> +
> +/** Add the PCI Enhanced Configuration Space Information to the MCFG Table.
> +
> +    @param [in]  Mcfg                Pointer to MCFG Table.
> +    @param [in]  PciCfgSpaceOffset   Offset for the PCI Configuration Space
> +                                     Info structure in the MCFG Table.
> +    @param [in]  PciCfgSpaceInfoList Pointer to the PCI Configuration Space
> +                                     Info List.
> +    @param [in]  PciCfgSpaceCount    Count of PCI Configuration Space Info.
> +*/
> +STATIC
> +VOID
> +AddPciConfigurationSpaceList (
> +  IN       MCFG_TABLE                   * CONST Mcfg,
> +  IN CONST UINTN                                PciCfgSpaceOffset,
> +  IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * CONST PciCfgSpaceInfoList,
> +  IN CONST UINTN                                PciCfgSpaceCount
> +)
> +{
> +  UINTN                  idx;
> +  MCFG_CFG_SPACE_ADDR  * PciCfgSpace;
> +
> +  ASSERT (Mcfg != NULL);
> +  ASSERT (PciCfgSpaceInfoList != NULL);
> +
> +  PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8*)Mcfg + PciCfgSpaceOffset);
> +  for (idx = 0; idx < PciCfgSpaceCount; idx++) {
> +    // Add PCI Configuration Space entry
> +    PciCfgSpace[idx].BaseAddress = PciCfgSpaceInfoList[idx].BaseAddress;
> +    PciCfgSpace[idx].PciSegmentGroupNumber =
> +      PciCfgSpaceInfoList[idx].PciSegmentGroupNumber;
> +    PciCfgSpace[idx].StartBusNumber = PciCfgSpaceInfoList[idx].StartBusNumber;
> +    PciCfgSpace[idx].EndBusNumber = PciCfgSpaceInfoList[idx].EndBusNumber;
> +    PciCfgSpace[idx].Reserved = EFI_ACPI_RESERVED_DWORD;
> +  }
> +}
> +
> +/** Construct the MCFG ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildMcfgTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UINTN                           TableSize;
> +  UINTN                           ConfigurationSpaceCount;
> +  CM_ARM_PCI_CONFIG_SPACE_INFO  * PciConfigSpaceInfoList = NULL;
> +  MCFG_TABLE                    * Mcfg;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +  Status = GetEArmObjPciConfigSpaceInfo (
> +              CfgMgrProtocol,
> +              &PciConfigSpaceInfoList,
> +              &ConfigurationSpaceCount
> +              );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to get PCI Configuration Space Information." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +  ASSERT (ConfigurationSpaceCount != 0);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MCFG: Configuration Space Count = %d\n",
> +    ConfigurationSpaceCount
> +    ));
> +
> +  // Calculate the MCFG Table Size
> +  TableSize = sizeof (MCFG_TABLE) +
> +    ((sizeof (MCFG_CFG_SPACE_ADDR) * ConfigurationSpaceCount));
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \
> +      " Status = %r\n",
> +      TableSize,
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Mcfg = (MCFG_TABLE*)*Table;
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MCFG: Mcfg = 0x%p TableSize = 0x%x\n",
> +    Mcfg,
> +    TableSize
> +    ));
> +
> +  Status = AddAcpiHeader (CfgMgrProtocol, This, &Mcfg->Header, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: MCFG: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  Mcfg->Reserved = EFI_ACPI_RESERVED_QWORD;
> +
> +  AddPciConfigurationSpaceList (
> +    Mcfg,
> +    sizeof (MCFG_TABLE),
> +    PciConfigSpaceInfoList,
> +    ConfigurationSpaceCount
> +    );
> +
> +  return EFI_SUCCESS;
> +
> +error_handler:
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the MCFG
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS           The resources were freed successfully.
> +    @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeMcfgTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MCFG: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the MCFG Table Generator revision.
> +*/
> +#define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the MCFG Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR McfgGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MCFG),
> +  // Generator Description
> +  L"ACPI.STD.MCFG.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  MCFG_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildMcfgTable,
> +  // Free Resource function
> +  FreeMcfgTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMcfgLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&McfgGenerator);
> +  DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiMcfgLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&McfgGenerator);
> +  DEBUG ((DEBUG_INFO, "MCFG: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..aaca70cba0a1a08c0730bd84134c1b8722edd7af
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
> @@ -0,0 +1,177 @@
> +/** @file
> +  MCFG Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** Construct the ACPI table using the ACPI table data provided.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildRawTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableData != NULL);
> +
> +  if (AcpiTableInfo->AcpiTableData == NULL) {
> +    *Table = NULL;
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Table = AcpiTableInfo->AcpiTableData;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Free any resources allocated for constructing the ACPI table.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +
> +*/
> +STATIC
> +EFI_STATUS
> +FreeRawTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the Raw Generator revision.
> +*/
> +#define RAW_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the Raw Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR RawGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RAW),
> +  // Generator Description
> +  L"ACPI.STD.RAW.GENERATOR",
> +  // ACPI Table Signature - Unused
> +  0,
> +  // ACPI Table Revision - Unused
> +  0,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  RAW_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildRawTable,
> +  // Free Resource function
> +  FreeRawTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                  is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiRawLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&RawGenerator);
> +  DEBUG ((DEBUG_INFO, "RAW: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +
> +EFI_STATUS
> +EFIAPI
> +AcpiRawLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&RawGenerator);
> +  DEBUG ((DEBUG_INFO, "RAW: UnRegister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..ccfbcf088cfaec1e4f9f3738f5fe09a65c93bc9e
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
> @@ -0,0 +1,323 @@
> +/** @file
> +  SPCR Table Generator
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/DebugLib.h>
> +#include <Library/AcpiLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ArmNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** ARM standard SPCR Table Generator
> +
> +    Generates the ACPI SPCR Table for ARM UARTs as specified by
> +    the Microsoft Serial Port Console Redirection Table
> +    Specification - Version 1.03 - August 10, 2015.
> +
> +    Constructs the SPCR table for PL011 or SBSA UART peripherals.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjSerialConsolePortInfo
> +
> +NOTE: This implementation ignores the possibility that the Serial settings may
> +      be modified from the UEFI Shell.  A more complex handler would be needed
> +      to (e.g.) recover serial port settings from the UART, or non-volatile
> +      storage.
> +*/
> +
> +#pragma pack(1)
> +
> +/** This macro defines the no flow control option.
> +*/
> +#define SPCR_FLOW_CONTROL_NONE           0
> +
> +/**A template for generating the SPCR Table.
> +
> +  Note: fields marked "{Template}" will be updated dynamically.
> +*/
> +STATIC
> +EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = {
> +  ACPI_HEADER (
> +    EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> +    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,
> +    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
> +    ),
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_PL011_UART,
> +  {
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE
> +  },
> +  ARM_GAS32 (0), // {Template}: Serial Port Base Address
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC,
> +  0, // Not used on ARM
> +  0, // {Template}: Serial Port Interrupt
> +  0, // {Template}: Serial Port Baudrate
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
> +  SPCR_FLOW_CONTROL_NONE,
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI,
> +  EFI_ACPI_RESERVED_BYTE,
> +  0xFFFF,
> +  0xFFFF,
> +  0x00,
> +  0x00,
> +  0x00,
> +  0x00000000,
> +  0x00,
> +  EFI_ACPI_RESERVED_DWORD
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Serial
> +    Port Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjSerialConsolePortInfo,
> +  CM_ARM_SERIAL_PORT_INFO
> +  )
> +
> +/** Construct the SPCR ACPI table.
> +
> +    This function invokes the Confguration Manager protocol interface
> +    to get the required hardware information for generating the ACPI
> +    table.
> +
> +    If this function allocates any resources then they must be freed
> +    in the FreeXXXXTableResources function.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +    @retval EFI_SUCCESS           Table generated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object was not found.
> +    @retval EFI_UNSUPPORTED       An unsupported baudrate was specified by the
> +                                  Confguration Manager.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildSpcrTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  CM_ARM_SERIAL_PORT_INFO  * SerialPortInfo = NULL;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *Table = NULL;
> +
> +  Status = GetEArmObjSerialConsolePortInfo (
> +             CfgMgrProtocol,
> +             &SerialPortInfo,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));
> +  DEBUG ((DEBUG_INFO, "  UART Base  = 0x%lx\n", SerialPortInfo->BaseAddress));
> +  DEBUG ((DEBUG_INFO, "  Clock      = %d\n", SerialPortInfo->Clock));
> +  DEBUG ((DEBUG_INFO, "  Baudrate   = %ld\n", SerialPortInfo->BaudRate));
> +  DEBUG ((DEBUG_INFO, "  Interrupt  = %d\n", SerialPortInfo->Interrupt));
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr,
> +             sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
> +  AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;
> +
> +  switch (SerialPortInfo->BaudRate) {
> +    case 9600:
> +      AcpiSpcr.BaudRate =
> +        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;
> +      break;
> +    case 19200:
> +      AcpiSpcr.BaudRate =
> +        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;
> +      break;
> +    case 57600:
> +      AcpiSpcr.BaudRate =
> +        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;
> +      break;
> +    case 115200:
> +      AcpiSpcr.BaudRate =
> +        EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;
> +      break;
> +    default:
> +      Status = EFI_UNSUPPORTED;
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
> +        SerialPortInfo->BaudRate,
> +        Status
> +        ));
> +      goto error_handler;
> +  } // switch
> +
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
> +
> +error_handler:
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the SPCR.
> +
> +    @param [in]  This           Pointer to the table generator.
> +    @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                                Protocol Interface.
> +    @param [in]  Table          Pointer to the ACPI Table.
> +
> +    @retval EFI_SUCCESS         The resources were freed successfully.
> +*/
> +STATIC
> +EFI_STATUS
> +FreeSpcrTableResources (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo,
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN        EFI_ACPI_DESCRIPTION_HEADER        ** CONST Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the SPCR Table Generator revision.
> +*/
> +#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the SPCR Table Generator.
> +*/
> +STATIC
> +CONST
> +ACPI_TABLE_GENERATOR SpcrGenerator = {
> +  // Generator ID
> +  CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_SPCR),
> +  // Generator Description
> +  L"ACPI.STD.SPCR.GENERATOR",
> +  // ACPI Table Signature
> +  EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> +  // ACPI Table Revision
> +  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
> +  // Creator ID
> +  TABLE_GENERATOR_CREATOR_ID_ARM,
> +  // Creator Revision
> +  SPCR_GENERATOR_REVISION,
> +  // Build Table function
> +  BuildSpcrTable,
> +  // Free Resource function
> +  FreeSpcrTableResources
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                is already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiSpcrLibConstructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&SpcrGenerator);
> +  DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Un-register the Generator from the ACPI Table Factory.
> +
> +    @param [in]  ImageHandle  The handle to the image.
> +    @param [in]  SystemTable  Pointer to the System Table.
> +
> +    @retval EFI_SUCCESS           The Generator is un-registered.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiSpcrLibDestructor (
> +  IN CONST EFI_HANDLE                ImageHandle,
> +  IN       EFI_SYSTEM_TABLE  * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = UnRegisterAcpiTableGenerator (&SpcrGenerator);
> +  DEBUG ((DEBUG_INFO, "SPCR: Unregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..8dc1d6b6f7c6eb71bd0ab16b690a9f5b4855dc3d
> --- /dev/null
> +++ b/MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
> @@ -0,0 +1,165 @@
> +/** @file
> +  Table Helper
> +
> +Copyright (c) 2017, ARM Limited. All rights reserved.
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD License
> +which accompanies this distribution.  The full text of the license may be found at
> +https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
> +    object from the Configuration Manager.
> +
> +    @param [in]  CfgMgrProtocol Pointer to the Configuration Manager protocol
> +                                interface.
> +    @param [out] CfgMfrInfo     Pointer to the Configuration Manager Info
> +                                object structure.
> +
> +    @retval EFI_SUCCESS           The object is returned.
> +    @retval EFI_INVALID_PARAMETER The Object ID is invalid.
> +    @retval EFI_NOT_FOUND         The requested Object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetCgfMgrInfo (
> +  IN  CONST EFI_CONFIGURATION_MANAGER_PROTOCOL      * CONST  CfgMgrProtocol,
> +  OUT       CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  **        CfgMfrInfo
> +  )
> +{
> +  EFI_STATUS         Status;
> +  CM_OBJ_DESCRIPTOR  CmObjectDesc;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (CfgMfrInfo != NULL);
> +
> +  *CfgMfrInfo = NULL;
> +  Status = CfgMgrProtocol->GetObject (
> +    CfgMgrProtocol,
> +    CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
> +    &CmObjectDesc
> +    );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Get Configuration Manager Info. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  ASSERT (CmObjectDesc.Size >= sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO));
> +  if (CmObjectDesc.Size < sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: EStdObjCfgMgrInfo: Buffer too small, size  = 0x%x\n",
> +      CmObjectDesc.Size
> +      ));
> +    return EFI_BAD_BUFFER_SIZE;
> +  }
> +
> +  *CfgMfrInfo = (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO*)CmObjectDesc.Data;
> +  return Status;
> +}
> +
> +/** The AddAcpiHeader function updates the ACPI header structure pointed by
> +    the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
> +    Manager protocol to obtain any information required for constructing the
> +    header.
> +
> +    @param [in]     CfgMgrProtocol Pointer to the Configuration Manager
> +                                   protocol interface.
> +    @param [in]     Generator      Pointer to the ACPI table Generator.
> +    @param [in,out] AcpiHeader     Pointer to the ACPI table header to be
> +                                   updated.
> +    @param [in]     Length         Length of the ACPI table.
> +
> +    @retval EFI_SUCCESS           The ACPI table is updated successfully.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The required object information is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AddAcpiHeader (
> +  IN      CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN      CONST ACPI_TABLE_GENERATOR                * CONST Generator,
> +  IN OUT  EFI_ACPI_DESCRIPTION_HEADER               * CONST AcpiHeader,
> +  IN      CONST UINT32                                      Length
> +  )
> +{
> +  EFI_STATUS                               Status;
> +  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
> +
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Generator != NULL);
> +  ASSERT (AcpiHeader != NULL);
> +  ASSERT (Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
> +
> +  if ((CfgMgrProtocol == NULL) ||
> +      (Generator == NULL) ||
> +      (AcpiHeader == NULL) ||
> +      (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))
> +    ) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
> +      Status
> +      ));
> +    goto error_handler;
> +  }
> +
> +  /* UINT32  Signature */
> +  AcpiHeader->Signature = Generator->AcpiTableSignature;
> +  /* UINT32  Length */
> +  AcpiHeader->Length = Length;
> +  /* UINT8   Revision */
> +  AcpiHeader->Revision = Generator->AcpiTableRevision;
> +  /* UINT8   Checksum */
> +  AcpiHeader->Checksum = 0;
> +
> +  /* UINT8   OemId[6] */
> +  CopyMem (AcpiHeader->OemId, CfgMfrInfo->OemId, sizeof (AcpiHeader->OemId));
> +
> +  /* UINT64  OemTableId */
> +  AcpiHeader->OemTableId = Generator->CreatorId; // Generator->GeneratorID;
> +  AcpiHeader->OemTableId <<= 32;
> +  AcpiHeader->OemTableId |= Generator->AcpiTableSignature;
> +
> +  /* UINT32  OemRevision */
> +  AcpiHeader->OemRevision = CfgMfrInfo->Revision;
> +
> +  /* UINT32  CreatorId */
> +  AcpiHeader->CreatorId = Generator->CreatorId;
> +  /* UINT32  CreatorRevision */
> +  AcpiHeader->CreatorRevision = Generator->CreatorRevision;
> +
> +  Status = EFI_SUCCESS;
> +error_handler:
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..79cf0f290ddb79499c71d6c553b420418dec50f1
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFactory/AcpiTableFactory.c
> @@ -0,0 +1,227 @@
> +/** @file
> +  ACPI Table Factory
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347155694&sdata=Vbi5fMjtzoPlo8V336zBbedbol0iV538QsEJCuyssSU%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The ACPI table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested ACPI table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetAcpiTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST ACPI_TABLE_GENERATOR_ID                     GeneratorId,
> +  OUT CONST ACPI_TABLE_GENERATOR               ** CONST Generator
> +  )
> +{
> +  UINT16                           TableId;
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
> +
> +  ASSERT (This != NULL);
> +
> +  FactoryInfo = This->TableFactoryInfo;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (GeneratorId)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not ACPI\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Generator = NULL;
> +  TableId = GET_TABLE_ID (GeneratorId);
> +  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->StdAcpiTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->StdAcpiTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->CustomAcpiTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->CustomAcpiTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Register ACPI table factory generator.
> +
> +    The ACPI table factory maintains a list of the Standard and OEM ACPI
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterAcpiTableGenerator (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: ACPI register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI register - Generator" \
> +      " Type is not ACPI\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Unregister ACPI generator.
> +
> +    This function is called by the ACPI table generator to unregister itself
> +    from the ACPI table factory.
> +
> +    @param [in]  Generator       Pointer to the ACPI table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterAcpiTableGenerator (
> +  IN  CONST ACPI_TABLE_GENERATOR                * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: ACPI un-register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI un-register - Generator" \
> +      " Type is not ACPI\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_ACPI_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_ACPI_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdAcpiTableGeneratorList[TableId] != NULL) {
> +      if (Generator != TableFactoryInfo.StdAcpiTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.StdAcpiTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomACPIGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomACPIGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] != NULL) {
> +      if (Generator !=
> +          TableFactoryInfo.CustomAcpiTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.CustomAcpiTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
> +  return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..64a0390cdd006d8e3222ff19b269d1b4326736c3
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
> @@ -0,0 +1,84 @@
> +/** @file
> +  Dynamic Table Factory Dxe
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347165698&sdata=QltD7gCgjwkiQSrrD6ZFKjuKJJjoNXfncV%2Fbs4sJkPc%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +/** The Dynamic Table Factory protocol structure that holds the
> +    list of registered ACPI and SMBIOS table generators.
> +*/
> +EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +
> +/** A structure describing the Dynamic Table Factory protocol.
> +*/
> +STATIC
> +CONST
> +EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL DynamicTableFactoryProtocol = {
> +  CREATE_REVISION (1, 0),
> +  GetAcpiTableGenerator,
> +  GetSmbiosTableGenerator,
> +  &TableFactoryInfo
> +};
> +
> +/** Entrypoint for Dynamic Table Factory Dxe.
> +
> +    @param  ImageHandle
> +    @param  SystemTable
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +    @retval EFI_NOT_FOUND         Required interface/object was not found.
> +    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
> +
> +*/
> +EFI_STATUS
> +EFIAPI
> +DynamicTableFactoryDxeInitialize (
> +  IN  EFI_HANDLE                 ImageHandle,
> +  IN  EFI_SYSTEM_TABLE   * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = gBS->InstallProtocolInterface (
> +                  &ImageHandle,
> +                  &gEfiDynamicTableFactoryProtocolGuid,
> +                  EFI_NATIVE_INTERFACE,
> +                  (VOID*)&DynamicTableFactoryProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to install the Dynamic Table Factory Protocol." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +  }
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..64b578f30a3413ac2b22ccef4f09368c1af38b67
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
> @@ -0,0 +1,227 @@
> +/** @file
> +  SMBIOS Table Factory
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347165698&sdata=QltD7gCgjwkiQSrrD6ZFKjuKJJjoNXfncV%2Fbs4sJkPc%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  @par Glossary:
> +    - Std - Standard
> +**/
> +
> +#include <Protocol/Smbios.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include "DynamicTableFactory.h"
> +
> +extern EFI_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo;
> +
> +/** Return a pointer to the SMBIOS table generator.
> +
> +    @param [in]  This         Poiner to the Dynamic Table Factory Protocol.
> +    @param [in]  GeneratorId  The SMBIOS table generator ID for the
> +                              requested generator.
> +    @param [out] Generator    Pointer to the requested SMBIOS table
> +                              generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +GetSmbiosTableGenerator (
> +  IN  CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST This,
> +  IN  CONST SMBIOS_TABLE_GENERATOR_ID                   GeneratorId,
> +  OUT CONST SMBIOS_TABLE_GENERATOR             ** CONST Generator
> +  )
> +{
> +  UINT16                           TableId;
> +  EFI_DYNAMIC_TABLE_FACTORY_INFO * FactoryInfo;
> +
> +  ASSERT (This != NULL);
> +
> +  FactoryInfo = This->TableFactoryInfo;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Invalid Generator pointer\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (GeneratorId)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not SMBIOS\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Generator = NULL;
> +  TableId = GET_TABLE_ID (GeneratorId);
> +  if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->StdSmbiosTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->StdSmbiosTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (FactoryInfo->CustomSmbiosTableGeneratorList[TableId] != NULL) {
> +      *Generator = FactoryInfo->CustomSmbiosTableGeneratorList[TableId];
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Register SMBIOS table factory generator.
> +
> +    The SMBIOS table factory maintains a list of the Standard and OEM SMBIOS
> +    table generators.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           The Generator was registered
> +                                  successfully.
> +    @retval EFI_INVALID_PARAMETER The Generator ID is invalid or
> +                                  the Generator pointer is NULL.
> +    @retval EFI_ALREADY_STARTED   The Generator for the Table ID is
> +                                  already registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +RegisterSmbiosTableGenerator (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SMBIOS register - Generator" \
> +      " Type is not SMBIOS\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Registering %s\n", Generator->Description));
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] == NULL) {
> +      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = Generator;
> +    } else {
> +      return EFI_ALREADY_STARTED;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Unregister SMBIOS generator.
> +
> +    This function is called by the SMBIOS table generator to unregister itself
> +    from the SMBIOS table factory.
> +
> +    @param [in]  Generator       Pointer to the SMBIOS table generator.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER The generator is invalid.
> +    @retval EFI_NOT_FOUND         The requested generator is not found
> +                                  in the list of registered generators.
> +*/
> +EFI_STATUS
> +EFIAPI
> +UnRegisterSmbiosTableGenerator (
> +  IN  CONST SMBIOS_TABLE_GENERATOR              * CONST Generator
> +  )
> +{
> +  UINT16  TableId;
> +
> +  if (Generator == NULL) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS un-register - Invalid Generator\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SMBIOS un-register - Generator" \
> +      " Type is not SMBIOS\n"
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TableId = GET_TABLE_ID (Generator->GeneratorID);
> +  if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> +    if (TableId >= (ESTD_SMBIOS_TABLE_ID_MAX)) {
> +      ASSERT (TableId < (ESTD_SMBIOS_TABLE_ID_MAX));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] != NULL) {
> +      if (Generator != TableFactoryInfo.StdSmbiosTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.StdSmbiosTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    if (TableId >= FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators)) {
> +      ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomSMBIOSGenerators));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +    if (TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] != NULL) {
> +      if (Generator !=
> +          TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId]) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      TableFactoryInfo.CustomSmbiosTableGeneratorList[TableId] = NULL;
> +    } else {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Unregistering %s\n", Generator->Description));
> +  return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..f84bf3bef910ddf86629062d6d1ca1dffafa5a28
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.c
> @@ -0,0 +1,531 @@
> +/** @file
> +  Dynamic Table Manager Dxe
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347165698&sdata=QltD7gCgjwkiQSrrD6ZFKjuKJJjoNXfncV%2Fbs4sJkPc%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/Smbios.h>
> +
> +#include <DynamicTables/TableGenerator.h>
> +#include <DynamicTables/AcpiTableGenerator.h>
> +#include <DynamicTables/SmbiosTableGenerator.h>
> +#include <DynamicTables/StandardNameSpaceObjects.h>
> +#include <DynamicTables/ConfigurationManagerObject.h>
> +#include <DynamicTables/ConfigurationManagerHelper.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include <Library/TableHelperLib.h>
> +
> +/** This macro expands to a function that retrieves the ACPI Table
> +    List from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceStandard,
> +  EStdObjAcpiTableList,
> +  CM_STD_OBJ_ACPI_TABLE_INFO
> +  )
> +
> +/** A helper function to invoke a Table generator
> +
> +    This is a helper function that invokes the Table generator interface
> +    for building an ACPI table. It uses the AcpiTableProtocol to install the
> +    table, then frees the resources allocated for generating it.
> +
> +    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> +                                      interface.
> +    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> +                                      Protocol Interface.
> +    @param [in]  AcpiTableProtocol    Pointer to the AcpiTable protocol.
> +    @param [in]  AcpiTableInfo        Pointer to the ACPI table Info.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +    @retval EFI_NOT_FOUND         Required object is not found.
> +    @retval EFI_BAD_BUFFER_SIZE   Size returned by the Configuration Manager
> +                                  is less than the Object size for the requested
> +                                  object.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildAndInstallAcpiTable (
> +  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST TableFactoryProtocol,
> +  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN       EFI_ACPI_TABLE_PROTOCOL             *       AcpiTableProtocol,
> +  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO          * CONST AcpiTableInfo
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  CONST ACPI_TABLE_GENERATOR  * Generator = NULL;
> +  EFI_ACPI_DESCRIPTION_HEADER * AcpiTable;
> +  UINTN                         TableHandle;
> +
> +  ASSERT (TableFactoryProtocol != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableProtocol != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: EStdObjAcpiTableList: Address = 0x%p," \
> +    " TableGeneratorId = 0x%x\n",
> +    AcpiTableInfo,
> +    AcpiTableInfo->TableGeneratorId
> +    ));
> +
> +  Status = TableFactoryProtocol->GetAcpiTableGenerator (
> +                                   TableFactoryProtocol,
> +                                   AcpiTableInfo->TableGeneratorId,
> +                                   &Generator
> +                                   );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Table Generator not found." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  ASSERT (Generator != NULL);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: Generator found : %s\n",
> +    Generator->Description
> +    ));
> +
> +  if (Generator->BuildAcpiTable == NULL) {
> +    Status = EFI_INVALID_PARAMETER;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Table Generator does not implement the" \
> +      " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  AcpiTable = NULL;
> +  Status = Generator->BuildAcpiTable (
> +                        Generator,
> +                        AcpiTableInfo,
> +                        CfgMgrProtocol,
> +                        &AcpiTable
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Build Table." \
> +      " TableGeneratorId = 0x%x. Status = %r\n",
> +      AcpiTableInfo->TableGeneratorId,
> +      Status
> +      ));
> +    // Free any allocated resources.
> +    goto error_handler;
> +  }
> +
> +  ASSERT (AcpiTable != NULL);
> +
> +  // Dump ACPI Table Header
> +  DUMP_ACPI_TABLE_HEADER (AcpiTable);
> +
> +  // Install ACPI table
> +  Status = AcpiTableProtocol->InstallAcpiTable (
> +                                AcpiTableProtocol,
> +                                AcpiTable,
> +                                AcpiTable->Length,
> +                                &TableHandle
> +                                );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to Install ACPI Table. Status = %r\n",
> +      Status
> +      ));
> +    // Free any allocated resources.
> +    goto error_handler;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: ACPI Table installed. Status = %r\n",
> +    Status
> +    ));
> +
> +error_handler:
> +  // Free any resources allocated for generating the tables.
> +  if ((AcpiTable != NULL) && (Generator->FreeTableResources != NULL)) {
> +    Status = Generator->FreeTableResources (
> +                          Generator,
> +                          AcpiTableInfo,
> +                          CfgMgrProtocol,
> +                          &AcpiTable
> +                          );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: Failed to Free Table Resources." \
> +        "TableGeneratorId = 0x%x. Status = %r\n",
> +        AcpiTableInfo->TableGeneratorId,
> +        Status
> +        ));
> +    }
> +  }
> +  return Status;
> +}
> +
> +/** The function checks if the Configuration Manager has provided the
> +    mandatory ACPI tables for installation.
> +
> +    @param [in]  AcpiTableInfo      Pointer to the ACPI Table Info list.
> +    @param [in]  AcpiTableCount     Count of ACPI Table Info.
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_NOT_FOUND         If mandatory table is not found.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +VerifyMandatoryTablesArePresent (
> +  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO  * CONST AcpiTableInfo,
> +  IN CONST UINTN                               AcpiTableCount
> +  )
> +{
> +  EFI_STATUS  Status = EFI_SUCCESS;
> +  BOOLEAN     FadtFound = FALSE;
> +  BOOLEAN     MadtFound = FALSE;
> +  BOOLEAN     GtdtFound = FALSE;
> +  BOOLEAN     DsdtFound = FALSE;
> +  BOOLEAN     Dbg2Found = FALSE;
> +  BOOLEAN     SpcrFound = FALSE;
> +  UINTN       idx;
> +
> +  ASSERT (AcpiTableInfo != NULL);
> +
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    switch (AcpiTableInfo[idx].AcpiTableSignature) {
> +      case EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
> +        FadtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
> +        MadtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:
> +        GtdtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
> +        DsdtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE:
> +        Dbg2Found = TRUE;
> +        break;
> +      case EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
> +        SpcrFound = TRUE;
> +        break;
> +      default:
> +        break;
> +    }
> +  }
> +
> +  // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
> +  if (!FadtFound) {
> +    DEBUG ((DEBUG_ERROR,"ERROR: FADT Table not found\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!MadtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!GtdtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!DsdtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +  if (!Dbg2Found) {
> +    DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));
> +  }
> +  if (!SpcrFound) {
> +    DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));
> +  }
> +  return Status;
> +}
> +
> +/** Generate and install ACPI tables.
> +
> +    The function gathers the information necessary for installing the
> +    ACPI tables from the Configuration Manager, invokes the generators
> +    and installs them (via BuildAndInstallAcpiTable).
> +
> +    @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> +                                      interface.
> +    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> +                                      Protocol Interface.
> +
> +
> +    @retval EFI_SUCCESS   Success.
> +    @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
> +*/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +ProcessAcpiTables (
> +  IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL  * CONST TableFactoryProtocol,
> +  IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_ACPI_TABLE_PROTOCOL     * AcpiTableProtocol;
> +  UINTN                         AcpiTableCount;
> +  CM_STD_OBJ_ACPI_TABLE_INFO  * AcpiTableInfo;
> +  UINTN                         idx;
> +
> +  ASSERT (TableFactoryProtocol != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +
> +  // Find the AcpiTable protocol
> +  Status = gBS->LocateProtocol (
> +                  &gEfiAcpiTableProtocolGuid,
> +                  NULL,
> +                  (VOID**)&AcpiTableProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Status = GetEStdObjAcpiTableList (
> +             CfgMgrProtocol,
> +             &AcpiTableInfo,
> +             &AcpiTableCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get ACPI Table List. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  if (0 == AcpiTableCount) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
> +      AcpiTableCount
> +      ));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
> +    AcpiTableCount
> +    ));
> +
> +  // Check if mandatory ACPI tables are present.
> +  Status = VerifyMandatoryTablesArePresent (
> +             AcpiTableInfo,
> +             AcpiTableCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find mandatory ACPI Table(s)."
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  // Add the FADT Table first.
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
> +        AcpiTableInfo[idx].TableGeneratorId) {
> +      Status = BuildAndInstallAcpiTable (
> +                 TableFactoryProtocol,
> +                 CfgMgrProtocol,
> +                 AcpiTableProtocol,
> +                 &AcpiTableInfo[idx]
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "ERROR: Failed to find build and install ACPI FADT Table." \
> +          " Status = %r\n",
> +          Status
> +          ));
> +        return Status;
> +      }
> +      break;
> +    }
> +  } // for
> +
> +  // Add remaining ACPI Tables
> +  for (idx = 0; idx < AcpiTableCount; idx++) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
> +      idx,
> +      AcpiTableInfo[idx].TableGeneratorId
> +      ));
> +
> +    // Skip FADT Table since we have already added
> +    if (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_FADT) ==
> +        AcpiTableInfo[idx].TableGeneratorId) {
> +      continue;
> +    }
> +
> +    // Skip the Reserved table Generator ID
> +    if ((CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_RESERVED) >=
> +           AcpiTableInfo[idx].TableGeneratorId)                     ||
> +        (CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_MAX)      <=
> +           AcpiTableInfo[idx].TableGeneratorId)) {
> +      DEBUG ((
> +        DEBUG_WARN,
> +        "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
> +        AcpiTableInfo[idx].TableGeneratorId
> +        ));
> +      continue;
> +    }
> +
> +    Status = BuildAndInstallAcpiTable (
> +               TableFactoryProtocol,
> +               CfgMgrProtocol,
> +               AcpiTableProtocol,
> +               &AcpiTableInfo[idx]
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: Failed to find, build, and install ACPI Table." \
> +        " Status = %r\n",
> +        Status
> +        ));
> +      return Status;
> +    }
> +  } // for
> +
> +  return Status;
> +}
> +
> +/** Entrypoint of Dynamic Table Manager Dxe.
> +
> +  The Dynamic Table Manager uses the Configuration Manager Protocol
> +  to get the list of ACPI and SMBIOS tables to install. For each table
> +  in the list it requests the corresponding ACPI/SMBIOS table factory for
> +  a generator capable of building the ACPI/SMBIOS table.
> +  If a suitable table generator is found, it invokes the generator interface
> +  to build the table. The Dynamic Table Manager then installs the
> +  table and invokes another generator interface to free any resources
> +  allocated for building the table.
> +
> +    @param  ImageHandle
> +    @param  SystemTable
> +
> +    @retval EFI_SUCCESS           Success.
> +    @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +    @retval EFI_NOT_FOUND         Required interface/object was not found.
> +    @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
> +
> +*/
> +EFI_STATUS
> +EFIAPI
> +DynamicTableManagerDxeInitialize (
> +  IN CONST EFI_HANDLE                 ImageHandle,
> +  IN       EFI_SYSTEM_TABLE   * CONST SystemTable
> +  )
> +{
> +  EFI_STATUS                               Status;
> +  EFI_CONFIGURATION_MANAGER_PROTOCOL     * CfgMgrProtocol;
> +  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO  * CfgMfrInfo;
> +  EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL     * TableFactoryProtocol;
> +
> +  // Locate the Dynamic Table Factory
> +  Status = gBS->LocateProtocol (
> +                  &gEfiDynamicTableFactoryProtocolGuid,
> +                  NULL,
> +                  (VOID**)&TableFactoryProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find Dynamic Table Factory protocol." \
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  // Locate the Configuration Manager for the Platform
> +  Status = gBS->LocateProtocol (
> +                  &gEfiConfigurationManagerProtocolGuid,
> +                  NULL,
> +                  (VOID**)&CfgMgrProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",
> +    CfgMfrInfo->Revision,
> +    CfgMfrInfo->OemId[0],
> +    CfgMfrInfo->OemId[1],
> +    CfgMfrInfo->OemId[2],
> +    CfgMfrInfo->OemId[3],
> +    CfgMfrInfo->OemId[4],
> +    CfgMfrInfo->OemId[5]
> +    ));
> +
> +  Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI Table processing failure. Status = %r\n",
> +      Status
> +      ));
> +  }
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> new file mode 100644
> index 0000000000000000000000000000000000000000..69012cf8242c8ddd13ac4033293ac8a7053dfbd8
> --- /dev/null
> +++ b/MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> @@ -0,0 +1,35 @@
> +## @file
> +#  fdf include file for Dynamic Tables Framework.
> +#
> +#  Copyright (c) 2017, ARM Limited. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopensource.org%2Flicenses%2Fbsd-license.php&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347165698&sdata=QltD7gCgjwkiQSrrD6ZFKjuKJJjoNXfncV%2Fbs4sJkPc%3D&reserved=0
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +################################################################################
> +#
> +# FV Section
> +#
> +# [FV] section is used to define what components or modules are placed within a flash
> +# device file.  This section also defines order the components and modules are positioned
> +# within the image.  The [FV] section consists of define statements, set statements and
> +# module statements.
> +#
> +################################################################################
> +
> +  #
> +  # Dynamic Table Factory Dxe
> +  #
> +  INF MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
> +
> +  #
> +  # Dynamic Tables Dxe
> +  #
> +  INF MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> -- 
> Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fmailman%2Flistinfo%2Fedk2-devel&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347165698&sdata=DOHnkhWF%2FPMDziy4%2FYIMOB439O0IvZaHuB1QL0CmdI8%3D&reserved=0
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fmailman%2Flistinfo%2Fedk2-devel&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347165698&sdata=DOHnkhWF%2FPMDziy4%2FYIMOB439O0IvZaHuB1QL0CmdI8%3D&reserved=0
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01.org%2Fmailman%2Flistinfo%2Fedk2-devel&data=02%7C01%7Csean.brogan%40microsoft.com%7C2ac4d526c9b240a1fa4308d50a7851cc%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636426434347165698&sdata=DOHnkhWF%2FPMDziy4%2FYIMOB439O0IvZaHuB1QL0CmdI8%3D&reserved=0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Dynamic Tables
  2017-10-02 19:47 [PATCH 0/2] Dynamic Tables evan.lloyd
                   ` (2 preceding siblings ...)
  2017-10-03 17:12 ` [PATCH 0/2] Dynamic Tables Evan Lloyd
@ 2017-10-10  2:29 ` Yao, Jiewen
  2017-10-10 18:52   ` Evan Lloyd
  3 siblings, 1 reply; 14+ messages in thread
From: Yao, Jiewen @ 2017-10-10  2:29 UTC (permalink / raw)
  To: evan.lloyd@arm.com, edk2-devel@lists.01.org
  Cc: "Matteo.Carlini@arm.com"@arm.com,
	"nd@arm.com"@arm.com,
	"ard.biesheuvel@linaro.org"@arm.com,
	"Stephanie.Hughes-Fitt@arm.com"@arm.com,
	"thomas.abraham@arm.com"@arm.com,
	"Arvind.Chauhan@arm.com"@arm.com,
	"leif.lindholm@linaro.org"@arm.com,
	"Daniil.Egranov@arm.com"@arm.com, Yao, Jiewen

HI Evan
Thanks for the contribution.

This is a very big feature. It may talk us more time to review and evaluate.
At same time, one of our key MdeModule package maintainer is in paternity leave. It may be longer than usual.

I notice you only defined ARM namespace in this patch, and implemented ARM library instance.
Also most consumers of ConfigurationManager are from ARM platform package. So if it urgent from ARM platform, you may consider to check into ArmPkg at first.



I only have a quick look at the patch. Would you please share more on the design philosophy?

1) It seems the final goal is still to generate ACPI table/SMBIOS table/DevTree. You just introduce a way to manage how these tables are generated, right?

2) Below definition is defined by the MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h.
Is there any industry standard to define below index? Or it is just defined by EDKII, and anyone can add extension here?

+Object ID's in the ARM Namespace:
+   0 - Reserved
+   1 - Boot Architecture Info
+   2 - CPU Info
+   3 - Power Management Profile Info
+   4 - GICC Info
+   5 - GICD Info
+   6 - GIC MSI Frame Info
+   7 - GIC Redistributor Info
+   8 - GIC ITS Info
+   9 - Serial Console Port Info
+  10 - Serial Debug Port Info
+  12 - Generic Timer Info
+  13 - Platform GT Block Info
+  14 - Platform Generic Watchdog
+  15 - PCI Configuration Space Info
+  16 - Hypervisor Vendor Id

3) I am not sure if you have known about datahub protocol. (IntelFrameworkPkg\Include\Protocol\DataHub.h)
Long time ago, we have platform module filling the SMBIOS needed information to datahub (such as CPU INFO, Memory Info).
The SMBIOS table is derived from datahub protocol. The setup driver can also from datahub.
But later, we think it is an overdesign and datahub is no longer used in the new IA platform.
People feel it is easier to fill industry defined SMBIOS record directly, than to fill the EDK defined datahub record.
They do not need to learn 2 different styles of data record format.

To me, this seems similar to datahub. Please help us understand the key difference.

4) In addition, EDKII/PI defined PCD (platform configuration database). It is an architecture way to manage the configuration data.
We are also implementing structure PCD to let platform fill data easily. (https://github.com/tianocore/edk2-staging/tree/StructurePcd)

I found some configuration can be as simple as a PCD, such as
+  // Boot architecture information
+  { EFI_ACPI_6_1_ARM_PSCI_COMPLIANT },              // BootArchFlags
+
+  // Power management profile information
+  { EFI_ACPI_6_1_PM_PROFILE_ENTERPRISE_SERVER },    // PowerManagement Profile

With the new structure PCD design, below definition can also be a structure PCD.
+  // SPCR Serial Port
+  {
+    FixedPcdGet64 (PcdSerialRegisterBase),  // UINT64  BaseAddress
+    FixedPcdGet32 (PL011UartInterrupt),     // UINT32  Interrupt
+    FixedPcdGet64 (PcdUartDefaultBaudRate), // UINT64  BaudRate
+    FixedPcdGet32 (PL011UartClkInHz)        // UINT32  Clock
+  },

+  // Debug Serial Port
+  {
+    FixedPcdGet64 (PcdSerialDbgRegisterBase), // UINT64  BaseAddress
+    38,                                       // UINT32  Interrupt
+    FixedPcdGet64 (PcdSerialDbgUartBaudRate), // UINT64  BaudRate
+    FixedPcdGet32 (PcdSerialDbgUartClkInHz)   // UINT32  Clock
+  },

What if we just use PCD to define these CPU info, GICC info? Do we really another ConfigurationManager?


All in all, if we can compare the difference of below design with pros/cons, that will be great.
That will help us understand more about the new design.
A) DataHub (IntelFrameworkPkg, do not recommend to use.)
B) PCD (MdePkg, in PI specification) and structure PCD (EDKII staging)
C) ConfigurationManager (this patch)


Thank you
Yao Jiewen

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> evan.lloyd@arm.com
> Sent: Tuesday, October 3, 2017 3:48 AM
> To: edk2-devel@lists.01.org
> Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com;
> "ard.biesheuvel@linaro.org"@arm.com;
> "Stephanie.Hughes-Fitt@arm.com"@arm.com;
> "thomas.abraham@arm.com"@arm.com;
> "Arvind.Chauhan@arm.com"@arm.com; "leif.lindholm@linaro.org"@arm.com;
> "Daniil.Egranov@arm.com"@arm.com
> Subject: [edk2] [PATCH 0/2] Dynamic Tables
> 
> From: EvanLloyd <evan.lloyd@arm.com>
> 
> Historically, ACPI code, SMBIOS tables, and UEFI firmware were
> often developed in isolation from each other.  This introduced
> several problems, not least of which was duplication of platform
> information between the various source trees.
> In addition, variants of platforms introduced a plethora of
> alternative builds of ACPI, SMBIOS and EDK2, with the concomitant
> risk of getting the mixture wrong in a build.
> 
> In the effort to resolve these problems, the solution prototyped
> here was devised.  The basic idea is to obtain the "variant"
> information from a management node.  That means the firmware image
> can be platform independent, with ACPI, SMBIOS (and potentially
> other) tables generated with information from the management
> node.  This example has the framework for that, but the
> configuration information is supplied directly, as an interim solution
> until a suitable management node implementation exists yet.
> 
> 
> Sami Mujawar (1):
>   MdeModulePkg: Dynamic Tables Framework
> 
>  MdeModulePkg/MdeModulePkg.dec
> |  13 +
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
> |  45 ++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2Lib
> Arm.inf                       |  49 ++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibAr
> m.inf                       |  47 ++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibA
> rm.inf                       |  46 ++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLib
> Arm.inf                       |  47 ++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLib
> Arm.inf                       |  47 ++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibAr
> m.inf                         |  44 ++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibAr
> m.inf                       |  44 ++
> 
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLi
> b.inf                         |  39 ++
> 
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTa
> bleFactoryDxe.inf              |  57 ++
> 
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicT
> ableManagerDxe.inf              |  47 ++
>  MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
> | 280 ++++++++
>  MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
> | 367 ++++++++++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
> | 112 +++
>  MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
> | 158 +++++
>  MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
> | 235 +++++++
>  MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
> |  93 +++
>  MdeModulePkg/Include/DynamicTables/TableGenerator.h
> | 235 +++++++
>  MdeModulePkg/Include/Library/TableHelperLib.h
> |  67 ++
>  MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
> | 121 ++++
>  MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
> | 113 +++
> 
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTa
> bleFactory.h                   |  91 +++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Genera
> tor.c                          | 440 ++++++++++++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerat
> or.c                          | 562 +++++++++++++++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerat
> or.c                          | 652 +++++++++++++++++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGener
> ator.c                          | 732 ++++++++++++++++++++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenera
> tor.c                          | 336 +++++++++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerat
> or.c                            | 177 +++++
> 
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerat
> or.c                          | 323 +++++++++
>  MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
> | 165 +++++
> 
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFa
> ctory/AcpiTableFactory.c     | 227 ++++++
> 
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTa
> bleFactoryDxe.c                |  84 +++
> 
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTabl
> eFactory/SmbiosTableFactory.c | 227 ++++++
> 
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicT
> ableManagerDxe.c                | 531 ++++++++++++++
>  MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> |  35 +
>  36 files changed, 6888 insertions(+)
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTables.dsc.inc
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2Lib
> Arm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibAr
> m.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibA
> rm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLib
> Arm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLib
> Arm.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/AcpiRawLibAr
> m.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibAr
> m.inf
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelperLi
> b.inf
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTa
> bleFactoryDxe.inf
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicT
> ableManagerDxe.inf
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/AcpiTableGenerator.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/ArmNameSpaceObjects.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/ConfigurationManagerHelper.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/SmbiosTableGenerator.h
>  create mode 100644
> MdeModulePkg/Include/DynamicTables/StandardNameSpaceObjects.h
>  create mode 100644 MdeModulePkg/Include/DynamicTables/TableGenerator.h
>  create mode 100644 MdeModulePkg/Include/Library/TableHelperLib.h
>  create mode 100644
> MdeModulePkg/Include/Protocol/ConfigurationManagerProtocol.h
>  create mode 100644
> MdeModulePkg/Include/Protocol/DynamicTableFactoryProtocol.h
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTa
> bleFactory.h
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiDbg2LibArm/Dbg2Genera
> tor.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiFadtLibArm/FadtGenerat
> or.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerat
> or.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMadtLibArm/MadtGener
> ator.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiMcfgLibArm/McfgGenera
> tor.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiRawLibArm/RawGenerat
> or.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerat
> or.c
>  create mode 100644
> MdeModulePkg/Library/DynamicTables/Common/TableHelperLib/TableHelper.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/AcpiTableFa
> ctory/AcpiTableFactory.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/DynamicTa
> bleFactoryDxe.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableFactoryDxe/SmbiosTabl
> eFactory/SmbiosTableFactory.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTableManagerDxe/DynamicT
> ableManagerDxe.c
>  create mode 100644
> MdeModulePkg/Universal/DynamicTables/DynamicTables.fdf.inc
> 
> --
> Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Dynamic Tables
  2017-10-10  2:29 ` Yao, Jiewen
@ 2017-10-10 18:52   ` Evan Lloyd
  2017-10-10 19:57     ` Laszlo Ersek
                       ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Evan Lloyd @ 2017-10-10 18:52 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: "Matteo.Carlini@arm.com"@arm.com,
	"nd@arm.com"@arm.com,
	"ard.biesheuvel@linaro.org"@arm.com,
	"Stephanie.Hughes-Fitt@arm.com"@arm.com,
	"thomas.abraham@arm.com"@arm.com,
	"Arvind.Chauhan@arm.com"@arm.com,
	"leif.lindholm@linaro.org"@arm.com,
	"Daniil.Egranov@arm.com"@arm.com

Hi Jiewen
(I hope that is your personal name, not your surname - but it is a bit hard for us barbarians to tell, sorry.)
Thank you for the very helpful feedback.
Responses are inline below.

> -----Original Message-----
> From: Yao, Jiewen [mailto:jiewen.yao@intel.com]
> Sent: 10 October 2017 03:29
> To: Evan Lloyd <Evan.Lloyd@arm.com>; edk2-devel@lists.01.org
> Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com;
> "ard.biesheuvel@linaro.org"@arm.com; "Stephanie.Hughes-
> Fitt@arm.com"@arm.com; "thomas.abraham@arm.com"@arm.com;
> "Arvind.Chauhan@arm.com"@arm.com;
> "leif.lindholm@linaro.org"@arm.com;
> "Daniil.Egranov@arm.com"@arm.com; Yao, Jiewen <jiewen.yao@intel.com>
> Subject: RE: [edk2] [PATCH 0/2] Dynamic Tables
>
> HI Evan
> Thanks for the contribution.
>
> This is a very big feature. It may talk us more time to review and evaluate.
> At same time, one of our key MdeModule package maintainer is in paternity
> leave. It may be longer than usual.
>
> I notice you only defined ARM namespace in this patch, and implemented
> ARM library instance.
> Also most consumers of ConfigurationManager are from ARM platform
> package. So if it urgent from ARM platform, you may consider to check into
> ArmPkg at first.

[[Evan Lloyd]] This sounds sensible, and I will discuss it with Leif.  Another option might be to start up a new module.

>
>
>
> I only have a quick look at the patch. Would you please share more on the
> design philosophy?

[[Evan Lloyd]] You are quite right - we will put a document together on this.

>
> 1) It seems the final goal is still to generate ACPI table/SMBIOS table/DevTree.
> You just introduce a way to manage how these tables are generated, right?

[[Evan Lloyd]] Yes.

>
> 2) Below definition is defined by the
> MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h.
> Is there any industry standard to define below index? Or it is just defined by
> EDKII, and anyone can add extension here?

[[Evan Lloyd]] This is an initial submission for discussion, but there is not currently a relevant standard.  We are providing a "proof of concept" for discussion and review.  The ids are currently internal to edk2.  We do anticipate some sort of standard definition (for the information supplier) but that might be no more than a version of ConfigurationManagerObject.h

>
> +Object ID's in the ARM Namespace:
> +   0 - Reserved
> +   1 - Boot Architecture Info
> +   2 - CPU Info
> +   3 - Power Management Profile Info
> +   4 - GICC Info
> +   5 - GICD Info
> +   6 - GIC MSI Frame Info
> +   7 - GIC Redistributor Info
> +   8 - GIC ITS Info
> +   9 - Serial Console Port Info
> +  10 - Serial Debug Port Info
> +  12 - Generic Timer Info
> +  13 - Platform GT Block Info
> +  14 - Platform Generic Watchdog
> +  15 - PCI Configuration Space Info
> +  16 - Hypervisor Vendor Id
>
> 3) I am not sure if you have known about datahub protocol.
> (IntelFrameworkPkg\Include\Protocol\DataHub.h)

[[Evan Lloyd]] We did not.  We have not previously paid much attention to IntelFrameworkPkg  😊
We will have a look at the DataHub stuff though, to see how it fits.

> Long time ago, we have platform module filling the SMBIOS needed
> information to datahub (such as CPU INFO, Memory Info).
> The SMBIOS table is derived from datahub protocol. The setup driver can
> also from datahub.
> But later, we think it is an overdesign and datahub is no longer used in the
> new IA platform.
> People feel it is easier to fill industry defined SMBIOS record directly, than to
> fill the EDK defined datahub record.
> They do not need to learn 2 different styles of data record format.
>
> To me, this seems similar to datahub. Please help us understand the key
> difference.

[[Evan Lloyd]]  From your description, there does seem to be an element of similarity with our submitted implementation.
However, our current code does not yet cover later options of obtaining the configuration data from a remote node, etc.
Our ultimate aim is to have a single UEFI image run on a range of platforms, taking guidance from the remote on what tables to publish with what content.  You say "People feel it is easier to fill industry defined SMBIOS record directly, than to fill the EDK defined datahub record."  I do not question your statement, in fact I am sure you are right.  However, might those people be the ones who make a living filling "industry defined SMBIOS record directly"?  Our experience is that there is significant overhead in building complete sets of platform dependent tables for each variant of a machine, and we would like to reduce that.

>
> 4) In addition, EDKII/PI defined PCD (platform configuration database). It is
> an architecture way to manage the configuration data.
> We are also implementing structure PCD to let platform fill data easily.
> (https://github.com/tianocore/edk2-staging/tree/StructurePcd)
>
> I found some configuration can be as simple as a PCD, such as
> +  // Boot architecture information
> +  { EFI_ACPI_6_1_ARM_PSCI_COMPLIANT },              // BootArchFlags
> +
> +  // Power management profile information
> +  { EFI_ACPI_6_1_PM_PROFILE_ENTERPRISE_SERVER },    //
> PowerManagement Profile
>
> With the new structure PCD design, below definition can also be a structure
> PCD.
> +  // SPCR Serial Port
> +  {
> +    FixedPcdGet64 (PcdSerialRegisterBase),  // UINT64  BaseAddress
> +    FixedPcdGet32 (PL011UartInterrupt),     // UINT32  Interrupt
> +    FixedPcdGet64 (PcdUartDefaultBaudRate), // UINT64  BaudRate
> +    FixedPcdGet32 (PL011UartClkInHz)        // UINT32  Clock
> +  },
>
> +  // Debug Serial Port
> +  {
> +    FixedPcdGet64 (PcdSerialDbgRegisterBase), // UINT64  BaseAddress
> +    38,                                       // UINT32  Interrupt
> +    FixedPcdGet64 (PcdSerialDbgUartBaudRate), // UINT64  BaudRate
> +    FixedPcdGet32 (PcdSerialDbgUartClkInHz)   // UINT32  Clock
> +  },
>
> What if we just use PCD to define these CPU info, GICC info? Do we really
> another ConfigurationManager?

[[Evan Lloyd]] PCDs are very useful.  However they (especially FixedPcds) are build time options.  Given the aim of a single UEFI image, they do not quite work.  We want the UEFI to be able to get the variant config from an external entity.  In theory, a complex enough PCD database could be used to provide the config information, and could be loaded from a remote, but it would be a very elaborate solution.

>
>
> All in all, if we can compare the difference of below design with pros/cons,
> that will be great.
> That will help us understand more about the new design.
> A) DataHub (IntelFrameworkPkg, do not recommend to use.)
> B) PCD (MdePkg, in PI specification) and structure PCD (EDKII staging)
> C) ConfigurationManager (this patch)

[[Evan Lloyd]] We will need to study DataHub to see what is there, but we will make a response when we have.

>
>
> Thank you
> Yao Jiewen
>
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> > evan.lloyd@arm.com
> > Sent: Tuesday, October 3, 2017 3:48 AM
> > To: edk2-devel@lists.01.org
> > Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com;
> > "ard.biesheuvel@linaro.org"@arm.com;
> > "Stephanie.Hughes-Fitt@arm.com"@arm.com;
> > "thomas.abraham@arm.com"@arm.com;
> > "Arvind.Chauhan@arm.com"@arm.com;
> "leif.lindholm@linaro.org"@arm.com;
> > "Daniil.Egranov@arm.com"@arm.com
> > Subject: [edk2] [PATCH 0/2] Dynamic Tables
> >
> > From: EvanLloyd <evan.lloyd@arm.com>
> >
> > Historically, ACPI code, SMBIOS tables, and UEFI firmware were often
> > developed in isolation from each other.  This introduced several
> > problems, not least of which was duplication of platform information
> > between the various source trees.
> > In addition, variants of platforms introduced a plethora of
> > alternative builds of ACPI, SMBIOS and EDK2, with the concomitant risk
> > of getting the mixture wrong in a build.
> >
> > In the effort to resolve these problems, the solution prototyped here
> > was devised.  The basic idea is to obtain the "variant"
> > information from a management node.  That means the firmware image
> can
> > be platform independent, with ACPI, SMBIOS (and potentially
> > other) tables generated with information from the management node.
> > This example has the framework for that, but the configuration
> > information is supplied directly, as an interim solution until a
> > suitable management node implementation exists yet.
> >
> >
...
> > --
> > Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Dynamic Tables
  2017-10-10 18:52   ` Evan Lloyd
@ 2017-10-10 19:57     ` Laszlo Ersek
  2017-10-11  1:25     ` Yao, Jiewen
  2017-10-12 15:43     ` Leif Lindholm
  2 siblings, 0 replies; 14+ messages in thread
From: Laszlo Ersek @ 2017-10-10 19:57 UTC (permalink / raw)
  To: Evan Lloyd, Yao, Jiewen, edk2-devel@lists.01.org
  Cc: "Matteo.Carlini@arm.com"@arm.com,
	"nd@arm.com"@arm.com,
	"ard.biesheuvel@linaro.org"@arm.com,
	"Stephanie.Hughes-Fitt@arm.com"@arm.com,
	"thomas.abraham@arm.com"@arm.com,
	"Arvind.Chauhan@arm.com"@arm.com,
	"leif.lindholm@linaro.org"@arm.com,
	"Daniil.Egranov@arm.com"@arm.com

On 10/10/17 20:52, Evan Lloyd wrote:
> Hi Jiewen
> (I hope that is your personal name, not your surname - but it is a bit hard for us barbarians to tell, sorry.)

Meta: I've been shamelessly exploiting the (apparent) custom that
@intel.com email addresses come in the following shapes:

<GivenName.Surname@intel.com>
<GivenName.InitialOfMiddleName.Surname@intel.com>

If my heuristic has been wrong all this time, at least now I'll learn
about it :)

(Yes, I've noticed the use of commas in some names; they don't help. The
order they dictate is not uniform between cultures. Email address
schemes are more reliable, within an organization anyway.)

Thanks,
Laszlo


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Dynamic Tables
  2017-10-10 18:52   ` Evan Lloyd
  2017-10-10 19:57     ` Laszlo Ersek
@ 2017-10-11  1:25     ` Yao, Jiewen
  2017-10-12 15:43     ` Leif Lindholm
  2 siblings, 0 replies; 14+ messages in thread
From: Yao, Jiewen @ 2017-10-11  1:25 UTC (permalink / raw)
  To: Evan Lloyd, edk2-devel@lists.01.org
  Cc: "Matteo.Carlini@arm.com"@arm.com,
	"nd@arm.com"@arm.com,
	"ard.biesheuvel@linaro.org"@arm.com,
	"Stephanie.Hughes-Fitt@arm.com"@arm.com,
	"thomas.abraham@arm.com"@arm.com,
	"Arvind.Chauhan@arm.com"@arm.com,
	"leif.lindholm@linaro.org"@arm.com,
	"Daniil.Egranov@arm.com"@arm.com

Thank you!

Comment in line.


From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Evan Lloyd
Sent: Wednesday, October 11, 2017 2:52 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
Cc: "Matteo.Carlini@arm.com"@arm.com; "nd@arm.com"@arm.com; "ard.biesheuvel@linaro.org"@arm.com; "Stephanie.Hughes-Fitt@arm.com"@arm.com; "thomas.abraham@arm.com"@arm.com; "Arvind.Chauhan@arm.com"@arm.com; "leif.lindholm@linaro.org"@arm.com; "Daniil.Egranov@arm.com"@arm.com
Subject: Re: [edk2] [PATCH 0/2] Dynamic Tables

Hi Jiewen
(I hope that is your personal name, not your surname - but it is a bit hard for us barbarians to tell, sorry.)

[Jiewen] Ah sorry about that. You are right. Jiewen is my given name. ☺

Thank you for the very helpful feedback.
Responses are inline below.

> -----Original Message-----
> From: Yao, Jiewen [mailto:jiewen.yao@intel.com]
> Sent: 10 October 2017 03:29
> To: Evan Lloyd <Evan.Lloyd@arm.com<mailto:Evan.Lloyd@arm.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: "Matteo.Carlini@arm.com"@arm.com<mailto:%22Matteo.Carlini@arm.com%22@arm.com>; "nd@arm.com"@arm.com<mailto:%22nd@arm.com%22@arm.com>;
> "ard.biesheuvel@linaro.org"@arm.com<mailto:%22ard.biesheuvel@linaro.org%22@arm.com>; "Stephanie.Hughes-
> Fitt@arm.com"@arm.com<mailto:Fitt@arm.com%22@arm.com>; "thomas.abraham@arm.com"@arm.com<mailto:%22thomas.abraham@arm.com%22@arm.com>;
> "Arvind.Chauhan@arm.com"@arm.com<mailto:%22Arvind.Chauhan@arm.com%22@arm.com>;
> "leif.lindholm@linaro.org"@arm.com<mailto:%22leif.lindholm@linaro.org%22@arm.com>;
> "Daniil.Egranov@arm.com"@arm.com<mailto:%22Daniil.Egranov@arm.com%22@arm.com>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> Subject: RE: [edk2] [PATCH 0/2] Dynamic Tables
>
> HI Evan
> Thanks for the contribution.
>
> This is a very big feature. It may talk us more time to review and evaluate.
> At same time, one of our key MdeModule package maintainer is in paternity
> leave. It may be longer than usual.
>
> I notice you only defined ARM namespace in this patch, and implemented
> ARM library instance.
> Also most consumers of ConfigurationManager are from ARM platform
> package. So if it urgent from ARM platform, you may consider to check into
> ArmPkg at first.

[[Evan Lloyd]] This sounds sensible, and I will discuss it with Leif.  Another option might be to start up a new module.

[Jiewen] Right. I also replied mail from Sean Brogan (MSFT), who has concern on putting this to MdeModulePkg. But the mail was so long that it was filtered before.
If ArmPkg can be the first landing zone, that is great.

>
>
>
> I only have a quick look at the patch. Would you please share more on the
> design philosophy?

[[Evan Lloyd]] You are quite right - we will put a document together on this.

>
> 1) It seems the final goal is still to generate ACPI table/SMBIOS table/DevTree.
> You just introduce a way to manage how these tables are generated, right?

[[Evan Lloyd]] Yes.

>
> 2) Below definition is defined by the
> MdeModulePkg/Include/DynamicTables/ConfigurationManagerObject.h.
> Is there any industry standard to define below index? Or it is just defined by
> EDKII, and anyone can add extension here?

[[Evan Lloyd]] This is an initial submission for discussion, but there is not currently a relevant standard.  We are providing a "proof of concept" for discussion and review.  The ids are currently internal to edk2.  We do anticipate some sort of standard definition (for the information supplier) but that might be no more than a version of ConfigurationManagerObject.h

>
> +Object ID's in the ARM Namespace:
> +   0 - Reserved
> +   1 - Boot Architecture Info
> +   2 - CPU Info
> +   3 - Power Management Profile Info
> +   4 - GICC Info
> +   5 - GICD Info
> +   6 - GIC MSI Frame Info
> +   7 - GIC Redistributor Info
> +   8 - GIC ITS Info
> +   9 - Serial Console Port Info
> +  10 - Serial Debug Port Info
> +  12 - Generic Timer Info
> +  13 - Platform GT Block Info
> +  14 - Platform Generic Watchdog
> +  15 - PCI Configuration Space Info
> +  16 - Hypervisor Vendor Id
>
> 3) I am not sure if you have known about datahub protocol.
> (IntelFrameworkPkg\Include\Protocol\DataHub.h)

[[Evan Lloyd]] We did not.  We have not previously paid much attention to IntelFrameworkPkg  😊
We will have a look at the DataHub stuff though, to see how it fits.

> Long time ago, we have platform module filling the SMBIOS needed
> information to datahub (such as CPU INFO, Memory Info).
> The SMBIOS table is derived from datahub protocol. The setup driver can
> also from datahub.
> But later, we think it is an overdesign and datahub is no longer used in the
> new IA platform.
> People feel it is easier to fill industry defined SMBIOS record directly, than to
> fill the EDK defined datahub record.
> They do not need to learn 2 different styles of data record format.
>
> To me, this seems similar to datahub. Please help us understand the key
> difference.

[[Evan Lloyd]]  From your description, there does seem to be an element of similarity with our submitted implementation.
However, our current code does not yet cover later options of obtaining the configuration data from a remote node, etc.
Our ultimate aim is to have a single UEFI image run on a range of platforms, taking guidance from the remote on what tables to publish with what content.  You say "People feel it is easier to fill industry defined SMBIOS record directly, than to fill the EDK defined datahub record."  I do not question your statement, in fact I am sure you are right.  However, might those people be the ones who make a living filling "industry defined SMBIOS record directly"?  Our experience is that there is significant overhead in building complete sets of platform dependent tables for each variant of a machine, and we would like to reduce that.

>
> 4) In addition, EDKII/PI defined PCD (platform configuration database). It is
> an architecture way to manage the configuration data.
> We are also implementing structure PCD to let platform fill data easily.
> (https://github.com/tianocore/edk2-staging/tree/StructurePcd)
>
> I found some configuration can be as simple as a PCD, such as
> +  // Boot architecture information
> +  { EFI_ACPI_6_1_ARM_PSCI_COMPLIANT },              // BootArchFlags
> +
> +  // Power management profile information
> +  { EFI_ACPI_6_1_PM_PROFILE_ENTERPRISE_SERVER },    //
> PowerManagement Profile
>
> With the new structure PCD design, below definition can also be a structure
> PCD.
> +  // SPCR Serial Port
> +  {
> +    FixedPcdGet64 (PcdSerialRegisterBase),  // UINT64  BaseAddress
> +    FixedPcdGet32 (PL011UartInterrupt),     // UINT32  Interrupt
> +    FixedPcdGet64 (PcdUartDefaultBaudRate), // UINT64  BaudRate
> +    FixedPcdGet32 (PL011UartClkInHz)        // UINT32  Clock
> +  },
>
> +  // Debug Serial Port
> +  {
> +    FixedPcdGet64 (PcdSerialDbgRegisterBase), // UINT64  BaseAddress
> +    38,                                       // UINT32  Interrupt
> +    FixedPcdGet64 (PcdSerialDbgUartBaudRate), // UINT64  BaudRate
> +    FixedPcdGet32 (PcdSerialDbgUartClkInHz)   // UINT32  Clock
> +  },
>
> What if we just use PCD to define these CPU info, GICC info? Do we really
> another ConfigurationManager?

[[Evan Lloyd]] PCDs are very useful.  However they (especially FixedPcds) are build time options.  Given the aim of a single UEFI image, they do not quite work.  We want the UEFI to be able to get the variant config from an external entity.  In theory, a complex enough PCD database could be used to provide the config information, and could be loaded from a remote, but it would be a very elaborate solution.

[Jiewen] PCD can be static or dynamic. PCD has lots of usage.
For dynamic PCD, you can fill a PCD at BIOS boot time, not build time.
For multi-sku, you can fill a SKU PCD to support different SKU at build time or boot time.
For structure PCD, you can fill a C-like data structure to a PCD value.

In one word, we are able to use PCD to get the variant config from an external entity.
If you think there is something that PCD cannot do, please let us know.


>
>
> All in all, if we can compare the difference of below design with pros/cons,
> that will be great.
> That will help us understand more about the new design.
> A) DataHub (IntelFrameworkPkg, do not recommend to use.)
> B) PCD (MdePkg, in PI specification) and structure PCD (EDKII staging)
> C) ConfigurationManager (this patch)

[[Evan Lloyd]] We will need to study DataHub to see what is there, but we will make a response when we have.

[Jiewen] Thank you!
If you have any question on DataHub or PCD, please let us know.

>
>
> Thank you
> Yao Jiewen
>
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> > evan.lloyd@arm.com<mailto:evan.lloyd@arm.com>
> > Sent: Tuesday, October 3, 2017 3:48 AM
> > To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> > Cc: "Matteo.Carlini@arm.com"@arm.com<mailto:%22Matteo.Carlini@arm.com%22@arm.com>; "nd@arm.com"@arm.com<mailto:%22nd@arm.com%22@arm.com>;
> > "ard.biesheuvel@linaro.org"@arm.com<mailto:%22ard.biesheuvel@linaro.org%22@arm.com>;
> > "Stephanie.Hughes-Fitt@arm.com"@arm.com<mailto:%22Stephanie.Hughes-Fitt@arm.com%22@arm.com>;
> > "thomas.abraham@arm.com"@arm.com<mailto:%22thomas.abraham@arm.com%22@arm.com>;
> > "Arvind.Chauhan@arm.com"@arm.com<mailto:%22Arvind.Chauhan@arm.com%22@arm.com>;
> "leif.lindholm@linaro.org"@arm.com<mailto:%22leif.lindholm@linaro.org%22@arm.com>;
> > "Daniil.Egranov@arm.com"@arm.com<mailto:%22Daniil.Egranov@arm.com%22@arm.com>
> > Subject: [edk2] [PATCH 0/2] Dynamic Tables
> >
> > From: EvanLloyd <evan.lloyd@arm.com<mailto:evan.lloyd@arm.com>>
> >
> > Historically, ACPI code, SMBIOS tables, and UEFI firmware were often
> > developed in isolation from each other.  This introduced several
> > problems, not least of which was duplication of platform information
> > between the various source trees.
> > In addition, variants of platforms introduced a plethora of
> > alternative builds of ACPI, SMBIOS and EDK2, with the concomitant risk
> > of getting the mixture wrong in a build.
> >
> > In the effort to resolve these problems, the solution prototyped here
> > was devised.  The basic idea is to obtain the "variant"
> > information from a management node.  That means the firmware image
> can
> > be platform independent, with ACPI, SMBIOS (and potentially
> > other) tables generated with information from the management node.
> > This example has the framework for that, but the configuration
> > information is supplied directly, as an interim solution until a
> > suitable management node implementation exists yet.
> >
> >
...
> > --
> > Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> > https://lists.01.org/mailman/listinfo/edk2-devel
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Dynamic Tables
  2017-10-10 18:52   ` Evan Lloyd
  2017-10-10 19:57     ` Laszlo Ersek
  2017-10-11  1:25     ` Yao, Jiewen
@ 2017-10-12 15:43     ` Leif Lindholm
  2017-10-12 15:46       ` Ard Biesheuvel
  2 siblings, 1 reply; 14+ messages in thread
From: Leif Lindholm @ 2017-10-12 15:43 UTC (permalink / raw)
  To: Evan Lloyd
  Cc: Yao, Jiewen, edk2-devel@lists.01.org, Matteo.Carlini,
	ard.biesheuvel, Stephanie.Hughes-Fitt, thomas.abraham,
	Arvind.Chauhan, Daniil.Egranov

On Tue, Oct 10, 2017 at 06:52:02PM +0000, Evan Lloyd wrote:
> > I notice you only defined ARM namespace in this patch, and implemented
> > ARM library instance.
> > Also most consumers of ConfigurationManager are from ARM platform
> > package. So if it urgent from ARM platform, you may consider to check into
> > ArmPkg at first.
> 
> [[Evan Lloyd]] This sounds sensible, and I will discuss it with
> Leif.  Another option might be to start up a new module.

My preference would be for this to start as a branch in edk2-staging.

While there, we can bikeshed over the naming and placement (but I will
admit to a certain affinity for Sean's suggestion to keep it separate).

I do not think it is a good fit for ArmPkg.

If Evan can send out a request for creation as described in
https://github.com/tianocore/edk2-staging/blob/about/README,
I am happy to do the mechanics.

/
    Leif


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Dynamic Tables
  2017-10-12 15:43     ` Leif Lindholm
@ 2017-10-12 15:46       ` Ard Biesheuvel
  0 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2017-10-12 15:46 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: Evan Lloyd, Yao, Jiewen, edk2-devel@lists.01.org, Matteo Carlini,
	Stephanie.Hughes-Fitt, thomas.abraham, Arvind.Chauhan,
	Daniil Egranov

On 12 October 2017 at 16:43, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> On Tue, Oct 10, 2017 at 06:52:02PM +0000, Evan Lloyd wrote:
>> > I notice you only defined ARM namespace in this patch, and implemented
>> > ARM library instance.
>> > Also most consumers of ConfigurationManager are from ARM platform
>> > package. So if it urgent from ARM platform, you may consider to check into
>> > ArmPkg at first.
>>
>> [[Evan Lloyd]] This sounds sensible, and I will discuss it with
>> Leif.  Another option might be to start up a new module.
>
> My preference would be for this to start as a branch in edk2-staging.
>
> While there, we can bikeshed over the naming and placement (but I will
> admit to a certain affinity for Sean's suggestion to keep it separate).
>
> I do not think it is a good fit for ArmPkg.
>

+1

We are working very hard to reduce ArmPkg to pieces that are actually
specific to the ARM architecture. The fact that the Intel engineers
may not be interested in using this new dynamic table feature for
their platforms does not make it an ARM thing.

> If Evan can send out a request for creation as described in
> https://github.com/tianocore/edk2-staging/blob/about/README,
> I am happy to do the mechanics.
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2017-10-12 15:43 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-02 19:47 [PATCH 0/2] Dynamic Tables evan.lloyd
2017-10-02 19:47 ` [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework evan.lloyd
2017-10-03 14:34   ` Zeng, Star
2017-10-03 16:03     ` Leif Lindholm
2017-10-03 18:44       ` Sean Brogan
2017-10-03 17:03     ` Evan Lloyd
2017-10-02 19:47 ` [PATCH 2/2] [edk2-platforms] Platform/ARM: Dynamic Tables support for FVP evan.lloyd
2017-10-03 17:12 ` [PATCH 0/2] Dynamic Tables Evan Lloyd
2017-10-10  2:29 ` Yao, Jiewen
2017-10-10 18:52   ` Evan Lloyd
2017-10-10 19:57     ` Laszlo Ersek
2017-10-11  1:25     ` Yao, Jiewen
2017-10-12 15:43     ` Leif Lindholm
2017-10-12 15:46       ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox