public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Leif Lindholm <leif.lindholm@linaro.org>
To: "Zeng, Star" <star.zeng@intel.com>
Cc: "evan.lloyd@arm.com" <evan.lloyd@arm.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
	Matteo.Carlini@arm.com, ard.biesheuvel@linaro.org, "Kinney,
	Michael D" <michael.d.kinney@intel.com>,
	thomas.abraham@arm.com, Arvind.Chauhan@arm.com, "Yao,
	Jiewen" <jiewen.yao@intel.com>,
	leif.lindholm@linaro.org, Daniil.Egranov@arm.com
Subject: Re: [PATCH 1/2] MdeModulePkg: Dynamic Tables Framework
Date: Tue, 3 Oct 2017 17:03:30 +0100	[thread overview]
Message-ID: <20171003153117.rrs4im264tgi2bkw@bivouac.eciton.net> (raw)
In-Reply-To: <0C09AFA07DD0434D9E2A0C6AEB0483103B97E09A@shsmsx102.ccr.corp.intel.com>

(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


  reply	other threads:[~2017-10-03 16:00 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171003153117.rrs4im264tgi2bkw@bivouac.eciton.net \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox