From: Evan Lloyd <Evan.Lloyd@arm.com>
To: Sami Mujawar <Sami.Mujawar@arm.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "leif.lindholm@linaro.org" <leif.lindholm@linaro.org>,
Matteo Carlini <Matteo.Carlini@arm.com>,
Stephanie Hughes-Fitt <Stephanie.Hughes-Fitt@arm.com>,
nd <nd@arm.com>
Subject: Re: [staging/dynamictables PATCH 2/2] DynamicTablesPkg: Dynamic Tables Framework
Date: Mon, 19 Mar 2018 16:16:35 +0000 [thread overview]
Message-ID: <HE1PR0801MB17717C3E7021546A0FE652248BD40@HE1PR0801MB1771.eurprd08.prod.outlook.com> (raw)
In-Reply-To: <20180319151847.85204-3-sami.mujawar@arm.com>
> -----Original Message-----
> From: Sami Mujawar [mailto:sami.mujawar@arm.com]
> Sent: 19 March 2018 15:19
> To: edk2-devel@lists.01.org
> Cc: Evan Lloyd <Evan.Lloyd@arm.com>; leif.lindholm@linaro.org; Matteo
> Carlini <Matteo.Carlini@arm.com>; Stephanie Hughes-Fitt
> <Stephanie.Hughes-Fitt@arm.com>; nd <nd@arm.com>
> Subject: [staging/dynamictables PATCH 2/2] DynamicTablesPkg: Dynamic
> Tables Framework
>
> 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
> Source Language (ASL), 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 provides 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 implement the functionality required for ARM
> architecture; the framework is extensible, and support for other
> architectures can be added easily.
>
> Contributions from the community are invited.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Evan Lloyd <evan.lloyd@arm.com>
> ---
>
> DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/AcpiTableFactory/Acpi
> TableFactory.c | 226 +++
>
> DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DeviceTreeTableFactor
> y/DeviceTreeTableFactory.c | 225 +++
>
> DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.
> h | 125 ++
>
> DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory
> Dxe.c | 84 +
>
> DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory
> Dxe.inf | 59 +
>
> DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/S
> mbiosTableFactory.c | 226 +++
>
> DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManag
> erDxe.c | 533 +++++
>
> DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManag
> erDxe.inf | 48 +
> DynamicTablesPkg/DynamicTables.dsc.inc
> | 46 +
> DynamicTablesPkg/DynamicTables.fdf.inc
> | 35 +
> DynamicTablesPkg/DynamicTablesPkg.dec
> | 42 +
> DynamicTablesPkg/Include/AcpiTableGenerator.h
> | 282 +++
> DynamicTablesPkg/Include/ArmNameSpaceObjects.h
> | 587 ++++++
> DynamicTablesPkg/Include/ConfigurationManagerHelper.h
> | 119 ++
> DynamicTablesPkg/Include/ConfigurationManagerObject.h
> | 176 ++
> DynamicTablesPkg/Include/DeviceTreeTableGenerator.h
> | 182 ++
> DynamicTablesPkg/Include/Library/TableHelperLib.h
> | 70 +
> DynamicTablesPkg/Include/Protocol/ConfigurationManagerProtocol.h
> | 128 ++
> DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h
> | 140 ++
> DynamicTablesPkg/Include/SmbiosTableGenerator.h
> | 240 +++
> DynamicTablesPkg/Include/StandardNameSpaceObjects.h
> | 116 ++
> DynamicTablesPkg/Include/TableGenerator.h
> | 252 +++
>
> DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
> | 47 +
> DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
> | 440 +++++
> DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
> | 41 +
> DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
> | 666 +++++++
> DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
> | 41 +
> DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
> | 670 +++++++
> DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm.inf
> | 41 +
> DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c
> | 2046 ++++++++++++++++++++
> DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h
> | 50 +
>
> DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.in
> f | 41 +
> DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
> | 717 +++++++
> DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
> | 41 +
> DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
> | 342 ++++
> DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> | 41 +
> DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
> | 142 ++
> DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
> | 41 +
> DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
> | 324 ++++
> DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
> | 164 ++
> DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
> | 35 +
> 41 files changed, 9871 insertions(+)
>
> diff --git
> a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/AcpiTableFactory/A
> cpiTableFactory.c
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/AcpiTableFactory/A
> cpiTableFactory.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..425b2f2d8feb959493
> 214d545aaa9b59a0fbeba2
> --- /dev/null
> +++
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/AcpiTableFactory/A
> cpiTableFactory.c
> @@ -0,0 +1,226 @@
> +/** @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 <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <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 Pointer 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;
> +}
> +
> +/** Deregister ACPI generator.
> +
> + This function is called by the ACPI table generator to deregister 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
> +DeregisterAcpiTableGenerator (
> + IN CONST ACPI_TABLE_GENERATOR * CONST Generator
> + )
> +{
> + UINT16 TableId;
> +
> + if (Generator == NULL) {
> + DEBUG ((DEBUG_ERROR, "ERROR: ACPI deregister - Invalid
> Generator\n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!IS_GENERATOR_TYPE_ACPI (Generator->GeneratorID)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: ACPI deregister - 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, "Deregistering %s\n", Generator->Description));
> + return EFI_SUCCESS;
> +}
> diff --git
> a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DeviceTreeTableFact
> ory/DeviceTreeTableFactory.c
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DeviceTreeTableFac
> tory/DeviceTreeTableFactory.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..9e4fa3f8ffce390f3aa8
> 5136f3508e139cca3326
> --- /dev/null
> +++
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DeviceTreeTableFac
> tory/DeviceTreeTableFactory.c
> @@ -0,0 +1,225 @@
> +/** @file
> + Device Tree 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 <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +
> +// Module specific include files.
> +#include <DeviceTreeTableGenerator.h>
> +#include <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 DT table generator.
> +
> + @param [in] This Pointer to the Dynamic Table Factory Protocol.
> + @param [in] GeneratorId The DT table generator ID for the
> + requested generator.
> + @param [out] Generator Pointer to the requested DT 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
> +GetDtTableGenerator (
> + IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL * CONST This,
> + IN CONST DT_TABLE_GENERATOR_ID GeneratorId,
> + OUT CONST DT_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_DT (GeneratorId)) {
> + DEBUG ((DEBUG_ERROR, "ERROR: Generator Type is not DT\n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + *Generator = NULL;
> + TableId = GET_TABLE_ID (GeneratorId);
> + if (IS_GENERATOR_NAMESPACE_STD (GeneratorId)) {
> + if (TableId >= (ESTD_DT_TABLE_ID_MAX)) {
> + ASSERT (TableId < (ESTD_DT_TABLE_ID_MAX));
> + return EFI_INVALID_PARAMETER;
> + }
> + if (FactoryInfo->StdDtTableGeneratorList[TableId] != NULL) {
> + *Generator = FactoryInfo->StdDtTableGeneratorList[TableId];
> + } else {
> + return EFI_NOT_FOUND;
> + }
> + } else {
> + if (TableId >= FixedPcdGet16 (PcdMaxCustomDTGenerators)) {
> + ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomDTGenerators));
> + return EFI_INVALID_PARAMETER;
> + }
> + if (FactoryInfo->CustomDtTableGeneratorList[TableId] != NULL) {
> + *Generator = FactoryInfo->CustomDtTableGeneratorList[TableId];
> + } else {
> + return EFI_NOT_FOUND;
> + }
> + }
> + return EFI_SUCCESS;
> +}
> +
> +/** Register DT table factory generator.
> +
> + The DT table factory maintains a list of the Standard and OEM DT
> + table generators.
> +
> + @param [in] Generator Pointer to the DT 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
> +RegisterDtTableGenerator (
> + IN CONST DT_TABLE_GENERATOR * CONST Generator
> + )
> +{
> + UINT16 TableId;
> +
> + if (Generator == NULL) {
> + DEBUG ((DEBUG_ERROR, "ERROR: DT register - Invalid Generator\n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!IS_GENERATOR_TYPE_DT (Generator->GeneratorID)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: DT register - Generator" \
> + " Type is not DT\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_DT_TABLE_ID_MAX)) {
> + ASSERT (TableId < (ESTD_DT_TABLE_ID_MAX));
> + return EFI_INVALID_PARAMETER;
> + }
> + if (TableFactoryInfo.StdDtTableGeneratorList[TableId] == NULL) {
> + TableFactoryInfo.StdDtTableGeneratorList[TableId] = Generator;
> + } else {
> + return EFI_ALREADY_STARTED;
> + }
> + } else {
> + if (TableId >= FixedPcdGet16 (PcdMaxCustomDTGenerators)) {
> + ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomDTGenerators));
> + return EFI_INVALID_PARAMETER;
> + }
> + if (TableFactoryInfo.CustomDtTableGeneratorList[TableId] == NULL) {
> + TableFactoryInfo.CustomDtTableGeneratorList[TableId] = Generator;
> + } else {
> + return EFI_ALREADY_STARTED;
> + }
> + }
> + return EFI_SUCCESS;
> +}
> +
> +/** Deregister DT generator.
> +
> + This function is called by the DT table generator to deregister itself
> + from the DT table factory.
> +
> + @param [in] Generator Pointer to the DT 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
> +DeregisterDtTableGenerator (
> + IN CONST DT_TABLE_GENERATOR * CONST Generator
> + )
> +{
> + UINT16 TableId;
> +
> + if (Generator == NULL) {
> + DEBUG ((DEBUG_ERROR, "ERROR: DT deregister - Invalid Generator\n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!IS_GENERATOR_TYPE_DT (Generator->GeneratorID)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: DT deregister - Generator" \
> + " Type is not DT\n"
> + ));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + TableId = GET_TABLE_ID (Generator->GeneratorID);
> + if (IS_GENERATOR_NAMESPACE_STD (Generator->GeneratorID)) {
> + if (TableId >= (ESTD_DT_TABLE_ID_MAX)) {
> + ASSERT (TableId < (ESTD_DT_TABLE_ID_MAX));
> + return EFI_INVALID_PARAMETER;
> + }
> + if (TableFactoryInfo.StdDtTableGeneratorList[TableId] != NULL) {
> + if (Generator != TableFactoryInfo.StdDtTableGeneratorList[TableId]) {
> + return EFI_INVALID_PARAMETER;
> + }
> + TableFactoryInfo.StdDtTableGeneratorList[TableId] = NULL;
> + } else {
> + return EFI_NOT_FOUND;
> + }
> + } else {
> + if (TableId >= FixedPcdGet16 (PcdMaxCustomDTGenerators)) {
> + ASSERT (TableId < FixedPcdGet16 (PcdMaxCustomDTGenerators));
> + return EFI_INVALID_PARAMETER;
> + }
> + if (TableFactoryInfo.CustomDtTableGeneratorList[TableId] != NULL) {
> + if (Generator !=
> + TableFactoryInfo.CustomDtTableGeneratorList[TableId]) {
> + return EFI_INVALID_PARAMETER;
> + }
> + TableFactoryInfo.CustomDtTableGeneratorList[TableId] = NULL;
> + } else {
> + return EFI_NOT_FOUND;
> + }
> + }
> +
> + DEBUG ((DEBUG_INFO, "Deregistering %s\n", Generator->Description));
> + return EFI_SUCCESS;
> +}
> diff --git
> a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactor
> y.h
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFacto
> ry.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..c0b4a2a11457933b1c
> 86950338f5619111747dc3
> --- /dev/null
> +++
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFacto
> ry.h
> @@ -0,0 +1,125 @@
> +/** @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
> + - DT - Device Tree
> +**/
> +
> +#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
> + )];
> +
> + /// An array for holding the list of Standard DT Table Generators.
> + CONST DT_TABLE_GENERATOR *
> + StdDtTableGeneratorList[ESTD_DT_TABLE_ID_MAX];
> +
> + /// An array for holding the list of Custom DT Table Generators.
> + CONST DT_TABLE_GENERATOR *
> + CustomDtTableGeneratorList[FixedPcdGet16 (
> + PcdMaxCustomDTGenerators
> + )];
> +} EFI_DYNAMIC_TABLE_FACTORY_INFO;
> +
> +/** Return a pointer to the ACPI table generator.
> +
> + @param [in] This Pointer 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 Pointer 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
> + );
> +
> +/** Return a pointer to the DT table generator.
> +
> + @param [in] This Pointer to the Dynamic Table Factory Protocol.
> + @param [in] GeneratorId The DT table generator ID for the
> + requested generator.
> + @param [out] Generator Pointer to the requested DT 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
> +GetDtTableGenerator (
> + IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL * CONST This,
> + IN CONST DT_TABLE_GENERATOR_ID GeneratorId,
> + OUT CONST DT_TABLE_GENERATOR ** CONST Generator
> + );
> +
> +#pragma pack()
> +
> +#endif // DYNAMIC_TABLE_FACTORY_H_
> diff --git
> a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactor
> yDxe.c
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFacto
> ryDxe.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..6ac291ab29a8f44ed91
> 845f5e6f65e0e5248f80b
> --- /dev/null
> +++
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFacto
> ryDxe.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 <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <DeviceTreeTableGenerator.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include <SmbiosTableGenerator.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,
> + GetDtTableGenerator,
> + &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/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactor
> yDxe.inf
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFacto
> ryDxe.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..346168d6b1496eb180
> 8565f830b9c0eae4b06f79
> --- /dev/null
> +++
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFacto
> ryDxe.inf
> @@ -0,0 +1,59 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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 = 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]
> + AcpiTableFactory/AcpiTableFactory.c
> + DeviceTreeTableFactory/DeviceTreeTableFactory.c
> + DynamicTableFactoryDxe.c
> + SmbiosTableFactory/SmbiosTableFactory.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + MemoryAllocationLib
> + PrintLib
> + TableHelperLib
> + UefiBootServicesTableLib
> + UefiDriverEntryPoint
> +
> +[FixedPcd]
> + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators
> + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators
> + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomDTGenerators
> +
> +[Protocols]
> + gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
> + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
> + gEfiConfigurationManagerProtocolGuid
> + gEfiDynamicTableFactoryProtocolGuid
> +
> +[Depex]
> + TRUE
> diff --git
> a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory
> /SmbiosTableFactory.c
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory
> /SmbiosTableFactory.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..01be8cd1ca5371770d
> 179ca1ec12de387bd49cd7
> --- /dev/null
> +++
> b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory
> /SmbiosTableFactory.c
> @@ -0,0 +1,226 @@
> +/** @file
> + SMBIOS Table Factory
> +
> + Copyright (c) 2017 - 2018, 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 <IndustryStandard/SmBios.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +
> +// Module specific include files.
> +#include <SmbiosTableGenerator.h>
> +#include <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 Pointer 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;
> +}
> +
> +/** Deregister SMBIOS generator.
> +
> + This function is called by the SMBIOS table generator to deregister 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
> +DeregisterSmbiosTableGenerator (
> + IN CONST SMBIOS_TABLE_GENERATOR * CONST Generator
> + )
> +{
> + UINT16 TableId;
> +
> + if (Generator == NULL) {
> + DEBUG ((DEBUG_ERROR, "ERROR: SMBIOS deregister - Invalid
> Generator\n"));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!IS_GENERATOR_TYPE_SMBIOS (Generator->GeneratorID)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: SMBIOS deregister - 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, "Deregistering %s\n", Generator->Description));
> + return EFI_SUCCESS;
> +}
> diff --git
> a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMan
> agerDxe.c
> b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMan
> agerDxe.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..5a3ad21220bd924bab
> ab3ca2a28c87c5a91efa0c
> --- /dev/null
> +++
> b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMan
> agerDxe.c
> @@ -0,0 +1,533 @@
> +/** @file
> + Dynamic Table Manager Dxe
> +
> + Copyright (c) 2017 - 2018, 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 <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <DeviceTreeTableGenerator.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include <SmbiosTableGenerator.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;
> + EFI_STATUS Status1;
> + CONST ACPI_TABLE_GENERATOR * Generator = NULL;
> + EFI_ACPI_DESCRIPTION_HEADER * AcpiTable = NULL;
> + 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;
> + }
> +
> + 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 exit_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 exit_handler;
> + }
> +
> + DEBUG ((
> + DEBUG_INFO,
> + "INFO: ACPI Table installed. Status = %r\n",
> + Status
> + ));
> +
> +exit_handler:
> + // Free any resources allocated for generating the tables.
> + if (Generator->FreeTableResources != NULL) {
> + Status1 = Generator->FreeTableResources (
> + Generator,
> + AcpiTableInfo,
> + CfgMgrProtocol,
> + &AcpiTable
> + );
> + if (EFI_ERROR (Status1)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: Failed to Free Table Resources." \
> + "TableGeneratorId = 0x%x. Status = %r\n",
> + AcpiTableInfo->TableGeneratorId,
> + Status
> + ));
> + }
> +
> + // Return the first error status in case of failure
> + if (!EFI_ERROR (Status)) {
> + Status = Status1;
> + }
> + }
> +
> + 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 UINT32 AcpiTableCount
> + )
> +{
> + EFI_STATUS Status = EFI_SUCCESS;
> + BOOLEAN FadtFound = FALSE;
> + BOOLEAN MadtFound = FALSE;
> + BOOLEAN GtdtFound = FALSE;
> + BOOLEAN DsdtFound = FALSE;
> + BOOLEAN Dbg2Found = FALSE;
> + BOOLEAN SpcrFound = FALSE;
> +
> + ASSERT (AcpiTableInfo != NULL);
> +
> + while (AcpiTableCount-- != 0) {
> + switch (AcpiTableInfo[AcpiTableCount].AcpiTableSignature) {
> + case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
> + FadtFound = TRUE;
> + break;
> + case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
> + MadtFound = TRUE;
> + break;
> + case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:
> + GtdtFound = TRUE;
> + break;
> + case
> EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
> + DsdtFound = TRUE;
> + break;
> + case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE:
> + Dbg2Found = TRUE;
> + break;
> + case
> EFI_ACPI_6_2_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;
> + CM_STD_OBJ_ACPI_TABLE_INFO * AcpiTableInfo;
> + UINT32 AcpiTableCount;
> + UINT32 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,
> + CM_NULL_TOKEN,
> + &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/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMan
> agerDxe.inf
> b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMan
> agerDxe.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..d006587a0119a8d5b4
> 33e3c651320d1c6e86f0f9
> --- /dev/null
> +++
> b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMan
> agerDxe.inf
> @@ -0,0 +1,48 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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 = 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + PrintLib
> + TableHelperLib
> + UefiBootServicesTableLib
> + UefiDriverEntryPoint
> +
> +[Protocols]
> + gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
> + gEfiConfigurationManagerProtocolGuid
> + gEfiDynamicTableFactoryProtocolGuid
> +
> +[Depex]
> + TRUE
> diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc
> b/DynamicTablesPkg/DynamicTables.dsc.inc
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..b89ea0c004710ebe98
> 34ac94a459bc98f9e1b5af
> --- /dev/null
> +++ b/DynamicTablesPkg/DynamicTables.dsc.inc
> @@ -0,0 +1,46 @@
> +## @file
> +# Dsc include file for Dynamic Tables Framework.
> +#
> +# Copyright (c) 2017 - 2018, 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 = -tc -li
> +
> +[LibraryClasses.common]
> +
> +[Components.common]
> + #
> + # Dynamic Table Factory Dxe
> + #
> +
> DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory
> Dxe.inf {
> + <LibraryClasses>
> +
> TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/Table
> HelperLib.inf
> +
> NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibAr
> m.inf
> +
> NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibAr
> m.inf
> +
> NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLib
> Arm.inf
> +
> NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibAr
> m.inf
> +
> NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibAr
> m.inf
> +
> NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibA
> rm.inf
> +
> NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibA
> rm.inf
> +
> NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm
> .inf
> + }
> +
> + #
> + # Dynamic Tables Manager Dxe
> + #
> +
> DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManag
> erDxe.inf {
> + <LibraryClasses>
> +
> TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/Table
> HelperLib.inf
> + }
> diff --git a/DynamicTablesPkg/DynamicTables.fdf.inc
> b/DynamicTablesPkg/DynamicTables.fdf.inc
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..51229c1cbfecae3ba14
> 0f38a43fa67f11d716c58
> --- /dev/null
> +++ b/DynamicTablesPkg/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
> DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory
> Dxe.inf
> +
> + #
> + # Dynamic Tables Dxe
> + #
> + INF
> DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManag
> erDxe.inf
> diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec
> b/DynamicTablesPkg/DynamicTablesPkg.dec
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..4ac88d12aa47f6a22f2
> c2b0e2d8dc64e28cff1fd
> --- /dev/null
> +++ b/DynamicTablesPkg/DynamicTablesPkg.dec
> @@ -0,0 +1,42 @@
> +## @file DynamicTablesPkg.dec
> +#
> +# 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.
> +# 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]
> + DEC_SPECIFICATION = 0x00010005
> + PACKAGE_NAME = DynamicTablesPkg
> + PACKAGE_GUID = 188EB346-8ABA-460E-A105-0F9D76F7324A
> + PACKAGE_VERSION = 1.0
> +
> +[Includes]
> + Include
> +
> +[Protocols]
> +
> + # 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 } }
> +
> +[PcdsFixedAtBuild]
> +
> + # Maximum number of Custom ACPI Generators
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators|1|UIN
> T16|0xC0000001
> +
> + # Maximum number of Custom SMBIOS Generators
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators|1|
> UINT16|0xC0000002
> +
> + # Maximum number of Custom DT Generators
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomDTGenerators|1|UINT1
> 6|0xC0000003
> +
> diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h
> b/DynamicTablesPkg/Include/AcpiTableGenerator.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..89fa713134857e2264
> 0b7a6f1f63a485048b7a72
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
> @@ -0,0 +1,282 @@
> +/** @file
> +
> + Copyright (c) 2017 - 2018, 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_
> +
> +#include <IndustryStandard/Acpi.h>
> +
> +// Module specific include files.
> +#include <TableGenerator.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 generators 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 a 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 a 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
> from
> + the Configuration Manager and builds the FADT table.
> + - MADT : The MADT generator collates the GIC information from the
> + Configuration Manager and builds the MADT table.
> + - GTDT : The GTDT generator collates the Timer information from the
> + Configuration Manager and builds the GTDT table.
> + - DBG2 : The DBG2 generator collates the debug serial port information
> from
> + the Configuration Manager and builds the DBG2 table.
> + - SPCR : The SPCR generator collates the serial port information from the
> + Configuration Manager and builds the SPCR table.
> + - MCFG : The MCFG generator collates the PCI configuration space
> information
> + from the Configuration Manager and builds the MCFG table.
> + - IORT : The IORT generator collates the IO Topology information from
> the
> + Configuration Manager and builds the IORT 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_IORT, ///< IORT 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] This 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 * This,
> + 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 used by the
> + Table Manager to give the generator an opportunity to free
> + any resources allocated for building the ACPI table.
> +
> + @param [in] This Pointer to the ACPI table generator.
> + @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in, out] Table Pointer to the 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 * CONST This,
> + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST
> AcpiTableInfo,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST 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
> + );
> +
> +/** Deregister ACPI generator.
> +
> + This function is called by the ACPI table generator to deregister 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
> +DeregisterAcpiTableGenerator (
> + IN CONST ACPI_TABLE_GENERATOR * CONST Generator
> + );
> +
> +#pragma pack()
> +
> +#endif // ACPI_TABLE_GENERATOR_H_
> +
> diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
> b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..abbd624eb026d14d22
> 80d766bf68633c60436829
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
> @@ -0,0 +1,587 @@
> +/** @file
> +
> + Copyright (c) 2017 - 2018, 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_
> +
> +#include <StandardNameSpaceObjects.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
> + EArmObjGTBlockTimerFrameInfo, ///< 13 - Generic Timer Block Frame
> Info
> + EArmObjPlatformGenericWatchdogInfo, ///< 14 - Platform Generic
> Watchdog
> + EArmObjPciConfigSpaceInfo, ///< 15 - PCI Configuration Space Info
> + EArmObjHypervisorVendorIdentity, ///< 16 - Hypervisor Vendor Id
> + EArmObjFixedFeatureFlags, ///< 17 - Fixed feature flags for FADT
> + EArmObjItsGroup, ///< 18 - ITS Group
> + EArmObjNamedComponent, ///< 19 - Named Component
> + EArmObjRootComplex, ///< 20 - Root Complex
> + EArmObjSmmuV1SmmuV2, ///< 21 - SMMUv1 or SMMUv2
> + EArmObjSmmuV3, ///< 22 - SMMUv3
> + EArmObjPmcg, ///< 23 - PMCG
> + EArmObjGicItsIdentifierArray, ///< 24 - GIC ITS Identifier Array
> + EArmObjIdMapping, ///< 25 - ID Mapping
> + EArmObjSmmuInterruptArray, ///< 26 - SMMU Interrupt Array
> + 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 maintenance 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;
> +
> + /// Serial Port subtype
> + UINT16 PortSubtype;
> +} 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;
> +
> + /// Reference token for the GT Block timer frame list
> + CM_OBJECT_TOKEN GTBlockTimerFrameToken;
> +} 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;
> +
> +/** A structure that describes the
> + Fixed feature flags for the Platform.
> +*/
> +typedef struct CmArmFixedFeatureFlags {
> + /// The Fixed feature flags
> + UINT32 Flags;
> +} CM_ARM_FIXED_FEATURE_FLAGS;
> +
> +/** A structure that describes the
> + ITS Group node for the Platform.
> +*/
> +typedef struct CmArmItsGroupNode {
> + /// An unique token used to ideintify this object
> + CM_OBJECT_TOKEN Token;
> + /// The number of ITS identifiers in the ITS node
> + UINT32 ItsIdCount;
> + /// Reference token for the ITS identifier array
> + CM_OBJECT_TOKEN ItsIdToken;
> +} CM_ARM_ITS_GROUP_NODE;
> +
> +/** A structure that describes the
> + GIC ITS Identifiers for an ITS Group node.
> +*/
> +typedef struct CmArmGicItsIdentifier {
> + /// The ITS Identifier
> + UINT32 ItsId;
> +} CM_ARM_ITS_IDENTIFIER;
> +
> +/** A structure that describes the
> + Named component node for the Platform.
> +*/
> +typedef struct CmArmNamedComponentNode {
> + /// An unique token used to ideintify this object
> + CM_OBJECT_TOKEN Token;
> + /// Number of ID mappings
> + UINT32 IdMappingCount;
> + /// Reference token for the ID mapping array
> + CM_OBJECT_TOKEN IdMappingToken;
> +
> + /// Flags for the named component
> + UINT32 Flags;
> +
> + /// Memory access properties : Cache coherent attributes
> + UINT32 CacheCoherent;
> + /// Memory access properties : Allocation hints
> + UINT8 AllocationHints;
> + /// Memory access properties : Memory access flags
> + UINT8 MemoryAccessFlags;
> +
> + /// Memory access properties : Address size limit
> + UINT8 AddressSizeLimit;
> + /** ASCII Null terminated string with the full path to
> + the entry in the namespace for this object.
> + */
> + CHAR8* ObjectName;
> +} CM_ARM_NAMED_COMPONENT_NODE;
> +
> +/** A structure that describes the
> + Root complex node for the Platform.
> +*/
> +typedef struct CmArmRootComplexNode {
> + /// An unique token used to ideintify this object
> + CM_OBJECT_TOKEN Token;
> + /// Number of ID mappings
> + UINT32 IdMappingCount;
> + /// Reference token for the ID mapping array
> + CM_OBJECT_TOKEN IdMappingToken;
> +
> + /// Memory access properties : Cache coherent attributes
> + UINT32 CacheCoherent;
> + /// Memory access properties : Allocation hints
> + UINT8 AllocationHints;
> + /// Memory access properties : Memory access flags
> + UINT8 MemoryAccessFlags;
> +
> + /// ATS attributes
> + UINT32 AtsAttribute;
> + /// PCI segment number
> + UINT32 PciSegmentNumber;
> +} CM_ARM_ROOT_COMPLEX_NODE;
> +
> +/** A structure that describes the
> + SMMUv1 or SMMUv2 node for the Platform.
> +*/
> +typedef struct CmArmSmmuV1SmmuV2Node {
> + /// An unique token used to ideintify this object
> + CM_OBJECT_TOKEN Token;
> + /// Number of ID mappings
> + UINT32 IdMappingCount;
> + /// Reference token for the ID mapping array
> + CM_OBJECT_TOKEN IdMappingToken;
> +
> + /// SMMU Base Address
> + UINT64 BaseAddress;
> + /// Length of the memory range covered by the SMMU
> + UINT64 Span;
> + /// SMMU Model
> + UINT32 Model;
> + /// SMMU flags
> + UINT32 Flags;
> +
> + /// Number of context interrupts
> + UINT32 ContextInterruptCount;
> + /// Reference token for the context interrupt array
> + CM_OBJECT_TOKEN ContextInterruptToken;
> +
> + /// Number of PMU interrupts
> + UINT32 PmuInterruptCount;
> + /// Reference token for the PMU interrupt array
> + CM_OBJECT_TOKEN PmuInterruptToken;
> +
> + /// GSIV of the SMMU_NSgIrpt interrupt
> + UINT32 SMMU_NSgIrpt;
> + /// SMMU_NSgIrpt interrupt flags
> + UINT32 SMMU_NSgIrptFlags;
> + /// GSIV of the SMMU_NSgCfgIrpt interrupt
> + UINT32 SMMU_NSgCfgIrpt;
> + /// SMMU_NSgCfgIrpt interrupt flags
> + UINT32 SMMU_NSgCfgIrptFlags;
> +} CM_ARM_SMMUV1_SMMUV2_NODE;
> +
> +/** A structure that describes the
> + SMMUv3 node for the Platform.
> +*/
> +typedef struct CmArmSmmuV3Node {
> + /// An unique token used to ideintify this object
> + CM_OBJECT_TOKEN Token;
> + /// Number of ID mappings
> + UINT32 IdMappingCount;
> + /// Reference token for the ID mapping array
> + CM_OBJECT_TOKEN IdMappingToken;
> +
> + /// SMMU Base Address
> + UINT64 BaseAddress;
> + /// SMMU flags
> + UINT32 Flags;
> + /// VATOS address
> + UINT64 VatosAddress;
> + /// Model
> + UINT32 Model;
> + /// GSIV of the Event interrupt if SPI based
> + UINT32 EventInterrupt;
> + /// PRI Interrupt if SPI based
> + UINT32 PriInterrupt;
> + /// GERR interrupt if GSIV based
> + UINT32 GerrInterrupt;
> + /// Sync interrupt if GSIV based
> + UINT32 SyncInterrupt;
> +
> + /// Proximity domain flag
> + UINT8 ProximityDomain;
> + /// Index into the array of ID mapping
> + UINT32 DeviceIdMappingIndex;
> +} CM_ARM_SMMUV3_NODE;
> +
> +/** A structure that describes the
> + PMCG node for the Platform.
> +*/
> +typedef struct CmArmPmcgNode {
> + /// An unique token used to ideintify this object
> + CM_OBJECT_TOKEN Token;
> + /// Number of ID mappings
> + UINT32 IdMappingCount;
> + /// Reference token for the ID mapping array
> + CM_OBJECT_TOKEN IdMappingToken;
> +
> + /// Base Address for performance monitor counter group
> + UINT64 BaseAddress;
> + /// GSIV for the Overflow interrupt
> + UINT32 OverflowInterrupt;
> +
> + /// Reference token for the IORT node associated with this node
> + CM_OBJECT_TOKEN ReferenceToken;
> +} CM_ARM_PMCG_NODE;
> +
> +/** A structure that describes the
> + ID Mappings for the Platform.
> +*/
> +typedef struct CmArmIdMapping {
> + /// Input base
> + UINT32 InputBase;
> + /// Number of input IDs
> + UINT32 NumIds;
> + /// Output Base
> + UINT32 OutputBase;
> + /// Reference token for the output node
> + CM_OBJECT_TOKEN OutputReferenceToken;
> + /// Flags
> + UINT32 Flags;
> +} CM_ARM_ID_MAPPING;
> +
> +/** A structure that describes the
> + SMMU interrupts for the Platform.
> +*/
> +typedef struct CmArmSmmuInterrupt {
> + /// Interrupt number
> + UINT32 Interrupt;
> +
> + /// Flags
> + UINT32 Flags;
> +} CM_ARM_SMMU_INTERRUPT;
> +
> +#pragma pack()
> +
> +#endif // ARM_NAMESPACE_OBJECTS_H_
> diff --git a/DynamicTablesPkg/Include/ConfigurationManagerHelper.h
> b/DynamicTablesPkg/Include/ConfigurationManagerHelper.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..7f39e2167166e1ea0e
> 895a535d85ddaf231bf394
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/ConfigurationManagerHelper.h
> @@ -0,0 +1,119 @@
> +/** @file
> +
> + Copyright (c) 2017 - 2018, 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,
> + IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
> + OUT Type ** List,
> + OUT UINT32 * Count OPTIONAL
> + );
> +
> + Generated function parameters:
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> protocol
> + interface.
> + @param [in] Token Reference token for the Object.
> + @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, \
> + IN CONST CM_OBJECT_TOKEN Token OPTIONAL, \
> + OUT Type ** List, \
> + OUT UINT32 * CONST Count OPTIONAL \
> + ) \
> +{ \
> + EFI_STATUS Status; \
> + CM_OBJ_DESCRIPTOR CmObjectDesc; \
> + UINT32 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 \
> + ), \
> + Token, \
> + &CmObjectDesc \
> + ); \
> + if (EFI_ERROR (Status)) { \
> + DEBUG (( \
> + DEBUG_INFO, \
> + "INFO: 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/DynamicTablesPkg/Include/ConfigurationManagerObject.h
> b/DynamicTablesPkg/Include/ConfigurationManagerObject.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..98329133a67f6ba477
> 1ceb98c8cd30d1f470bd19
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/ConfigurationManagerObject.h
> @@ -0,0 +1,176 @@
> +/** @file
> +
> + Copyright (c) 2017 - 2018, 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_
> +
> +#include <ArmNameSpaceObjects.h>
> +#include <StandardNameSpaceObjects.h>
> +
> +#pragma pack(1)
> +
> +/** The CM_OBJECT_ID type is used to identify the Configuration 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
> + 11 - Generic Timer Info
> + 12 - Platform GT Block Info
> + 13 - Platform Generic Watchdog
> + 14 - PCI Configuration Space Info
> + 15 - Hypervisor Vendor Id
> + 16 - Fixed feature flags for FADT
> +*/
> +typedef UINT32 CM_OBJECT_ID;
> +
> +/** A mask for Object ID
> +*/
> +#define OBJECT_ID_MASK 0xFF
> +
> +/** A mask for Namespace ID
> +*/
> +#define NAMESPACE_ID_MASK 0xF
> +
> +/** Starting bit position for Namespace ID
> +*/
> +#define NAMESPACE_ID_BIT_SHIFT 28
> +
> +/** The EOBJECT_NAMESPACE_ID enum describes the defined
> namespaces
> + for the Configuration Manager Objects.
> +*/
> +typedef enum ObjectNameSpaceID {
> + EObjNameSpaceStandard, ///< Standard Objects Namespace
> + EObjNameSpaceArm, ///< ARM Objects Namespace
> + EObjNameSpaceOem = 0x8, ///< OEM Objects Namespace
> + EObjNameSpaceMax
> +} EOBJECT_NAMESPACE_ID;
> +
> +/** A descriptor for Configuration Manager Objects.
> +
> + The Configuration Manager Protocol interface uses this descriptor
> + to return the Configuration Manager Objects.
> +*/
> +typedef struct CmObjDescriptor {
> + /// sizeof the described Object or Object List.
> + UINT32 Size;
> +
> + /// Pointer to the described Object or Object List.
> + VOID * 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) >> NAMESPACE_ID_BIT_SHIFT) & \
> + NAMESPACE_ID_MASK)
> +
> +/** 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) &
> OBJECT_ID_MASK)
> +
> +/** 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) & NAMESPACE_ID_MASK) <<
> NAMESPACE_ID_BIT_SHIFT) | \
> + ((ObjectId) & OBJECT_ID_MASK))
> +
> +/** 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/DynamicTablesPkg/Include/DeviceTreeTableGenerator.h
> b/DynamicTablesPkg/Include/DeviceTreeTableGenerator.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..767a62d383e6d530e5
> 51b69a0a7146359f6fd093
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/DeviceTreeTableGenerator.h
> @@ -0,0 +1,182 @@
> +/** @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 DEVICETREE_TABLE_GENERATOR_H_
> +#define DEVICETREE_TABLE_GENERATOR_H_
> +
> +#include <TableGenerator.h>
> +
> +#pragma pack(1)
> +
> +/** The DT_TABLE_GENERATOR_ID type describes Device Tree table
> generator ID.
> +*/
> +typedef TABLE_GENERATOR_ID DT_TABLE_GENERATOR_ID;
> +
> +/** The ESTD_DT_TABLE_ID enum describes the DT table IDs reserved for
> + the standard generators.
> +*/
> +typedef enum StdDtTableId {
> + ESTD_DT_TABLE_ID_RESERVED = 0x0000, ///< Reserved.
> + ESTD_DT_TABLE_ID_RAW, ///< RAW Generator.
> + ESTD_DT_TABLE_ID_MAX
> +} ESTD_DT_TABLE_ID;
> +
> +/** This macro checks if the Table Generator ID is for an DT Table
> Generator.
> +
> + @param [in] TableGeneratorId The table generator ID.
> +
> + @returns TRUE if the table generator ID is for an DT Table
> + Generator.
> +*/
> +#define IS_GENERATOR_TYPE_DT(TableGeneratorId) \
> + (GET_TABLE_TYPE(TableGeneratorId) == ETableGeneratorTypeDt)
> +
> +/** This macro checks if the Table Generator ID is for a standard DT
> + Table Generator.
> +
> + @param [in] TableGeneratorId The table generator ID.
> +
> + @returns TRUE if the table generator ID is for a standard DT
> + Table Generator.
> +*/
> +#define IS_VALID_STD_DT_GENERATOR_ID(TableGeneratorId) \
> + ( \
> + IS_GENERATOR_NAMESPACE_STD(TableGeneratorId) && \
> + IS_GENERATOR_TYPE_DT(TableGeneratorId) && \
> + ((GET_TABLE_ID(GeneratorId) >= ESTD_DT_TABLE_ID_RAW) && \
> + (GET_TABLE_ID(GeneratorId) < ESTD_DT_TABLE_ID_MAX)) \
> + )
> +
> +/** This macro creates a standard DT Table Generator ID.
> +
> + @param [in] TableId The table generator ID.
> +
> + @returns a standard DT table generator ID.
> +*/
> +#define CREATE_STD_DT_TABLE_GEN_ID(TableId) \
> + CREATE_TABLE_GEN_ID ( \
> + ETableGeneratorTypeDt, \
> + ETableGeneratorNameSpaceStd, \
> + TableId \
> + )
> +
> +/** Forward declarations.
> +*/
> +typedef struct ConfigurationManagerProtocol
> EFI_CONFIGURATION_MANAGER_PROTOCOL;
> +typedef struct CmAStdObjDtTableInfo CM_STD_OBJ_DT_TABLE_INFO;
> +typedef struct DtTableGenerator DT_TABLE_GENERATOR;
> +
> +/** This function pointer describes the interface to DT table build
> + functions provided by the DT table generator and called by the
> + Table Manager to build an DT table.
> +
> + @param [in] Generator Pointer to the DT table generator.
> + @param [in] DtTableInfo Pointer to the DT table information.
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol interface.
> + @param [out] Table Pointer to the generated DT table.
> +
> + @returns EFI_SUCCESS If the table is generated successfully or other
> + failure codes as returned by the generator.
> +*/
> +typedef EFI_STATUS (*DT_TABLE_GENERATOR_BUILD_TABLE) (
> + IN CONST DT_TABLE_GENERATOR * Generator,
> + IN CONST CM_STD_OBJ_DT_TABLE_INFO * CONST DtTableInfo,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + OUT VOID ** 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 DT table.
> +
> + @param [in] Generator Pointer to the DT table generator.
> + @param [in] DtTableInfo Pointer to the DT table information.
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol interface.
> + @param [in] Table Pointer to the generated DT table.
> +
> + @returns EFI_SUCCESS If freed successfully or other failure codes
> + as returned by the generator.
> +*/
> +typedef EFI_STATUS (*DT_TABLE_GENERATOR_FREE_TABLE) (
> + IN CONST DT_TABLE_GENERATOR * Generator,
> + IN CONST CM_STD_OBJ_DT_TABLE_INFO * CONST DtTableInfo,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN VOID ** Table
> + );
> +
> +/** The DT_TABLE_GENERATOR structure provides an interface that the
> + Table Manager can use to invoke the functions to build DT tables.
> +*/
> +typedef struct DtTableGenerator {
> + /// The DT table generator ID.
> + DT_TABLE_GENERATOR_ID GeneratorID;
> +
> + /// String describing the DT table generator.
> + CONST CHAR16 * Description;
> +
> + /// DT table build function pointer.
> + DT_TABLE_GENERATOR_BUILD_TABLE BuildDtTable;
> +
> + /// The function to free any resources allocated for building the DT table.
> + DT_TABLE_GENERATOR_FREE_TABLE FreeTableResources;
> +} DT_TABLE_GENERATOR;
> +
> +/** Register DT table factory generator.
> +
> + The DT table factory maintains a list of the Standard and OEM DT
> + table generators.
> +
> + @param [in] Generator Pointer to the DT 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
> +RegisterDtTableGenerator (
> + IN CONST DT_TABLE_GENERATOR * CONST Generator
> + );
> +
> +/** Deregister DT generator.
> +
> + This function is called by the DT table generator to deregister itself
> + from the DT table factory.
> +
> + @param [in] Generator Pointer to the DT 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
> +DeregisterDtTableGenerator (
> + IN CONST DT_TABLE_GENERATOR * CONST Generator
> + );
> +
> +#pragma pack()
> +
> +#endif // DEVICETREE_TABLE_GENERATOR_H_
> +
> diff --git a/DynamicTablesPkg/Include/Library/TableHelperLib.h
> b/DynamicTablesPkg/Include/Library/TableHelperLib.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..71efd2e7b94d072feeb
> a39921e19a2460641e1d1
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/Library/TableHelperLib.h
> @@ -0,0 +1,70 @@
> +/** @file
> +
> + Copyright (c) 2017 - 2018, 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_
> +
> +/** A helper macro to align a value to the 32-bit word boundary
> +*/
> +#define ALIGN32(x) ((x) + (sizeof (UINT32) - 1)) & ~(sizeof (UINT32) - 1)
> +
> +/** 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. It
> uses the
> + ACPI table Generator and the Configuration Manager protocol to obtain
> the
> + 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/DynamicTablesPkg/Include/Protocol/ConfigurationManagerProtocol.h
> b/DynamicTablesPkg/Include/Protocol/ConfigurationManagerProtocol.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..15ca0a22aac5129e5b
> 291f1385f058113e186070
> --- /dev/null
> +++
> b/DynamicTablesPkg/Include/Protocol/ConfigurationManagerProtocol.h
> @@ -0,0 +1,128 @@
> +/** @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_
> +
> +#include <ConfigurationManagerObject.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 Pointer to the Configuration Manager Protocol.
> + @param [in] CmObjectId The Configuration Manager Object ID.
> + @param [in] Token An optional token identifying the object. If
> + unused this must be CM_NULL_TOKEN.
> + @param [out] CmObject Pointer to the Configuration Manager Object
> + descriptor describing the requested 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.
> +*/
> +typedef
> +EFI_STATUS
> +(EFIAPI * EFI_CONFIGURATION_MANAGER_GET_OBJECT) (
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST This,
> + IN CONST CM_OBJECT_ID CmObjectId,
> + IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
> + 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 Pointer to the Configuration Manager Protocol.
> + @param [in] CmObjectId The Configuration Manager Object ID.
> + @param [in] Token An optional token identifying the object. If
> + unused this must be CM_NULL_TOKEN.
> + @param [out] CmObject Pointer to the Configuration Manager Object
> + descriptor describing the Object.
> +
> + @retval EFI_SUCCESS The operation completed 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.
> + @retval 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 CONST CM_OBJECT_TOKEN Token OPTIONAL,
> + 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;
> +
> +/** The Configuration Manager Protocol GUID.
> +*/
> +extern EFI_GUID gEfiConfigurationManagerProtocolGuid;
> +
> +#pragma pack()
> +
> +#endif // CONFIGURATION_MANAGER_PROTOCOL_H_
> diff --git
> a/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h
> b/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..8688d0a40900c9dcd9
> 0c76bfb38911ccd6b4add6
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h
> @@ -0,0 +1,140 @@
> +/** @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 DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> +#define DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> +
> +#include <AcpiTableGenerator.h>
> +#include <SmbiosTableGenerator.h>
> +#include <DeviceTreeTableGenerator.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 Pointer 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 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_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 Pointer 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
> + );
> +
> +/** Return a pointer to the Device Tree table generator.
> +
> + @param [in] This Pointer to the Dynamic Table Factory Protocol.
> + @param [in] TableId The Device Tree table generator ID for the
> + requested generator.
> + @param [out] Generator Pointer to the requested Device Tree 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_DT_TABLE_GENERATOR) (
> + IN CONST EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL * CONST This,
> + IN CONST DT_TABLE_GENERATOR_ID GeneratorId,
> + OUT CONST DT_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;
> +
> + /// The interface used to request a Device Tree Table Generator.
> + EFI_DYNAMIC_TABLE_FACTORY_GET_DT_TABLE_GENERATOR
> GetDtTableGenerator;
> +
> + /** Pointer to the data structure that holds the
> + list of registered table generators
> + */
> + EFI_DYNAMIC_TABLE_FACTORY_INFO * TableFactoryInfo;
> +} EFI_DYNAMIC_TABLE_FACTORY_PROTOCOL;
> +
> +/** The Dynamic Table Factory Protocol GUID.
> +*/
> +extern EFI_GUID gEfiDynamicTableFactoryProtocolGuid;
> +
> +#pragma pack()
> +
> +#endif // DYNAMIC_TABLE_FACTORY_PROTOCOL_H_
> diff --git a/DynamicTablesPkg/Include/SmbiosTableGenerator.h
> b/DynamicTablesPkg/Include/SmbiosTableGenerator.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..139d31464db473da9d
> f427e1848835f3d693c41b
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/SmbiosTableGenerator.h
> @@ -0,0 +1,240 @@
> +/** @file
> +
> + Copyright (c) 2017 - 2018, 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_
> +
> +#include <IndustryStandard/SmBios.h>
> +
> +#include <TableGenerator.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
> + );
> +
> +/** Deregister SMBIOS generator.
> +
> + This function is called by the SMBIOS table generator to deregister 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
> +DeregisterSmbiosTableGenerator (
> + IN CONST SMBIOS_TABLE_GENERATOR * CONST Generator
> + );
> +#pragma pack()
> +
> +#endif // SMBIOS_TABLE_GENERATOR_H_
> +
> diff --git a/DynamicTablesPkg/Include/StandardNameSpaceObjects.h
> b/DynamicTablesPkg/Include/StandardNameSpaceObjects.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..bcc9287527da4cdbc3
> 2a929ec6f68773a88a74f6
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/StandardNameSpaceObjects.h
> @@ -0,0 +1,116 @@
> +/** @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 <AcpiTableGenerator.h>
> +#include <SmbiosTableGenerator.h>
> +
> +#pragma pack(1)
> +
> +/** A macro defining a reserved zero/NULL token value that
> + does not identify any object.
> +*/
> +#define CM_NULL_TOKEN 0
> +
> +/** A reference token that the Configuration Manager can use
> + to identify a Configuration Manager object.
> +
> + This can be used to differentiate between instances of
> + objects of the same types. The identification scheme is
> + implementation defined and is defined by the Configuration
> + Manager.
> +
> + Typically the token is used to identify a specific instance
> + from a set of objects in a call to the GetObject()/SetObject(),
> + implemented by the Configuration Manager protocol.
> +
> + Note: The token value 0 is reserved for a NULL token and does
> + not identify any object.
> +*/
> +typedef UINTN CM_OBJECT_TOKEN;
> +
> +/** 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/DynamicTablesPkg/Include/TableGenerator.h
> b/DynamicTablesPkg/Include/TableGenerator.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..171609f1b73736596d
> edff906ef8de275f2c8cca
> --- /dev/null
> +++ b/DynamicTablesPkg/Include/TableGenerator.h
> @@ -0,0 +1,252 @@
> +/** @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)
> +
> +/** Starting bit position for the Table Type bits
> +*/
> +#define TABLE_TYPE_BIT_SHIFT 28
> +
> +/** Starting bit position for the Table Namespace ID bit
> +*/
> +#define TABLE_NAMESPACE_ID_BIT_SHIFT 31
> +
> +/** 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) >>
> TABLE_TYPE_BIT_SHIFT)
> +
> +/** 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) >> \
> + TABLE_NAMESPACE_ID_BIT_SHIFT)
> +
> +/** 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) << TABLE_TYPE_BIT_SHIFT) & TABLE_TYPE_MASK) | \
> + (((TableNameSpaceId) << TABLE_NAMESPACE_ID_BIT_SHIFT) & \
> + TABLE_NAMESPACEID_MASK) | ((TableId) & TABLE_ID_MASK))
> +
> +/** Starting bit position for MAJOR revision
> +*/
> +#define MAJOR_REVISION_BIT_SHIFT 16
> +
> +/** A mask for Major revision.
> +*/
> +#define MAJOR_REVISION_MASK 0xFFFF
> +
> +/** A mask for Minor revision.
> +*/
> +#define MINOR_REVISION_MASK 0xFFFF
> +
> +/** 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) & MAJOR_REVISION_MASK) <<
> MAJOR_REVISION_BIT_SHIFT) | \
> + ((Minor) & MINOR_REVISION_MASK))
> +
> +/** This macro returns the Major revision
> +
> + 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) >> MAJOR_REVISION_BIT_SHIFT) &
> MAJOR_REVISION_MASK)
> +
> +/** This macro returns the Minor revision
> +
> + 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) &
> MINOR_REVISION_MASK)
> +
> +#endif // TABLE_GENERATOR_H_
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.i
> nf
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.i
> nf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..e81ad7018334075758
> 441b1180a6a2d5e8565db3
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.i
> nf
> @@ -0,0 +1,47 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + SerialPortLib
> +
> +[FixedPcd]
> + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
> + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
> + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
> + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
> +
> +[Protocols]
> +
> +[Guids]
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..910b9b68f43b4a9e7d
> 0d8e9a8c879abb172a9678
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
> @@ -0,0 +1,440 @@
> +/** @file
> + DBG2 Table Generator
> +
> + Copyright (c) 2017 - 2018, 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 Reference(s):
> + - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.
> +
> +**/
> +
> +#include <IndustryStandard/DebugPort2Table.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PL011UartLib.h>
> +#include <Protocol/AcpiTable.h>
> +#include <Protocol/SerialIo.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** ARM standard DBG2 Table Generator
> +
> + 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)
> +
> +/** The number of debug ports represented by the Table.
> +*/
> +#define DBG2_NUM_DEBUG_PORTS 1
> +
> +/** The number of Generic Address Registers
> + presented in the debug device information.
> +*/
> +#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1
> +
> +/** The index for the debug port 1 in the Debug port information list.
> +*/
> +#define DBG_PORT_INDEX_PORT1 0
> +
> +/** A string representing the name of the debug port 1.
> +*/
> +#define NAME_STR_PORT1 "COM1"
> +
> +/** The length of the namespace string.
> +*/
> +#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof
> (NAME_STR_PORT1)
> +
> +/** The PL011 UART address range length.
> +*/
> +#define PL011_UART_LENGTH 0x1000
> +
> +/** A structure that provides the OS with the required information
> + 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_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
> +
> + /// The address size
> + UINT32 AddressSize;
> +
> + /// The debug port name string
> + UINT8 NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
> +} DBG2_DEBUG_DEVICE_INFORMATION;
> +
> +/** A structure representing 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 initializing 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_2_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_2_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,
> + 0, // {Template}: Serial Port Subtype
> + 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 Configuration 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;
> +
> + 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,
> + CM_NULL_TOKEN,
> + &SerialPortInfo,
> + NULL
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + if (SerialPortInfo->BaseAddress == 0) {
> + Status = EFI_INVALID_PARAMETER;
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: DBG2: Uart port base address is invalid. BaseAddress =
> 0x%lx\n",
> + SerialPortInfo->BaseAddress
> + ));
> + goto error_handler;
> + }
> +
> + if ((SerialPortInfo->PortSubtype !=
> + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&
> + (SerialPortInfo->PortSubtype !=
> +
> EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X)
> &&
> + (SerialPortInfo->PortSubtype !=
> + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART)
> &&
> + (SerialPortInfo->PortSubtype !=
> + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) {
> + Status = EFI_INVALID_PARAMETER;
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: DBG2: Uart port sybtype is invalid. PortSubtype = 0x%x\n",
> + SerialPortInfo->PortSubtype
> + ));
> + 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;
> + }
> +
> + // Update the base address
> +
> AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.
> Address =
> + SerialPortInfo->BaseAddress;
> +
> + // Update the serial port subtype
> +
> AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].Dbg2Device.PortSubty
> pe =
> + SerialPortInfo->PortSubtype;
> +
> + // Initialize the serial port
> + 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;
> +}
> +
> +/** 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_2_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,
> + // No additional resources are allocated by the generator.
> + // Hence the Free Resource function is not required.
> + NULL
> +};
> +
> +/** 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 = RegisterAcpiTableGenerator (&Dbg2Generator);
> + DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> +
> + return Status;
> +}
> +
> +/** Deregister 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 deregistered.
> + @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 = DeregisterAcpiTableGenerator (&Dbg2Generator);
> + DEBUG ((DEBUG_INFO, "DBG2: Deregister Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.in
> f
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.in
> f
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..db8b04845434fd7d0c
> db5230699b9279914b3900
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.in
> f
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> +
> +[Pcd]
> +
> +[Protocols]
> +
> +[Guids]
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..f33c3ef9a77cd980ff26
> 8a21c933026bdde7ccf7
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c
> @@ -0,0 +1,666 @@
> +/** @file
> + FADT Table Generator
> +
> + Copyright (c) 2017 - 2018, 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 Reference(s):
> + - ACPI 6.2 Specification - Errata A, September 2017
> +
> +**/
> +
> +#include <Library/AcpiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** ARM standard FADT Generator
> +
> +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_2_HW_REDUCED_ACPI | \
> + EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE)
> +
> +/** This macro defines the valid mask for the FADT flag option
> + if HW_REDUCED_ACPI flag in the table is set.
> +
> + Invalid bits are: 1, 2, 3,7, 8, 13, 14,16, 17 and
> + 22-31 (reserved).
> +
> + Valid bits are:
> + EFI_ACPI_6_2_WBINVD BIT0
> + EFI_ACPI_6_2_PWR_BUTTON BIT4
> + EFI_ACPI_6_2_SLP_BUTTON BIT5
> + EFI_ACPI_6_2_FIX_RTC BIT6
> + EFI_ACPI_6_2_DCK_CAP BIT9
> + EFI_ACPI_6_2_RESET_REG_SUP BIT10
> + EFI_ACPI_6_2_SEALED_CASE BIT11
> + EFI_ACPI_6_2_HEADLESS BIT12
> + EFI_ACPI_6_2_USE_PLATFORM_CLOCK BIT15
> + EFI_ACPI_6_2_FORCE_APIC_CLUSTER_MODEL BIT18
> + EFI_ACPI_6_2_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19
> + EFI_ACPI_6_2_HW_REDUCED_ACPI BIT20
> + EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE BIT21
> +*/
> +#define VALID_HARDWARE_REDUCED_FLAG_MASK ( \
> + EFI_ACPI_6_2_WBINVD | \
> + EFI_ACPI_6_2_PWR_BUTTON | \
> + EFI_ACPI_6_2_SLP_BUTTON | \
> + EFI_ACPI_6_2_FIX_RTC | \
> + EFI_ACPI_6_2_DCK_CAP | \
> + EFI_ACPI_6_2_RESET_REG_SUP | \
> + EFI_ACPI_6_2_SEALED_CASE | \
> + EFI_ACPI_6_2_HEADLESS | \
> + EFI_ACPI_6_2_USE_PLATFORM_CLOCK | \
> + EFI_ACPI_6_2_FORCE_APIC_CLUSTER_MODEL | \
> + EFI_ACPI_6_2_FORCE_APIC_PHYSICAL_DESTINATION_MODE | \
> + EFI_ACPI_6_2_HW_REDUCED_ACPI | \
> + EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE)
> +
> +#pragma pack(1)
> +
> +/** The AcpiFadt is a template
> EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE
> + structure used for generating the FADT Table.
> + Note: fields marked with "{Template}" will be updated dynamically.
> +*/
> +STATIC
> +EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = {
> + ACPI_HEADER (
> + EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> + EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE,
> + EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
> + ),
> + // UINT32 FirmwareCtrl
> + 0,
> + // UINT32 Dsdt
> + 0,
> + // UINT8 Reserved0
> + EFI_ACPI_RESERVED_BYTE,
> + // UINT8 PreferredPmProfile
> + EFI_ACPI_6_2_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_2_GENERIC_ADDRESS_STRUCTURE ResetReg
> + NULL_GAS,
> + // UINT8 ResetValue
> + 0,
> + // UINT16 ArmBootArch
> + EFI_ACPI_6_2_ARM_PSCI_COMPLIANT, // {Template}: ARM Boot
> Architecture Flags
> + // UINT8 MinorRevision
> + EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION,
> + // UINT64 XFirmwareCtrl
> + 0,
> + // UINT64 XDsdt
> + 0,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk
> + NULL_GAS,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk
> + NULL_GAS,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk
> + NULL_GAS,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk
> + NULL_GAS,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk
> + NULL_GAS,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk
> + NULL_GAS,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XGpe0Blk
> + NULL_GAS,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XGpe1Blk
> + NULL_GAS,
> + // EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE SleepControlReg
> + NULL_GAS,
> + // EFI_ACPI_6_2_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
> + );
> +
> +/** This macro expands to a function that retrieves the Fixed
> + feature flags for the platform from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjFixedFeatureFlags,
> + CM_ARM_FIXED_FEATURE_FLAGS
> + );
> +
> +/** 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;
> +
> + ASSERT (CfgMgrProtocol != NULL);
> +
> + // Get the Power Management Profile from the Platform Configuration
> Manager
> + Status = GetEArmObjPowerManagementProfileInfo (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &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;
> +
> + ASSERT (CfgMgrProtocol != NULL);
> +
> + // Get the Boot Architecture flags from the Platform Configuration
> Manager
> + Status = GetEArmObjBootArchInfo (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &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;
> +
> + ASSERT (CfgMgrProtocol != NULL);
> +
> + // Get the Hypervisor Vendor ID from the Platform Configuration
> Manager
> + Status = GetEArmObjHypervisorVendorIdentity (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &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;
> +}
> +
> +/** Update the Fixed Feature Flags 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
> +FadtAddFixedFeatureFlags (
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol
> +)
> +{
> + EFI_STATUS Status;
> + CM_ARM_FIXED_FEATURE_FLAGS * FixedFeatureFlags;
> +
> + ASSERT (CfgMgrProtocol != NULL);
> +
> + // Get the Fixed feature flags from the Platform Configuration Manager
> + Status = GetEArmObjFixedFeatureFlags (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &FixedFeatureFlags,
> + NULL
> + );
> + if (EFI_ERROR (Status)) {
> + if (Status == EFI_NOT_FOUND) {
> + DEBUG ((
> + DEBUG_INFO,
> + "INFO: FADT: Platform does not define additional Fixed feature flags."
> + "Status = %r\n",
> + Status
> + ));
> + } else {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: FADT: Failed to get Fixed feature flags. Status = %r\n",
> + Status
> + ));
> + }
> + goto error_handler;
> + }
> +
> + DEBUG ((
> + DEBUG_INFO,
> + "FADT: EArmObjFixedFeatureFlags = 0x%x\n",
> + FixedFeatureFlags->Flags
> + ));
> +
> + if ((FixedFeatureFlags->Flags &
> ~(VALID_HARDWARE_REDUCED_FLAG_MASK)) != 0) {
> + DEBUG ((
> + DEBUG_WARN,
> + "FADT: Invalid Fixed feature flags defined by platform,"
> + "Invalid Flags bits are = 0x%x\n",
> + (FixedFeatureFlags->Flags &
> ~(VALID_HARDWARE_REDUCED_FLAG_MASK))
> + ));
> + }
> +
> + AcpiFadt.Flags |= (FixedFeatureFlags->Flags &
> + VALID_HARDWARE_REDUCED_FLAG_MASK);
> +
> +error_handler:
> + return Status;
> +}
> +
> +/** Construct the FADT table.
> +
> + This function invokes the Configuration 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_2_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;
> + }
> + }
> +
> + Status = FadtAddFixedFeatureFlags (CfgMgrProtocol);
> + if (EFI_ERROR (Status)) {
> + if (Status == EFI_NOT_FOUND) {
> + DEBUG ((
> + DEBUG_INFO,
> + "INFO: FADT: No Fixed feature flags found," \
> + " assuming no additional flags are defined for the platform.\n"
> + ));
> + Status = EFI_SUCCESS;
> + } else {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: FADT: Error reading Fixed feature flags, Status = %r",
> + Status
> + ));
> + goto error_handler;
> + }
> + }
> +
> + *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiFadt;
> +error_handler:
> + return Status;
> +}
> +
> +/** 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_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> + // ACPI Table Revision
> + EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
> + // Creator ID
> + TABLE_GENERATOR_CREATOR_ID_ARM,
> + // Creator Revision
> + FADT_GENERATOR_REVISION,
> + // Build Table function
> + BuildFadtTable,
> + // No additional resources are allocated by the generator.
> + // Hence the Free Resource function is not required.
> + NULL
> +};
> +
> +/** 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 = RegisterAcpiTableGenerator (&FadtGenerator);
> + DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> +
> +/** Deregister 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 deregistered.
> + @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 = DeregisterAcpiTableGenerator (&FadtGenerator);
> + DEBUG ((DEBUG_INFO, "FADT: Deregister Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.in
> f
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.in
> f
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..701cc8b019f564469fc
> 1ec411ed11b367c48ff01
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.in
> f
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> +
> +[FixedPcd]
> +
> +[Protocols]
> +
> +[Guids]
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..3bc34769346eeedb9c
> 75ce76148d187b61b6fac1
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
> @@ -0,0 +1,670 @@
> +/** @file
> + GTDT Table Generator
> +
> + Copyright (c) 2017 - 2018, 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 Reference(s):
> + - ACPI 6.2 Specification - Errata A, September 2017
> +
> +**/
> +
> +#include <Library/AcpiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** ARM standard GTDT Generator
> +
> +Requirements:
> + The following Configuration Manager Object(s) are required by
> + this Generator:
> + - EArmObjGenericTimerInfo
> + - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)
> + - EArmObjPlatformGTBlockInfo (OPTIONAL)
> + - EArmObjGTBlockTimerFrameInfo (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
> + );
> +
> +/** This macro expands to a function that retrieves the Generic
> + Timer Block Timer Frame Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjGTBlockTimerFrameInfo,
> + CM_ARM_GTBLOCK_TIMER_FRAME_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_2_GENERIC_TIMER_DESCRIPTION_TABLE * CONST
> Gtdt,
> + IN CONST UINT32 PlatformTimerCount
> +)
> +{
> + EFI_STATUS Status;
> + CM_ARM_GENERIC_TIMER_INFO * GenericTimerInfo;
> +
> + ASSERT (CfgMgrProtocol != NULL);
> + ASSERT (Gtdt != NULL);
> +
> + Status = GetEArmObjGenericTimerInfo (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &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->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;
> + Gtdt->CntReadBasePhysicalAddress =
> + GenericTimerInfo->CounterReadBaseAddress;
> + Gtdt->PlatformTimerCount = PlatformTimerCount;
> + Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :
> + sizeof (EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE);
> +
> + 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_2_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,
> + IN CONST UINT32 WatchdogOffset,
> + IN CONST CM_ARM_GENERIC_WATCHDOG_INFO *
> WatchdogInfoList,
> + IN UINT32 WatchdogCount
> + )
> +{
> + EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *
> Watchdog;
> +
> + ASSERT (Gtdt != NULL);
> + ASSERT (WatchdogInfoList != NULL);
> +
> + Watchdog =
> (EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *)
> + ((UINT8*)Gtdt + WatchdogOffset);
> +
> + while (WatchdogCount-- != 0) {
> + // Add watchdog entry
> + DEBUG ((DEBUG_INFO, "GTDT: Watchdog = 0x%p\n", Watchdog));
> + Watchdog->Type = EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG;
> + Watchdog->Length =
> + sizeof (EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);
> + Watchdog->Reserved = EFI_ACPI_RESERVED_BYTE;
> + Watchdog->RefreshFramePhysicalAddress =
> + WatchdogInfoList->RefreshFrameAddress;
> + Watchdog->WatchdogControlFramePhysicalAddress =
> + WatchdogInfoList->ControlFrameAddress;
> + Watchdog->WatchdogTimerGSIV = WatchdogInfoList->TimerGSIV;
> + Watchdog->WatchdogTimerFlags = WatchdogInfoList->Flags;
> + Watchdog++;
> + WatchdogInfoList++;
> + } // 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_2_GTDT_GT_BLOCK_TIMER_STRUCTURE *
> GtBlockFrame,
> + IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO *
> GTBlockTimerFrameList,
> + IN UINT32 GTBlockFrameCount
> +)
> +{
> + 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;
> + }
> +
> + while (GTBlockFrameCount-- != 0) {
> + DEBUG ((
> + DEBUG_INFO,
> + "GTDT: GtBlockFrame = 0x%p\n",
> + GtBlockFrame
> + ));
> +
> + GtBlockFrame->GTFrameNumber = GTBlockTimerFrameList-
> >FrameNumber;
> + GtBlockFrame->Reserved[0] = EFI_ACPI_RESERVED_BYTE;
> + GtBlockFrame->Reserved[1] = EFI_ACPI_RESERVED_BYTE;
> + GtBlockFrame->Reserved[2] = EFI_ACPI_RESERVED_BYTE;
> +
> + GtBlockFrame->CntBaseX = GTBlockTimerFrameList-
> >PhysicalAddressCntBase;
> + GtBlockFrame->CntEL0BaseX =
> + GTBlockTimerFrameList->PhysicalAddressCntEL0Base;
> +
> + GtBlockFrame->GTxPhysicalTimerGSIV =
> + GTBlockTimerFrameList->PhysicalTimerGSIV;
> + GtBlockFrame->GTxPhysicalTimerFlags =
> + GTBlockTimerFrameList->PhysicalTimerFlags;
> +
> + GtBlockFrame->GTxVirtualTimerGSIV = GTBlockTimerFrameList-
> >VirtualTimerGSIV;
> + GtBlockFrame->GTxVirtualTimerFlags =
> + GTBlockTimerFrameList->VirtualTimerFlags;
> +
> + GtBlockFrame->GTxCommonFlags = GTBlockTimerFrameList-
> >CommonFlags;
> + GtBlockFrame++;
> + GTBlockTimerFrameList++;
> + } // for
> + return EFI_SUCCESS;
> +}
> +
> +/** Add the GT Block Timers in the GTDT Table.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @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 CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,
> + IN CONST UINT32 GTBlockOffset,
> + IN CONST CM_ARM_GTBLOCK_INFO * GTBlockInfo,
> + IN UINT32 BlockTimerCount
> +)
> +{
> + EFI_STATUS Status;
> + EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE * GTBlock;
> + EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE * GtBlockFrame;
> + CM_ARM_GTBLOCK_TIMER_FRAME_INFO *
> GTBlockTimerFrameList;
> + UINT32 GTBlockTimerFrameCount;
> +
> + ASSERT (Gtdt != NULL);
> + ASSERT (GTBlockInfo != NULL);
> +
> + GTBlock = (EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)Gtdt
> +
> + GTBlockOffset);
> +
> + while (BlockTimerCount-- != 0) {
> + DEBUG ((DEBUG_INFO, "GTDT: GTBlock = 0x%p\n", GTBlock));
> +
> + Status = GetEArmObjGTBlockTimerFrameInfo (
> + CfgMgrProtocol,
> + GTBlockInfo->GTBlockTimerFrameToken,
> + >BlockTimerFrameList,
> + >BlockTimerFrameCount
> + );
> + if (EFI_ERROR (Status) ||
> + (GTBlockTimerFrameCount != GTBlockInfo-
> >GTBlockTimerFrameCount)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: GTDT: Failed to get Generic Timer Frames. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> +
> + GTBlock->Type = EFI_ACPI_6_2_GTDT_GT_BLOCK;
> + GTBlock->Length = sizeof (EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE)
> +
> + (sizeof (EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE)
> *
> + GTBlockInfo->GTBlockTimerFrameCount);
> +
> + GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;
> + GTBlock->CntCtlBase = GTBlockInfo->GTBlockPhysicalAddress;
> + GTBlock->GTBlockTimerCount = GTBlockInfo->GTBlockTimerFrameCount;
> + GTBlock->GTBlockTimerOffset =
> + sizeof (EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE);
> +
> + GtBlockFrame = (EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE*)
> + ((UINT8*)GTBlock + GTBlock->GTBlockTimerOffset);
> +
> + // Add GT Block Timer frames
> + Status = AddGTBlockTimerFrames (
> + GtBlockFrame,
> + GTBlockTimerFrameList,
> + 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_2_GTDT_GT_BLOCK_STRUCTURE
> *)((UINT8*)GTBlock +
> + GTBlock->Length);
> + GTBlockInfo++;
> + }// for
> + return EFI_SUCCESS;
> +}
> +
> +/** Construct the GTDT ACPI table.
> +
> + Called by the Dynamic Table Manager, this function invokes the
> + Configuration 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;
> + UINT32 TableSize;
> + UINT32 PlatformTimerCount = 0;
> + UINT32 WatchdogCount;
> + UINT32 BlockTimerCount;
> + CM_ARM_GENERIC_WATCHDOG_INFO * WatchdogInfoList;
> + CM_ARM_GTBLOCK_INFO * GTBlockInfo;
> + EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE * Gtdt;
> + UINT32 idx;
> + UINT32 GTBlockOffset;
> + UINT32 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,
> + CM_NULL_TOKEN,
> + >BlockInfo,
> + &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,
> + CM_NULL_TOKEN,
> + &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_2_GENERIC_TIMER_DESCRIPTION_TABLE);
> + if (BlockTimerCount != 0) {
> + GTBlockOffset = TableSize;
> + PlatformTimerCount += BlockTimerCount;
> + TableSize += (sizeof (EFI_ACPI_6_2_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_2_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_2_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_2_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 (
> + CfgMgrProtocol,
> + 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, out] 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 OUT 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_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
> + // ACPI Table Revision
> + EFI_ACPI_6_2_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 = RegisterAcpiTableGenerator (&GtdtGenerator);
> + DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> +
> +/** Deregister 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 deregistered.
> + @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 = DeregisterAcpiTableGenerator (&GtdtGenerator);
> + DEBUG ((DEBUG_INFO, "GTDT: Deregister Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm.inf
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..1d77a3bb58cfa9643b
> 4c1b47b83e1ab4e53d26cb
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm.inf
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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 = AcpiIortLibArm
> + FILE_GUID = 25682BA8-B41D-4403-B034-253769E0DAD5
> + VERSION_STRING = 1.0
> + MODULE_TYPE = DXE_DRIVER
> + LIBRARY_CLASS = NULL|DXE_DRIVER
> + CONSTRUCTOR = AcpiIortLibConstructor
> + DESTRUCTOR = AcpiIortLibDestructor
> +
> +[Sources]
> + IortGenerator.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + EmbeddedPkg/EmbeddedPkg.dec
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> +
> +[Pcd]
> +
> +[Protocols]
> +
> +[Guids]
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..cee960fba4e4c19a9c5
> 2f2c38e887741a074e2a9
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c
> @@ -0,0 +1,2046 @@
> +/** @file
> + IORT Table Generator
> +
> + Copyright (c) 2017 - 2018, 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 Reference(s):
> + - IO Remapping Table, Platform Design Document,
> + Document number: ARM DEN 0049C, Issue C, 15 May 2017
> +
> +**/
> +
> +#include <IndustryStandard/IoRemappingTable.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +#include "IortGenerator.h"
> +
> +/** ARM standard IORT Generator
> +
> +Requirements:
> + The following Configuration Manager Object(s) are required by
> + this Generator:
> + - EArmObjItsGroup
> + - EArmObjNamedComponent
> + - EArmObjRootComplex
> + - EArmObjSmmuV1SmmuV2
> + - EArmObjSmmuV3
> + - EArmObjPmcg
> + - EArmObjGicItsIdentifierArray
> + - EArmObjIdMapping
> + - EArmObjGicItsIdentifierArray
> +*/
> +
> +/** This macro expands to a function that retrieves the ITS
> + Group node information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjItsGroup,
> + CM_ARM_ITS_GROUP_NODE
> + );
> +
> +/** This macro expands to a function that retrieves the
> + Named Component node information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjNamedComponent,
> + CM_ARM_NAMED_COMPONENT_NODE
> + );
> +
> +/** This macro expands to a function that retrieves the
> + Root Complex node information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjRootComplex,
> + CM_ARM_ROOT_COMPLEX_NODE
> + );
> +
> +/** This macro expands to a function that retrieves the
> + SMMU v1/v2 node information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjSmmuV1SmmuV2,
> + CM_ARM_SMMUV1_SMMUV2_NODE
> + );
> +
> +/** This macro expands to a function that retrieves the
> + SMMU v3 node information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjSmmuV3,
> + CM_ARM_SMMUV3_NODE
> + );
> +
> +/** This macro expands to a function that retrieves the
> + PMCG node information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjPmcg,
> + CM_ARM_PMCG_NODE
> + );
> +
> +/** This macro expands to a function that retrieves the
> + ITS Identifier Array information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjGicItsIdentifierArray,
> + CM_ARM_ITS_IDENTIFIER
> + );
> +
> +/** This macro expands to a function that retrieves the
> + Id Mapping Array information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjIdMapping,
> + CM_ARM_ID_MAPPING
> + );
> +
> +/** This macro expands to a function that retrieves the
> + SMMU Interrupt Array information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjSmmuInterruptArray,
> + CM_ARM_SMMU_INTERRUPT
> + );
> +
> +/** Returns the size of the ITS Group node.
> +
> + @param [in] Node Pointer to ITS Group node.
> +
> + @retval Size of the ITS Group Node.
> +*/
> +STATIC
> +UINT32
> +GetItsGroupNodeSize (
> + IN CONST CM_ARM_ITS_GROUP_NODE * Node
> + )
> +{
> + ASSERT (Node != NULL);
> +
> + // Size of ITS Group Node
> + UINT32 Size = sizeof (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE);
> +
> + // Size of ITS Identifier array
> + Size += (Node->ItsIdCount * sizeof (UINT32));
> + return Size;
> +}
> +
> +/** Returns the total size required for the ITS Group nodes and
> + updates the Node Indexer.
> +
> + This function calculates the size required for the node group
> + and also populates the Node Indexer array with offsets for the
> + individual nodes.
> +
> + @param [in] NodeStartOffset Offset from the start of the
> + IORT where this node group starts.
> + @param [in] NodeList Pointer to ITS Group node list.
> + @param [in] NodeCount Count of the ITS Group nodes.
> + @param [in, out] NodeIndexer Pointer to the next Node Indexer.
> +
> + @retval Total size of the ITS Group Nodes.
> +*/
> +STATIC
> +UINT32
> +GetSizeofItsGroupNodes (
> + IN CONST UINT32 NodeStartOffset,
> + IN CONST CM_ARM_ITS_GROUP_NODE * NodeList,
> + IN UINT32 NodeCount,
> + IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer
> + )
> +{
> + UINT32 Size = 0;
> +
> + ASSERT (NodeList != NULL);
> +
> + while (NodeCount-- != 0) {
> + (*NodeIndexer)->Token = NodeList->Token;
> + (*NodeIndexer)->Object = (VOID*)NodeList;
> + (*NodeIndexer)->Offset = Size + NodeStartOffset;
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
> + *NodeIndexer,
> + (*NodeIndexer)->Token,
> + (*NodeIndexer)->Object,
> + (*NodeIndexer)->Offset
> + ));
> +
> + Size += GetItsGroupNodeSize (NodeList);
> + (*NodeIndexer)++;
> + NodeList++;
> + }
> + return Size;
> +}
> +
> +/** Returns the size of the Named Component node.
> +
> + @param [in] Node Pointer to Named Component node.
> +
> + @retval Size of the Named Component node.
> +*/
> +STATIC
> +UINT32
> +GetNamedComponentNodeSize (
> + IN CONST CM_ARM_NAMED_COMPONENT_NODE * Node
> + )
> +{
> + ASSERT (Node != NULL);
> +
> + // Size of Named Component node
> + UINT32 Size = sizeof
> (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE);
> +
> + // Size of ID mapping array
> + Size += (Node->IdMappingCount * sizeof
> (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE));
> +
> + /* Size of ASCII string + NULL termination + 'padding to
> + 32-bit word aligned'.
> + */
> + Size += ALIGN32 (AsciiStrLen (Node->ObjectName) + 1);
> + return Size;
> +}
> +
> +/** Returns the total size required for the Named Component nodes and
> + updates the Node Indexer.
> +
> + This function calculates the size required for the node group
> + and also populates the Node Indexer array with offsets for the
> + individual nodes.
> +
> + @param [in] NodeStartOffset Offset from the start of the
> + IORT where this node group starts.
> + @param [in] NodeList Pointer to Named Component node list.
> + @param [in] NodeCount Count of the Named Component nodes.
> + @param [in, out] NodeIndexer Pointer to the next Node Indexer.
> +
> + @retval Total size of the Named Component nodes.
> +*/
> +STATIC
> +UINT32
> +GetSizeofNamedComponentNodes (
> + IN CONST UINT32 NodeStartOffset,
> + IN CONST CM_ARM_NAMED_COMPONENT_NODE * NodeList,
> + IN UINT32 NodeCount,
> + IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer
> + )
> +{
> + UINT32 Size = 0;
> +
> + ASSERT (NodeList != NULL);
> +
> + while (NodeCount-- != 0) {
> + (*NodeIndexer)->Token = NodeList->Token;
> + (*NodeIndexer)->Object = (VOID*)NodeList;
> + (*NodeIndexer)->Offset = Size + NodeStartOffset;
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
> + *NodeIndexer,
> + (*NodeIndexer)->Token,
> + (*NodeIndexer)->Object,
> + (*NodeIndexer)->Offset
> + ));
> +
> + Size += GetNamedComponentNodeSize (NodeList);
> + (*NodeIndexer)++;
> + NodeList++;
> + }
> +
> + return Size;
> +}
> +
> +/** Returns the size of the Root Complex node.
> +
> + @param [in] Node Pointer to Root Complex node.
> +
> + @retval Size of the Root Complex node.
> +*/
> +STATIC
> +UINT32
> +GetRootComplexNodeSize (
> + IN CONST CM_ARM_ROOT_COMPLEX_NODE * Node
> + )
> +{
> + ASSERT (Node != NULL);
> +
> + // Size of Root Complex node
> + UINT32 Size = sizeof (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE);
> +
> + // Size of ID mapping array
> + Size += (Node->IdMappingCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE));
> + return Size;
> +}
> +
> +/** Returns the total size required for the Root Complex nodes and
> + updates the Node Indexer.
> +
> + This function calculates the size required for the node group
> + and also populates the Node Indexer array with offsets for the
> + individual nodes.
> +
> + @param [in] NodeStartOffset Offset from the start of the
> + IORT where this node group starts.
> + @param [in] NodeList Pointer to Root Complex node list.
> + @param [in] NodeCount Count of the Root Complex nodes.
> + @param [in, out] NodeIndexer Pointer to the next Node Indexer.
> +
> + @retval Total size of the Root Complex nodes.
> +*/
> +STATIC
> +UINT32
> +GetSizeofRootComplexNodes (
> + IN CONST UINT32 NodeStartOffset,
> + IN CONST CM_ARM_ROOT_COMPLEX_NODE * NodeList,
> + IN UINT32 NodeCount,
> + IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer
> + )
> +{
> + UINT32 Size = 0;
> +
> + ASSERT (NodeList != NULL);
> +
> + while (NodeCount-- != 0) {
> + (*NodeIndexer)->Token = NodeList->Token;
> + (*NodeIndexer)->Object = (VOID*)NodeList;
> + (*NodeIndexer)->Offset = Size + NodeStartOffset;
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
> + *NodeIndexer,
> + (*NodeIndexer)->Token,
> + (*NodeIndexer)->Object,
> + (*NodeIndexer)->Offset
> + ));
> +
> + Size += GetRootComplexNodeSize (NodeList);
> + (*NodeIndexer)++;
> + NodeList++;
> + }
> +
> + return Size;
> +}
> +
> +/** Returns the size of the SMMUv1/SMMUv2 node.
> +
> + @param [in] Node Pointer to SMMUv1/SMMUv2 node list.
> +
> + @retval Size of the SMMUv1/SMMUv2 node.
> +*/
> +STATIC
> +UINT32
> +GetSmmuV1V2NodeSize (
> + IN CONST CM_ARM_SMMUV1_SMMUV2_NODE * Node
> + )
> +{
> + ASSERT (Node != NULL);
> +
> + // Size of SMMU v1/SMMU v2 node
> + UINT32 Size = sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE);
> +
> + // Size of ID mapping array
> + Size += (Node->IdMappingCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE));
> +
> + // Size of context interrupt array
> + Size += (Node->ContextInterruptCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT));
> +
> + // Size of PMU interrupt array
> + Size += (Node->PmuInterruptCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT));
> + return Size;
> +}
> +
> +/** Returns the total size required for the SMMUv1/SMMUv2 nodes and
> + updates the Node Indexer.
> +
> + This function calculates the size required for the node group
> + and also populates the Node Indexer array with offsets for the
> + individual nodes.
> +
> + @param [in] NodeStartOffset Offset from the start of the
> + IORT where this node group starts.
> + @param [in] NodeList Pointer to SMMUv1/SMMUv2 node list.
> + @param [in] NodeCount Count of the SMMUv1/SMMUv2 nodes.
> + @param [in, out] NodeIndexer Pointer to the next Node Indexer.
> +
> + @retval Total size of the SMMUv1/SMMUv2 nodes.
> +*/
> +STATIC
> +UINT32
> +GetSizeofSmmuV1V2Nodes (
> + IN CONST UINT32 NodeStartOffset,
> + IN CONST CM_ARM_SMMUV1_SMMUV2_NODE * NodeList,
> + IN UINT32 NodeCount,
> + IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer
> + )
> +{
> + UINT32 Size = 0;
> +
> + ASSERT (NodeList != NULL);
> +
> + while (NodeCount-- != 0) {
> + (*NodeIndexer)->Token = NodeList->Token;
> + (*NodeIndexer)->Object = (VOID*)NodeList;
> + (*NodeIndexer)->Offset = Size + NodeStartOffset;
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
> + *NodeIndexer,
> + (*NodeIndexer)->Token,
> + (*NodeIndexer)->Object,
> + (*NodeIndexer)->Offset
> + ));
> +
> + Size += GetSmmuV1V2NodeSize (NodeList);
> + (*NodeIndexer)++;
> + NodeList++;
> + }
> + return Size;
> +}
> +
> +/** Returns the size of the SMMUv3 node.
> +
> + @param [in] Node Pointer to SMMUv3 node list.
> +
> + @retval Total size of the SMMUv3 nodes.
> +*/
> +STATIC
> +UINT32
> +GetSmmuV3NodeSize (
> + IN CONST CM_ARM_SMMUV3_NODE * Node
> + )
> +{
> + ASSERT (Node != NULL);
> +
> + // Size of SMMU v1/SMMU v2 node
> + UINT32 Size = sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE);
> +
> + // Size of ID mapping array
> + Size += (Node->IdMappingCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE));
> + return Size;
> +}
> +
> +/** Returns the total size required for the SMMUv3 nodes and
> + updates the Node Indexer.
> +
> + This function calculates the size required for the node group
> + and also populates the Node Indexer array with offsets for the
> + individual nodes.
> +
> + @param [in] NodeStartOffset Offset from the start of the
> + IORT where this node group starts.
> + @param [in] NodeList Pointer to SMMUv3 node list.
> + @param [in] NodeCount Count of the SMMUv3 nodes.
> + @param [in, out] NodeIndexer Pointer to the next Node Indexer.
> +
> + @retval Total size of the SMMUv3 nodes.
> +*/
> +STATIC
> +UINT32
> +GetSizeofSmmuV3Nodes (
> + IN CONST UINT32 NodeStartOffset,
> + IN CONST CM_ARM_SMMUV3_NODE * NodeList,
> + IN UINT32 NodeCount,
> + IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer
> + )
> +{
> + UINT32 Size = 0;
> +
> + ASSERT (NodeList != NULL);
> +
> + while (NodeCount-- != 0) {
> + (*NodeIndexer)->Token = NodeList->Token;
> + (*NodeIndexer)->Object = (VOID*)NodeList;
> + (*NodeIndexer)->Offset = Size + NodeStartOffset;
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
> + *NodeIndexer,
> + (*NodeIndexer)->Token,
> + (*NodeIndexer)->Object,
> + (*NodeIndexer)->Offset
> + ));
> +
> + Size += GetSmmuV3NodeSize (NodeList);
> + (*NodeIndexer)++;
> + NodeList++;
> + }
> + return Size;
> +}
> +
> +/** Returns the size of the PMCG node.
> +
> + @param [in] Node Pointer to PMCG node.
> +
> + @retval Size of the PMCG node.
> +*/
> +STATIC
> +UINT32
> +GetPmcgNodeSize (
> + IN CONST CM_ARM_PMCG_NODE * Node
> + )
> +{
> + ASSERT (Node != NULL);
> +
> + // Size of PMCG node
> + UINT32 Size = sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE);
> +
> + // Size of ID mapping array
> + Size += (Node->IdMappingCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE));
> + return Size;
> +}
> +
> +/** Returns the total size required for the PMCG nodes and
> + updates the Node Indexer.
> +
> + This function calculates the size required for the node group
> + and also populates the Node Indexer array with offsets for the
> + individual nodes.
> +
> + @param [in] NodeStartOffset Offset from the start of the
> + IORT where this node group starts.
> + @param [in] NodeList Pointer to PMCG node list.
> + @param [in] NodeCount Count of the PMCG nodes.
> + @param [in, out] NodeIndexer Pointer to the next Node Indexer.
> +
> + @retval Total size of the PMCG nodes.
> +*/
> +STATIC
> +UINT32
> +GetSizeofPmcgNodes (
> + IN CONST UINT32 NodeStartOffset,
> + IN CONST CM_ARM_PMCG_NODE * NodeList,
> + IN UINT32 NodeCount,
> + IN OUT IORT_NODE_INDEXER ** CONST NodeIndexer
> + )
> +{
> + UINT32 Size = 0;
> +
> + ASSERT (NodeList != NULL);
> +
> + while (NodeCount-- != 0) {
> + (*NodeIndexer)->Token = NodeList->Token;
> + (*NodeIndexer)->Object = (VOID*)NodeList;
> + (*NodeIndexer)->Offset = Size + NodeStartOffset;
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
> + *NodeIndexer,
> + (*NodeIndexer)->Token,
> + (*NodeIndexer)->Object,
> + (*NodeIndexer)->Offset
> + ));
> +
> + Size += GetPmcgNodeSize (NodeList);
> + (*NodeIndexer)++;
> + NodeList++;
> + }
> + return Size;
> +}
> +
> +/** Returns the offset of the Node referenced by the Token.
> +
> + @param [in] NodeIndexer Pointer to node indexer array.
> + @param [in] NodeCount Count of the nodes.
> + @param [in] Token Reference token for the node.
> + @param [out] NodeOffset Offset of the node from the
> + start of the IORT table.
> +
> + @retval EFI_SUCCESS Success.
> + @retval EFI_NOT_FOUND No matching token reference
> + found in node indexer array.
> +*/
> +STATIC
> +EFI_STATUS
> +GetNodeOffsetReferencedByToken (
> + IN IORT_NODE_INDEXER * NodeIndexer,
> + IN UINT32 NodeCount,
> + IN CM_OBJECT_TOKEN Token,
> + OUT UINT32 * NodeOffset
> + )
> +{
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer: Search Token = %p\n",
> + Token
> + ));
> + while (NodeCount-- != 0) {
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer: NodeIndexer->Token = %p, Offset = %d\n",
> + NodeIndexer->Token,
> + NodeIndexer->Offset
> + ));
> + if (NodeIndexer->Token == Token) {
> + *NodeOffset = NodeIndexer->Offset;
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer: Token = %p, Found\n",
> + Token
> + ));
> + return EFI_SUCCESS;
> + }
> + NodeIndexer++;
> + }
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Node Indexer: Token = %p, Not Found\n",
> + Token
> + ));
> + return EFI_NOT_FOUND;
> +}
> +
> +/** Update the Id Mapping Array.
> +
> + This function retrieves the Id Mapping Array object referenced by the
> + IdMappingToken and updates the IdMapArray.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in] IdMapArray Pointer to an array of Id Mappings.
> + @param [in] IdCount Number of Id Mappings.
> + @param [in] IdMappingToken Reference Token for retrieving the
> + Id Mapping Array object.
> +
> + @retval EFI_SUCCESS Table generated successfully.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The required object was not found.
> +*/
> +STATIC
> +EFI_STATUS
> +AddIdMappingArray (
> + IN CONST ACPI_TABLE_GENERATOR * CONST This,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray,
> + IN UINT32 IdCount,
> + IN CONST CM_OBJECT_TOKEN IdMappingToken
> + )
> +{
> + EFI_STATUS Status;
> + CM_ARM_ID_MAPPING * IdMappings;
> + UINT32 IdMappingCount;
> + ACPI_IORT_GENERATOR * Generator = (ACPI_IORT_GENERATOR*)This;
> +
> + ASSERT (IdMapArray != NULL);
> +
> + // Get the Id Mapping Array
> + Status = GetEArmObjIdMapping (
> + CfgMgrProtocol,
> + IdMappingToken,
> + &IdMappings,
> + &IdMappingCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get Id Mapping array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> +
> + if (IdMappingCount < IdCount) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get the required number of Id Mappings.\n"
> + ));
> + return EFI_NOT_FOUND;
> + }
> +
> + // Populate the Id Mapping array
> + while (IdCount-- != 0) {
> + Status = GetNodeOffsetReferencedByToken (
> + Generator->NodeIndexer,
> + Generator->IortNodeCount,
> + IdMappings->OutputReferenceToken,
> + &IdMapArray->OutputReference
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get Output Reference for ITS Identifier array."
> + "Reference Token = %p"
> + " Status = %r\n",
> + IdMappings->OutputReferenceToken,
> + Status
> + ));
> + return Status;
> + }
> +
> + IdMapArray->InputBase = IdMappings->InputBase;
> + IdMapArray->NumIds = IdMappings->NumIds;
> + IdMapArray->OutputBase = IdMappings->OutputBase;
> + IdMapArray->Flags = IdMappings->Flags;
> +
> + IdMapArray++;
> + IdMappings++;
> + } // Id Mapping array
> +
> + return EFI_SUCCESS;
> +}
> +
> +/** Update the ITS Group Node Information.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in] Iort Pointer to IORT table structure.
> + @param [in] NodesStartOffset Offset for the start of the ITS Group
> + Nodes.
> + @param [in] NodeList Pointer to an array of ITS Group Node
> + Objects.
> + @param [in] NodeCount Number of ITS Group Node Objects.
> +
> + @retval EFI_SUCCESS Table generated successfully.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The required object was not found.
> +*/
> +STATIC
> +EFI_STATUS
> +AddItsGroupNodes (
> + IN CONST ACPI_TABLE_GENERATOR * CONST This,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,
> + IN CONST UINT32 NodesStartOffset,
> + IN CONST CM_ARM_ITS_GROUP_NODE * NodeList,
> + IN UINT32 NodeCount
> + )
> +{
> + EFI_STATUS Status;
> + EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE * ItsGroupNode;
> + UINT32 * ItsIds;
> + CM_ARM_ITS_IDENTIFIER * ItsIdentifier;
> + UINT32 ItsIdentifierCount;
> + UINT32 IdIndex;
> +
> + ASSERT (Iort != NULL);
> +
> + ItsGroupNode =
> (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE*)((UINT8*)Iort +
> + NodesStartOffset);
> +
> + while (NodeCount-- != 0) {
> + // Populate the node header
> + ItsGroupNode->Node.Type = EFI_ACPI_IORT_TYPE_ITS_GROUP;
> + ItsGroupNode->Node.Length = GetItsGroupNodeSize (NodeList);
> + ItsGroupNode->Node.Revision = 0;
> + ItsGroupNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;
> + ItsGroupNode->Node.NumIdMappings = 0;
> + ItsGroupNode->Node.IdReference = 0;
> +
> + // IORT specific data
> + ItsGroupNode->NumItsIdentifiers = NodeList->ItsIdCount;
> + ItsIds = (UINT32*)((UINT8*)ItsGroupNode +
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE));
> +
> + Status = GetEArmObjGicItsIdentifierArray (
> + CfgMgrProtocol,
> + NodeList->ItsIdToken,
> + &ItsIdentifier,
> + &ItsIdentifierCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get ITS Identifier array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> +
> + if (ItsIdentifierCount < ItsGroupNode->NumItsIdentifiers) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get the required number of ITS Identifiers.\n"
> + ));
> + return EFI_NOT_FOUND;
> + }
> +
> + // Populate the ITS identifier array
> + for (IdIndex = 0; IdIndex < ItsGroupNode->NumItsIdentifiers; IdIndex++)
> {
> + ItsIds[IdIndex] = ItsIdentifier[IdIndex].ItsId;
> + } // ITS identifier array
> +
> + // Next IORT Group Node
> + ItsGroupNode =
> (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE*)((UINT8*)ItsGroupNode +
> + ItsGroupNode->Node.Length);
> + NodeList++;
> + } // IORT Group Node
> +
> + return EFI_SUCCESS;
> +}
> +
> +/** Update the Named Component Node Information.
> +
> + This function updates the Named Component node information in the
> IORT
> + table.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in] Iort Pointer to IORT table structure.
> + @param [in] NodesStartOffset Offset for the start of the Named
> + Component Nodes.
> + @param [in] NodeList Pointer to an array of Named Component
> + Node Objects.
> + @param [in] NodeCount Number of Named Component Node
> Objects.
> +
> + @retval EFI_SUCCESS Table generated successfully.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The required object was not found.
> +*/
> +STATIC
> +EFI_STATUS
> +AddNamedComponentNodes (
> + IN CONST ACPI_TABLE_GENERATOR * CONST This,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,
> + IN CONST UINT32 NodesStartOffset,
> + IN CONST CM_ARM_NAMED_COMPONENT_NODE * NodeList,
> + IN UINT32 NodeCount
> + )
> +{
> + EFI_STATUS Status;
> + EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE * NcNode;
> + EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;
> + UINT32 ObjectNameLenght;
> + CHAR8 * ObjectName;
> +
> + ASSERT (Iort != NULL);
> +
> + NcNode =
> (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE*)((UINT8*)Iort +
> + NodesStartOffset);
> +
> + while (NodeCount-- != 0) {
> + // Populate the node header
> + NcNode->Node.Type = EFI_ACPI_IORT_TYPE_NAMED_COMP;
> + NcNode->Node.Length =
> + GetNamedComponentNodeSize (NodeList);
> + NcNode->Node.Revision = 1;
> + NcNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;
> + NcNode->Node.NumIdMappings = NodeList->IdMappingCount;
> +
> + ObjectNameLenght = AsciiStrLen (NodeList->ObjectName) + 1;
> + NcNode->Node.IdReference =
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE) +
> + (ALIGN32 (ObjectNameLenght));
> +
> + // Named Component specific data
> + NcNode->Flags = NodeList->Flags;
> + NcNode->CacheCoherent = NodeList->CacheCoherent;
> + NcNode->AllocationHints = NodeList->AllocationHints;
> + NcNode->Reserved = EFI_ACPI_RESERVED_WORD;
> + NcNode->MemoryAccessFlags = NodeList->MemoryAccessFlags;
> + NcNode->AddressSizeLimit = NodeList->AddressSizeLimit;
> +
> + // Copy the object name
> + ObjectName = (CHAR8*)((UINT8*)NcNode +
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE));
> + Status = AsciiStrCpyS (
> + ObjectName,
> + ObjectNameLenght,
> + NodeList->ObjectName
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to copy Object Name. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> +
> + if ((NodeList->IdMappingCount > 0) &&
> + (NodeList->IdMappingToken != CM_NULL_TOKEN)) {
> + // Ids for Named Component
> + IdMapArray =
> (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)NcNode +
> + NcNode->Node.IdReference);
> +
> + Status = AddIdMappingArray (
> + This,
> + CfgMgrProtocol,
> + IdMapArray,
> + NodeList->IdMappingCount,
> + NodeList->IdMappingToken
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> + }
> +
> + // Next Named Component Node
> + NcNode =
> (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE*)((UINT8*)NcNode
> +
> + NcNode->Node.Length);
> + NodeList++;
> + } // Named Component Node
> +
> + return EFI_SUCCESS;
> +}
> +
> +/** Update the Root Complex Node Information.
> +
> + This function updates the Root Complex node information in the IORT
> table.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in] Iort Pointer to IORT table structure.
> + @param [in] NodesStartOffset Offset for the start of the Root
> Complex
> + Nodes.
> + @param [in] NodeList Pointer to an array of Root Complex Node
> + Objects.
> + @param [in] NodeCount Number of Root Complex Node Objects.
> +
> + @retval EFI_SUCCESS Table generated successfully.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The required object was not found.
> +*/
> +STATIC
> +EFI_STATUS
> +AddRootComplexNodes (
> + IN CONST ACPI_TABLE_GENERATOR * CONST This,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,
> + IN CONST UINT32 NodesStartOffset,
> + IN CONST CM_ARM_ROOT_COMPLEX_NODE * NodeList,
> + IN UINT32 NodeCount
> + )
> +{
> + EFI_STATUS Status;
> + EFI_ACPI_6_0_IO_REMAPPING_RC_NODE * RcNode;
> + EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;
> +
> + ASSERT (Iort != NULL);
> +
> + RcNode = (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE*)((UINT8*)Iort +
> + NodesStartOffset);
> +
> + while (NodeCount-- != 0) {
> + // Populate the node header
> + RcNode->Node.Type = EFI_ACPI_IORT_TYPE_ROOT_COMPLEX;
> + RcNode->Node.Length = GetRootComplexNodeSize (NodeList);
> + RcNode->Node.Revision = 0;
> + RcNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;
> + RcNode->Node.NumIdMappings = NodeList->IdMappingCount;
> + RcNode->Node.IdReference = sizeof
> (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE);
> +
> + // Root Complex specific data
> + RcNode->CacheCoherent = NodeList->CacheCoherent;
> + RcNode->AllocationHints = NodeList->AllocationHints;
> + RcNode->Reserved = EFI_ACPI_RESERVED_WORD;
> + RcNode->MemoryAccessFlags = NodeList->MemoryAccessFlags;
> + RcNode->AtsAttribute = NodeList->AtsAttribute;
> + RcNode->PciSegmentNumber = NodeList->PciSegmentNumber;
> +
> + if ((NodeList->IdMappingCount > 0) &&
> + (NodeList->IdMappingToken != CM_NULL_TOKEN)) {
> + // Ids for Root Complex
> + IdMapArray =
> (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)RcNode +
> + RcNode->Node.IdReference);
> + Status = AddIdMappingArray (
> + This,
> + CfgMgrProtocol,
> + IdMapArray,
> + NodeList->IdMappingCount,
> + NodeList->IdMappingToken
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> + }
> +
> + // Next Root Complex Node
> + RcNode = (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE*)((UINT8*)RcNode
> +
> + RcNode->Node.Length);
> + NodeList++;
> + } // Root Complex Node
> +
> + return EFI_SUCCESS;
> +}
> +
> +/** Update the SMMU Interrupt Array.
> +
> + This function retrieves the InterruptArray object referenced by the
> + InterruptToken and updates the SMMU InterruptArray.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in] InterruptArray Pointer to an array of Interrupts.
> + @param [in] InterruptCount Number of entries in the InterruptArray.
> + @param [in] InterruptToken Reference Token for retrieving the
> SMMU
> + InterruptArray object.
> +
> + @retval EFI_SUCCESS Table generated successfully.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The required object was not found.
> +*/
> +STATIC
> +EFI_STATUS
> +AddSmmuInterrruptArray (
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN OUT EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT *
> InterruptArray,
> + IN UINT32 InterruptCount,
> + IN CONST CM_OBJECT_TOKEN InterruptToken
> + )
> +{
> + EFI_STATUS Status;
> + CM_ARM_SMMU_INTERRUPT * SmmuInterrupt;
> + UINT32 SmmuInterruptCount;
> +
> + ASSERT (InterruptArray != NULL);
> +
> + // Get the SMMU Interrupt Array
> + Status = GetEArmObjSmmuInterruptArray (
> + CfgMgrProtocol,
> + InterruptToken,
> + &SmmuInterrupt,
> + &SmmuInterruptCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get SMMU Interrupt array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> +
> + if (SmmuInterruptCount < InterruptCount) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get the required number of SMMU
> Interrupts.\n"
> + ));
> + return EFI_NOT_FOUND;
> + }
> +
> + // Populate the Id Mapping array
> + while (InterruptCount-- != 0) {
> + InterruptArray->Interrupt = SmmuInterrupt->Interrupt;
> + InterruptArray->InterruptFlags = SmmuInterrupt->Flags;
> + InterruptArray++;
> + SmmuInterrupt++;
> + } // Id Mapping array
> +
> + return EFI_SUCCESS;
> +}
> +
> +/** Update the SMMU v1/v2 Node Information.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in] Iort Pointer to IORT table structure.
> + @param [in] NodesStartOffset Offset for the start of the SMMU v1/v2
> + Nodes.
> + @param [in] NodeList Pointer to an array of SMMU v1/v2 Node
> + Objects.
> + @param [in] NodeCount Number of SMMU v1/v2 Node Objects.
> +
> + @retval EFI_SUCCESS Table generated successfully.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The required object was not found.
> +*/
> +STATIC
> +EFI_STATUS
> +AddSmmuV1V2Nodes (
> + IN CONST ACPI_TABLE_GENERATOR * CONST This,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,
> + IN CONST UINT32 NodesStartOffset,
> + IN CONST CM_ARM_SMMUV1_SMMUV2_NODE * NodeList,
> + IN UINT32 NodeCount
> + )
> +{
> + EFI_STATUS Status;
> + EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE * SmmuNode;
> + EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;
> +
> + EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT * ContextInterruptArray;
> + EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT * PmuInterruptArray;
> +
> + ASSERT (Iort != NULL);
> +
> + SmmuNode =
> (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE*)((UINT8*)Iort +
> + NodesStartOffset);
> +
> + while (NodeCount-- != 0) {
> + // Populate the node header
> + SmmuNode->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv1v2;
> + SmmuNode->Node.Length = GetSmmuV1V2NodeSize (NodeList);
> + SmmuNode->Node.Revision = 0;
> + SmmuNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;
> + SmmuNode->Node.NumIdMappings = NodeList->IdMappingCount;
> + SmmuNode->Node.IdReference = sizeof
> (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE) +
> + (NodeList->ContextInterruptCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT)) +
> + (NodeList->PmuInterruptCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT));
> +
> + // SMMU v1/v2 specific data
> + SmmuNode->Base = NodeList->BaseAddress;
> + SmmuNode->Span = NodeList->Span;
> + SmmuNode->Model = NodeList->Model;
> + SmmuNode->Flags = NodeList->Flags;
> +
> + // Reference to Global Interrupt Array
> + SmmuNode->GlobalInterruptArrayRef =
> + OFFSET_OF (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE,
> SMMU_NSgIrpt);
> +
> + // Context Interrupt
> + SmmuNode->NumContextInterrupts = NodeList-
> >ContextInterruptCount;
> + SmmuNode->ContextInterruptArrayRef =
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE);
> + ContextInterruptArray =
> + (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT*)((UINT8*)SmmuNode +
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE));
> +
> + // PMU Interrupt
> + SmmuNode->NumPmuInterrupts = NodeList->PmuInterruptCount;
> + SmmuNode->PmuInterruptArrayRef = SmmuNode-
> >ContextInterruptArrayRef +
> + (NodeList->ContextInterruptCount *
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT));
> + PmuInterruptArray =
> + (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT*)((UINT8*)SmmuNode +
> + SmmuNode->PmuInterruptArrayRef);
> +
> + SmmuNode->SMMU_NSgIrpt = NodeList->SMMU_NSgIrpt;
> + SmmuNode->SMMU_NSgIrptFlags = NodeList->SMMU_NSgIrptFlags;
> + SmmuNode->SMMU_NSgCfgIrpt = NodeList->SMMU_NSgCfgIrpt;
> + SmmuNode->SMMU_NSgCfgIrptFlags = NodeList-
> >SMMU_NSgCfgIrptFlags;
> +
> + // Add Context Interrupt Array
> + Status = AddSmmuInterrruptArray (
> + CfgMgrProtocol,
> + ContextInterruptArray,
> + SmmuNode->NumContextInterrupts,
> + NodeList->ContextInterruptToken
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to Context Interrupt Array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> +
> + // Add PMU Interrupt Array
> + if ((SmmuNode->NumPmuInterrupts > 0) &&
> + (NodeList->PmuInterruptToken != CM_NULL_TOKEN)) {
> + Status = AddSmmuInterrruptArray (
> + CfgMgrProtocol,
> + PmuInterruptArray,
> + SmmuNode->NumPmuInterrupts,
> + NodeList->PmuInterruptToken
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to PMU Interrupt Array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> + }
> +
> + if ((NodeList->IdMappingCount > 0) &&
> + (NodeList->IdMappingToken != CM_NULL_TOKEN)) {
> + // Ids for SMMU v1/v2 Node
> + IdMapArray =
> (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)SmmuNode +
> + SmmuNode->Node.IdReference);
> + Status = AddIdMappingArray (
> + This,
> + CfgMgrProtocol,
> + IdMapArray,
> + NodeList->IdMappingCount,
> + NodeList->IdMappingToken
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> + }
> + // Next SMMU v1/v2 Node
> + SmmuNode =
> (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE*)((UINT8*)SmmuNode +
> + SmmuNode->Node.Length);
> + NodeList++;
> + } // SMMU v1/v2 Node
> +
> + return EFI_SUCCESS;
> +}
> +
> +/** Update the SMMUv3 Node Information.
> +
> + This function updates the SMMUv3 node information in the IORT table.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in] Iort Pointer to IORT table structure.
> + @param [in] NodesStartOffset Offset for the start of the SMMUv3
> Nodes.
> + @param [in] NodeList Pointer to an array of SMMUv3 Node
> Objects.
> + @param [in] NodeCount Number of SMMUv3 Node Objects.
> +
> + @retval EFI_SUCCESS Table generated successfully.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The required object was not found.
> +*/
> +STATIC
> +EFI_STATUS
> +AddSmmuV3Nodes (
> + IN CONST ACPI_TABLE_GENERATOR * CONST This,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,
> + IN CONST UINT32 NodesStartOffset,
> + IN CONST CM_ARM_SMMUV3_NODE * NodeList,
> + IN UINT32 NodeCount
> + )
> +{
> + EFI_STATUS Status;
> + EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE * SmmuV3Node;
> + EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;
> +
> + ASSERT (Iort != NULL);
> +
> + SmmuV3Node =
> (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE*)((UINT8*)Iort +
> + NodesStartOffset);
> +
> + while (NodeCount-- != 0) {
> + // Populate the node header
> + SmmuV3Node->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv3;
> + SmmuV3Node->Node.Length = GetSmmuV3NodeSize (NodeList);
> + SmmuV3Node->Node.Revision = 1;
> + SmmuV3Node->Node.Reserved = EFI_ACPI_RESERVED_DWORD;
> + SmmuV3Node->Node.NumIdMappings = NodeList->IdMappingCount;
> + SmmuV3Node->Node.IdReference =
> + sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE);
> +
> + // SMMUv3 specific data
> + SmmuV3Node->Base = NodeList->BaseAddress;
> + SmmuV3Node->Flags = NodeList->Flags;
> + SmmuV3Node->Reserved = EFI_ACPI_RESERVED_WORD;
> + SmmuV3Node->VatosAddress = NodeList->VatosAddress;
> + SmmuV3Node->Model = NodeList->Model;
> + SmmuV3Node->Event = NodeList->EventInterrupt;
> + SmmuV3Node->Pri = NodeList->PriInterrupt;
> + SmmuV3Node->Gerr = NodeList->GerrInterrupt;
> + SmmuV3Node->Sync = NodeList->SyncInterrupt;
> +
> + if ((SmmuV3Node->Flags &
> EFI_ACPI_IORT_SMMUv3_FLAG_PROXIMITY_DOMAIN) != 0) {
> + // The Proximity Domain Valid flag is set to 1
> + SmmuV3Node->ProximityDomain = NodeList->ProximityDomain;
> + } else {
> + SmmuV3Node->ProximityDomain = 0;
> + }
> +
> + SmmuV3Node->Reserved1[0] = EFI_ACPI_RESERVED_BYTE;
> + SmmuV3Node->Reserved1[1] = EFI_ACPI_RESERVED_BYTE;
> + SmmuV3Node->Reserved1[2] = EFI_ACPI_RESERVED_BYTE;
> +
> + if ((SmmuV3Node->Event != 0) && (SmmuV3Node->Pri != 0) &&
> + (SmmuV3Node->Gerr != 0) && (SmmuV3Node->Sync != 0)) {
> + // If all the SMMU control interrupts are GSIV based,
> + // the DeviceID mapping index field is ignored.
> + SmmuV3Node->DeviceIdMappingIndex = 0;
> + } else {
> + SmmuV3Node->DeviceIdMappingIndex = NodeList-
> >DeviceIdMappingIndex;
> + }
> +
> + if ((NodeList->IdMappingCount > 0) &&
> + (NodeList->IdMappingToken != CM_NULL_TOKEN)) {
> + // Ids for SMMUv3 node
> + IdMapArray =
> (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)SmmuV3Node +
> + SmmuV3Node->Node.IdReference);
> + Status = AddIdMappingArray (
> + This,
> + CfgMgrProtocol,
> + IdMapArray,
> + NodeList->IdMappingCount,
> + NodeList->IdMappingToken
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> + }
> +
> + // Next SMMUv3 Node
> + SmmuV3Node =
> (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE*)((UINT8*)SmmuV3Node
> +
> + SmmuV3Node->Node.Length);
> + NodeList++;
> + } // SMMUv3 Node
> +
> + return EFI_SUCCESS;
> +}
> +
> +/** Update the PMCG Node Information.
> +
> + This function updates the PMCG node information in the IORT table.
> +
> + @param [in] CfgMgrProtocol Pointer to the Configuration Manager
> + Protocol Interface.
> + @param [in] Iort Pointer to IORT table structure.
> + @param [in] NodesStartOffset Offset for the start of the PMCG Nodes.
> + @param [in] NodeList Pointer to an array of PMCG Node Objects.
> + @param [in] NodeCount Number of PMCG Node Objects.
> +
> + @retval EFI_SUCCESS Table generated successfully.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The required object was not found.
> +*/
> +STATIC
> +EFI_STATUS
> +AddPmcgNodes (
> + IN CONST ACPI_TABLE_GENERATOR * CONST This,
> + IN CONST EFI_CONFIGURATION_MANAGER_PROTOCOL * CONST
> CfgMgrProtocol,
> + IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort,
> + IN CONST UINT32 NodesStartOffset,
> + IN CONST CM_ARM_PMCG_NODE * NodeList,
> + IN UINT32 NodeCount
> + )
> +{
> + EFI_STATUS Status;
> + EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE * PmcgNode;
> + EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE * IdMapArray;
> + ACPI_IORT_GENERATOR * Generator =
> (ACPI_IORT_GENERATOR*)This;
> +
> + ASSERT (Iort != NULL);
> +
> + PmcgNode =
> (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE*)((UINT8*)Iort +
> + NodesStartOffset);
> +
> + while (NodeCount-- != 0) {
> + // Populate the node header
> + PmcgNode->Node.Type = EFI_ACPI_IORT_TYPE_PMCG;
> + PmcgNode->Node.Length = GetPmcgNodeSize (NodeList);
> + PmcgNode->Node.Revision = 0;
> + PmcgNode->Node.Reserved = EFI_ACPI_RESERVED_DWORD;
> + PmcgNode->Node.NumIdMappings = NodeList->IdMappingCount;
> + PmcgNode->Node.IdReference = sizeof
> (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE);
> +
> + // PMCG specific data
> + PmcgNode->Base = NodeList->BaseAddress;
> + PmcgNode->OverflowInterruptGsiv = NodeList->OverflowInterrupt;
> +
> + Status = GetNodeOffsetReferencedByToken (
> + Generator->NodeIndexer,
> + Generator->IortNodeCount,
> + NodeList->ReferenceToken,
> + &PmcgNode->NodeReference
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get Output Reference for PMCG Node."
> + "Reference Token = %p"
> + " Status = %r\n",
> + NodeList->ReferenceToken,
> + Status
> + ));
> + return Status;
> + }
> +
> + if ((NodeList->IdMappingCount > 0) &&
> + (NodeList->IdMappingToken != CM_NULL_TOKEN)) {
> + // Ids for PMCG node
> + IdMapArray =
> (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE*)((UINT8*)PmcgNode +
> + PmcgNode->Node.IdReference);
> +
> + Status = AddIdMappingArray (
> + This,
> + CfgMgrProtocol,
> + IdMapArray,
> + NodeList->IdMappingCount,
> + NodeList->IdMappingToken
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> + }
> +
> + // Next PMCG Node
> + PmcgNode =
> (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE*)((UINT8*)PmcgNode +
> + PmcgNode->Node.Length);
> + NodeList++;
> + } // PMCG Node
> +
> + return EFI_SUCCESS;
> +}
> +
> +/** Construct the IORT ACPI table.
> +
> + This function invokes the Configuration 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
> +BuildIortTable (
> + 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;
> + UINT32 TableSize;
> + UINT32 IortNodeCount;
> +
> + UINT32 ItsGroupNodeCount;
> + UINT32 NamedComponentNodeCount;
> + UINT32 RootComplexNodeCount;
> + UINT32 SmmuV1V2NodeCount;
> + UINT32 SmmuV3NodeCount;
> + UINT32 PmcgNodeCount;
> +
> + UINT32 ItsGroupOffset;
> + UINT32 NamedComponentOffset;
> + UINT32 RootComplexOffset;
> + UINT32 SmmuV1V2Offset;
> + UINT32 SmmuV3Offset;
> + UINT32 PmcgOffset;
> +
> + CM_ARM_ITS_GROUP_NODE * ItsGroupNodeList;
> + CM_ARM_NAMED_COMPONENT_NODE *
> NamedComponentNodeList;
> + CM_ARM_ROOT_COMPLEX_NODE * RootComplexNodeList;
> + CM_ARM_SMMUV1_SMMUV2_NODE * SmmuV1V2NodeList;
> + CM_ARM_SMMUV3_NODE * SmmuV3NodeList;
> + CM_ARM_PMCG_NODE * PmcgNodeList;
> +
> + EFI_ACPI_6_0_IO_REMAPPING_TABLE * Iort;
> + IORT_NODE_INDEXER * NodeIndexer;
> + ACPI_IORT_GENERATOR * Generator;
> +
> + ASSERT (This != NULL);
> + ASSERT (AcpiTableInfo != NULL);
> + ASSERT (CfgMgrProtocol != NULL);
> + ASSERT (Table != NULL);
> + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> + Generator = (ACPI_IORT_GENERATOR*)This;
> + *Table = NULL;
> +
> + // Get the ITS group node info
> + Status = GetEArmObjItsGroup (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &ItsGroupNodeList,
> + &ItsGroupNodeCount
> + );
> + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get ITS Group Node Info. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + // Add the ITS group node count
> + IortNodeCount = ItsGroupNodeCount;
> +
> + // Get the Named component node info
> + Status = GetEArmObjNamedComponent (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &NamedComponentNodeList,
> + &NamedComponentNodeCount
> + );
> + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get Named Component Node Info. Status
> = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + // Add the Named Component group count
> + IortNodeCount += NamedComponentNodeCount;
> +
> + // Get the Root complex node info
> + Status = GetEArmObjRootComplex (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &RootComplexNodeList,
> + &RootComplexNodeCount
> + );
> + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get Root Complex Node Info. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + // Add the Root Complex node count
> + IortNodeCount += RootComplexNodeCount;
> +
> + // Get the SMMU v1/v2 node info
> + Status = GetEArmObjSmmuV1SmmuV2 (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &SmmuV1V2NodeList,
> + &SmmuV1V2NodeCount
> + );
> + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get SMMUv1/SMMUv2 Node Info. Status
> = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + // Add the SMMU v1/v2 node count
> + IortNodeCount += SmmuV1V2NodeCount;
> +
> + // Get the SMMUv3 node info
> + Status = GetEArmObjSmmuV3 (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &SmmuV3NodeList,
> + &SmmuV3NodeCount
> + );
> + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get SMMUv3 Node Info. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + // Add the SMMUv3 node count
> + IortNodeCount += SmmuV3NodeCount;
> +
> + // Get the PMCG node info
> + Status = GetEArmObjPmcg (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &PmcgNodeList,
> + &PmcgNodeCount
> + );
> + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to get PMCG Node Info. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + // Add the PMCG node count
> + IortNodeCount += PmcgNodeCount;
> +
> + // Allocate Node Indexer array
> + NodeIndexer = (IORT_NODE_INDEXER*)AllocateZeroPool (
> + (sizeof (IORT_NODE_INDEXER) *
> + IortNodeCount)
> + );
> + if (NodeIndexer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to allocate memory for Node Indexer" \
> + " Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + DEBUG ((DEBUG_INFO, "INFO: NodeIndexer = %p\n", NodeIndexer));
> + Generator->IortNodeCount = IortNodeCount;
> + Generator->NodeIndexer = NodeIndexer;
> +
> + // Calculate the size of the IORT table
> + TableSize = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE);
> +
> + // ITS Group Nodes
> + if (ItsGroupNodeCount > 0) {
> + ItsGroupOffset = TableSize;
> + // Size of ITS Group node list.
> + TableSize += GetSizeofItsGroupNodes (
> + ItsGroupOffset,
> + ItsGroupNodeList,
> + ItsGroupNodeCount,
> + &NodeIndexer
> + );
> + }
> +
> + // Named Component Nodes
> + if (NamedComponentNodeCount > 0) {
> + NamedComponentOffset = TableSize;
> + // Size of Named Component node list.
> + TableSize += GetSizeofNamedComponentNodes (
> + NamedComponentOffset,
> + NamedComponentNodeList,
> + NamedComponentNodeCount,
> + &NodeIndexer
> + );
> + }
> +
> + // Root Complex Nodes
> + if (RootComplexNodeCount > 0) {
> + RootComplexOffset = TableSize;
> + // Size of Root Complex node list.
> + TableSize += GetSizeofRootComplexNodes (
> + RootComplexOffset,
> + RootComplexNodeList,
> + RootComplexNodeCount,
> + &NodeIndexer
> + );
> + }
> +
> + // SMMUv1/SMMUv2 Nodes
> + if (SmmuV1V2NodeCount > 0) {
> + SmmuV1V2Offset = TableSize;
> + // Size of SMMUv1/SMMUv2 node list.
> + TableSize += GetSizeofSmmuV1V2Nodes (
> + SmmuV1V2Offset,
> + SmmuV1V2NodeList,
> + SmmuV1V2NodeCount,
> + &NodeIndexer
> + );
> + }
> +
> + // SMMUv3 Nodes
> + if (SmmuV3NodeCount > 0) {
> + SmmuV3Offset = TableSize;
> + // Size of SMMUv3 node list.
> + TableSize += GetSizeofSmmuV3Nodes (
> + SmmuV3Offset,
> + SmmuV3NodeList,
> + SmmuV3NodeCount,
> + &NodeIndexer
> + );
> + }
> +
> + // PMCG Nodes
> + if (PmcgNodeCount > 0) {
> + PmcgOffset = TableSize;
> + // Size of PMCG node list.
> + TableSize += GetSizeofPmcgNodes (
> + PmcgOffset,
> + PmcgNodeList,
> + PmcgNodeCount,
> + &NodeIndexer
> + );
> + }
> +
> + DEBUG ((
> + DEBUG_INFO,
> + "INFO: IORT:\n" \
> + " IortNodeCount = %d\n" \
> + " TableSize = %d\n",
> + IortNodeCount,
> + TableSize
> + ));
> +
> + DEBUG ((
> + DEBUG_INFO,
> + " ItsGroupNodeCount = %d\n" \
> + " ItsGroupOffset = %d\n",
> + ItsGroupNodeCount,
> + ItsGroupOffset
> + ));
> +
> + DEBUG ((
> + DEBUG_INFO,
> + " NamedComponentNodeCount = %d\n" \
> + " NamedComponentOffset = %d\n",
> + NamedComponentNodeCount,
> + NamedComponentOffset
> + ));
> +
> + DEBUG ((
> + DEBUG_INFO,
> + " RootComplexNodeCount = %d\n" \
> + " RootComplexOffset = %d\n",
> + RootComplexNodeCount,
> + RootComplexOffset
> + ));
> +
> + DEBUG ((
> + DEBUG_INFO,
> + " SmmuV1V2NodeCount = %d\n" \
> + " SmmuV1V2Offset = %d\n",
> + SmmuV1V2NodeCount,
> + SmmuV1V2Offset
> + ));
> +
> + DEBUG ((
> + DEBUG_INFO,
> + " SmmuV3NodeCount = %d\n" \
> + " SmmuV3Offset = %d\n",
> + SmmuV3NodeCount,
> + SmmuV3Offset
> + ));
> +
> + DEBUG ((
> + DEBUG_INFO,
> + " PmcgNodeCount = %d\n" \
> + " PmcgOffset = %d\n",
> + PmcgNodeCount,
> + PmcgOffset
> + ));
> +
> + // Allocate the Buffer for IORT table
> + *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
> + if (*Table == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to allocate memory for IORT Table, Size = %d," \
> + " Status = %r\n",
> + TableSize,
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + Iort = (EFI_ACPI_6_0_IO_REMAPPING_TABLE*)*Table;
> +
> + DEBUG ((
> + DEBUG_INFO,
> + "IORT: Iort = 0x%p TableSize = 0x%x\n",
> + Iort,
> + TableSize
> + ));
> +
> + Status = AddAcpiHeader (CfgMgrProtocol, This, &Iort->Header, TableSize);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add ACPI header. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + // Update IORT table
> + Iort->NumNodes = IortNodeCount;
> + Iort->NodeOffset = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE);
> + Iort->Reserved = EFI_ACPI_RESERVED_DWORD;
> +
> + if (ItsGroupNodeCount > 0) {
> + Status = AddItsGroupNodes (
> + This,
> + CfgMgrProtocol,
> + Iort,
> + ItsGroupOffset,
> + ItsGroupNodeList,
> + ItsGroupNodeCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add ITS Group Node. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> + }
> +
> + if (NamedComponentNodeCount > 0) {
> + Status = AddNamedComponentNodes (
> + This,
> + CfgMgrProtocol,
> + Iort,
> + NamedComponentOffset,
> + NamedComponentNodeList,
> + NamedComponentNodeCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add Named Component Node. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> + }
> +
> + if (RootComplexNodeCount > 0) {
> + Status = AddRootComplexNodes (
> + This,
> + CfgMgrProtocol,
> + Iort,
> + RootComplexOffset,
> + RootComplexNodeList,
> + RootComplexNodeCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add Root Complex Node. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> + }
> +
> + if (SmmuV1V2NodeCount > 0) {
> + Status = AddSmmuV1V2Nodes (
> + This,
> + CfgMgrProtocol,
> + Iort,
> + SmmuV1V2Offset,
> + SmmuV1V2NodeList,
> + SmmuV1V2NodeCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add SMMU v1/v2 Node. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> + }
> +
> + if (SmmuV3NodeCount > 0) {
> + Status = AddSmmuV3Nodes (
> + This,
> + CfgMgrProtocol,
> + Iort,
> + SmmuV3Offset,
> + SmmuV3NodeList,
> + SmmuV3NodeCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add SMMUv3 Node. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> + }
> +
> + if (PmcgNodeCount > 0) {
> + Status = AddPmcgNodes (
> + This,
> + CfgMgrProtocol,
> + Iort,
> + PmcgOffset,
> + PmcgNodeList,
> + PmcgNodeCount
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: IORT: Failed to add SMMUv3 Node. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> + }
> +
> + return EFI_SUCCESS;
> +
> +error_handler:
> + if (Generator->NodeIndexer != NULL) {
> + FreePool (Generator->NodeIndexer);
> + Generator->NodeIndexer = NULL;
> + }
> +
> + if (*Table != NULL) {
> + FreePool (*Table);
> + *Table = NULL;
> + }
> + return Status;
> +}
> +
> +/** Free any resources allocated for constructing the IORT
> +
> + @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, out] 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
> +FreeIortTableResources (
> + 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 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table
> + )
> +{
> + ACPI_IORT_GENERATOR * Generator;
> + ASSERT (This != NULL);
> + ASSERT (AcpiTableInfo != NULL);
> + ASSERT (CfgMgrProtocol != NULL);
> + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> + Generator = (ACPI_IORT_GENERATOR*)This;
> +
> + // Free any memory allocated by the generator
> + if (Generator->NodeIndexer != NULL) {
> + FreePool (Generator->NodeIndexer);
> + Generator->NodeIndexer = NULL;
> + }
> +
> + if ((Table == NULL) || (*Table == NULL)) {
> + DEBUG ((DEBUG_ERROR, "ERROR: IORT: Invalid Table Pointer\n"));
> + ASSERT ((Table != NULL) && (*Table != NULL));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + FreePool (*Table);
> + *Table = NULL;
> + return EFI_SUCCESS;
> +}
> +
> +/** The IORT Table Generator revision.
> +*/
> +#define IORT_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the MADT Table Generator.
> +*/
> +STATIC
> +ACPI_IORT_GENERATOR IortGenerator = {
> + // ACPI table generator header
> + {
> + // Generator ID
> + CREATE_STD_ACPI_TABLE_GEN_ID (ESTD_ACPI_TABLE_ID_IORT),
> + // Generator Description
> + L"ACPI.STD.IORT.GENERATOR",
> + // ACPI Table Signature
> + EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE,
> + // ACPI Table Revision
> + EFI_ACPI_IO_REMAPPING_TABLE_REVISION,
> + // Creator ID
> + TABLE_GENERATOR_CREATOR_ID_ARM,
> + // Creator Revision
> + IORT_GENERATOR_REVISION,
> + // Build Table function
> + BuildIortTable,
> + // Free Resource function
> + FreeIortTableResources
> + },
> +
> + // IORT Generator private data
> +
> + // Iort Node count
> + 0,
> + // Pointer to Iort node indexer
> + NULL
> +};
> +
> +/** 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
> +AcpiIortLibConstructor (
> + IN CONST EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE * CONST SystemTable
> + )
> +{
> + EFI_STATUS Status = RegisterAcpiTableGenerator
> (&IortGenerator.Header);
> + DEBUG ((DEBUG_INFO, "IORT: Register Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> +
> +/** Deregister 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 deregistered.
> + @retval EFI_INVALID_PARAMETER A parameter is invalid.
> + @retval EFI_NOT_FOUND The Generator is not registered.
> +*/
> +EFI_STATUS
> +EFIAPI
> +AcpiIortLibDestructor (
> + IN CONST EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE * CONST SystemTable
> + )
> +{
> + EFI_STATUS Status = DeregisterAcpiTableGenerator
> (&IortGenerator.Header);
> + DEBUG ((DEBUG_INFO, "Iort: Deregister Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..44c89042e23d50ca73
> 70ee6cae0761e692b78d31
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h
> @@ -0,0 +1,50 @@
> +/** @file
> +
> + Copyright (c) 2018, 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 IORT_GENERATOR_H_
> +#define IORT_GENERATOR_H_
> +
> +#pragma pack(1)
> +
> +/** A structure that describes the Node indexer
> + used for indexing the IORT nodes.
> +*/
> +typedef struct IortNodeIndexer {
> + /// Index token for the Node
> + CM_OBJECT_TOKEN Token;
> + /// Pointer to the node
> + VOID * Object;
> + /// Node offset from the start of the IORT table
> + UINT32 Offset;
> +} IORT_NODE_INDEXER;
> +
> +typedef struct AcpiIortGenerator {
> + /// ACPI Table generator header
> + ACPI_TABLE_GENERATOR Header;
> +
> + // IORT Generator private data
> +
> + /// IORT node count
> + UINT32 IortNodeCount;
> + /// Pointer to the node indexer array
> + IORT_NODE_INDEXER * NodeIndexer;
> +} ACPI_IORT_GENERATOR;
> +
> +#pragma pack()
> +
> +#endif // IORT_GENERATOR_H_
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.
> inf
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.
> inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..03be5a2ab6e8df5029
> d1c823f51ff01a4293f694
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.
> inf
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> +
> +[Pcd]
> +
> +[Protocols]
> +
> +[Guids]
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..a08832aa813a6df0df5
> 1f82741084f81d511b30a
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
> @@ -0,0 +1,717 @@
> +/** @file
> + MADT Table Generator
> +
> + Copyright (c) 2017 - 2018, 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 Reference(s):
> + - ACPI 6.2 Specification - Errata A, September 2017
> +
> +**/
> +
> +#include <Library/AcpiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** ARM standard MADT Generator
> +
> +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 Service 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_2_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_2_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_2_GIC;
> + // UINT8 Length
> + Gicc->Length = sizeof (EFI_ACPI_6_2_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_2_GIC_STRUCTURE * Gicc,
> + IN CONST CM_ARM_GICC_INFO * GicCInfo,
> + IN UINT32 GicCCount
> + )
> +{
> + ASSERT (Gicc != NULL);
> + ASSERT (GicCInfo != NULL);
> +
> + while (GicCCount-- != 0) {
> + 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_2_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_2_GICD;
> + // UINT8 Length
> + Gicd->Length = sizeof (EFI_ACPI_6_2_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 = EFI_ACPI_RESERVED_DWORD;
> + // 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;
> +}
> +
> +/** 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_2_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_2_GIC_MSI_FRAME;
> + GicMsiFrame->Length = sizeof
> (EFI_ACPI_6_2_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_2_GIC_MSI_FRAME_STRUCTURE * GicMsiFrame,
> + IN CONST CM_ARM_GIC_MSI_FRAME_INFO * GicMsiFrameInfo,
> + IN UINT32 GicMsiFrameCount
> +)
> +{
> + ASSERT (GicMsiFrame != NULL);
> + ASSERT (GicMsiFrameInfo != NULL);
> +
> + while (GicMsiFrameCount-- != 0) {
> + 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_2_GICR_STRUCTURE * CONST Gicr,
> + IN CONST CM_ARM_GIC_REDIST_INFO * CONST GicRedisributorInfo
> + )
> +{
> + ASSERT (Gicr != NULL);
> + ASSERT (GicRedisributorInfo != NULL);
> +
> + Gicr->Type = EFI_ACPI_6_2_GICR;
> + Gicr->Length = sizeof (EFI_ACPI_6_2_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_2_GICR_STRUCTURE * Gicr,
> + IN CONST CM_ARM_GIC_REDIST_INFO * GicRInfo,
> + IN UINT32 GicRCount
> +)
> +{
> + ASSERT (Gicr != NULL);
> + ASSERT (GicRInfo != NULL);
> +
> + while (GicRCount-- != 0) {
> + 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_2_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_2_GIC_ITS;
> + GicIts->Length = sizeof (EFI_ACPI_6_2_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_2_GIC_ITS_STRUCTURE * GicIts,
> + IN CONST CM_ARM_GIC_ITS_INFO * GicItsInfo,
> + IN UINT32 GicItsCount
> +)
> +{
> + ASSERT (GicIts != NULL);
> + ASSERT (GicItsInfo != NULL);
> +
> + while (GicItsCount-- != 0) {
> + AddGICInterruptTranslationService (GicIts++, GicItsInfo++);
> + }
> +}
> +
> +/** Construct the MADT ACPI table.
> +
> + This function invokes the Configuration 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;
> + UINT32 TableSize;
> + UINT32 GicCCount;
> + UINT32 GicDCount;
> + UINT32 GicMSICount;
> + UINT32 GicRedistCount;
> + UINT32 GicItsCount;
> + CM_ARM_GICC_INFO * GicCInfo;
> + CM_ARM_GICD_INFO * GicDInfo;
> + CM_ARM_GIC_MSI_FRAME_INFO * GicMSIInfo;
> + CM_ARM_GIC_REDIST_INFO * GicRedistInfo;
> + CM_ARM_GIC_ITS_INFO * GicItsInfo;
> + UINT32 GicCOffset;
> + UINT32 GicDOffset;
> + UINT32 GicMSIOffset;
> + UINT32 GicRedistOffset;
> + UINT32 GicItsOffset;
> +
> + EFI_ACPI_6_2_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,
> + CM_NULL_TOKEN,
> + &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,
> + CM_NULL_TOKEN,
> + &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;
> + }
> +
> + if (GicDCount > 1) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: MADT: One, and only one, GIC distributor must be present."
> + "GicDCount = %d\n",
> + GicDCount
> + ));
> + ASSERT (GicDCount <= 1);
> + Status = EFI_INVALID_PARAMETER;
> + goto error_handler;
> + }
> +
> + Status = GetEArmObjGicMsiFrameInfo (
> + CfgMgrProtocol,
> + CM_NULL_TOKEN,
> + &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,
> + CM_NULL_TOKEN,
> + &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,
> + CM_NULL_TOKEN,
> + &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_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
> +
> + GicCOffset = TableSize;
> + TableSize += (sizeof (EFI_ACPI_6_2_GIC_STRUCTURE) * GicCCount);
> +
> + GicDOffset = TableSize;
> + TableSize += (sizeof (EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE) *
> GicDCount);
> +
> + GicMSIOffset = TableSize;
> + TableSize += (sizeof (EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE) *
> GicMSICount);
> +
> + GicRedistOffset = TableSize;
> + TableSize += (sizeof (EFI_ACPI_6_2_GICR_STRUCTURE) * GicRedistCount);
> +
> + GicItsOffset = TableSize;
> + TableSize += (sizeof (EFI_ACPI_6_2_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_2_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_2_GIC_STRUCTURE*)((UINT8*)Madt + GicCOffset),
> + GicCInfo,
> + GicCCount
> + );
> +
> + AddGICD (
> + (EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE*)((UINT8*)Madt +
> GicDOffset),
> + GicDInfo
> + );
> +
> + if (GicMSICount != 0) {
> + AddGICMsiFrameInfoList (
> + (EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE*)((UINT8*)Madt +
> GicMSIOffset),
> + GicMSIInfo,
> + GicMSICount
> + );
> + }
> +
> + if (GicRedistCount != 0) {
> + AddGICRedistributorList (
> + (EFI_ACPI_6_2_GICR_STRUCTURE*)((UINT8*)Madt + GicRedistOffset),
> + GicRedistInfo,
> + GicRedistCount
> + );
> + }
> +
> + if (GicItsCount != 0) {
> + AddGICItsList (
> + (EFI_ACPI_6_2_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, out] 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 OUT 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_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
> + // ACPI Table Revision
> + EFI_ACPI_6_2_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 = RegisterAcpiTableGenerator (&MadtGenerator);
> + DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> +
> +/** Deregister 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 deregistered.
> + @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 = DeregisterAcpiTableGenerator (&MadtGenerator);
> + DEBUG ((DEBUG_INFO, "MADT: Deregister Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.i
> nf
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.i
> nf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..dfd20dbb86ff1cf9150e
> 8f6a219b2d1008f2116f
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.i
> nf
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> +
> +[Pcd]
> +
> +[Protocols]
> +
> +[Guids]
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..8b95fd3d5c7f97e9cf7c
> cd956fcba56d46fc6cf1
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
> @@ -0,0 +1,342 @@
> +/** @file
> + MCFG Table Generator
> +
> + Copyright (c) 2017 - 2018, 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 Reference(s):
> + - PCI Firmware Specification - Revision 3.2, January 26, 2015.
> +
> +**/
> +
> +#include
> <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** ARM standard MCFG Generator
> +
> +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_HE
> ADER
> + 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 UINT32 PciCfgSpaceOffset,
> + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * PciCfgSpaceInfoList,
> + IN UINT32 PciCfgSpaceCount
> +)
> +{
> + MCFG_CFG_SPACE_ADDR * PciCfgSpace;
> +
> + ASSERT (Mcfg != NULL);
> + ASSERT (PciCfgSpaceInfoList != NULL);
> +
> + PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8*)Mcfg +
> PciCfgSpaceOffset);
> +
> + while (PciCfgSpaceCount-- != 0) {
> + // Add PCI Configuration Space entry
> + PciCfgSpace->BaseAddress = PciCfgSpaceInfoList->BaseAddress;
> + PciCfgSpace->PciSegmentGroupNumber =
> + PciCfgSpaceInfoList->PciSegmentGroupNumber;
> + PciCfgSpace->StartBusNumber = PciCfgSpaceInfoList->StartBusNumber;
> + PciCfgSpace->EndBusNumber = PciCfgSpaceInfoList->EndBusNumber;
> + PciCfgSpace->Reserved = EFI_ACPI_RESERVED_DWORD;
> + PciCfgSpace++;
> + PciCfgSpaceInfoList++;
> + }
> +}
> +
> +/** Construct the MCFG ACPI table.
> +
> + This function invokes the Configuration 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;
> + UINT32 TableSize;
> + UINT32 ConfigurationSpaceCount;
> + CM_ARM_PCI_CONFIG_SPACE_INFO * PciConfigSpaceInfoList;
> + 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,
> + CM_NULL_TOKEN,
> + &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;
> + }
> +
> + if (ConfigurationSpaceCount == 0) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: MCFG: Configuration Space Count = %d\n",
> + ConfigurationSpaceCount
> + ));
> + Status = EFI_INVALID_PARAMETER;
> + ASSERT (ConfigurationSpaceCount != 0);
> + goto error_handler;
> + }
> +
> + 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, out] 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 OUT 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_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE
> _BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> + // ACPI Table Revision
> +
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_RE
> VISION,
> + // 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 = RegisterAcpiTableGenerator (&McfgGenerator);
> + DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> +
> +/** Deregister 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 deregistered.
> + @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 = DeregisterAcpiTableGenerator (&McfgGenerator);
> + DEBUG ((DEBUG_INFO, "MCFG: Deregister Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..cbb53ecef6b5b16405b
> 03bebf28a664259928518
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> +
> +[Pcd]
> +
> +[Protocols]
> +
> +[Guids]
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..974b2993c24ae148ee
> b88342c5e32fa997a31c0e
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c
> @@ -0,0 +1,142 @@
> +/** @file
> + MCFG Table Generator
> +
> + Copyright (c) 2017 - 2018, 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 <Library/AcpiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** Construct the ACPI table using the ACPI table data provided.
> +
> + This function invokes the Configuration 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;
> +}
> +
> +/** 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,
> + // No additional resources are allocated by the generator.
> + // Hence the Free Resource function is not required.
> + NULL
> +};
> +
> +/** 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 = RegisterAcpiTableGenerator (&RawGenerator);
> + DEBUG ((DEBUG_INFO, "RAW: Register Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> +
> +/** Deregister 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 deregistered.
> + @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 = DeregisterAcpiTableGenerator (&RawGenerator);
> + DEBUG ((DEBUG_INFO, "RAW: Deregister Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.in
> f
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..35c17089986f728a55
> 3d73849744e3f904f28b24
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.in
> f
> @@ -0,0 +1,41 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> +
> +[Pcd]
> +
> +[Protocols]
> +
> +[Guids]
> +
> diff --git
> a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..04b64b2c91951d3047
> a01bb5a807a3adb321ca50
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
> @@ -0,0 +1,324 @@
> +/** @file
> + SPCR Table Generator
> +
> + Copyright (c) 2017 - 2018, 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 Reference(s):
> + - Microsoft Serial Port Console Redirection Table
> + Specification - Version 1.03 - August 10, 2015.
> +
> +**/
> +
> +#include <IndustryStandard/DebugPort2Table.h>
> +#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +/** ARM standard SPCR Table Generator
> +
> + 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_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
> + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,
> + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
> + ),
> + 0, // {Template}: Serial Port Subtype
> + {
> + 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_PARIT
> Y,
> + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
> + SPCR_FLOW_CONTROL_NONE,
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_A
> NSI,
> + EFI_ACPI_RESERVED_BYTE,
> + 0xFFFF,
> + 0xFFFF,
> + 0x00,
> + 0x00,
> + 0x00,
> + 0x00000000,
> + 0x00,
> + EFI_ACPI_RESERVED_DWORD
> +};
> +
> +#pragma pack()
> +
> +/** This macro expands to a function that retrieves the Serial
> + Port Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> + EObjNameSpaceArm,
> + EArmObjSerialConsolePortInfo,
> + CM_ARM_SERIAL_PORT_INFO
> + )
> +
> +/** Construct the SPCR ACPI table.
> +
> + This function invokes the Configuration 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
> + Configuration 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;
> +
> + 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,
> + CM_NULL_TOKEN,
> + &SerialPortInfo,
> + NULL
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
> + Status
> + ));
> + goto error_handler;
> + }
> +
> + if (SerialPortInfo->BaseAddress == 0) {
> + Status = EFI_INVALID_PARAMETER;
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: SPCR: Uart port base address is invalid. BaseAddress =
> 0x%lx\n",
> + SerialPortInfo->BaseAddress
> + ));
> + goto error_handler;
> + }
> +
> + if ((SerialPortInfo->PortSubtype !=
> + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&
> + (SerialPortInfo->PortSubtype !=
> +
> EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X)
> &&
> + (SerialPortInfo->PortSubtype !=
> + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART)
> &&
> + (SerialPortInfo->PortSubtype !=
> + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) {
> + Status = EFI_INVALID_PARAMETER;
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: SPCR: Uart port sybtype is invalid. PortSubtype = 0x%x\n",
> + SerialPortInfo->PortSubtype
> + ));
> + 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;
> + }
> +
> + // Update the serial port subtype
> + AcpiSpcr.InterfaceType = SerialPortInfo->PortSubtype;
> +
> + // Update the base address
> + AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
> +
> + // Update the UART interrupt
> + 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_1920
> 0;
> + break;
> + case 57600:
> + AcpiSpcr.BaudRate =
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_5760
> 0;
> + break;
> + case 115200:
> + AcpiSpcr.BaudRate =
> +
> EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_1152
> 00;
> + 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;
> +}
> +
> +/** 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_2_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,
> + // No additional resources are allocated by the generator.
> + // Hence the Free Resource function is not required.
> + NULL
> +};
> +
> +/** 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 = RegisterAcpiTableGenerator (&SpcrGenerator);
> + DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> +
> +/** Deregister 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 deregistered.
> + @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 = DeregisterAcpiTableGenerator (&SpcrGenerator);
> + DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n",
> Status));
> + ASSERT_EFI_ERROR (Status);
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
> b/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..16bce37e4c0cb2666e
> 8f2d0895c4fa55f350f2f1
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
> @@ -0,0 +1,164 @@
> +/** @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>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.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),
> + CM_NULL_TOKEN,
> + &CmObjectDesc
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: Failed to Get Configuration Manager Info. Status = %r\n",
> + Status
> + ));
> + return Status;
> + }
> +
> + if (CmObjectDesc.Size < sizeof
> (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "ERROR: EStdObjCfgMgrInfo: Buffer too small, size = 0x%x\n",
> + CmObjectDesc.Size
> + ));
> + ASSERT (
> + CmObjectDesc.Size >= sizeof
> (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO)
> + );
> + 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;
> + 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;
> +
> +error_handler:
> + return Status;
> +}
> diff --git
> a/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
> b/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..5faadd198f053d3f628
> 1019aff97466932917b8d
> --- /dev/null
> +++
> b/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +#
> +# Copyright (c) 2017 - 2018, 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
> + DynamicTablesPkg/DynamicTablesPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> +
> +[Protocols]
> +
> +[Guids]
> +
> --
> 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
>
next prev parent reply other threads:[~2018-03-19 16:10 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-19 15:18 [staging/dynamictables PATCH 0/2] Dynamic Tables Framework core Sami Mujawar
2018-03-19 15:18 ` [staging/dynamictables PATCH 1/2] MdePkg: SMMUv3 updates for IORT table definitions Sami Mujawar
2018-03-19 15:21 ` Ard Biesheuvel
2018-03-19 15:27 ` Sami Mujawar
2018-03-19 16:16 ` Evan Lloyd
2018-03-19 15:18 ` [staging/dynamictables PATCH 2/2] DynamicTablesPkg: Dynamic Tables Framework Sami Mujawar
2018-03-19 16:16 ` Evan Lloyd [this message]
2018-03-20 22:07 ` [staging/dynamictables PATCH 0/2] Dynamic Tables Framework core Desimone, Nathaniel L
2018-03-21 13:23 ` Evan Lloyd
2018-03-23 23:46 ` Desimone, Nathaniel L
2018-03-21 2:56 ` Leif Lindholm
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=HE1PR0801MB17717C3E7021546A0FE652248BD40@HE1PR0801MB1771.eurprd08.prod.outlook.com \
--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