public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v1 0/7] Create a SSDT PCIe generator
@ 2021-06-23 11:58 PierreGondois
  2021-06-23 11:58 ` [PATCH v1 1/7] DynamicTablesPkg: AML Code generation for memory ranges PierreGondois
                   ` (6 more replies)
  0 siblings, 7 replies; 15+ messages in thread
From: PierreGondois @ 2021-06-23 11:58 UTC (permalink / raw)
  To: devel, Sami Mujawar, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei

From: Pierre Gondois <Pierre.Gondois@arm.com>

As part of the DynamicTablesPkg, add a generator creating a
SSDT table describing a PCIe bus.
This patch-set also adds new functions to generate AML bytecode
in the AmlLib.

The changes can be seen at: https://github.com/PierreARM/edk2/tree/1781_Create_ssdt_pcie_generator_v1
The results of the CI can be seen at: https://github.com/tianocore/edk2/pull/1747

This patch-set is dependent over the following patch-sets:
  [PATCH v1 00/10] Various DynamicTablesPkg modifications 
  https://edk2.groups.io/g/devel/message/76929
and:
  [PATCH v1 00/13] Create a SSDT CPU topology generator 
  https://edk2.groups.io/g/devel/message/76941

Pierre Gondois (7):
  DynamicTablesPkg: AML Code generation for memory ranges
  DynamicTablesPkg: AML Code generation to create a named Package()
  DynamicTablesPkg: AML Code generation to create a named
    ResourceTemplate()
  DynamicTablesPkg: AML Code generation to add _PRT entries
  DynamicTablesPkg: Add AmlAttachNode()
  DynamicTablesPkg: Add Pci related objects
  DynamicTablesPkg: SSDT Pci express generator

 DynamicTablesPkg/DynamicTables.dsc.inc        |    2 +
 DynamicTablesPkg/Include/AcpiTableGenerator.h |    5 +
 .../Include/ArmNameSpaceObjects.h             |   78 +
 .../Include/Library/AmlLib/AmlLib.h           |  430 +++++
 .../AcpiSsdtPcieLibArm/SsdtPcieGenerator.c    | 1417 +++++++++++++++++
 .../AcpiSsdtPcieLibArm/SsdtPcieGenerator.h    |  134 ++
 .../Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf |   32 +
 .../SsdtPcieOscTemplate.asl                   |   80 +
 .../Library/Common/AmlLib/Api/AmlApi.c        |   36 +
 .../Common/AmlLib/CodeGen/AmlCodeGen.c        |  320 ++++
 .../AmlLib/CodeGen/AmlResourceDataCodeGen.c   |  945 +++++++++++
 .../ConfigurationManagerObjectParser.c        |   28 +-
 12 files changed, 3506 insertions(+), 1 deletion(-)
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl

-- 
2.17.1


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

* [PATCH v1 1/7] DynamicTablesPkg: AML Code generation for memory ranges
  2021-06-23 11:58 [PATCH v1 0/7] Create a SSDT PCIe generator PierreGondois
@ 2021-06-23 11:58 ` PierreGondois
  2021-10-06 15:14   ` Sami Mujawar
  2021-06-23 11:58 ` [PATCH v1 2/7] DynamicTablesPkg: AML Code generation to create a named Package() PierreGondois
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: PierreGondois @ 2021-06-23 11:58 UTC (permalink / raw)
  To: devel, Sami Mujawar, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei

From: Pierre Gondois <Pierre.Gondois@arm.com>

Add helper functions to generate AML Resource Data describing memory
ranges. Memory ranges can be one, double or four words long. They
can be of 'normal', IO or bus number memory type. The following
APIs are exposed:
 - AmlCodeGenRdDWordIo ()
 - AmlCodeGenRdDWordMemory ()
 - AmlCodeGenRdWordBusNumber ()
 - AmlCodeGenRdQWordMemory ()

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../Include/Library/AmlLib/AmlLib.h           | 289 ++++++
 .../AmlLib/CodeGen/AmlResourceDataCodeGen.c   | 945 ++++++++++++++++++
 2 files changed, 1234 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 4932f6fd9c8b..cbbbb7a478f7 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -418,6 +418,295 @@ AmlUpdateRdQWord (
   IN  UINT64                BaseAddressLength
   );
 
+/** Code generation for the "DWordIO ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.2 "DWord Address Space Descriptor".
+   - s19.6.34 "DWordIO".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @ingroup CodeGenApis
+
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsaRanges            Available values are:
+                                     0-Reserved
+                                     1-NonISAOnly
+                                     2-ISAOnly
+                                     3-EntireRange
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.34 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.34 for more.
+                                    Not supported.
+  @param [in]  IsDenseTranslation   TranslationDensity parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsTypeStatic         TranslationType parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordIo (
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        UINT8                   IsaRanges,
+  IN        UINT32                  AddressGranularity,
+  IN        UINT32                  AddressMinimum,
+  IN        UINT32                  AddressMaximum,
+  IN        UINT32                  AddressTranslation,
+  IN        UINT32                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        BOOLEAN                 IsDenseTranslation,
+  IN        BOOLEAN                 IsTypeStatic,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  );
+
+/** Code generation for the "DWordMemory ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.2 "DWord Address Space Descriptor".
+   - s19.6.35 "DWordMemory".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @ingroup CodeGenApis
+
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  Cacheable            Available values are:
+                                    0-The memory is non-cacheable
+                                    1-The memory is cacheable
+                                    2-The memory is cacheable and supports
+                                      write combining
+                                    3-The memory is cacheable and prefetchable
+  @param [in]  IsReadWrite          ReadAndWrite parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.35 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.35 for more.
+                                    Not supported.
+  @param [in]  MemoryRangeType      Available values are:
+                                      0-AddressRangeMemory
+                                      1-AddressRangeReserved
+                                      2-AddressRangeACPI
+                                      3-AddressRangeNVS
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsTypeStatic         TranslationType parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordMemory (
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        UINT8                   Cacheable,
+  IN        BOOLEAN                 IsReadWrite,
+  IN        UINT32                  AddressGranularity,
+  IN        UINT32                  AddressMinimum,
+  IN        UINT32                  AddressMaximum,
+  IN        UINT32                  AddressTranslation,
+  IN        UINT32                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        UINT8                   MemoryRangeType,
+  IN        BOOLEAN                 IsTypeStatic,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  );
+
+/** Code generation for the "WordBusNumber ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.3 "Word Address Space Descriptor".
+   - s19.6.149 "WordBusNumber".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @ingroup CodeGenApis
+
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.149 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.149 for more.
+                                    Not supported.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdWordBusNumber (
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        UINT32                  AddressGranularity,
+  IN        UINT32                  AddressMinimum,
+  IN        UINT32                  AddressMaximum,
+  IN        UINT32                  AddressTranslation,
+  IN        UINT32                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  );
+
+/** Code generation for the "QWordMemory ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.1 "QWord Address Space Descriptor".
+   - s19.6.110 "QWordMemory".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @ingroup CodeGenApis
+
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  Cacheable            Available values are:
+                                    0-The memory is non-cacheable
+                                    1-The memory is cacheable
+                                    2-The memory is cacheable and supports
+                                      write combining
+                                    3-The memory is cacheable and prefetchable
+  @param [in]  IsReadWrite          ReadAndWrite parameter,
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.110 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.110 for more.
+                                    Not supported.
+  @param [in]  MemoryRangeType      Available values are:
+                                      0-AddressRangeMemory
+                                      1-AddressRangeReserved
+                                      2-AddressRangeACPI
+                                      3-AddressRangeNVS
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  IsTypeStatic         TranslationType parameter,
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdQWordMemory (
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        UINT8                   Cacheable,
+  IN        BOOLEAN                 IsReadWrite,
+  IN        UINT64                  AddressGranularity,
+  IN        UINT64                  AddressMinimum,
+  IN        UINT64                  AddressMaximum,
+  IN        UINT64                  AddressTranslation,
+  IN        UINT64                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        UINT8                   MemoryRangeType,
+  IN        BOOLEAN                 IsTypeStatic,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  );
+
 /** Code generation for the "Interrupt ()" ASL function.
 
   The Resource Data effectively created is an Extended Interrupt Resource
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
index 78910cc5d4b4..3ab78d4fce22 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
@@ -94,6 +94,951 @@ error_handler:
   return Status;
 }
 
+/** Populate the TypeSpecificFlags field for IO ranges.
+
+  @param [in]  IsaRanges            Available values are:
+                                     0-Reserved
+                                     1-NonISAOnly
+                                     2-ISAOnly
+                                     3-EntireRange
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsDenseTranslation   TranslationDensity parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsTypeStatic         TranslationType parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+
+  @return A TypeSpecificFlagsvalue.
+          MAX_UINT8 if error.
+**/
+STATIC
+UINT8
+EFIAPI
+RdIoRangeSpecificFlags (
+  IN  UINT8     IsaRanges,
+  IN  BOOLEAN   IsDenseTranslation,
+  IN  BOOLEAN   IsTypeStatic
+  )
+{
+  // Only check type specific parameters.
+  if (IsaRanges > 3) {
+    ASSERT (0);
+    return MAX_UINT8;
+  }
+
+  // Populate TypeSpecificFlags and call the generic function.
+  // Cf ACPI 6.4 specification, Table 6.50:
+  // "Table 6.50: I/O Resource Flag (Resource Type = 1) Definitions"
+  return  IsaRanges                 |
+          (IsTypeStatic ? 0 : BIT4) |
+          (IsDenseTranslation ? 0 : BIT5);
+}
+
+/** Populate the TypeSpecificFlags field for Memory ranges.
+
+  @param [in]  Cacheable            Available values are:
+                                    0-The memory is non-cacheable
+                                    1-The memory is cacheable
+                                    2-The memory is cacheable and supports
+                                      write combining
+                                    3-The memory is cacheable and prefetchable
+  @param [in]  IsReadWrite          ReadAndWrite parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  MemoryRangeType      Available values are:
+                                      0-AddressRangeMemory
+                                      1-AddressRangeReserved
+                                      2-AddressRangeACPI
+                                      3-AddressRangeNVS
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsTypeStatic         TranslationType parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+
+  @return A TypeSpecificFlagsvalue.
+          MAX_UINT8 if error.
+**/
+STATIC
+UINT8
+EFIAPI
+MemoryRangeSpecificFlags (
+  IN  UINT8     Cacheable,
+  IN  BOOLEAN   IsReadWrite,
+  IN  UINT8     MemoryRangeType,
+  IN  BOOLEAN   IsTypeStatic
+  )
+{
+  // Only check type specific parameters.
+  if ((Cacheable > 3) ||
+      (MemoryRangeType > 3)) {
+    ASSERT (0);
+    return MAX_UINT8;
+  }
+
+  // Populate TypeSpecificFlags and call the generic function.
+  // Cf ACPI 6.4 specification, Table 6.49:
+  // "Memory Resource Flag (Resource Type = 0) Definitions"
+  return (IsReadWrite ? BIT0 : 0)  |
+         (Cacheable << 1)          |
+         (MemoryRangeType << 3)    |
+         (IsTypeStatic ? 0 : BIT5);
+}
+
+/** Populate the GeneralFlags field of any Address Space Resource Descriptors.
+
+  E.g.:
+  ACPI 6.4 specification, s6.4.3.5.1 "QWord Address Space Descriptor"
+  for QWord
+
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.36 for more.
+
+  @return A TypeSpecificFlagsvalue.
+**/
+STATIC
+UINT8
+EFIAPI
+AddressSpaceGeneralFlags (
+  IN  BOOLEAN   IsPosDecode,
+  IN  BOOLEAN   IsMinFixed,
+  IN  BOOLEAN   IsMaxFixed
+  )
+{
+  return (IsPosDecode ? 0 : BIT1)    |
+         (IsMinFixed ? BIT2 : 0)     |
+         (IsMaxFixed ? BIT3 : 0);
+}
+
+/** Check Address Space Descriptor Fields.
+
+  Cf. ACPI 6.4 Table 6.44:
+  "Valid Combination of Address Space Descriptor Fields"
+
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.36 for more.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CheckAddressSpaceFields (
+  IN  BOOLEAN   IsMinFixed,
+  IN  BOOLEAN   IsMaxFixed,
+  IN  UINT64    AddressGranularity,
+  IN  UINT64    AddressMinimum,
+  IN  UINT64    AddressMaximum,
+  IN  UINT64    AddressTranslation,
+  IN  UINT64    RangeLength
+  )
+{
+  if ((AddressMinimum > AddressMaximum)                     ||
+      (RangeLength > (AddressMaximum - AddressMinimum + 1)) ||
+      ((AddressGranularity != 0) &&
+       ((AddressGranularity + 1) & AddressGranularity) != 0)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (RangeLength != 0) {
+    if (IsMinFixed ^ IsMaxFixed) {
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    } else if (IsMinFixed                 &&
+               IsMaxFixed                 &&
+               (AddressGranularity != 0)  &&
+               ((AddressMaximum - AddressMinimum + 1) != RangeLength)) {
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    }
+  } else {
+    if (IsMinFixed && IsMaxFixed) {
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    } else if (IsMinFixed &&
+              ((AddressMinimum & AddressGranularity) != 0)) {
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    } else if (IsMaxFixed &&
+              (((AddressMaximum + 1) & AddressGranularity) != 0)) {
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Code generation for the "DWordSpace ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.2 "DWord Address Space Descriptor".
+   - s19.6.36 "DWordSpace".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @param [in]  ResourceType         See ACPI 6.4 spec, s6.4.3.5.2 for more.
+                                    Available values are:
+                                      0:        Memory range
+                                      1:        I/O range
+                                      2:        Bus number range
+                                      3-191:    Reserved
+                                      192-255:  Hardware Vendor Defined
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  TypeSpecificFlags    See ACPI 6.4 spec, s6.4.3.5.5
+                                    "Resource Type Specific Flags".
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.36 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.36 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.36 for more.
+                                    Not supported.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordSpace (
+  IN        UINT8                   ResourceType,
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        UINT8                   TypeSpecificFlags,
+  IN        UINT32                  AddressGranularity,
+  IN        UINT32                  AddressMinimum,
+  IN        UINT32                  AddressMaximum,
+  IN        UINT32                  AddressTranslation,
+  IN        UINT32                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  )
+{
+  EFI_STATUS                                Status;
+  AML_DATA_NODE                           * RdNode;
+  EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR   RdDWord;
+
+  // ResourceSource and ResourceSourceIndex are not supported.
+  if ((TypeSpecificFlags == MAX_UINT8)  ||
+      (ResourceSourceIndex != 0)        ||
+      (ResourceSource != NULL)          ||
+      ((NameOpNode == NULL) && (NewRdNode == NULL))) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = CheckAddressSpaceFields (
+             IsMinFixed,
+             IsMaxFixed,
+             AddressGranularity,
+             AddressMinimum,
+             AddressMaximum,
+             AddressTranslation,
+             RangeLength
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Header
+  RdDWord.Header.Header.Bits.Name =
+    ACPI_LARGE_DWORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
+  RdDWord.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
+  RdDWord.Header.Length = sizeof (EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR) -
+                               sizeof (ACPI_LARGE_RESOURCE_HEADER);
+
+  // Body
+  RdDWord.ResType = ResourceType;
+  RdDWord.GenFlag = AddressSpaceGeneralFlags (
+                      IsPosDecode,
+                      IsMinFixed,
+                      IsMaxFixed
+                      );
+  RdDWord.SpecificFlag = TypeSpecificFlags;
+  RdDWord.AddrSpaceGranularity = AddressGranularity;
+  RdDWord.AddrRangeMin = AddressMinimum;
+  RdDWord.AddrRangeMax = AddressMaximum;
+  RdDWord.AddrTranslationOffset = AddressTranslation;
+  RdDWord.AddrLen = RangeLength;
+
+  Status = AmlCreateDataNode (
+             EAmlNodeDataTypeResourceData,
+             (UINT8*)&RdDWord,
+             sizeof (EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR),
+             &RdNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  return LinkRdNode (RdNode, NameOpNode, NewRdNode);
+}
+
+/** Code generation for the "DWordIO ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.2 "DWord Address Space Descriptor".
+   - s19.6.34 "DWordIO".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsaRanges            Available values are:
+                                     0-Reserved
+                                     1-NonISAOnly
+                                     2-ISAOnly
+                                     3-EntireRange
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.34 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.34 for more.
+                                    Not supported.
+  @param [in]  IsDenseTranslation   TranslationDensity parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  IsTypeStatic         TranslationType parameter,
+                                    See ACPI 6.4 spec, s19.6.34 for more.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordIo (
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        UINT8                   IsaRanges,
+  IN        UINT32                  AddressGranularity,
+  IN        UINT32                  AddressMinimum,
+  IN        UINT32                  AddressMaximum,
+  IN        UINT32                  AddressTranslation,
+  IN        UINT32                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        BOOLEAN                 IsDenseTranslation,
+  IN        BOOLEAN                 IsTypeStatic,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  )
+{
+  return AmlCodeGenRdDWordSpace (
+           ACPI_ADDRESS_SPACE_TYPE_IO,
+           IsResourceConsumer,
+           IsPosDecode,
+           IsMinFixed,
+           IsMaxFixed,
+           RdIoRangeSpecificFlags (
+             IsaRanges,
+             IsDenseTranslation,
+             IsTypeStatic
+             ),
+           AddressGranularity,
+           AddressMinimum,
+           AddressMaximum,
+           AddressTranslation,
+           RangeLength,
+           ResourceSourceIndex,
+           ResourceSource,
+           NameOpNode,
+           NewRdNode
+           );
+}
+
+/** Code generation for the "DWordMemory ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.2 "DWord Address Space Descriptor".
+   - s19.6.35 "DWordMemory".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  Cacheable            Available values are:
+                                    0-The memory is non-cacheable
+                                    1-The memory is cacheable
+                                    2-The memory is cacheable and supports
+                                      write combining
+                                    3-The memory is cacheable and prefetchable
+  @param [in]  IsReadWrite          ReadAndWrite parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.35 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.35 for more.
+                                    Not supported.
+  @param [in]  MemoryRangeType      Available values are:
+                                      0-AddressRangeMemory
+                                      1-AddressRangeReserved
+                                      2-AddressRangeACPI
+                                      3-AddressRangeNVS
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  IsTypeStatic         TranslationType parameter,
+                                    See ACPI 6.4 spec, s19.6.35 for more.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordMemory (
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        UINT8                   Cacheable,
+  IN        BOOLEAN                 IsReadWrite,
+  IN        UINT32                  AddressGranularity,
+  IN        UINT32                  AddressMinimum,
+  IN        UINT32                  AddressMaximum,
+  IN        UINT32                  AddressTranslation,
+  IN        UINT32                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        UINT8                   MemoryRangeType,
+  IN        BOOLEAN                 IsTypeStatic,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  )
+{
+  return AmlCodeGenRdDWordSpace (
+           ACPI_ADDRESS_SPACE_TYPE_MEM,
+           IsResourceConsumer,
+           IsPosDecode,
+           IsMinFixed,
+           IsMaxFixed,
+           MemoryRangeSpecificFlags (
+             Cacheable,
+             IsReadWrite,
+             MemoryRangeType,
+             IsTypeStatic
+             ),
+           AddressGranularity,
+           AddressMinimum,
+           AddressMaximum,
+           AddressTranslation,
+           RangeLength,
+           ResourceSourceIndex,
+           ResourceSource,
+           NameOpNode,
+           NewRdNode
+           );
+}
+
+/** Code generation for the "WordSpace ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.3 "Word Address Space Descriptor".
+   - s19.6.151 "WordSpace".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @param [in]  ResourceType         See ACPI 6.4 spec, s6.4.3.5.3 for more.
+                                    Available values are:
+                                      0:        Memory range
+                                      1:        I/O range
+                                      2:        Bus number range
+                                      3-191:    Reserved
+                                      192-255:  Hardware Vendor Defined
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  TypeSpecificFlags    See ACPI 6.4 spec, s6.4.3.5.5
+                                    "Resource Type Specific Flags".
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.151 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.151 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.151 for more.
+                                    Not supported.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdWordSpace (
+  IN        UINT8                   ResourceType,
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        UINT8                   TypeSpecificFlags,
+  IN        UINT16                  AddressGranularity,
+  IN        UINT16                  AddressMinimum,
+  IN        UINT16                  AddressMaximum,
+  IN        UINT16                  AddressTranslation,
+  IN        UINT16                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  )
+{
+  EFI_STATUS                                Status;
+  AML_DATA_NODE                           * RdNode;
+  EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR    Rdword;
+
+  // ResourceSource and ResourceSourceIndex are not supported.
+  if ((TypeSpecificFlags == MAX_UINT8)  ||
+      (ResourceSourceIndex != 0)        ||
+      (ResourceSource != NULL)          ||
+      ((NameOpNode == NULL) && (NewRdNode == NULL))) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = CheckAddressSpaceFields (
+             IsMinFixed,
+             IsMaxFixed,
+             AddressGranularity,
+             AddressMinimum,
+             AddressMaximum,
+             AddressTranslation,
+             RangeLength
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Header
+  Rdword.Header.Header.Bits.Name =
+    ACPI_LARGE_WORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
+  Rdword.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
+  Rdword.Header.Length = sizeof (EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR) -
+                               sizeof (ACPI_LARGE_RESOURCE_HEADER);
+
+  // Body
+  Rdword.ResType = ResourceType;
+  Rdword.GenFlag = AddressSpaceGeneralFlags (
+                     IsPosDecode,
+                     IsMinFixed,
+                     IsMaxFixed
+                     );
+  Rdword.SpecificFlag = TypeSpecificFlags;
+  Rdword.AddrSpaceGranularity = AddressGranularity;
+  Rdword.AddrRangeMin = AddressMinimum;
+  Rdword.AddrRangeMax = AddressMaximum;
+  Rdword.AddrTranslationOffset = AddressTranslation;
+  Rdword.AddrLen = RangeLength;
+
+  Status = AmlCreateDataNode (
+             EAmlNodeDataTypeResourceData,
+             (UINT8*)&Rdword,
+             sizeof (EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR),
+             &RdNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  return LinkRdNode (RdNode, NameOpNode, NewRdNode);
+}
+
+/** Code generation for the "WordBusNumber ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.3 "Word Address Space Descriptor".
+   - s19.6.149 "WordBusNumber".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.149 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.149 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.149 for more.
+                                    Not supported.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdWordBusNumber (
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        UINT32                  AddressGranularity,
+  IN        UINT32                  AddressMinimum,
+  IN        UINT32                  AddressMaximum,
+  IN        UINT32                  AddressTranslation,
+  IN        UINT32                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  )
+{
+  // There is no Type Specific Flags for buses.
+  return AmlCodeGenRdWordSpace (
+           ACPI_ADDRESS_SPACE_TYPE_BUS,
+           IsResourceConsumer,
+           IsPosDecode,
+           IsMinFixed,
+           IsMaxFixed,
+           0,
+           AddressGranularity,
+           AddressMinimum,
+           AddressMaximum,
+           AddressTranslation,
+           RangeLength,
+           ResourceSourceIndex,
+           ResourceSource,
+           NameOpNode,
+           NewRdNode
+           );
+}
+
+/** Code generation for the "QWordSpace ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.1 "QWord Address Space Descriptor".
+   - s19.6.111 "QWordSpace".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @param [in]  ResourceType         See ACPI 6.4 spec, s6.4.3.5.1 for more.
+                                    Available values are:
+                                      0:        Memory range
+                                      1:        I/O range
+                                      2:        Bus number range
+                                      3-191:    Reserved
+                                      192-255:  Hardware Vendor Defined
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  TypeSpecificFlags    See ACPI 6.4 spec, s6.4.3.5.5
+                                    "Resource Type Specific Flags".
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.111 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.111 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.111 for more.
+                                    Not supported.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdQWordSpace (
+  IN        UINT8                   ResourceType,
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        UINT8                   TypeSpecificFlags,
+  IN        UINT64                  AddressGranularity,
+  IN        UINT64                  AddressMinimum,
+  IN        UINT64                  AddressMaximum,
+  IN        UINT64                  AddressTranslation,
+  IN        UINT64                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  )
+{
+  EFI_STATUS                                Status;
+  AML_DATA_NODE                           * RdNode;
+  EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR   RdQword;
+
+  // ResourceSource and ResourceSourceIndex are not supported.
+  if ((TypeSpecificFlags == MAX_UINT8)  ||
+      (ResourceSourceIndex != 0)        ||
+      (ResourceSource != NULL)          ||
+      ((NameOpNode == NULL) && (NewRdNode == NULL))) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = CheckAddressSpaceFields (
+             IsMinFixed,
+             IsMaxFixed,
+             AddressGranularity,
+             AddressMinimum,
+             AddressMaximum,
+             AddressTranslation,
+             RangeLength
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Header
+  RdQword.Header.Header.Bits.Name =
+    ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
+  RdQword.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
+  RdQword.Header.Length = sizeof (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) -
+                               sizeof (ACPI_LARGE_RESOURCE_HEADER);
+
+  // Body
+  RdQword.ResType = ResourceType;
+  RdQword.GenFlag = AddressSpaceGeneralFlags (
+                      IsPosDecode,
+                      IsMinFixed,
+                      IsMaxFixed
+                      );
+  RdQword.SpecificFlag = TypeSpecificFlags;
+  RdQword.AddrSpaceGranularity = AddressGranularity;
+  RdQword.AddrRangeMin = AddressMinimum;
+  RdQword.AddrRangeMax = AddressMaximum;
+  RdQword.AddrTranslationOffset = AddressTranslation;
+  RdQword.AddrLen = RangeLength;
+
+  Status = AmlCreateDataNode (
+             EAmlNodeDataTypeResourceData,
+             (UINT8*)&RdQword,
+             sizeof (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR),
+             &RdNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  return LinkRdNode (RdNode, NameOpNode, NewRdNode);
+}
+
+/** Code generation for the "QWordMemory ()" ASL function.
+
+  The Resource Data effectively created is an Extended Interrupt Resource
+  Data. Cf ACPI 6.4:
+   - s6.4.3.5.1 "QWord Address Space Descriptor".
+   - s19.6.110 "QWordMemory".
+
+  The created resource data node can be:
+   - appended to the list of resource data elements of the NameOpNode.
+     In such case NameOpNode must be defined by a the "Name ()" ASL statement
+     and initially contain a "ResourceTemplate ()".
+   - returned through the NewRdNode parameter.
+
+  @param [in]  IsResourceConsumer   ResourceUsage parameter,
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  IsPosDecode          Decode parameter,
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  Cacheable            Available values are:
+                                    0-The memory is non-cacheable
+                                    1-The memory is cacheable
+                                    2-The memory is cacheable and supports
+                                      write combining
+                                    3-The memory is cacheable and prefetchable
+  @param [in]  IsReadWrite          ReadAndWrite parameter,
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.110 for more.
+                                    Not supported.
+  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.110 for more.
+                                    Not supported.
+  @param [in]  MemoryRangeType      Available values are:
+                                      0-AddressRangeMemory
+                                      1-AddressRangeReserved
+                                      2-AddressRangeACPI
+                                      3-AddressRangeNVS
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  IsTypeStatic         TranslationType parameter,
+                                    See ACPI 6.4 spec, s19.6.110 for more.
+  @param [in]  NameOpNode           NameOp object node defining a named object.
+                                    If provided, append the new resource data
+                                    node to the list of resource data elements
+                                    of this node.
+  @param [out] NewRdNode            If provided and success,
+                                    contain the created node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdQWordMemory (
+  IN        BOOLEAN                 IsResourceConsumer,
+  IN        BOOLEAN                 IsPosDecode,
+  IN        BOOLEAN                 IsMinFixed,
+  IN        BOOLEAN                 IsMaxFixed,
+  IN        UINT8                   Cacheable,
+  IN        BOOLEAN                 IsReadWrite,
+  IN        UINT64                  AddressGranularity,
+  IN        UINT64                  AddressMinimum,
+  IN        UINT64                  AddressMaximum,
+  IN        UINT64                  AddressTranslation,
+  IN        UINT64                  RangeLength,
+  IN        UINT8                   ResourceSourceIndex,
+  IN  CONST CHAR8                   *ResourceSource,
+  IN        UINT8                   MemoryRangeType,
+  IN        BOOLEAN                 IsTypeStatic,
+  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
+  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
+  )
+{
+  return AmlCodeGenRdQWordSpace (
+           ACPI_ADDRESS_SPACE_TYPE_MEM,
+           IsResourceConsumer,
+           IsPosDecode,
+           IsMinFixed,
+           IsMaxFixed,
+           MemoryRangeSpecificFlags (
+             Cacheable,
+             IsReadWrite,
+             MemoryRangeType,
+             IsTypeStatic
+             ),
+           AddressGranularity,
+           AddressMinimum,
+           AddressMaximum,
+           AddressTranslation,
+           RangeLength,
+           ResourceSourceIndex,
+           ResourceSource,
+           NameOpNode,
+           NewRdNode
+           );
+}
+
 /** Code generation for the "Interrupt ()" ASL function.
 
   The Resource Data effectively created is an Extended Interrupt Resource
-- 
2.17.1


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

* [PATCH v1 2/7] DynamicTablesPkg: AML Code generation to create a named Package()
  2021-06-23 11:58 [PATCH v1 0/7] Create a SSDT PCIe generator PierreGondois
  2021-06-23 11:58 ` [PATCH v1 1/7] DynamicTablesPkg: AML Code generation for memory ranges PierreGondois
@ 2021-06-23 11:58 ` PierreGondois
  2021-10-06 15:15   ` Sami Mujawar
  2021-06-23 11:58 ` [PATCH v1 3/7] DynamicTablesPkg: AML Code generation to create a named ResourceTemplate() PierreGondois
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: PierreGondois @ 2021-06-23 11:58 UTC (permalink / raw)
  To: devel, Sami Mujawar, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei

From: Pierre Gondois <Pierre.Gondois@arm.com>

Add AmlCodeGenNamePackage() to generate code for a Package().

AmlCodeGenNamePackage ("PACK", ParentNode, NewObjectNode) is
equivalent of the following ASL code:
   Name(PACK, Package () {})

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../Include/Library/AmlLib/AmlLib.h           | 28 ++++++++++
 .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 55 +++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index cbbbb7a478f7..412db886e1f2 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -852,6 +852,34 @@ AmlCodeGenNameInteger (
   OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
   );
 
+/** AML code generation for a Name object node, containing a Package.
+
+  AmlCodeGenNamePackage ("PKG0", ParentNode, NewObjectNode) is
+  equivalent of the following ASL code:
+    Name(PKG0, Package () {})
+
+  @ingroup CodeGenApis
+
+  @param [in]  NameString     The new variable name.
+                              Must be a NULL-terminated ASL NameString
+                              e.g.: "DEV0", "DV15.DEV0", etc.
+                              The input string is copied.
+  @param [in]  ParentNode     If provided, set ParentNode as the parent
+                              of the node created.
+  @param [out] NewObjectNode  If success, contains the created node.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNamePackage (
+  IN  CONST CHAR8                   * NameString,
+  IN        AML_NODE_HANDLE           ParentNode,     OPTIONAL
+  OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
+  );
+
 /** AML code generation for a Device object node.
 
   AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index f0861040191f..f9175c623622 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -747,6 +747,61 @@ AmlCodeGenNameInteger (
   return Status;
 }
 
+/** AML code generation for a Name object node, containing a Package.
+
+  AmlCodeGenNamePackage ("PKG0", ParentNode, NewObjectNode) is
+  equivalent of the following ASL code:
+    Name(PKG0, Package () {})
+
+  @param [in]  NameString     The new variable name.
+                              Must be a NULL-terminated ASL NameString
+                              e.g.: "DEV0", "DV15.DEV0", etc.
+                              The input string is copied.
+  @param [in]  ParentNode     If provided, set ParentNode as the parent
+                              of the node created.
+  @param [out] NewObjectNode  If success, contains the created node.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNamePackage (
+  IN  CONST CHAR8              * NameString,
+  IN        AML_NODE_HEADER    * ParentNode,     OPTIONAL
+  OUT       AML_OBJECT_NODE   ** NewObjectNode   OPTIONAL
+  )
+{
+  EFI_STATUS          Status;
+  AML_OBJECT_NODE   * PackageNode;
+
+  if ((NameString == NULL)  ||
+      ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = AmlCodeGenPackage (&PackageNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  Status = AmlCodeGenName (
+             NameString,
+             PackageNode,
+             ParentNode,
+             NewObjectNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    AmlDeleteTree ((AML_NODE_HEADER*)PackageNode);
+  }
+
+  return Status;
+}
+
 /** AML code generation for a Device object node.
 
   AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
-- 
2.17.1


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

* [PATCH v1 3/7] DynamicTablesPkg: AML Code generation to create a named ResourceTemplate()
  2021-06-23 11:58 [PATCH v1 0/7] Create a SSDT PCIe generator PierreGondois
  2021-06-23 11:58 ` [PATCH v1 1/7] DynamicTablesPkg: AML Code generation for memory ranges PierreGondois
  2021-06-23 11:58 ` [PATCH v1 2/7] DynamicTablesPkg: AML Code generation to create a named Package() PierreGondois
@ 2021-06-23 11:58 ` PierreGondois
  2021-10-06 15:16   ` Sami Mujawar
  2021-06-23 11:58 ` [PATCH v1 4/7] DynamicTablesPkg: AML Code generation to add _PRT entries PierreGondois
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: PierreGondois @ 2021-06-23 11:58 UTC (permalink / raw)
  To: devel, Sami Mujawar, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei

From: Pierre Gondois <Pierre.Gondois@arm.com>

Add AmlCodeGenNameResourceTemplate() to generate code for a
ResourceTemplate().

AmlCodeGenNameResourceTemplate ("REST", ParentNode, NewObjectNode) is
equivalent of the following ASL code:
  Name(REST, ResourceTemplate () {})

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../Include/Library/AmlLib/AmlLib.h           | 28 ++++++++++
 .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 55 +++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 412db886e1f2..544bc670c455 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -880,6 +880,34 @@ AmlCodeGenNamePackage (
   OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
   );
 
+/** AML code generation for a Name object node, containing a ResourceTemplate.
+
+  AmlCodeGenNameResourceTemplate ("PRS0", ParentNode, NewObjectNode) is
+  equivalent of the following ASL code:
+    Name(PRS0, ResourceTemplate () {})
+
+  @ingroup CodeGenApis
+
+  @param [in]  NameString     The new variable name.
+                              Must be a NULL-terminated ASL NameString
+                              e.g.: "DEV0", "DV15.DEV0", etc.
+                              The input string is copied.
+  @param [in]  ParentNode     If provided, set ParentNode as the parent
+                              of the node created.
+  @param [out] NewObjectNode  If success, contains the created node.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNameResourceTemplate (
+  IN  CONST CHAR8                   * NameString,
+  IN        AML_NODE_HANDLE           ParentNode,     OPTIONAL
+  OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
+  );
+
 /** AML code generation for a Device object node.
 
   AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index f9175c623622..eaa49a5834c2 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -802,6 +802,61 @@ AmlCodeGenNamePackage (
   return Status;
 }
 
+/** AML code generation for a Name object node, containing a ResourceTemplate.
+
+  AmlCodeGenNameResourceTemplate ("PRS0", ParentNode, NewObjectNode) is
+  equivalent of the following ASL code:
+    Name(PRS0, ResourceTemplate () {})
+
+  @param [in]  NameString     The new variable name.
+                              Must be a NULL-terminated ASL NameString
+                              e.g.: "DEV0", "DV15.DEV0", etc.
+                              The input string is copied.
+  @param [in]  ParentNode     If provided, set ParentNode as the parent
+                              of the node created.
+  @param [out] NewObjectNode  If success, contains the created node.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNameResourceTemplate (
+  IN  CONST CHAR8              * NameString,
+  IN        AML_NODE_HEADER    * ParentNode,     OPTIONAL
+  OUT       AML_OBJECT_NODE   ** NewObjectNode   OPTIONAL
+  )
+{
+  EFI_STATUS          Status;
+  AML_OBJECT_NODE   * ResourceTemplateNode;
+
+  if ((NameString == NULL)  ||
+      ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  Status = AmlCodeGenName (
+             NameString,
+             ResourceTemplateNode,
+             ParentNode,
+             NewObjectNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    AmlDeleteTree ((AML_NODE_HEADER*)ResourceTemplateNode);
+  }
+
+  return Status;
+}
+
 /** AML code generation for a Device object node.
 
   AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
-- 
2.17.1


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

* [PATCH v1 4/7] DynamicTablesPkg: AML Code generation to add _PRT entries
  2021-06-23 11:58 [PATCH v1 0/7] Create a SSDT PCIe generator PierreGondois
                   ` (2 preceding siblings ...)
  2021-06-23 11:58 ` [PATCH v1 3/7] DynamicTablesPkg: AML Code generation to create a named ResourceTemplate() PierreGondois
@ 2021-06-23 11:58 ` PierreGondois
  2021-10-06 15:17   ` Sami Mujawar
  2021-06-23 11:58 ` [PATCH v1 5/7] DynamicTablesPkg: Add AmlAttachNode() PierreGondois
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: PierreGondois @ 2021-06-23 11:58 UTC (permalink / raw)
  To: devel, Sami Mujawar, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei

From: Pierre Gondois <Pierre.Gondois@arm.com>

_PRT entries can describe interrupt mapping for Pci devices. The
object is described in ACPI 6.4 s6.2.13 "_PRT (PCI Routing Table)".

Add AmlCodeGenPrtEntry() helper function to add _PRT entries
to an existing _PRT object.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../Include/Library/AmlLib/AmlLib.h           |  52 +++++
 .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 210 ++++++++++++++++++
 2 files changed, 262 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 544bc670c455..4a10da8cd7bb 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -908,6 +908,58 @@ AmlCodeGenNameResourceTemplate (
   OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
   );
 
+/** Add a _PRT entry.
+
+  AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
+  equivalent of the following ASL code:
+    Package (4) {
+      0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
+      0,       // Pin: PCI pin number of the device (0-INTA, ...).
+      LNKA     // Source: Name of the device that allocates the interrupt
+               // to which the above pin is connected.
+      0        // Source Index: Source is assumed to only describe one
+               // interrupt, so let it to index 0.
+    }
+
+  The package is added at the tail of the list of the input _PRT node
+  name:
+    Name (_PRT, Package () {
+      [Pre-existing _PRT entries],
+      [Newly created _PRT entry]
+    })
+
+  Cf. ACPI 6.4, s6.2.13 "_PRT (PCI Routing Table)"
+
+  @ingroup CodeGenApis
+
+  @param [in]  Address        Address. Cf ACPI 6.4 specification, Table 6.2:
+                              "ADR Object Address Encodings":
+                              High word-Device #, Low word-Function #. (for
+                              example, device 3, function 2 is 0x00030002).
+                              To refer to all the functions on a device #,
+                              use a function number of FFFF).
+  @param [in]  Pin            PCI pin number of the device (0-INTA ... 3-INTD).
+                              Must be between 0-3.
+  @param [in]  LinkName       Link Name, i.e. device in the AML NameSpace
+                              describing the interrupt used.
+                              The input string is copied.
+  @param [in]  SourceIndex    Source index or GSIV.
+  @param [in]  PrtNameNode    Prt Named node to add the object to ....
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddPrtEntry (
+  IN        UINT32                    Address,
+  IN        UINT8                     Pin,
+  IN  CONST CHAR8                   * LinkName,
+  IN        UINT32                    SourceIndex,
+  IN        AML_OBJECT_NODE_HANDLE    PrtNameNode
+  );
+
 /** AML code generation for a Device object node.
 
   AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index eaa49a5834c2..9bf4e110d05c 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -857,6 +857,216 @@ AmlCodeGenNameResourceTemplate (
   return Status;
 }
 
+/** Add a _PRT entry.
+
+  AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
+  equivalent of the following ASL code:
+    Package (4) {
+      0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
+      0,       // Pin: PCI pin number of the device (0-INTA, ...).
+      LNKA     // Source: Name of the device that allocates the interrupt
+               // to which the above pin is connected.
+      0        // Source Index: Source is assumed to only describe one
+               // interrupt, so let it to index 0.
+    }
+
+  The package is added at the tail of the list of the input _PRT node
+  name:
+    Name (_PRT, Package () {
+      [Pre-existing _PRT entries],
+      [Newly created _PRT entry]
+    })
+
+  Cf. ACPI 6.4 specification:
+   - s6.2.13 "_PRT (PCI Routing Table)"
+   - s6.1.1 "_ADR (Address)"
+
+  @param [in]  Address        Address. Cf ACPI 6.4 specification, Table 6.2:
+                              "ADR Object Address Encodings":
+                              High word-Device #, Low word-Function #. (for
+                              example, device 3, function 2 is 0x00030002).
+                              To refer to all the functions on a device #,
+                              use a function number of FFFF).
+  @param [in]  Pin            PCI pin number of the device (0-INTA ... 3-INTD).
+                              Must be between 0-3.
+  @param [in]  LinkName       Link Name, i.e. device in the AML NameSpace
+                              describing the interrupt used.
+                              The input string is copied.
+  @param [in]  SourceIndex    Source index or GSIV.
+  @param [in]  PrtNameNode    Prt Named node to add the object to ....
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddPrtEntry (
+  IN        UINT32                    Address,
+  IN        UINT8                     Pin,
+  IN  CONST CHAR8                   * LinkName,
+  IN        UINT32                    SourceIndex,
+  IN        AML_OBJECT_NODE_HANDLE    PrtNameNode
+  )
+{
+  EFI_STATUS          Status;
+  AML_OBJECT_NODE   * PrtEntryList;
+  AML_OBJECT_NODE   * PackageNode;
+  AML_OBJECT_NODE   * NewElementNode;
+
+  CHAR8             * AmlNameString;
+  UINT32              AmlNameStringSize;
+  AML_DATA_NODE     * DataNode;
+
+  if ((Pin > 3)                 ||
+      (LinkName == NULL)        ||
+      (PrtNameNode == NULL)     ||
+      (AmlGetNodeType ((AML_NODE_HANDLE)PrtNameNode) != EAmlNodeObject) ||
+      (!AmlNodeHasOpCode (PrtNameNode, AML_NAME_OP, 0))                 ||
+      !AmlNameOpCompareName (PrtNameNode, "_PRT")) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NewElementNode = NULL;
+  AmlNameString = NULL;
+  DataNode = NULL;
+
+  // Get the Package object node of the _PRT node,
+  // which is the 2nd fixed argument (i.e. index 1).
+  PrtEntryList = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
+                                           PrtNameNode,
+                                           EAmlParseIndexTerm1
+                                           );
+  if ((PrtEntryList == NULL)                                              ||
+      (AmlGetNodeType ((AML_NODE_HANDLE)PrtEntryList) != EAmlNodeObject)  ||
+      (!AmlNodeHasOpCode (PrtEntryList, AML_PACKAGE_OP, 0))) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // The new _PRT entry.
+  Status = AmlCodeGenPackage (&PackageNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  Status = AmlCodeGenInteger (Address, &NewElementNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)PackageNode,
+             (AML_NODE_HANDLE)NewElementNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  NewElementNode = NULL;
+
+  Status = AmlCodeGenInteger (Pin, &NewElementNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)PackageNode,
+             (AML_NODE_HANDLE)NewElementNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  NewElementNode = NULL;
+
+  Status = ConvertAslNameToAmlName (LinkName, &AmlNameString);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  Status = AmlCreateDataNode (
+             EAmlNodeDataTypeNameString,
+             (UINT8*)AmlNameString,
+             AmlNameStringSize,
+             &DataNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  // AmlNameString will be freed before returning.
+
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)PackageNode,
+             (AML_NODE_HANDLE)DataNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  DataNode = NULL;
+
+  Status = AmlCodeGenInteger (SourceIndex, &NewElementNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)PackageNode,
+             (AML_NODE_HANDLE)NewElementNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  // Append to the the list of _PRT entries.
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)PrtEntryList,
+             (AML_NODE_HANDLE)PackageNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto error_handler;
+  }
+
+  // Free AmlNameString before returning as it is copied
+  // in the call to AmlCreateDataNode().
+  goto exit_handler;
+
+error_handler:
+  AmlDeleteTree ((AML_NODE_HANDLE)PackageNode);
+  if (NewElementNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)NewElementNode);
+  }
+  if (DataNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)DataNode);
+  }
+
+exit_handler:
+  if (AmlNameString != NULL) {
+    FreePool (AmlNameString);
+  }
+  return Status;
+}
+
 /** AML code generation for a Device object node.
 
   AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
-- 
2.17.1


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

* [PATCH v1 5/7] DynamicTablesPkg: Add AmlAttachNode()
  2021-06-23 11:58 [PATCH v1 0/7] Create a SSDT PCIe generator PierreGondois
                   ` (3 preceding siblings ...)
  2021-06-23 11:58 ` [PATCH v1 4/7] DynamicTablesPkg: AML Code generation to add _PRT entries PierreGondois
@ 2021-06-23 11:58 ` PierreGondois
  2021-10-06 15:17   ` Sami Mujawar
  2021-06-23 11:58 ` [PATCH v1 6/7] DynamicTablesPkg: Add Pci related objects PierreGondois
  2021-06-23 11:58 ` [PATCH v1 7/7] DynamicTablesPkg: SSDT Pci express generator PierreGondois
  6 siblings, 1 reply; 15+ messages in thread
From: PierreGondois @ 2021-06-23 11:58 UTC (permalink / raw)
  To: devel, Sami Mujawar, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei

From: Pierre Gondois <Pierre.Gondois@arm.com>

This function allows to add a node as the last node of a parent node
in an AML tree. For instance,
ASL code corresponding to NewNode:
  Name (_UID, 0)

ASL code corresponding to ParentNode:
  Device (PCI0) {
    Name(_HID, EISAID("PNP0A08"))
  }

"AmlAttachNode (ParentNode, NewNode)" will result in:
ASL code:
  Device (PCI0) {
    Name(_HID, EISAID("PNP0A08"))
    Name (_UID, 0)
  }

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../Include/Library/AmlLib/AmlLib.h           | 33 +++++++++++++++++
 .../Library/Common/AmlLib/Api/AmlApi.c        | 36 +++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 4a10da8cd7bb..b4766726e84d 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -166,6 +166,39 @@ AmlDetachNode (
   IN  AML_NODE_HANDLE   Node
   );
 
+/** Attach a node in an AML tree.
+
+  The node will be added as the last statement of the ParentNode.
+  E.g.:
+  ASL code corresponding to NewNode:
+  Name (_UID, 0)
+
+  ASL code corresponding to ParentNode:
+  Device (PCI0) {
+    Name(_HID, EISAID("PNP0A08"))
+  }
+
+  "AmlAttachNode (ParentNode, NewNode)" will result in:
+  ASL code:
+  Device (PCI0) {
+    Name(_HID, EISAID("PNP0A08"))
+    Name (_UID, 0)
+  }
+
+  @param  [in]  ParentNode  Pointer to the parent node.
+                            Must be a root or an object node.
+  @param  [in]  NewNode     Pointer to the node to add.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlAttachNode (
+  IN  AML_NODE_HANDLE   ParentNode,
+  IN  AML_NODE_HANDLE   NewNode
+  );
+
 /** Find a node in the AML namespace, given an ASL path and a reference Node.
 
    - The AslPath can be an absolute path, or a relative path from the
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
index 6f9e3f6f2805..def581299f5c 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
@@ -379,6 +379,42 @@ AmlNameOpGetNextRdNode (
   return EFI_SUCCESS;
 }
 
+/** Attach a node in an AML tree.
+
+  The node will be added as the last statement of the ParentNode.
+  E.g.:
+  ASL code corresponding to NewNode:
+  Name (_UID, 0)
+
+  ASL code corresponding to ParentNode:
+  Device (PCI0) {
+    Name(_HID, EISAID("PNP0A08"))
+  }
+
+  "AmlAttachNode (ParentNode, NewNode)" will result in:
+  ASL code:
+  Device (PCI0) {
+    Name(_HID, EISAID("PNP0A08"))
+    Name (_UID, 0)
+  }
+
+  @param  [in]  ParentNode  Pointer to the parent node.
+                            Must be a root or an object node.
+  @param  [in]  NewNode     Pointer to the node to add.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlAttachNode (
+  IN  AML_NODE_HANDLE   ParentNode,
+  IN  AML_NODE_HANDLE   NewNode
+  )
+{
+  return AmlVarListAddTail (ParentNode, NewNode);
+}
+
 // DEPRECATED APIS
 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
 
-- 
2.17.1


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

* [PATCH v1 6/7] DynamicTablesPkg: Add Pci related objects
  2021-06-23 11:58 [PATCH v1 0/7] Create a SSDT PCIe generator PierreGondois
                   ` (4 preceding siblings ...)
  2021-06-23 11:58 ` [PATCH v1 5/7] DynamicTablesPkg: Add AmlAttachNode() PierreGondois
@ 2021-06-23 11:58 ` PierreGondois
  2021-10-06 15:18   ` Sami Mujawar
  2021-06-23 11:58 ` [PATCH v1 7/7] DynamicTablesPkg: SSDT Pci express generator PierreGondois
  6 siblings, 1 reply; 15+ messages in thread
From: PierreGondois @ 2021-06-23 11:58 UTC (permalink / raw)
  To: devel, Sami Mujawar, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei

From: Pierre Gondois <Pierre.Gondois@arm.com>

Introduce the following CmObj in the ArmNameSpaceObjects:
 - CM_ARM_PCI_ADDRESS_MAP_INFO
 - CM_ARM_PCI_INTERRUPT_MAP_INFO

These objects allow to describe address range mapping
of Pci busses and interrupt mapping of Pci devices.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../Include/ArmNameSpaceObjects.h             | 78 +++++++++++++++++++
 .../ConfigurationManagerObjectParser.c        | 28 ++++++-
 2 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
index 9c49091def59..b3779f828c17 100644
--- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
+++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
@@ -59,6 +59,8 @@ typedef enum ArmObjectID {
   EArmObjSerialPortInfo,               ///< 35 - Generic Serial Port Info
   EArmObjCmn600Info,                   ///< 36 - CMN-600 Info
   EArmObjLpiInfo,                      ///< 37 - Lpi Info
+  EArmObjPciAddressMapInfo,            ///< 38 - Pci Address Map Info
+  EArmObjPciInterruptMapInfo,          ///< 39 - Pci Interrupt Map Info
   EArmObjMax
 } EARM_OBJECT_ID;
 
@@ -433,6 +435,14 @@ typedef struct CmArmPciConfigSpaceInfo {
 
   /// The end bus number
   UINT8   EndBusNumber;
+
+  /// Optional field: Reference Token for address mapping.
+  /// Token identifying a CM_ARM_OBJ_REF structure.
+  CM_OBJECT_TOKEN   AddressMapToken;
+
+  /// Optional field: Reference Token for interrupt mapping.
+  /// Token identifying a CM_ARM_OBJ_REF structure.
+  CM_OBJECT_TOKEN   InterruptMapToken;
 } CM_ARM_PCI_CONFIG_SPACE_INFO;
 
 /** A structure that describes the
@@ -666,6 +676,10 @@ typedef struct CmArmGenericInterrupt {
   UINT32    Interrupt;
 
   /// Flags
+  /// BIT0: 0: Interrupt is Level triggered
+  ///       1: Interrupt is Edge triggered
+  /// BIT1: 0: Interrupt is Active high
+  ///       1: Interrupt is Active low
   UINT32    Flags;
 } CM_ARM_GENERIC_INTERRUPT;
 
@@ -946,6 +960,70 @@ typedef struct CmArmLpiInfo {
   CHAR8                                   StateName[16];
 } CM_ARM_LPI_INFO;
 
+/** A structure that describes a PCI Address Map.
+
+  The memory-ranges used by the PCI bus are described by this object.
+
+  ID: EArmObjPciAddressMapInfo
+*/
+typedef struct CmArmPciAddressMapInfo {
+  /** Pci address space code
+
+  Available values are:
+   - 0: Configuration Space
+   - 1: I/O Space
+   - 2: 32-bit-address Memory Space
+   - 3: 64-bit-address Memory Space
+  */
+  UINT8                     SpaceCode;
+
+  /// PCI address
+  UINT64                    PciAddress;
+
+  /// Cpu address
+  UINT64                    CpuAddress;
+
+  /// Address size
+  UINT64                    AddressSize;
+} CM_ARM_PCI_ADDRESS_MAP_INFO;
+
+/** A structure that describes a PCI Interrupt Map.
+
+  The legacy PCI interrupts used by PCI devices are described by this object.
+
+  Cf Devicetree Specification - Release v0.3
+  s2.4.3 "Interrupt Nexus Properties"
+
+  ID: EArmObjPciInterruptMapInfo
+*/
+typedef struct CmArmPciInterruptMapInfo {
+  /// Pci Bus.
+  /// Value on 8 bits (max 255).
+  UINT8                       PciBus;
+
+  /// Pci Bus.
+  /// Value on 5 bits (max 31).
+  UINT8                       PciDevice;
+
+  /** PCI interrupt
+
+  ACPI bindings are used:
+  Cf. ACPI 6.4, s6.2.13 _PRT (PCI Routing Table):
+      "0-INTA, 1-INTB, 2-INTC, 3-INTD"
+
+  Device-tree bindings are shifted by 1:
+      "INTA=1, INTB=2, INTC=3, INTD=4"
+  */
+  UINT8                       PciInterrupt;
+
+  /** Interrupt controller interrupt.
+
+  Cf Devicetree Specification - Release v0.3
+  s2.4.3 "Interrupt Nexus Properties": "parent interrupt specifier"
+  */
+  CM_ARM_GENERIC_INTERRUPT    IntcInterrupt;
+} CM_ARM_PCI_INTERRUPT_MAP_INFO;
+
 #pragma pack()
 
 #endif // ARM_NAMESPACE_OBJECTS_H_
diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
index da5f5846edd9..0ba4e6e5faff 100644
--- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
+++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
@@ -152,7 +152,9 @@ STATIC CONST CM_OBJ_PARSER CmArmPciConfigSpaceInfoParser[] = {
   {"BaseAddress", 8, "0x%llx", NULL},
   {"PciSegmentGroupNumber", 2, "0x%x", NULL},
   {"StartBusNumber", 1, "0x%x", NULL},
-  {"EndBusNumber", 1, "0x%x", NULL}
+  {"EndBusNumber", 1, "0x%x", NULL},
+  {"AddressMapToken", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL},
+  {"InterruptMapToken", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL},
 };
 
 /** A parser for EArmObjHypervisorVendorIdentity.
@@ -401,6 +403,26 @@ STATIC CONST CM_OBJ_PARSER CmArmLpiInfoParser[] = {
   {"StateName", 16, "0x%a", NULL},
 };
 
+/** A parser for EArmObjPciAddressMapInfo.
+*/
+STATIC CONST CM_OBJ_PARSER CmArmPciAddressMapInfoParser[] = {
+  {"SpaceCode", 1, "%d", NULL},
+  {"PciAddress", 8, "0x%llx", NULL},
+  {"CpuAddress", 8, "0x%llx", NULL},
+  {"AddressSize", 8, "0x%llx", NULL},
+};
+
+/** A parser for EArmObjPciInterruptMapInfo.
+*/
+STATIC CONST CM_OBJ_PARSER CmPciInterruptMapInfoParser[] = {
+  {"PciBus", 1, "0x%x", NULL},
+  {"PciDevice", 1, "0x%x", NULL},
+  {"PciInterrupt", 1, "0x%x", NULL},
+  {"IntcInterrupt", sizeof (CM_ARM_GENERIC_INTERRUPT),
+    NULL, NULL, CmArmGenericInterruptParser,
+    ARRAY_SIZE (CmArmGenericInterruptParser)},
+};
+
 /** A parser for Arm namespace objects.
 */
 STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = {
@@ -475,6 +497,10 @@ STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = {
     ARRAY_SIZE (CmArmCmn600InfoParser)},
   {"EArmObjLpiInfo", CmArmLpiInfoParser,
       ARRAY_SIZE (CmArmLpiInfoParser)},
+  {"EArmObjPciAddressMapInfo", CmArmPciAddressMapInfoParser,
+    ARRAY_SIZE (CmArmPciAddressMapInfoParser)},
+  {"EArmObjPciInterruptMapInfo", CmPciInterruptMapInfoParser,
+    ARRAY_SIZE (CmPciInterruptMapInfoParser)},
   {"EArmObjMax", NULL, 0},
 };
 
-- 
2.17.1


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

* [PATCH v1 7/7] DynamicTablesPkg: SSDT Pci express generator
  2021-06-23 11:58 [PATCH v1 0/7] Create a SSDT PCIe generator PierreGondois
                   ` (5 preceding siblings ...)
  2021-06-23 11:58 ` [PATCH v1 6/7] DynamicTablesPkg: Add Pci related objects PierreGondois
@ 2021-06-23 11:58 ` PierreGondois
  2021-10-07 11:11   ` Sami Mujawar
  6 siblings, 1 reply; 15+ messages in thread
From: PierreGondois @ 2021-06-23 11:58 UTC (permalink / raw)
  To: devel, Sami Mujawar, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei

From: Pierre Gondois <Pierre.Gondois@arm.com>

This generator allows to generate a SSDT table describing
a Pci express Bus. It uses the following CmObj:
- EArmObjCmRef
- EArmObjPciConfigSpaceInfo
- EArmObjPciAddressMapInfo
- EArmObjPciInterruptMapInfo

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 DynamicTablesPkg/DynamicTables.dsc.inc        |    2 +
 DynamicTablesPkg/Include/AcpiTableGenerator.h |    5 +
 .../AcpiSsdtPcieLibArm/SsdtPcieGenerator.c    | 1417 +++++++++++++++++
 .../AcpiSsdtPcieLibArm/SsdtPcieGenerator.h    |  134 ++
 .../Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf |   32 +
 .../SsdtPcieOscTemplate.asl                   |   80 +
 6 files changed, 1670 insertions(+)
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl

diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
index 292215c39456..60bcf4b199e8 100644
--- a/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -39,6 +39,7 @@ [Components.common]
 
   # AML Codegen
   DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf
+  DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
 
   #
   # Dynamic Table Factory Dxe
@@ -62,6 +63,7 @@ [Components.common]
 
       # AML Codegen
       NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf
+      NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
   }
 
   #
diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
index 45c808ba740d..58ec941f2a35 100644
--- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
+++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
@@ -67,6 +67,10 @@ The Dynamic Tables Framework implements the following ACPI table generators:
             The SSDT Cpu-Topology generator collates the cpu and LPI
             information from the Configuration Manager and generates a
             SSDT table describing the CPU hierarchy.
+  - SSDT Pci-Express:
+            The SSDT Pci Express generator collates the Pci Express
+            information from the Configuration Manager and generates a
+            SSDT table describing a Pci Express bus.
 */
 
 /** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
@@ -93,6 +97,7 @@ typedef enum StdAcpiTableId {
   EStdAcpiTableIdSsdtSerialPort,                ///< SSDT Serial-Port Generator
   EStdAcpiTableIdSsdtCmn600,                    ///< SSDT Cmn-600 Generator
   EStdAcpiTableIdSsdtCpuTopology,               ///< SSDT Cpu Topology
+  EStdAcpiTableIdSsdtPciExpress,                ///< SSDT Pci Express Generator
   EStdAcpiTableIdMax
 } ESTD_ACPI_TABLE_ID;
 
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
new file mode 100644
index 000000000000..478bc60ef6f3
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
@@ -0,0 +1,1417 @@
+/** @file
+  SSDT Pcie Table Generator.
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - PCI Firmware Specification - Revision 3.0
+  - ACPI 6.4 specification:
+   - s6.2.13 "_PRT (PCI Routing Table)"
+   - s6.1.1 "_ADR (Address)"
+  - linux kernel code
+**/
+
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/AcpiHelperLib.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include "SsdtPcieGenerator.h"
+
+/** ARM standard SSDT Pcie Table Generator.
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjCmRef
+  - EArmObjPciConfigSpaceInfo
+  - EArmObjPciAddressMapInfo
+  - EArmObjPciInterruptMapInfo
+*/
+
+/** This macro expands to a function that retrieves the cross-CM-object-
+    reference information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjCmRef,
+  CM_ARM_OBJ_REF
+  );
+
+/** This macro expands to a function that retrieves the Pci
+    Configuration Space Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPciConfigSpaceInfo,
+  CM_ARM_PCI_CONFIG_SPACE_INFO
+  );
+
+/** This macro expands to a function that retrieves the Pci
+    Address Mapping Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPciAddressMapInfo,
+  CM_ARM_PCI_ADDRESS_MAP_INFO
+  );
+
+/** This macro expands to a function that retrieves the Pci
+    Interrupt Mapping Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPciInterruptMapInfo,
+  CM_ARM_PCI_INTERRUPT_MAP_INFO
+  );
+
+/** Initialize the MappingTable.
+
+  @param [in] MappingTable  The mapping table structure.
+  @param [in] Count         Number of entries to allocate in the
+                            MappingTable.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MappingTableInitialize (
+  IN  MAPPING_TABLE   * MappingTable,
+  IN  UINT32            Count
+  )
+{
+  UINT32  * Table;
+
+  if ((MappingTable == NULL)  ||
+      (Count == 0)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Table = AllocateZeroPool (sizeof (*Table) * Count);
+  if (Table == NULL) {
+    ASSERT (0);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  MappingTable->Table = Table;
+  MappingTable->LastIndex = 0;
+  MappingTable->MaxIndex = Count;
+
+  return EFI_SUCCESS;
+}
+
+/** Free the MappingTable.
+
+  @param [in, out]  MappingTable  The mapping table structure.
+**/
+STATIC
+VOID
+EFIAPI
+MappingTableFree (
+  IN  OUT MAPPING_TABLE   * MappingTable
+  )
+{
+  ASSERT (MappingTable != NULL);
+  ASSERT (MappingTable->Table != NULL);
+
+  if (MappingTable->Table != NULL) {
+    FreePool (MappingTable->Table);
+  }
+}
+
+/** Add a new entry to the MappingTable and return its index.
+
+  If an entry with [Integer] is already available in the table,
+  return its index without adding a new entry.
+
+  @param [in] MappingTable  The mapping table structure.
+  @param [in] Integer       New Integer entry to add.
+
+  @retval The index of the Integer entry in the MappingTable.
+**/
+STATIC
+UINT32
+EFIAPI
+MappingTableAdd (
+  IN  MAPPING_TABLE   * MappingTable,
+  IN  UINT32            Integer
+  )
+{
+  UINT32    * Table;
+  UINT32      Index;
+  UINT32      LastIndex;
+
+  ASSERT (MappingTable != NULL);
+  ASSERT (MappingTable->Table != NULL);
+
+  Table = MappingTable->Table;
+  LastIndex = MappingTable->LastIndex;
+
+  // Search if there is already an entry with this Integer.
+  for (Index = 0; Index < LastIndex; Index++) {
+    if (Table[Index] == Integer) {
+      return Index;
+    }
+  }
+
+  ASSERT (LastIndex < MAX_PCI_LEGACY_INTERRUPT);
+  ASSERT (LastIndex < MappingTable->MaxIndex);
+
+  // If no, create a new entry.
+  Table[LastIndex] = Integer;
+
+  return MappingTable->LastIndex++;
+}
+
+/** Generate required Pci device information.
+
+  ASL code:
+    Name (_UID, [Uid])                // Uid of the Pci device
+    Name (_HID, EISAID ("PNP0A08"))   // PCI Express Root Bridge
+    Name (_CID, EISAID ("PNP0A03"))   // Compatible PCI Root Bridge
+    Name (_SEG, [Pci segment group])  // PCI Segment Group number
+    Name (_BBN, [Bus number])         // PCI Base Bus Number
+    Name (_CCA, 1)                    // Initially mark the PCI coherent
+
+  @param [in]       PciInfo         Pci device information.
+  @param [in]       Uid             Unique Id of the Pci device.
+  @param [in, out]  PciNode         Pci node to amend.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePciDeviceInfo (
+  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO  * PciInfo,
+  IN            UINT32                          Uid,
+  IN  OUT       AML_OBJECT_NODE_HANDLE          PciNode
+  )
+{
+  EFI_STATUS    Status;
+  UINT32        EisaId;
+
+  ASSERT (PciInfo != NULL);
+  ASSERT (PciNode != NULL);
+
+  // ASL: Name (_UID, [Uid])
+  Status = AmlCodeGenNameInteger ("_UID", Uid, PciNode, NULL);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL: Name (_HID, EISAID ("PNP0A08"))
+  Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+  Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL: Name (_CID, EISAID ("PNP0A03"))
+  Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+  Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL: Name (_SEG, [Pci segment group])
+  Status = AmlCodeGenNameInteger (
+             "_SEG",
+             PciInfo->PciSegmentGroupNumber,
+             PciNode,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL: Name (_BBN, [Bus number])
+  Status = AmlCodeGenNameInteger (
+             "_BBN",
+             PciInfo->StartBusNumber,
+             PciNode,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL: Name (_CCA, 1)
+  // Must be aligned with the IORT CCA property in
+  // "Table 14 Memory access properties"
+  Status = AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+  }
+  return Status;
+}
+
+/** Generate a Link device.
+
+  The Link device is added at the beginning of the ASL Pci device definition.
+
+  Each Link device represents a Pci legacy interrupt (INTA-...-INTD).
+
+  ASL code:
+  Device ([Link Name]) {
+    Name (_UID, [Uid]])
+    Name (_HID, EISAID ("PNP0C0F"))
+    Name (_PRS, ResourceTemplate () {
+      Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { [Irq]] }
+      })
+    Method (_CRS, 0) { Return (_PRS) }
+    Method (_SRS, 1) { }
+    Method (_DIS) { }
+  }
+
+  The list of objects to define is available at:
+  PCI Firmware Specification - Revision 3.3,
+  s3.5. "Device State at Firmware/Operating System Handoff"
+
+  @param [in]       Irq         Interrupt controller interrupt.
+  @param [in]       IrqFlags    Interrupt flags.
+  @param [in]       LinkIndex   Legacy Pci interrupt index.
+                                Must be between 0-INTA and 3-INTD.
+  @param [in, out]  PciNode     Pci node to amend.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenerateLinkDevice (
+  IN      UINT32                    Irq,
+  IN      UINT32                    IrqFlags,
+  IN      UINT32                    LinkIndex,
+  IN  OUT AML_OBJECT_NODE_HANDLE    PciNode
+  )
+{
+  EFI_STATUS                Status;
+  CHAR8                     AslName[AML_NAME_SEG_SIZE + 1];
+  AML_OBJECT_NODE_HANDLE    LinkNode;
+  AML_OBJECT_NODE_HANDLE    CrsNode;
+  UINT32                    EisaId;
+
+  ASSERT (LinkIndex < 4);
+  ASSERT (PciNode != NULL);
+
+  CopyMem (AslName, "LNKx", AML_NAME_SEG_SIZE + 1);
+  AslName[AML_NAME_SEG_SIZE - 1] = 'A' + LinkIndex;
+
+  // ASL: Device (LNKx) {}
+  Status = AmlCodeGenDevice (AslName, NULL, &LinkNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // The LNKx devices must be defined before being referenced.
+  // Thus add it to the head of the Pci list of variable arguments.
+  Status = AmlAttachNode (PciNode, LinkNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    // Failed to add.
+    AmlDeleteTree ((AML_NODE_HANDLE)LinkNode);
+    return Status;
+  }
+
+  // ASL: Name (_UID, [Uid])
+  Status = AmlCodeGenNameInteger ("_UID", LinkIndex, LinkNode, NULL);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL: Name (_HID, EISAID ("PNP0C0F"))
+  Status = AmlGetEisaIdFromString ("PNP0C0F", &EisaId);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+  Status = AmlCodeGenNameInteger ("_HID", EisaId, LinkNode, NULL);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL:
+  // Name (_PRS, ResourceTemplate () {
+  //   Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { [Irq] }
+  // })
+  Status = AmlCodeGenNameResourceTemplate ("_PRS", LinkNode, &CrsNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+  Status = AmlCodeGenRdInterrupt (
+             FALSE,
+             (IrqFlags & BIT0) != 0,
+             (IrqFlags & BIT1) != 0,
+             FALSE,
+             &Irq,
+             1,
+             CrsNode,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL:
+  // Method (_CRS, 0) {
+  //   Return (_PRS)
+  // }
+  Status = AmlCodeGenMethodRetNameString (
+             "_CRS",
+             "_PRS",
+             0,
+             FALSE,
+             0,
+             LinkNode,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL: Method (_SRS, 1) {}
+  // Not possible to set interrupts.
+  Status = AmlCodeGenMethodRetNameString (
+             "_SRS",
+             NULL,
+             1,
+             FALSE,
+             0,
+             LinkNode,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL:Method (_DIS, 1) {}
+  // Not possible to disable interrupts.
+  Status = AmlCodeGenMethodRetNameString (
+             "_DIS",
+             NULL,
+             0,
+             FALSE,
+             0,
+             LinkNode,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // _STA:
+  // ACPI 6.4, s6.3.7 "_STA (Device Status)":
+  // If a device object describes a device that is not on an enumerable bus
+  // and the device object does not have an _STA object, then OSPM assumes
+  // that the device is present, enabled, shown in the UI, and functioning.
+
+  // _MAT:
+  // Not supported. Mainly used for processors.
+
+  return Status;
+}
+
+/** Generate Pci slots devices.
+
+  PCI Firmware Specification - Revision 3.3,
+  s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot
+  used. It should be possible to enumerate them, but this is additional
+  information.
+
+  @param [in]  MappingTable  The mapping table structure.
+  @param [in, out]  PciNode     Pci node to amend.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePciSlots (
+  IN      CONST MAPPING_TABLE           * MappingTable,
+  IN  OUT       AML_OBJECT_NODE_HANDLE    PciNode
+  )
+{
+  EFI_STATUS                Status;
+  UINT32                    Index;
+  UINT32                    LastIndex;
+  UINT32                    DeviceId;
+  CHAR8                     AslName[AML_NAME_SEG_SIZE + 1];
+  AML_OBJECT_NODE_HANDLE    DeviceNode;
+
+  ASSERT (MappingTable != NULL);
+  ASSERT (PciNode != NULL);
+
+  // Generic device name is "Dxx".
+  CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);
+
+  LastIndex = MappingTable->LastIndex;
+
+  // There are at most 32 devices on a Pci bus.
+  ASSERT (LastIndex < 32);
+
+  for (Index = 0; Index < LastIndex; Index++) {
+    DeviceId = MappingTable->Table[Index];
+    AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);
+    AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);
+
+    // ASL:
+    // Device (Dxx) {
+    //   Name (_ADR, [address value])
+    // }
+    Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+
+    /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
+       High word-Device #, Low word-Function #. (for example, device 3,
+       function 2 is 0x00030002). To refer to all the functions on a device #,
+       use a function number of FFFF).
+    */
+    Status = AmlCodeGenNameInteger (
+               "_ADR",
+               (DeviceId << 16) | 0xFFFF,
+               DeviceNode,
+               NULL
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+
+    // _SUN object is not generated as we don't know which slot will be used.
+  }
+
+  return Status;
+}
+
+/** Generate a _PRT object (Pci Routing Table) for the Pci device.
+
+  Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)"
+
+  @param [in]       Generator       The SSDT Pci generator.
+  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager
+                                    Protocol interface.
+  @param [in]       PciInfo         Pci device information.
+  @param [in, out]  PciNode         Pci node to amend.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePrt (
+  IN            ACPI_PCI_GENERATOR                    *       Generator,
+  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO          *       PciInfo,
+  IN  OUT       AML_OBJECT_NODE_HANDLE                        PciNode
+  )
+{
+  EFI_STATUS                        Status;
+  INT32                             Index;
+  UINT32                            IrqTableIndex;
+  AML_OBJECT_NODE_HANDLE            PrtNode;
+  CHAR8                             AslName[AML_NAME_SEG_SIZE + 1];
+  CM_ARM_OBJ_REF                  * RefInfo;
+  UINT32                            RefCount;
+  CM_ARM_PCI_INTERRUPT_MAP_INFO   * IrqMapInfo;
+  UINT32                            IrqFlags;
+  UINT32                            PrevIrqFlags;
+
+  ASSERT (Generator != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (PciInfo != NULL);
+  ASSERT (PciNode != NULL);
+
+  // Get the array of CM_ARM_OBJ_REF referencing the
+  // CM_ARM_PCI_INTERRUPT_MAP_INFO objects.
+  Status = GetEArmObjCmRef (
+             CfgMgrProtocol,
+             PciInfo->InterruptMapToken,
+             &RefInfo,
+             &RefCount
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Initialized IrqTable.
+  Status = MappingTableInitialize (&Generator->IrqTable, RefCount);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Initialized DeviceTable.
+  Status = MappingTableInitialize (&Generator->DeviceTable, RefCount);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto exit_handler;
+  }
+
+  // ASL: Name (_PRT, Package () {})
+  Status = AmlCodeGenNamePackage ("_PRT", PciNode, &PrtNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto exit_handler;
+  }
+
+  CopyMem (AslName, "LNKx", AML_NAME_SEG_SIZE + 1);
+
+  for (Index = 0; Index < RefCount; Index++) {
+    // Get CM_ARM_PCI_INTERRUPT_MAP_INFO structures one by one.
+    Status = GetEArmObjPciInterruptMapInfo (
+               CfgMgrProtocol,
+               RefInfo[Index].ReferenceToken,
+               &IrqMapInfo,
+               NULL
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      goto exit_handler;
+    }
+
+    // Add the interrupt in the IrqTable and get the link name.
+    IrqTableIndex = MappingTableAdd (
+                      &Generator->IrqTable,
+                      IrqMapInfo->IntcInterrupt.Interrupt
+                      );
+    AslName[AML_NAME_SEG_SIZE - 1] = 'A' + IrqTableIndex;
+
+    // Check that the interrupts flags are identical for all interrupts.
+    PrevIrqFlags = IrqFlags;
+    IrqFlags = IrqMapInfo->IntcInterrupt.Flags;
+    if ((Index > 0) && (PrevIrqFlags != IrqFlags)) {
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    // Add the device to the DeviceTable.
+    MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice);
+
+    /* Add a _PRT entry.
+       ASL
+       Name (_PRT, Package () {
+          [OldPrtEntries],
+         [NewPrtEntry]
+       })
+
+     Address is set as:
+     ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
+       High word-Device #, Low word-Function #. (for example, device 3,
+       function 2 is 0x00030002). To refer to all the functions on a device #,
+       use a function number of FFFF).
+    */
+    Status = AmlAddPrtEntry (
+               (IrqMapInfo->PciDevice << 16) | 0xFFFF,
+               IrqMapInfo->PciInterrupt,
+               AslName,
+               0,
+               PrtNode
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      goto exit_handler;
+    }
+  } // for
+
+  // Generate the LNKx devices now that we know all the interrupts used.
+  // To look nicer, do it in reverse order since LNKx are added to the head.
+  for (Index = Generator->IrqTable.LastIndex - 1; Index >= 0; Index--) {
+    Status = GenerateLinkDevice (
+               Generator->IrqTable.Table[Index],
+               IrqFlags,
+               Index,
+               PciNode
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      goto exit_handler;
+    }
+  } // for
+
+  // Generate the Pci slots once all the device have been added.
+  Status = GeneratePciSlots (&Generator->DeviceTable, PciNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto exit_handler;
+  }
+
+exit_handler:
+  MappingTableFree (&Generator->IrqTable);
+  MappingTableFree (&Generator->DeviceTable);
+
+  return Status;
+}
+
+/** Generate a _CRS method for the Pci device.
+
+  @param [in]       Generator       The SSDT Pci generator.
+  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager
+                                    Protocol interface.
+  @param [in]       PciInfo         Pci device information.
+  @param [in, out]  PciNode         Pci node to amend.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePciCrs (
+  IN            ACPI_PCI_GENERATOR                    *       Generator,
+  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO          *       PciInfo,
+  IN  OUT       AML_OBJECT_NODE_HANDLE                        PciNode
+  )
+{
+  EFI_STATUS                        Status;
+  BOOLEAN                           Translation;
+  UINT32                            Index;
+  CM_ARM_OBJ_REF                  * RefInfo;
+  UINT32                            RefCount;
+  CM_ARM_PCI_ADDRESS_MAP_INFO     * AddrMapInfo;
+  AML_OBJECT_NODE_HANDLE            CrsNode;
+
+  ASSERT (Generator != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (PciInfo != NULL);
+  ASSERT (PciNode != NULL);
+
+  // ASL: Name (_CRS, ResourceTemplate () {})
+  Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // ASL:
+  // WordBusNumber (          // Bus numbers assigned to this root
+  //   ResourceProducer, MinFixed, MaxFixed, PosDecode,
+  //   0,                     // AddressGranularity
+  //   [Start],               // AddressMinimum - Minimum Bus Number
+  //   [End],                 // AddressMaximum - Maximum Bus Number
+  //   0,                     // AddressTranslation - Set to 0
+  //   [End] - [Start] + 1    // RangeLength - Number of Busses
+  // )
+  Status = AmlCodeGenRdWordBusNumber (
+             FALSE, TRUE, TRUE, TRUE,
+             0,
+             PciInfo->StartBusNumber,
+             PciInfo->EndBusNumber,
+             0,
+             PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1,
+             0,
+             NULL,
+             CrsNode,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Get the array of CM_ARM_OBJ_REF referencing the
+  // CM_ARM_PCI_ADDRESS_MAP_INFO objects.
+  Status = GetEArmObjCmRef (
+             CfgMgrProtocol,
+             PciInfo->AddressMapToken,
+             &RefInfo,
+             &RefCount
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  for (Index = 0; Index < RefCount; Index++) {
+    // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.
+    Status = GetEArmObjPciAddressMapInfo (
+               CfgMgrProtocol,
+               RefInfo[Index].ReferenceToken,
+               &AddrMapInfo,
+               NULL
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+
+    Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);
+
+    switch (AddrMapInfo->SpaceCode) {
+      case PCI_SS_IO:
+        Status = AmlCodeGenRdDWordIo (
+                   FALSE, TRUE, TRUE, TRUE, 3,
+                   0,
+                   AddrMapInfo->PciAddress,
+                   AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
+                   Translation ? AddrMapInfo->CpuAddress : 0,
+                   AddrMapInfo->AddressSize,
+                   0, NULL,
+                   TRUE,
+                   FALSE,
+                   CrsNode,
+                   NULL
+                   );
+        break;
+
+      case PCI_SS_M32:
+        Status = AmlCodeGenRdDWordMemory (
+                   FALSE, TRUE, TRUE, TRUE, TRUE, TRUE,
+                   0,
+                   AddrMapInfo->PciAddress,
+                   AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
+                   Translation ? AddrMapInfo->CpuAddress : 0,
+                   AddrMapInfo->AddressSize,
+                   0, NULL,
+                   0,
+                   TRUE,
+                   CrsNode,
+                   NULL
+                   );
+        break;
+
+      case PCI_SS_M64:
+        Status = AmlCodeGenRdQWordMemory (
+                   FALSE, TRUE, TRUE, TRUE, TRUE, TRUE,
+                   0,
+                   AddrMapInfo->PciAddress,
+                   AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
+                   Translation ? AddrMapInfo->CpuAddress : 0,
+                   AddrMapInfo->AddressSize,
+                   0, NULL,
+                   0,
+                   TRUE,
+                   CrsNode,
+                   NULL
+                   );
+        break;
+
+      default:
+        Status = EFI_INVALID_PARAMETER;
+    } // switch
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+  } // for
+  return Status;
+}
+
+/** Add an _OSC template method to the PciNode.
+
+  The _OSC method is provided as an AML blob. The blob is
+  parsed and attached at the end of the PciNode list of variable elements.
+
+  @param [in, out]  PciNode     Pci node to amend.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AddOscMethod (
+  IN  OUT   AML_OBJECT_NODE_HANDLE      PciNode
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_STATUS                    Status1;
+  EFI_ACPI_DESCRIPTION_HEADER * SsdtPcieOscTemplate;
+  AML_ROOT_NODE_HANDLE          RootNode;
+  AML_OBJECT_NODE_HANDLE        OscNode;
+
+  ASSERT (PciNode != NULL);
+
+  // Parse the Ssdt Pci Osc Template.
+  SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER*)
+                          ssdtpcieosctemplate_aml_code;
+
+  RootNode = NULL;
+  Status = AmlParseDefinitionBlock (
+      SsdtPcieOscTemplate,
+             &RootNode
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."
+      " Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  Status = AmlFindNode (RootNode, "\\_OSC", &OscNode);
+  if (EFI_ERROR (Status)) {
+    goto error_handler;
+  }
+
+  Status = AmlDetachNode (OscNode);
+  if (EFI_ERROR (Status)) {
+    goto error_handler;
+  }
+
+  Status = AmlAttachNode (PciNode, OscNode);
+  if (EFI_ERROR (Status)) {
+    goto error_handler;
+  }
+
+error_handler:
+  // Cleanup
+  Status1 = AmlDeleteTree (RootNode);
+  if (EFI_ERROR (Status1)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."
+      " Status = %r\n",
+      Status1
+      ));
+    // If Status was success but we failed to delete the AML Tree
+    // return Status1 else return the original error code, i.e. Status.
+    if (!EFI_ERROR (Status)) {
+      return Status1;
+    }
+  }
+
+  return Status;
+}
+
+/** Generate a Pci device.
+
+  @param [in]       Generator       The SSDT Pci generator.
+  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager
+                                    Protocol interface.
+  @param [in]       PciInfo         Pci device information.
+  @param [in]       Uid             Unique Id of the Pci device.
+  @param [in, out]  RootNode        RootNode of the AML tree to populate.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePciDevice (
+  IN            ACPI_PCI_GENERATOR                    *       Generator,
+  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO          *       PciInfo,
+  IN            UINT32                                        Uid,
+  IN  OUT       AML_ROOT_NODE_HANDLE                  *       RootNode
+  )
+{
+  EFI_STATUS                Status;
+
+  CHAR8                     AslName[AML_NAME_SEG_SIZE + 1];
+  AML_OBJECT_NODE_HANDLE    ScopeNode;
+  AML_OBJECT_NODE_HANDLE    PciNode;
+
+  ASSERT (Generator != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (PciInfo != NULL);
+  ASSERT (RootNode != NULL);
+
+  PciNode = NULL;
+
+  // ASL: Scope (\_SB) {}
+  Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Write the name of the PCI device.
+  CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);
+  AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid);
+
+  // ASL: Device (PCIx) {}
+  Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Populate the PCIx node with some Id values.
+  Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Generate the Pci Routing Table (_PRT).
+  if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) {
+    Status = GeneratePrt (
+               Generator,
+               CfgMgrProtocol,
+               PciInfo,
+               PciNode
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+  }
+
+  // Generate the _CRS method.
+  Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  // Add the template _OSC method.
+  Status = AddOscMethod (PciNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+  }
+
+  return Status;
+}
+
+/** Build an Ssdt table describing a Pci device.
+
+  @param [in]  Generator        The SSDT Pci generator.
+  @param [in]  CfgMgrProtocol   Pointer to the Configuration Manager
+                                Protocol interface.
+  @param [in]  PciInfo          Pci device information.
+  @param [in]  Uid              Unique Id of the Pci device.
+  @param [out] Table            If success, contains the created SSDT table.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSsdtPciTable (
+  IN        ACPI_PCI_GENERATOR                    *       Generator,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
+  IN  CONST CM_ARM_PCI_CONFIG_SPACE_INFO          *       PciInfo,
+  IN        UINT32                                        Uid,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER          **       Table
+  )
+{
+  EFI_STATUS              Status;
+  EFI_STATUS              Status1;
+  AML_ROOT_NODE_HANDLE    RootNode;
+  CHAR8                   OemTableId[9];
+
+  ASSERT (Generator != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (PciInfo != NULL);
+  ASSERT (Table != NULL);
+
+  CopyMem (OemTableId, "SSDTPCIx", sizeof (OemTableId) + 1);
+  OemTableId[7] = AsciiFromHex(Uid);
+
+  // Create a new Ssdt table.
+  Status = AmlCodeGenDefinitionBlock (
+             "SSDT",
+             "ARMLTD",
+             OemTableId,
+             1,
+             &RootNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  Status = GeneratePciDevice (
+             Generator,
+             CfgMgrProtocol,
+             PciInfo,
+             Uid,
+             RootNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    goto exit_handler;
+  }
+
+  // Serialize the tree.
+  Status = AmlSerializeDefinitionBlock (
+             RootNode,
+             Table
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."
+      " Status = %r\n",
+      Status
+      ));
+  }
+
+exit_handler:
+  // Cleanup
+  Status1 = AmlDeleteTree (RootNode);
+  if (EFI_ERROR (Status1)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT-PCI: Failed to cleanup AML tree."
+      " Status = %r\n",
+      Status1
+      ));
+    // If Status was success but we failed to delete the AML Tree
+    // return Status1 else return the original error code, i.e. Status.
+    if (!EFI_ERROR (Status)) {
+      return Status1;
+    }
+  }
+
+  return Status;
+}
+
+/** Construct SSDT tables describing Pci root complexes.
+
+  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 FreeXXXXTableResourcesEx function.
+
+  @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 a list of generated ACPI table(s).
+  @param [out] TableCount      Number of generated ACPI table(s).
+
+  @retval EFI_SUCCESS            Table generated successfully.
+  @retval EFI_BAD_BUFFER_SIZE    The size returned by the Configuration
+                                 Manager is less than the Object size for
+                                 the requested object.
+  @retval EFI_INVALID_PARAMETER  A parameter is invalid.
+  @retval EFI_NOT_FOUND          Could not find information.
+  @retval EFI_OUT_OF_RESOURCES   Could not allocate memory.
+  @retval EFI_UNSUPPORTED        Unsupported configuration.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSsdtPciTableEx (
+  IN  CONST ACPI_TABLE_GENERATOR                   *       This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO             * CONST AcpiTableInfo,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL   * CONST CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER          ***       Table,
+  OUT       UINTN                                  * CONST TableCount
+  )
+{
+  EFI_STATUS                      Status;
+  CM_ARM_PCI_CONFIG_SPACE_INFO  * PciInfo;
+  UINT32                          PciCount;
+  UINTN                           Index;
+  EFI_ACPI_DESCRIPTION_HEADER  ** TableList;
+  ACPI_PCI_GENERATOR            * Generator;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (TableCount != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  *TableCount = 0;
+  Generator = (ACPI_PCI_GENERATOR*)This;
+
+  Status = GetEArmObjPciConfigSpaceInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &PciInfo,
+             &PciCount
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT-PCI: Too many Pci root complexes: %d."
+      " Maximum Pci root complexes supported = %d.\n",
+      PciCount,
+      MAX_PCI_ROOT_COMPLEXES_SUPPORTED
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Allocate a table to store pointers to the SSDT tables.
+  TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
+              AllocateZeroPool (
+                (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * PciCount)
+                );
+  if (TableList == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT-PCI: Failed to allocate memory for Table List."
+      " Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  // Setup the table list early so that appropriate cleanup
+  // can be done in case of failure.
+  *Table = TableList;
+
+  for (Index = 0; Index < PciCount; Index++) {
+    // Build a SSDT table describing the Pci devices.
+    Status = BuildSsdtPciTable (
+               Generator,
+               CfgMgrProtocol,
+               &PciInfo[Index],
+               Index,
+               &TableList[Index]
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: SSDT-PCI: Failed to build associated SSDT table."
+        " Status = %r\n",
+        Status
+        ));
+      goto error_handler;
+    }
+
+    *TableCount += 1;
+  } // for
+
+error_handler:
+  // Note: Table list and Table count have been setup. The
+  // error handler does nothing here as the framework will invoke
+  // FreeSsdtPciTableEx () even on failure.
+  return Status;
+}
+
+/** Free any resources allocated for constructing the tables.
+
+  @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 an array of pointers
+                                  to ACPI Table(s).
+  @param [in]      TableCount     Number of ACPI table(s).
+
+  @retval EFI_SUCCESS           The resources were freed successfully.
+  @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeSsdtPciTableEx (
+  IN      CONST ACPI_TABLE_GENERATOR                   * CONST This,
+  IN      CONST CM_STD_OBJ_ACPI_TABLE_INFO             * CONST AcpiTableInfo,
+  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL   * CONST CfgMgrProtocol,
+  IN OUT        EFI_ACPI_DESCRIPTION_HEADER          *** CONST Table,
+  IN      CONST UINTN                                          TableCount
+  )
+{
+  EFI_ACPI_DESCRIPTION_HEADER    ** TableList;
+  UINTN                             Index;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((Table == NULL)   ||
+      (*Table == NULL)  ||
+      (TableCount == 0)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TableList = *Table;
+  for (Index = 0; Index < TableCount; Index++) {
+    if ((TableList[Index] != NULL) &&
+        (TableList[Index]->Signature ==
+         EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
+      FreePool (TableList[Index]);
+    } else {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: SSDT-PCI: Could not free SSDT table at index %d.",
+        Index
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+  } //for
+
+  // Free the table list.
+  FreePool (*Table);
+
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the SSDT Pci Table Generator revision.
+*/
+#define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the SSDT Pci Table Generator.
+*/
+STATIC
+ACPI_PCI_GENERATOR SsdtPcieGenerator = {
+  // ACPI table generator header
+  {
+    // Generator ID
+    CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress),
+    // Generator Description
+    L"ACPI.STD.SSDT.PCI.GENERATOR",
+    // ACPI Table Signature
+    EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+    // ACPI Table Revision - Unused
+    0,
+    // Minimum ACPI Table Revision - Unused
+    0,
+    // Creator ID
+    TABLE_GENERATOR_CREATOR_ID_ARM,
+    // Creator Revision
+    SSDT_PCI_GENERATOR_REVISION,
+    // Build table function. Use the extended version instead.
+    NULL,
+    // Free table function. Use the extended version instead.
+    NULL,
+    // Extended Build table function.
+    BuildSsdtPciTableEx,
+    // Extended free function.
+    FreeSsdtPciTableEx
+  },
+
+  // Private fields are defined from here.
+
+  // IrqTable
+  {
+      // Table
+      NULL,
+      // LastIndex
+      0,
+      // MaxIndex
+      0
+  },
+  // DeviceTable
+  {
+      // Table
+      NULL,
+      // LastIndex
+      0,
+      // MaxIndex
+      0
+  },
+};
+
+/** 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
+AcpiSsdtPcieLibConstructor (
+  IN  EFI_HANDLE           ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *  SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  Status = RegisterAcpiTableGenerator (&SsdtPcieGenerator.Header);
+  DEBUG ((
+    DEBUG_INFO,
+    "SSDT-PCI: 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
+AcpiSsdtPcieLibDestructor (
+  IN  EFI_HANDLE           ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *  SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  Status = DeregisterAcpiTableGenerator (&SsdtPcieGenerator.Header);
+  DEBUG ((
+    DEBUG_INFO,
+    "SSDT-PCI: Deregister Generator. Status = %r\n",
+    Status
+    ));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
new file mode 100644
index 000000000000..2b7f40447d87
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
@@ -0,0 +1,134 @@
+/** @file
+  SSDT Pcie Table Generator.
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - PCI Firmware Specification - Revision 3.0
+  - ACPI 6.4 specification:
+   - s6.2.13 "_PRT (PCI Routing Table)"
+   - s6.1.1 "_ADR (Address)"
+  - linux kernel code
+**/
+
+#ifndef SSDT_PCIE_GENERATOR_H_
+#define SSDT_PCIE_GENERATOR_H_
+
+/** Pci address attributes.
+*/
+#define PCI_SS_CONFIG   0
+#define PCI_SS_IO       1
+#define PCI_SS_M32      2
+#define PCI_SS_M64      3
+
+/** Maximum Pci root complexes supported by this generator.
+
+  Note: This is not a hard limitation and can be extended if needed.
+        Corresponding changes would be needed to support the Name and
+        UID fields describing the Pci root complexes.
+*/
+#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED    16
+
+/** Maximum number of Pci legacy interrupts.
+
+  Currently 4 for INTA-INTB-INTC-INTD.
+*/
+#define MAX_PCI_LEGACY_INTERRUPT            4
+
+// _SB scope of the AML namespace.
+#define SB_SCOPE                            "\\_SB_"
+
+/** C array containing the compiled AML template.
+    This symbol is defined in the auto generated C file
+    containing the AML bytecode array.
+*/
+extern CHAR8  ssdtpcieosctemplate_aml_code[];
+
+#pragma pack(1)
+
+/** Structure used to map integer to an index.
+*/
+typedef struct MappingTable {
+  /// Mapping table.
+  /// Contains the Index <-> integer mapping
+  UINT32             * Table;
+
+  /// Last used index of the Table.
+  /// Bound by MaxIndex.
+  UINT32               LastIndex;
+
+  /// Number of entries in the Table.
+  UINT32               MaxIndex;
+} MAPPING_TABLE;
+
+/** A structure holding the Pcie generator and additional private data.
+*/
+typedef struct AcpiPcieGenerator {
+  /// ACPI Table generator header
+  ACPI_TABLE_GENERATOR    Header;
+
+  // Private fields are defined from here.
+
+  /** A structure used to handle the Address and Interrupt Map referencing.
+
+    A CM_ARM_PCI_CONFIG_SPACE_INFO structure references two CM_ARM_OBJ_REF:
+     - one for the address mapping, referencing
+       CM_ARM_PCI_ADDRESS_MAP_INFO structures.
+     - one for the address mapping, referencing
+       CM_ARM_PCI_INTERRUPT_MAP_INFO structures.
+
+    Example (for the interrupt mapping):
+    (Pci0)
+    CM_ARM_PCI_CONFIG_SPACE_INFO
+                |
+                v
+    (List of references to address mappings)
+    CM_ARM_OBJ_REF
+                |
+                +----------------------------------------
+                |                                       |
+                v                                       v
+    (A first interrupt mapping)               (A second interrupt mapping)
+    CM_ARM_PCI_INTERRUPT_MAP_INFO[0]          CM_ARM_PCI_INTERRUPT_MAP_INFO[1]
+
+    The CM_ARM_PCI_INTERRUPT_MAP_INFO objects cannot be handled individually.
+    Device's Pci legacy interrupts that are mapped to the same CPU interrupt
+    are grouped under a Link device.
+    For instance, the following mapping:
+     - [INTA of device 0] mapped on [GIC irq 168]
+     - [INTB of device 1] mapped on [GIC irq 168]
+    will be represented in an SSDT table as:
+     - [INTA of device 0] mapped on [Link device A]
+     - [INTB of device 1] mapped on [Link device A]
+     - [Link device A] mapped on [GIC irq 168]
+
+    Counting the number of Cpu interrupts used and grouping them in Link
+    devices is done through this IRQ_TABLE.
+
+    ASL code:
+    Scope (_SB) {
+      Device (LNKA) {
+        [...]
+        Name (_PRS, ResourceTemplate () {
+          Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { 168 }
+        })
+      }
+
+      Device (PCI0) {
+        Name (_PRT, Package () {
+          Package (0x0FFFF, 0, LNKA, 0)  // INTA of device 0 <-> LNKA
+          Package (0x1FFFF, 1, LNKA, 0)  // INTB of device 1 <-> LNKA
+          })
+        }
+    }
+  */
+  MAPPING_TABLE           IrqTable;
+
+  /// Table to map: Index <-> Pci device
+  MAPPING_TABLE           DeviceTable;
+} ACPI_PCI_GENERATOR;
+
+#pragma pack()
+
+#endif // SSDT_PCIE_GENERATOR_H_
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
new file mode 100644
index 000000000000..283b5648017c
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
@@ -0,0 +1,32 @@
+## @file
+# Ssdt Serial Port Table Generator
+#
+#  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION    = 0x0001001B
+  BASE_NAME      = SsdtPcieLibArm
+  FILE_GUID      = E431D7FD-26BF-4E3D-9064-5B13B0439057
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiSsdtPcieLibConstructor
+  DESTRUCTOR     = AcpiSsdtPcieLibDestructor
+
+[Sources]
+  SsdtPcieGenerator.c
+  SsdtPcieGenerator.h
+  SsdtPcieOscTemplate.asl
+
+[Packages]
+  DynamicTablesPkg/DynamicTablesPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  AcpiHelperLib
+  AmlLib
+  BaseLib
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl
new file mode 100644
index 000000000000..feaf56b53384
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl
@@ -0,0 +1,80 @@
+/** @file
+  SSDT Pci Osc (Operating System Capabilities)
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - PCI Firmware Specification - Revision 3.3
+  - ACPI 6.4 specification:
+   - s6.2.13 "_PRT (PCI Routing Table)"
+   - s6.1.1 "_ADR (Address)"
+  - linux kernel code
+**/
+
+DefinitionBlock ("SsdtPciOsc.aml", "SSDT", 2, "ARMLTD", "PCI-OSC", 1) {
+
+  // This table is just a template and is never installed as a table.
+  // Pci devices are dynamically created at runtime as:
+  // ASL:
+  // Device (PCIx) {
+  //   ...
+  // }
+  // and the _OSC method available below is appended to the PCIx device as:
+  // ASL:
+  // Device (PCIx) {
+  //   ...
+  //   Method (_OSC, 4 {
+  //    ...
+  //   })
+  // }
+  Method (_OSC, 4) {
+    //
+    // OS Control Handoff
+    //
+    Name (SUPP, Zero) // PCI _OSC Support Field value
+    Name (CTRL, Zero) // PCI _OSC Control Field value
+
+    // Create DWord-addressable fields from the Capabilities Buffer
+    CreateDWordField (Arg3, 0, CDW1)
+    CreateDWordField (Arg3, 4, CDW2)
+    CreateDWordField (Arg3, 8, CDW3)
+
+    // Check for proper UUID
+    If (LEqual (Arg0,ToUUID ("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
+
+      // Save Capabilities DWord2 & 3
+      Store (CDW2, SUPP)
+      Store (CDW3, CTRL)
+
+      // Only allow native hot plug control if OS supports:
+      // * ASPM
+      // * Clock PM
+      // * MSI/MSI-X
+      If (LNotEqual (And (SUPP, 0x16), 0x16)) {
+        And (CTRL, 0x1E, CTRL) // Mask bit 0 (and undefined bits)
+      }
+
+      // Always allow native PME, AER (no dependencies)
+
+      // Never allow SHPC (no SHPC controller in this system)
+      And (CTRL, 0x1D, CTRL)
+
+      If (LNotEqual (Arg1, One)) {  // Unknown revision
+        Or (CDW1, 0x08, CDW1)
+      }
+
+      If (LNotEqual (CDW3, CTRL)) {  // Capabilities bits were masked
+        Or (CDW1, 0x10, CDW1)
+      }
+
+      // Update DWORD3 in the buffer
+      Store (CTRL,CDW3)
+      Return (Arg3)
+    } Else {
+      Or (CDW1, 4, CDW1) // Unrecognized UUID
+      Return (Arg3)
+    } // If
+  } // _OSC
+}
-- 
2.17.1


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

* Re: [PATCH v1 1/7] DynamicTablesPkg: AML Code generation for memory ranges
  2021-06-23 11:58 ` [PATCH v1 1/7] DynamicTablesPkg: AML Code generation for memory ranges PierreGondois
@ 2021-10-06 15:14   ` Sami Mujawar
  0 siblings, 0 replies; 15+ messages in thread
From: Sami Mujawar @ 2021-10-06 15:14 UTC (permalink / raw)
  To: Pierre.Gondois, devel, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei, nd

Hi Pierre,

Please find my feedback marked inline as [SAMI].

Regards,

Sami Mujawar


On 23/06/2021 12:58 PM, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <Pierre.Gondois@arm.com>
>
> Add helper functions to generate AML Resource Data describing memory
> ranges. Memory ranges can be one, double or four words long. They
> can be of 'normal', IO or bus number memory type. The following
> APIs are exposed:
>   - AmlCodeGenRdDWordIo ()
>   - AmlCodeGenRdDWordMemory ()
>   - AmlCodeGenRdWordBusNumber ()
>   - AmlCodeGenRdQWordMemory ()
>
> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
> ---
>   .../Include/Library/AmlLib/AmlLib.h           | 289 ++++++
>   .../AmlLib/CodeGen/AmlResourceDataCodeGen.c   | 945 ++++++++++++++++++
>   2 files changed, 1234 insertions(+)
>
> diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> index 4932f6fd9c8b..cbbbb7a478f7 100644
> --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> @@ -418,6 +418,295 @@ AmlUpdateRdQWord (
>     IN  UINT64                BaseAddressLength
>     );
>   
> +/** Code generation for the "DWordIO ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
[SAMI] I think the text above needs updating. Same comment for other 
functions in this patch.
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.2 "DWord Address Space Descriptor".
> +   - s19.6.34 "DWordIO".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @ingroup CodeGenApis
> +
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.34 for more.
[SAMI] Add brief description about the parameter in addition to the 
specification reference.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsaRanges            Available values are:
> +                                     0-Reserved
> +                                     1-NonISAOnly
> +                                     2-ISAOnly
> +                                     3-EntireRange
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.34 for more.
> +                                    Not supported.
[SAMI] I think it would be good to mention that this parameter is unused 
and is provided here for compatibility with the ACPI DWordIo() resource 
descriptor macro.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.34 for more.
> +                                    Not supported.
> +  @param [in]  IsDenseTranslation   TranslationDensity parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsTypeStatic         TranslationType parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdDWordIo (
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        UINT8                   IsaRanges,
> +  IN        UINT32                  AddressGranularity,
> +  IN        UINT32                  AddressMinimum,
> +  IN        UINT32                  AddressMaximum,
> +  IN        UINT32                  AddressTranslation,
> +  IN        UINT32                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        BOOLEAN                 IsDenseTranslation,
> +  IN        BOOLEAN                 IsTypeStatic,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  );
> +
> +/** Code generation for the "DWordMemory ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.2 "DWord Address Space Descriptor".
> +   - s19.6.35 "DWordMemory".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @ingroup CodeGenApis
> +
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  Cacheable            Available values are:
> +                                    0-The memory is non-cacheable
> +                                    1-The memory is cacheable
> +                                    2-The memory is cacheable and supports
> +                                      write combining
> +                                    3-The memory is cacheable and prefetchable
> +  @param [in]  IsReadWrite          ReadAndWrite parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.35 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.35 for more.
> +                                    Not supported.
> +  @param [in]  MemoryRangeType      Available values are:
> +                                      0-AddressRangeMemory
> +                                      1-AddressRangeReserved
> +                                      2-AddressRangeACPI
> +                                      3-AddressRangeNVS
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsTypeStatic         TranslationType parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdDWordMemory (
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        UINT8                   Cacheable,
> +  IN        BOOLEAN                 IsReadWrite,
> +  IN        UINT32                  AddressGranularity,
> +  IN        UINT32                  AddressMinimum,
> +  IN        UINT32                  AddressMaximum,
> +  IN        UINT32                  AddressTranslation,
> +  IN        UINT32                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        UINT8                   MemoryRangeType,
> +  IN        BOOLEAN                 IsTypeStatic,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  );
> +
> +/** Code generation for the "WordBusNumber ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.3 "Word Address Space Descriptor".
> +   - s19.6.149 "WordBusNumber".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @ingroup CodeGenApis
> +
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.149 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.149 for more.
> +                                    Not supported.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdWordBusNumber (
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        UINT32                  AddressGranularity,
> +  IN        UINT32                  AddressMinimum,
> +  IN        UINT32                  AddressMaximum,
> +  IN        UINT32                  AddressTranslation,
> +  IN        UINT32                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  );
> +
> +/** Code generation for the "QWordMemory ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.1 "QWord Address Space Descriptor".
> +   - s19.6.110 "QWordMemory".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @ingroup CodeGenApis
> +
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  Cacheable            Available values are:
> +                                    0-The memory is non-cacheable
> +                                    1-The memory is cacheable
> +                                    2-The memory is cacheable and supports
> +                                      write combining
> +                                    3-The memory is cacheable and prefetchable
> +  @param [in]  IsReadWrite          ReadAndWrite parameter,
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.110 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.110 for more.
> +                                    Not supported.
> +  @param [in]  MemoryRangeType      Available values are:
> +                                      0-AddressRangeMemory
> +                                      1-AddressRangeReserved
> +                                      2-AddressRangeACPI
> +                                      3-AddressRangeNVS
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  IsTypeStatic         TranslationType parameter,
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdQWordMemory (
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        UINT8                   Cacheable,
> +  IN        BOOLEAN                 IsReadWrite,
> +  IN        UINT64                  AddressGranularity,
> +  IN        UINT64                  AddressMinimum,
> +  IN        UINT64                  AddressMaximum,
> +  IN        UINT64                  AddressTranslation,
> +  IN        UINT64                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        UINT8                   MemoryRangeType,
> +  IN        BOOLEAN                 IsTypeStatic,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  );
> +
>   /** Code generation for the "Interrupt ()" ASL function.
>   
>     The Resource Data effectively created is an Extended Interrupt Resource
> diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
> index 78910cc5d4b4..3ab78d4fce22 100644
> --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
> +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
> @@ -94,6 +94,951 @@ error_handler:
>     return Status;
>   }
>   
> +/** Populate the TypeSpecificFlags field for IO ranges.
> +
> +  @param [in]  IsaRanges            Available values are:
> +                                     0-Reserved
> +                                     1-NonISAOnly
> +                                     2-ISAOnly
> +                                     3-EntireRange
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsDenseTranslation   TranslationDensity parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsTypeStatic         TranslationType parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +
> +  @return A TypeSpecificFlagsvalue.
> +          MAX_UINT8 if error.
> +**/
> +STATIC
> +UINT8
> +EFIAPI
> +RdIoRangeSpecificFlags (
> +  IN  UINT8     IsaRanges,
> +  IN  BOOLEAN   IsDenseTranslation,
> +  IN  BOOLEAN   IsTypeStatic
> +  )
> +{
> +  // Only check type specific parameters.
> +  if (IsaRanges > 3) {
> +    ASSERT (0);
> +    return MAX_UINT8;
> +  }
> +
> +  // Populate TypeSpecificFlags and call the generic function.
> +  // Cf ACPI 6.4 specification, Table 6.50:
> +  // "Table 6.50: I/O Resource Flag (Resource Type = 1) Definitions"
> +  return  IsaRanges                 |
> +          (IsTypeStatic ? 0 : BIT4) |
> +          (IsDenseTranslation ? 0 : BIT5);
> +}
> +
> +/** Populate the TypeSpecificFlags field for Memory ranges.
[SAMI] Construct type specific flags for Memory ranges? Same for other 
functions in this patch.
> +
> +  @param [in]  Cacheable            Available values are:
[SAMI] Maybe the description should say Possible values are.
> +                                    0-The memory is non-cacheable
> +                                    1-The memory is cacheable
> +                                    2-The memory is cacheable and supports
> +                                      write combining
> +                                    3-The memory is cacheable and prefetchable
> +  @param [in]  IsReadWrite          ReadAndWrite parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  MemoryRangeType      Available values are:
> +                                      0-AddressRangeMemory
> +                                      1-AddressRangeReserved
> +                                      2-AddressRangeACPI
> +                                      3-AddressRangeNVS
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsTypeStatic         TranslationType parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +
> +  @return A TypeSpecificFlagsvalue.
[SAMI] I think this should be changed to 'Returns a type specific flag 
value'.
> +          MAX_UINT8 if error.
> +**/
> +STATIC
> +UINT8
> +EFIAPI
> +MemoryRangeSpecificFlags (
> +  IN  UINT8     Cacheable,
> +  IN  BOOLEAN   IsReadWrite,
> +  IN  UINT8     MemoryRangeType,
> +  IN  BOOLEAN   IsTypeStatic
> +  )
> +{
> +  // Only check type specific parameters.
> +  if ((Cacheable > 3) ||
> +      (MemoryRangeType > 3)) {
> +    ASSERT (0);
> +    return MAX_UINT8;
> +  }
> +
> +  // Populate TypeSpecificFlags and call the generic function.
> +  // Cf ACPI 6.4 specification, Table 6.49:
> +  // "Memory Resource Flag (Resource Type = 0) Definitions"
> +  return (IsReadWrite ? BIT0 : 0)  |
> +         (Cacheable << 1)          |
> +         (MemoryRangeType << 3)    |
> +         (IsTypeStatic ? 0 : BIT5);
> +}
> +
> +/** Populate the GeneralFlags field of any Address Space Resource Descriptors.
> +
> +  E.g.:
> +  ACPI 6.4 specification, s6.4.3.5.1 "QWord Address Space Descriptor"
> +  for QWord
> +
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.36 for more.
> +
> +  @return A TypeSpecificFlagsvalue.
> +**/
> +STATIC
> +UINT8
> +EFIAPI
> +AddressSpaceGeneralFlags (
> +  IN  BOOLEAN   IsPosDecode,
> +  IN  BOOLEAN   IsMinFixed,
> +  IN  BOOLEAN   IsMaxFixed
> +  )
> +{
> +  return (IsPosDecode ? 0 : BIT1)    |
> +         (IsMinFixed ? BIT2 : 0)     |
> +         (IsMaxFixed ? BIT3 : 0);
> +}
> +
> +/** Check Address Space Descriptor Fields.
> +
> +  Cf. ACPI 6.4 Table 6.44:
> +  "Valid Combination of Address Space Descriptor Fields"
> +
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.36 for more.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +CheckAddressSpaceFields (
> +  IN  BOOLEAN   IsMinFixed,
> +  IN  BOOLEAN   IsMaxFixed,
> +  IN  UINT64    AddressGranularity,
> +  IN  UINT64    AddressMinimum,
> +  IN  UINT64    AddressMaximum,
> +  IN  UINT64    AddressTranslation,
> +  IN  UINT64    RangeLength
> +  )
> +{
> +  if ((AddressMinimum > AddressMaximum)                     ||
> +      (RangeLength > (AddressMaximum - AddressMinimum + 1)) ||
> +      ((AddressGranularity != 0) &&
> +       ((AddressGranularity + 1) & AddressGranularity) != 0)) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (RangeLength != 0) {
> +    if (IsMinFixed ^ IsMaxFixed) {
> +      ASSERT (0);
> +      return EFI_INVALID_PARAMETER;
> +    } else if (IsMinFixed                 &&
> +               IsMaxFixed                 &&
> +               (AddressGranularity != 0)  &&
> +               ((AddressMaximum - AddressMinimum + 1) != RangeLength)) {
> +      ASSERT (0);
> +      return EFI_INVALID_PARAMETER;
> +    }
> +  } else {
> +    if (IsMinFixed && IsMaxFixed) {
> +      ASSERT (0);
> +      return EFI_INVALID_PARAMETER;
> +    } else if (IsMinFixed &&
> +              ((AddressMinimum & AddressGranularity) != 0)) {
> +      ASSERT (0);
> +      return EFI_INVALID_PARAMETER;
> +    } else if (IsMaxFixed &&
> +              (((AddressMaximum + 1) & AddressGranularity) != 0)) {
> +      ASSERT (0);
> +      return EFI_INVALID_PARAMETER;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Code generation for the "DWordSpace ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.2 "DWord Address Space Descriptor".
> +   - s19.6.36 "DWordSpace".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @param [in]  ResourceType         See ACPI 6.4 spec, s6.4.3.5.2 for more.
> +                                    Available values are:
> +                                      0:        Memory range
> +                                      1:        I/O range
> +                                      2:        Bus number range
> +                                      3-191:    Reserved
> +                                      192-255:  Hardware Vendor Defined
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  TypeSpecificFlags    See ACPI 6.4 spec, s6.4.3.5.5
> +                                    "Resource Type Specific Flags".
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.36 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.36 for more.
> +                                    Not supported.
[SAMI] I think you should mentions 'Not supported, must be 0.'
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.36 for more.
> +                                    Not supported.
[SAMI] I think you should mentions 'Not supported, must be NULL.'
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdDWordSpace (
> +  IN        UINT8                   ResourceType,
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        UINT8                   TypeSpecificFlags,
> +  IN        UINT32                  AddressGranularity,
> +  IN        UINT32                  AddressMinimum,
> +  IN        UINT32                  AddressMaximum,
> +  IN        UINT32                  AddressTranslation,
> +  IN        UINT32                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  )
> +{
> +  EFI_STATUS                                Status;
> +  AML_DATA_NODE                           * RdNode;
> +  EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR   RdDWord;
> +
> +  // ResourceSource and ResourceSourceIndex are not supported.
> +  if ((TypeSpecificFlags == MAX_UINT8)  ||
> +      (ResourceSourceIndex != 0)        ||
> +      (ResourceSource != NULL)          ||
> +      ((NameOpNode == NULL) && (NewRdNode == NULL))) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = CheckAddressSpaceFields (
> +             IsMinFixed,
> +             IsMaxFixed,
> +             AddressGranularity,
> +             AddressMinimum,
> +             AddressMaximum,
> +             AddressTranslation,
> +             RangeLength
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Header
> +  RdDWord.Header.Header.Bits.Name =
> +    ACPI_LARGE_DWORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
> +  RdDWord.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
> +  RdDWord.Header.Length = sizeof (EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR) -
> +                               sizeof (ACPI_LARGE_RESOURCE_HEADER);
> +
> +  // Body
> +  RdDWord.ResType = ResourceType;
> +  RdDWord.GenFlag = AddressSpaceGeneralFlags (
> +                      IsPosDecode,
> +                      IsMinFixed,
> +                      IsMaxFixed
> +                      );
> +  RdDWord.SpecificFlag = TypeSpecificFlags;
> +  RdDWord.AddrSpaceGranularity = AddressGranularity;
> +  RdDWord.AddrRangeMin = AddressMinimum;
> +  RdDWord.AddrRangeMax = AddressMaximum;
> +  RdDWord.AddrTranslationOffset = AddressTranslation;
> +  RdDWord.AddrLen = RangeLength;
> +
> +  Status = AmlCreateDataNode (
> +             EAmlNodeDataTypeResourceData,
> +             (UINT8*)&RdDWord,
> +             sizeof (EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR),
> +             &RdNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  return LinkRdNode (RdNode, NameOpNode, NewRdNode);
> +}
> +
> +/** Code generation for the "DWordIO ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.2 "DWord Address Space Descriptor".
> +   - s19.6.34 "DWordIO".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsaRanges            Available values are:
> +                                     0-Reserved
> +                                     1-NonISAOnly
> +                                     2-ISAOnly
> +                                     3-EntireRange
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.34 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.34 for more.
> +                                    Not supported.
> +  @param [in]  IsDenseTranslation   TranslationDensity parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  IsTypeStatic         TranslationType parameter,
> +                                    See ACPI 6.4 spec, s19.6.34 for more.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdDWordIo (
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        UINT8                   IsaRanges,
> +  IN        UINT32                  AddressGranularity,
> +  IN        UINT32                  AddressMinimum,
> +  IN        UINT32                  AddressMaximum,
> +  IN        UINT32                  AddressTranslation,
> +  IN        UINT32                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        BOOLEAN                 IsDenseTranslation,
> +  IN        BOOLEAN                 IsTypeStatic,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  )
> +{
> +  return AmlCodeGenRdDWordSpace (
> +           ACPI_ADDRESS_SPACE_TYPE_IO,
> +           IsResourceConsumer,
> +           IsPosDecode,
> +           IsMinFixed,
> +           IsMaxFixed,
> +           RdIoRangeSpecificFlags (
> +             IsaRanges,
> +             IsDenseTranslation,
> +             IsTypeStatic
> +             ),
> +           AddressGranularity,
> +           AddressMinimum,
> +           AddressMaximum,
> +           AddressTranslation,
> +           RangeLength,
> +           ResourceSourceIndex,
> +           ResourceSource,
> +           NameOpNode,
> +           NewRdNode
> +           );
> +}
> +
> +/** Code generation for the "DWordMemory ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.2 "DWord Address Space Descriptor".
> +   - s19.6.35 "DWordMemory".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  Cacheable            Available values are:
> +                                    0-The memory is non-cacheable
> +                                    1-The memory is cacheable
> +                                    2-The memory is cacheable and supports
> +                                      write combining
> +                                    3-The memory is cacheable and prefetchable
> +  @param [in]  IsReadWrite          ReadAndWrite parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.35 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.35 for more.
> +                                    Not supported.
> +  @param [in]  MemoryRangeType      Available values are:
> +                                      0-AddressRangeMemory
> +                                      1-AddressRangeReserved
> +                                      2-AddressRangeACPI
> +                                      3-AddressRangeNVS
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  IsTypeStatic         TranslationType parameter,
> +                                    See ACPI 6.4 spec, s19.6.35 for more.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdDWordMemory (
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        UINT8                   Cacheable,
> +  IN        BOOLEAN                 IsReadWrite,
> +  IN        UINT32                  AddressGranularity,
> +  IN        UINT32                  AddressMinimum,
> +  IN        UINT32                  AddressMaximum,
> +  IN        UINT32                  AddressTranslation,
> +  IN        UINT32                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        UINT8                   MemoryRangeType,
> +  IN        BOOLEAN                 IsTypeStatic,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  )
> +{
> +  return AmlCodeGenRdDWordSpace (
> +           ACPI_ADDRESS_SPACE_TYPE_MEM,
> +           IsResourceConsumer,
> +           IsPosDecode,
> +           IsMinFixed,
> +           IsMaxFixed,
> +           MemoryRangeSpecificFlags (
> +             Cacheable,
> +             IsReadWrite,
> +             MemoryRangeType,
> +             IsTypeStatic
> +             ),
> +           AddressGranularity,
> +           AddressMinimum,
> +           AddressMaximum,
> +           AddressTranslation,
> +           RangeLength,
> +           ResourceSourceIndex,
> +           ResourceSource,
> +           NameOpNode,
> +           NewRdNode
> +           );
> +}
> +
> +/** Code generation for the "WordSpace ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.3 "Word Address Space Descriptor".
> +   - s19.6.151 "WordSpace".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @param [in]  ResourceType         See ACPI 6.4 spec, s6.4.3.5.3 for more.
> +                                    Available values are:
> +                                      0:        Memory range
> +                                      1:        I/O range
> +                                      2:        Bus number range
> +                                      3-191:    Reserved
> +                                      192-255:  Hardware Vendor Defined
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  TypeSpecificFlags    See ACPI 6.4 spec, s6.4.3.5.5
> +                                    "Resource Type Specific Flags".
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.151 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.151 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.151 for more.
> +                                    Not supported.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdWordSpace (
> +  IN        UINT8                   ResourceType,
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        UINT8                   TypeSpecificFlags,
> +  IN        UINT16                  AddressGranularity,
> +  IN        UINT16                  AddressMinimum,
> +  IN        UINT16                  AddressMaximum,
> +  IN        UINT16                  AddressTranslation,
> +  IN        UINT16                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  )
> +{
> +  EFI_STATUS                                Status;
> +  AML_DATA_NODE                           * RdNode;
> +  EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR    Rdword;
> +
> +  // ResourceSource and ResourceSourceIndex are not supported.
> +  if ((TypeSpecificFlags == MAX_UINT8)  ||
> +      (ResourceSourceIndex != 0)        ||
> +      (ResourceSource != NULL)          ||
> +      ((NameOpNode == NULL) && (NewRdNode == NULL))) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = CheckAddressSpaceFields (
> +             IsMinFixed,
> +             IsMaxFixed,
> +             AddressGranularity,
> +             AddressMinimum,
> +             AddressMaximum,
> +             AddressTranslation,
> +             RangeLength
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Header
> +  Rdword.Header.Header.Bits.Name =
> +    ACPI_LARGE_WORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
> +  Rdword.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
> +  Rdword.Header.Length = sizeof (EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR) -
> +                               sizeof (ACPI_LARGE_RESOURCE_HEADER);
> +
> +  // Body
> +  Rdword.ResType = ResourceType;
> +  Rdword.GenFlag = AddressSpaceGeneralFlags (
> +                     IsPosDecode,
> +                     IsMinFixed,
> +                     IsMaxFixed
> +                     );
> +  Rdword.SpecificFlag = TypeSpecificFlags;
> +  Rdword.AddrSpaceGranularity = AddressGranularity;
> +  Rdword.AddrRangeMin = AddressMinimum;
> +  Rdword.AddrRangeMax = AddressMaximum;
> +  Rdword.AddrTranslationOffset = AddressTranslation;
> +  Rdword.AddrLen = RangeLength;
> +
> +  Status = AmlCreateDataNode (
> +             EAmlNodeDataTypeResourceData,
> +             (UINT8*)&Rdword,
> +             sizeof (EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR),
> +             &RdNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  return LinkRdNode (RdNode, NameOpNode, NewRdNode);
> +}
> +
> +/** Code generation for the "WordBusNumber ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.3 "Word Address Space Descriptor".
> +   - s19.6.149 "WordBusNumber".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.149 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.149 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.149 for more.
> +                                    Not supported.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdWordBusNumber (
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        UINT32                  AddressGranularity,
> +  IN        UINT32                  AddressMinimum,
> +  IN        UINT32                  AddressMaximum,
> +  IN        UINT32                  AddressTranslation,
> +  IN        UINT32                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  )
> +{
> +  // There is no Type Specific Flags for buses.
> +  return AmlCodeGenRdWordSpace (
> +           ACPI_ADDRESS_SPACE_TYPE_BUS,
> +           IsResourceConsumer,
> +           IsPosDecode,
> +           IsMinFixed,
> +           IsMaxFixed,
> +           0,
> +           AddressGranularity,
> +           AddressMinimum,
> +           AddressMaximum,
> +           AddressTranslation,
> +           RangeLength,
> +           ResourceSourceIndex,
> +           ResourceSource,
> +           NameOpNode,
> +           NewRdNode
> +           );
> +}
> +
> +/** Code generation for the "QWordSpace ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.1 "QWord Address Space Descriptor".
> +   - s19.6.111 "QWordSpace".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @param [in]  ResourceType         See ACPI 6.4 spec, s6.4.3.5.1 for more.
> +                                    Available values are:
> +                                      0:        Memory range
> +                                      1:        I/O range
> +                                      2:        Bus number range
> +                                      3-191:    Reserved
> +                                      192-255:  Hardware Vendor Defined
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  TypeSpecificFlags    See ACPI 6.4 spec, s6.4.3.5.5
> +                                    "Resource Type Specific Flags".
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.111 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.111 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.111 for more.
> +                                    Not supported.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdQWordSpace (
> +  IN        UINT8                   ResourceType,
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        UINT8                   TypeSpecificFlags,
> +  IN        UINT64                  AddressGranularity,
> +  IN        UINT64                  AddressMinimum,
> +  IN        UINT64                  AddressMaximum,
> +  IN        UINT64                  AddressTranslation,
> +  IN        UINT64                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  )
> +{
> +  EFI_STATUS                                Status;
> +  AML_DATA_NODE                           * RdNode;
> +  EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR   RdQword;
> +
> +  // ResourceSource and ResourceSourceIndex are not supported.
> +  if ((TypeSpecificFlags == MAX_UINT8)  ||
> +      (ResourceSourceIndex != 0)        ||
> +      (ResourceSource != NULL)          ||
> +      ((NameOpNode == NULL) && (NewRdNode == NULL))) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = CheckAddressSpaceFields (
> +             IsMinFixed,
> +             IsMaxFixed,
> +             AddressGranularity,
> +             AddressMinimum,
> +             AddressMaximum,
> +             AddressTranslation,
> +             RangeLength
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Header
> +  RdQword.Header.Header.Bits.Name =
> +    ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
> +  RdQword.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
> +  RdQword.Header.Length = sizeof (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) -
> +                               sizeof (ACPI_LARGE_RESOURCE_HEADER);
> +
> +  // Body
> +  RdQword.ResType = ResourceType;
> +  RdQword.GenFlag = AddressSpaceGeneralFlags (
> +                      IsPosDecode,
> +                      IsMinFixed,
> +                      IsMaxFixed
> +                      );
> +  RdQword.SpecificFlag = TypeSpecificFlags;
> +  RdQword.AddrSpaceGranularity = AddressGranularity;
> +  RdQword.AddrRangeMin = AddressMinimum;
> +  RdQword.AddrRangeMax = AddressMaximum;
> +  RdQword.AddrTranslationOffset = AddressTranslation;
> +  RdQword.AddrLen = RangeLength;
> +
> +  Status = AmlCreateDataNode (
> +             EAmlNodeDataTypeResourceData,
> +             (UINT8*)&RdQword,
> +             sizeof (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR),
> +             &RdNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  return LinkRdNode (RdNode, NameOpNode, NewRdNode);
> +}
> +
> +/** Code generation for the "QWordMemory ()" ASL function.
> +
> +  The Resource Data effectively created is an Extended Interrupt Resource
> +  Data. Cf ACPI 6.4:
> +   - s6.4.3.5.1 "QWord Address Space Descriptor".
> +   - s19.6.110 "QWordMemory".
> +
> +  The created resource data node can be:
> +   - appended to the list of resource data elements of the NameOpNode.
> +     In such case NameOpNode must be defined by a the "Name ()" ASL statement
> +     and initially contain a "ResourceTemplate ()".
> +   - returned through the NewRdNode parameter.
> +
> +  @param [in]  IsResourceConsumer   ResourceUsage parameter,
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  IsPosDecode          Decode parameter,
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  IsMinFixed           See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  IsMaxFixed           See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  Cacheable            Available values are:
> +                                    0-The memory is non-cacheable
> +                                    1-The memory is cacheable
> +                                    2-The memory is cacheable and supports
> +                                      write combining
> +                                    3-The memory is cacheable and prefetchable
> +  @param [in]  IsReadWrite          ReadAndWrite parameter,
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  AddressGranularity   See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  AddressMinimum       See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  AddressMaximum       See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  AddressTranslation   See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  RangeLength          See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  ResourceSourceIndex  See ACPI 6.4 spec, s19.6.110 for more.
> +                                    Not supported.
> +  @param [in]  ResourceSource       See ACPI 6.4 spec, s19.6.110 for more.
> +                                    Not supported.
> +  @param [in]  MemoryRangeType      Available values are:
> +                                      0-AddressRangeMemory
> +                                      1-AddressRangeReserved
> +                                      2-AddressRangeACPI
> +                                      3-AddressRangeNVS
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  IsTypeStatic         TranslationType parameter,
> +                                    See ACPI 6.4 spec, s19.6.110 for more.
> +  @param [in]  NameOpNode           NameOp object node defining a named object.
> +                                    If provided, append the new resource data
> +                                    node to the list of resource data elements
> +                                    of this node.
> +  @param [out] NewRdNode            If provided and success,
> +                                    contain the created node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenRdQWordMemory (
> +  IN        BOOLEAN                 IsResourceConsumer,
> +  IN        BOOLEAN                 IsPosDecode,
> +  IN        BOOLEAN                 IsMinFixed,
> +  IN        BOOLEAN                 IsMaxFixed,
> +  IN        UINT8                   Cacheable,
> +  IN        BOOLEAN                 IsReadWrite,
> +  IN        UINT64                  AddressGranularity,
> +  IN        UINT64                  AddressMinimum,
> +  IN        UINT64                  AddressMaximum,
> +  IN        UINT64                  AddressTranslation,
> +  IN        UINT64                  RangeLength,
> +  IN        UINT8                   ResourceSourceIndex,
> +  IN  CONST CHAR8                   *ResourceSource,
> +  IN        UINT8                   MemoryRangeType,
> +  IN        BOOLEAN                 IsTypeStatic,
> +  IN        AML_OBJECT_NODE_HANDLE  NameOpNode, OPTIONAL
> +  OUT       AML_DATA_NODE_HANDLE    *NewRdNode  OPTIONAL
> +  )
> +{
> +  return AmlCodeGenRdQWordSpace (
> +           ACPI_ADDRESS_SPACE_TYPE_MEM,
> +           IsResourceConsumer,
> +           IsPosDecode,
> +           IsMinFixed,
> +           IsMaxFixed,
> +           MemoryRangeSpecificFlags (
> +             Cacheable,
> +             IsReadWrite,
> +             MemoryRangeType,
> +             IsTypeStatic
> +             ),
> +           AddressGranularity,
> +           AddressMinimum,
> +           AddressMaximum,
> +           AddressTranslation,
> +           RangeLength,
> +           ResourceSourceIndex,
> +           ResourceSource,
> +           NameOpNode,
> +           NewRdNode
> +           );
> +}
> +
>   /** Code generation for the "Interrupt ()" ASL function.
>   
>     The Resource Data effectively created is an Extended Interrupt Resource


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

* Re: [PATCH v1 2/7] DynamicTablesPkg: AML Code generation to create a named Package()
  2021-06-23 11:58 ` [PATCH v1 2/7] DynamicTablesPkg: AML Code generation to create a named Package() PierreGondois
@ 2021-10-06 15:15   ` Sami Mujawar
  0 siblings, 0 replies; 15+ messages in thread
From: Sami Mujawar @ 2021-10-06 15:15 UTC (permalink / raw)
  To: Pierre.Gondois, devel, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei, nd

Hi Pierre,

Thank you for this patch. These changes look good to me.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar


On 23/06/2021 12:58 PM, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <Pierre.Gondois@arm.com>
>
> Add AmlCodeGenNamePackage() to generate code for a Package().
>
> AmlCodeGenNamePackage ("PACK", ParentNode, NewObjectNode) is
> equivalent of the following ASL code:
>     Name(PACK, Package () {})
>
> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
> ---
>   .../Include/Library/AmlLib/AmlLib.h           | 28 ++++++++++
>   .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 55 +++++++++++++++++++
>   2 files changed, 83 insertions(+)
>
> diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> index cbbbb7a478f7..412db886e1f2 100644
> --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> @@ -852,6 +852,34 @@ AmlCodeGenNameInteger (
>     OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
>     );
>   
> +/** AML code generation for a Name object node, containing a Package.
> +
> +  AmlCodeGenNamePackage ("PKG0", ParentNode, NewObjectNode) is
> +  equivalent of the following ASL code:
> +    Name(PKG0, Package () {})
> +
> +  @ingroup CodeGenApis
> +
> +  @param [in]  NameString     The new variable name.
> +                              Must be a NULL-terminated ASL NameString
> +                              e.g.: "DEV0", "DV15.DEV0", etc.
> +                              The input string is copied.
> +  @param [in]  ParentNode     If provided, set ParentNode as the parent
> +                              of the node created.
> +  @param [out] NewObjectNode  If success, contains the created node.
> +
> +  @retval EFI_SUCCESS             Success.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenNamePackage (
> +  IN  CONST CHAR8                   * NameString,
> +  IN        AML_NODE_HANDLE           ParentNode,     OPTIONAL
> +  OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
> +  );
> +
>   /** AML code generation for a Device object node.
>   
>     AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
> diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> index f0861040191f..f9175c623622 100644
> --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> @@ -747,6 +747,61 @@ AmlCodeGenNameInteger (
>     return Status;
>   }
>   
> +/** AML code generation for a Name object node, containing a Package.
> +
> +  AmlCodeGenNamePackage ("PKG0", ParentNode, NewObjectNode) is
> +  equivalent of the following ASL code:
> +    Name(PKG0, Package () {})
> +
> +  @param [in]  NameString     The new variable name.
> +                              Must be a NULL-terminated ASL NameString
> +                              e.g.: "DEV0", "DV15.DEV0", etc.
> +                              The input string is copied.
> +  @param [in]  ParentNode     If provided, set ParentNode as the parent
> +                              of the node created.
> +  @param [out] NewObjectNode  If success, contains the created node.
> +
> +  @retval EFI_SUCCESS             Success.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenNamePackage (
> +  IN  CONST CHAR8              * NameString,
> +  IN        AML_NODE_HEADER    * ParentNode,     OPTIONAL
> +  OUT       AML_OBJECT_NODE   ** NewObjectNode   OPTIONAL
> +  )
> +{
> +  EFI_STATUS          Status;
> +  AML_OBJECT_NODE   * PackageNode;
> +
> +  if ((NameString == NULL)  ||
> +      ((ParentNode == NULL) && (NewObjectNode == NULL))) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = AmlCodeGenPackage (&PackageNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  Status = AmlCodeGenName (
> +             NameString,
> +             PackageNode,
> +             ParentNode,
> +             NewObjectNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    AmlDeleteTree ((AML_NODE_HEADER*)PackageNode);
> +  }
> +
> +  return Status;
> +}
> +
>   /** AML code generation for a Device object node.
>   
>     AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is


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

* Re: [PATCH v1 3/7] DynamicTablesPkg: AML Code generation to create a named ResourceTemplate()
  2021-06-23 11:58 ` [PATCH v1 3/7] DynamicTablesPkg: AML Code generation to create a named ResourceTemplate() PierreGondois
@ 2021-10-06 15:16   ` Sami Mujawar
  0 siblings, 0 replies; 15+ messages in thread
From: Sami Mujawar @ 2021-10-06 15:16 UTC (permalink / raw)
  To: Pierre.Gondois, devel, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei, nd

Hi Pierre,

This patch looks good to me.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar


On 23/06/2021 12:58 PM, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <Pierre.Gondois@arm.com>
>
> Add AmlCodeGenNameResourceTemplate() to generate code for a
> ResourceTemplate().
>
> AmlCodeGenNameResourceTemplate ("REST", ParentNode, NewObjectNode) is
> equivalent of the following ASL code:
>    Name(REST, ResourceTemplate () {})
>
> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
> ---
>   .../Include/Library/AmlLib/AmlLib.h           | 28 ++++++++++
>   .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 55 +++++++++++++++++++
>   2 files changed, 83 insertions(+)
>
> diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> index 412db886e1f2..544bc670c455 100644
> --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> @@ -880,6 +880,34 @@ AmlCodeGenNamePackage (
>     OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
>     );
>   
> +/** AML code generation for a Name object node, containing a ResourceTemplate.
> +
> +  AmlCodeGenNameResourceTemplate ("PRS0", ParentNode, NewObjectNode) is
> +  equivalent of the following ASL code:
> +    Name(PRS0, ResourceTemplate () {})
> +
> +  @ingroup CodeGenApis
> +
> +  @param [in]  NameString     The new variable name.
> +                              Must be a NULL-terminated ASL NameString
> +                              e.g.: "DEV0", "DV15.DEV0", etc.
> +                              The input string is copied.
> +  @param [in]  ParentNode     If provided, set ParentNode as the parent
> +                              of the node created.
> +  @param [out] NewObjectNode  If success, contains the created node.
> +
> +  @retval EFI_SUCCESS             Success.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenNameResourceTemplate (
> +  IN  CONST CHAR8                   * NameString,
> +  IN        AML_NODE_HANDLE           ParentNode,     OPTIONAL
> +  OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
> +  );
> +
>   /** AML code generation for a Device object node.
>   
>     AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
> diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> index f9175c623622..eaa49a5834c2 100644
> --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> @@ -802,6 +802,61 @@ AmlCodeGenNamePackage (
>     return Status;
>   }
>   
> +/** AML code generation for a Name object node, containing a ResourceTemplate.
> +
> +  AmlCodeGenNameResourceTemplate ("PRS0", ParentNode, NewObjectNode) is
> +  equivalent of the following ASL code:
> +    Name(PRS0, ResourceTemplate () {})
> +
> +  @param [in]  NameString     The new variable name.
> +                              Must be a NULL-terminated ASL NameString
> +                              e.g.: "DEV0", "DV15.DEV0", etc.
> +                              The input string is copied.
> +  @param [in]  ParentNode     If provided, set ParentNode as the parent
> +                              of the node created.
> +  @param [out] NewObjectNode  If success, contains the created node.
> +
> +  @retval EFI_SUCCESS             Success.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlCodeGenNameResourceTemplate (
> +  IN  CONST CHAR8              * NameString,
> +  IN        AML_NODE_HEADER    * ParentNode,     OPTIONAL
> +  OUT       AML_OBJECT_NODE   ** NewObjectNode   OPTIONAL
> +  )
> +{
> +  EFI_STATUS          Status;
> +  AML_OBJECT_NODE   * ResourceTemplateNode;
> +
> +  if ((NameString == NULL)  ||
> +      ((ParentNode == NULL) && (NewObjectNode == NULL))) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  Status = AmlCodeGenName (
> +             NameString,
> +             ResourceTemplateNode,
> +             ParentNode,
> +             NewObjectNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    AmlDeleteTree ((AML_NODE_HEADER*)ResourceTemplateNode);
> +  }
> +
> +  return Status;
> +}
> +
>   /** AML code generation for a Device object node.
>   
>     AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is


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

* Re: [PATCH v1 4/7] DynamicTablesPkg: AML Code generation to add _PRT entries
  2021-06-23 11:58 ` [PATCH v1 4/7] DynamicTablesPkg: AML Code generation to add _PRT entries PierreGondois
@ 2021-10-06 15:17   ` Sami Mujawar
  0 siblings, 0 replies; 15+ messages in thread
From: Sami Mujawar @ 2021-10-06 15:17 UTC (permalink / raw)
  To: Pierre.Gondois, devel, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei, nd

Hi Pierre,

Thank you for this patch.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar


On 23/06/2021 12:58 PM, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <Pierre.Gondois@arm.com>
>
> _PRT entries can describe interrupt mapping for Pci devices. The
> object is described in ACPI 6.4 s6.2.13 "_PRT (PCI Routing Table)".
>
> Add AmlCodeGenPrtEntry() helper function to add _PRT entries
> to an existing _PRT object.
>
> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
> ---
>   .../Include/Library/AmlLib/AmlLib.h           |  52 +++++
>   .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 210 ++++++++++++++++++
>   2 files changed, 262 insertions(+)
>
> diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> index 544bc670c455..4a10da8cd7bb 100644
> --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> @@ -908,6 +908,58 @@ AmlCodeGenNameResourceTemplate (
>     OUT       AML_OBJECT_NODE_HANDLE  * NewObjectNode   OPTIONAL
>     );
>   
> +/** Add a _PRT entry.
> +
> +  AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
> +  equivalent of the following ASL code:
> +    Package (4) {
> +      0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
> +      0,       // Pin: PCI pin number of the device (0-INTA, ...).
> +      LNKA     // Source: Name of the device that allocates the interrupt
> +               // to which the above pin is connected.
> +      0        // Source Index: Source is assumed to only describe one
> +               // interrupt, so let it to index 0.
> +    }
> +
> +  The package is added at the tail of the list of the input _PRT node
> +  name:
> +    Name (_PRT, Package () {
> +      [Pre-existing _PRT entries],
> +      [Newly created _PRT entry]
> +    })
> +
> +  Cf. ACPI 6.4, s6.2.13 "_PRT (PCI Routing Table)"
> +
> +  @ingroup CodeGenApis
> +
> +  @param [in]  Address        Address. Cf ACPI 6.4 specification, Table 6.2:
> +                              "ADR Object Address Encodings":
> +                              High word-Device #, Low word-Function #. (for
> +                              example, device 3, function 2 is 0x00030002).
> +                              To refer to all the functions on a device #,
> +                              use a function number of FFFF).
> +  @param [in]  Pin            PCI pin number of the device (0-INTA ... 3-INTD).
> +                              Must be between 0-3.
> +  @param [in]  LinkName       Link Name, i.e. device in the AML NameSpace
> +                              describing the interrupt used.
> +                              The input string is copied.
> +  @param [in]  SourceIndex    Source index or GSIV.
> +  @param [in]  PrtNameNode    Prt Named node to add the object to ....
> +
> +  @retval EFI_SUCCESS             Success.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlAddPrtEntry (
> +  IN        UINT32                    Address,
> +  IN        UINT8                     Pin,
> +  IN  CONST CHAR8                   * LinkName,
> +  IN        UINT32                    SourceIndex,
> +  IN        AML_OBJECT_NODE_HANDLE    PrtNameNode
> +  );
> +
>   /** AML code generation for a Device object node.
>   
>     AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
> diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> index eaa49a5834c2..9bf4e110d05c 100644
> --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
> @@ -857,6 +857,216 @@ AmlCodeGenNameResourceTemplate (
>     return Status;
>   }
>   
> +/** Add a _PRT entry.
> +
> +  AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
> +  equivalent of the following ASL code:
> +    Package (4) {
> +      0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
> +      0,       // Pin: PCI pin number of the device (0-INTA, ...).
> +      LNKA     // Source: Name of the device that allocates the interrupt
> +               // to which the above pin is connected.
> +      0        // Source Index: Source is assumed to only describe one
> +               // interrupt, so let it to index 0.
> +    }
> +
> +  The package is added at the tail of the list of the input _PRT node
> +  name:
> +    Name (_PRT, Package () {
> +      [Pre-existing _PRT entries],
> +      [Newly created _PRT entry]
> +    })
> +
> +  Cf. ACPI 6.4 specification:
> +   - s6.2.13 "_PRT (PCI Routing Table)"
> +   - s6.1.1 "_ADR (Address)"
> +
> +  @param [in]  Address        Address. Cf ACPI 6.4 specification, Table 6.2:
> +                              "ADR Object Address Encodings":
> +                              High word-Device #, Low word-Function #. (for
> +                              example, device 3, function 2 is 0x00030002).
> +                              To refer to all the functions on a device #,
> +                              use a function number of FFFF).
> +  @param [in]  Pin            PCI pin number of the device (0-INTA ... 3-INTD).
> +                              Must be between 0-3.
> +  @param [in]  LinkName       Link Name, i.e. device in the AML NameSpace
> +                              describing the interrupt used.
> +                              The input string is copied.
> +  @param [in]  SourceIndex    Source index or GSIV.
> +  @param [in]  PrtNameNode    Prt Named node to add the object to ....
> +
> +  @retval EFI_SUCCESS             Success.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlAddPrtEntry (
> +  IN        UINT32                    Address,
> +  IN        UINT8                     Pin,
> +  IN  CONST CHAR8                   * LinkName,
> +  IN        UINT32                    SourceIndex,
> +  IN        AML_OBJECT_NODE_HANDLE    PrtNameNode
> +  )
> +{
> +  EFI_STATUS          Status;
> +  AML_OBJECT_NODE   * PrtEntryList;
> +  AML_OBJECT_NODE   * PackageNode;
> +  AML_OBJECT_NODE   * NewElementNode;
> +
> +  CHAR8             * AmlNameString;
> +  UINT32              AmlNameStringSize;
> +  AML_DATA_NODE     * DataNode;
> +
> +  if ((Pin > 3)                 ||
> +      (LinkName == NULL)        ||
> +      (PrtNameNode == NULL)     ||
> +      (AmlGetNodeType ((AML_NODE_HANDLE)PrtNameNode) != EAmlNodeObject) ||
> +      (!AmlNodeHasOpCode (PrtNameNode, AML_NAME_OP, 0))                 ||
> +      !AmlNameOpCompareName (PrtNameNode, "_PRT")) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  NewElementNode = NULL;
> +  AmlNameString = NULL;
> +  DataNode = NULL;
> +
> +  // Get the Package object node of the _PRT node,
> +  // which is the 2nd fixed argument (i.e. index 1).
> +  PrtEntryList = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
> +                                           PrtNameNode,
> +                                           EAmlParseIndexTerm1
> +                                           );
> +  if ((PrtEntryList == NULL)                                              ||
> +      (AmlGetNodeType ((AML_NODE_HANDLE)PrtEntryList) != EAmlNodeObject)  ||
> +      (!AmlNodeHasOpCode (PrtEntryList, AML_PACKAGE_OP, 0))) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // The new _PRT entry.
> +  Status = AmlCodeGenPackage (&PackageNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  Status = AmlCodeGenInteger (Address, &NewElementNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  Status = AmlVarListAddTail (
> +             (AML_NODE_HANDLE)PackageNode,
> +             (AML_NODE_HANDLE)NewElementNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  NewElementNode = NULL;
> +
> +  Status = AmlCodeGenInteger (Pin, &NewElementNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  Status = AmlVarListAddTail (
> +             (AML_NODE_HANDLE)PackageNode,
> +             (AML_NODE_HANDLE)NewElementNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  NewElementNode = NULL;
> +
> +  Status = ConvertAslNameToAmlName (LinkName, &AmlNameString);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  Status = AmlCreateDataNode (
> +             EAmlNodeDataTypeNameString,
> +             (UINT8*)AmlNameString,
> +             AmlNameStringSize,
> +             &DataNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  // AmlNameString will be freed before returning.
> +
> +  Status = AmlVarListAddTail (
> +             (AML_NODE_HANDLE)PackageNode,
> +             (AML_NODE_HANDLE)DataNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  DataNode = NULL;
> +
> +  Status = AmlCodeGenInteger (SourceIndex, &NewElementNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  Status = AmlVarListAddTail (
> +             (AML_NODE_HANDLE)PackageNode,
> +             (AML_NODE_HANDLE)NewElementNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  // Append to the the list of _PRT entries.
> +  Status = AmlVarListAddTail (
> +             (AML_NODE_HANDLE)PrtEntryList,
> +             (AML_NODE_HANDLE)PackageNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto error_handler;
> +  }
> +
> +  // Free AmlNameString before returning as it is copied
> +  // in the call to AmlCreateDataNode().
> +  goto exit_handler;
> +
> +error_handler:
> +  AmlDeleteTree ((AML_NODE_HANDLE)PackageNode);
> +  if (NewElementNode != NULL) {
> +    AmlDeleteTree ((AML_NODE_HANDLE)NewElementNode);
> +  }
> +  if (DataNode != NULL) {
> +    AmlDeleteTree ((AML_NODE_HANDLE)DataNode);
> +  }
> +
> +exit_handler:
> +  if (AmlNameString != NULL) {
> +    FreePool (AmlNameString);
> +  }
> +  return Status;
> +}
> +
>   /** AML code generation for a Device object node.
>   
>     AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is


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

* Re: [PATCH v1 5/7] DynamicTablesPkg: Add AmlAttachNode()
  2021-06-23 11:58 ` [PATCH v1 5/7] DynamicTablesPkg: Add AmlAttachNode() PierreGondois
@ 2021-10-06 15:17   ` Sami Mujawar
  0 siblings, 0 replies; 15+ messages in thread
From: Sami Mujawar @ 2021-10-06 15:17 UTC (permalink / raw)
  To: Pierre.Gondois, devel, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei, nd

Hi Pierre,

Thank you for this patch.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar


On 23/06/2021 12:58 PM, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <Pierre.Gondois@arm.com>
>
> This function allows to add a node as the last node of a parent node
> in an AML tree. For instance,
> ASL code corresponding to NewNode:
>    Name (_UID, 0)
>
> ASL code corresponding to ParentNode:
>    Device (PCI0) {
>      Name(_HID, EISAID("PNP0A08"))
>    }
>
> "AmlAttachNode (ParentNode, NewNode)" will result in:
> ASL code:
>    Device (PCI0) {
>      Name(_HID, EISAID("PNP0A08"))
>      Name (_UID, 0)
>    }
>
> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
> ---
>   .../Include/Library/AmlLib/AmlLib.h           | 33 +++++++++++++++++
>   .../Library/Common/AmlLib/Api/AmlApi.c        | 36 +++++++++++++++++++
>   2 files changed, 69 insertions(+)
>
> diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> index 4a10da8cd7bb..b4766726e84d 100644
> --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
> @@ -166,6 +166,39 @@ AmlDetachNode (
>     IN  AML_NODE_HANDLE   Node
>     );
>   
> +/** Attach a node in an AML tree.
> +
> +  The node will be added as the last statement of the ParentNode.
> +  E.g.:
> +  ASL code corresponding to NewNode:
> +  Name (_UID, 0)
> +
> +  ASL code corresponding to ParentNode:
> +  Device (PCI0) {
> +    Name(_HID, EISAID("PNP0A08"))
> +  }
> +
> +  "AmlAttachNode (ParentNode, NewNode)" will result in:
> +  ASL code:
> +  Device (PCI0) {
> +    Name(_HID, EISAID("PNP0A08"))
> +    Name (_UID, 0)
> +  }
> +
> +  @param  [in]  ParentNode  Pointer to the parent node.
> +                            Must be a root or an object node.
> +  @param  [in]  NewNode     Pointer to the node to add.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlAttachNode (
> +  IN  AML_NODE_HANDLE   ParentNode,
> +  IN  AML_NODE_HANDLE   NewNode
> +  );
> +
>   /** Find a node in the AML namespace, given an ASL path and a reference Node.
>   
>      - The AslPath can be an absolute path, or a relative path from the
> diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
> index 6f9e3f6f2805..def581299f5c 100644
> --- a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
> +++ b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
> @@ -379,6 +379,42 @@ AmlNameOpGetNextRdNode (
>     return EFI_SUCCESS;
>   }
>   
> +/** Attach a node in an AML tree.
> +
> +  The node will be added as the last statement of the ParentNode.
> +  E.g.:
> +  ASL code corresponding to NewNode:
> +  Name (_UID, 0)
> +
> +  ASL code corresponding to ParentNode:
> +  Device (PCI0) {
> +    Name(_HID, EISAID("PNP0A08"))
> +  }
> +
> +  "AmlAttachNode (ParentNode, NewNode)" will result in:
> +  ASL code:
> +  Device (PCI0) {
> +    Name(_HID, EISAID("PNP0A08"))
> +    Name (_UID, 0)
> +  }
> +
> +  @param  [in]  ParentNode  Pointer to the parent node.
> +                            Must be a root or an object node.
> +  @param  [in]  NewNode     Pointer to the node to add.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AmlAttachNode (
> +  IN  AML_NODE_HANDLE   ParentNode,
> +  IN  AML_NODE_HANDLE   NewNode
> +  )
> +{
> +  return AmlVarListAddTail (ParentNode, NewNode);
> +}
> +
>   // DEPRECATED APIS
>   #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
>   


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

* Re: [PATCH v1 6/7] DynamicTablesPkg: Add Pci related objects
  2021-06-23 11:58 ` [PATCH v1 6/7] DynamicTablesPkg: Add Pci related objects PierreGondois
@ 2021-10-06 15:18   ` Sami Mujawar
  0 siblings, 0 replies; 15+ messages in thread
From: Sami Mujawar @ 2021-10-06 15:18 UTC (permalink / raw)
  To: Pierre.Gondois, devel, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei, nd

Hi Pierre,

This patch looks good to me.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar


On 23/06/2021 12:58 PM, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <Pierre.Gondois@arm.com>
>
> Introduce the following CmObj in the ArmNameSpaceObjects:
>   - CM_ARM_PCI_ADDRESS_MAP_INFO
>   - CM_ARM_PCI_INTERRUPT_MAP_INFO
>
> These objects allow to describe address range mapping
> of Pci busses and interrupt mapping of Pci devices.
>
> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
> ---
>   .../Include/ArmNameSpaceObjects.h             | 78 +++++++++++++++++++
>   .../ConfigurationManagerObjectParser.c        | 28 ++++++-
>   2 files changed, 105 insertions(+), 1 deletion(-)
>
> diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
> index 9c49091def59..b3779f828c17 100644
> --- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
> +++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
> @@ -59,6 +59,8 @@ typedef enum ArmObjectID {
>     EArmObjSerialPortInfo,               ///< 35 - Generic Serial Port Info
>     EArmObjCmn600Info,                   ///< 36 - CMN-600 Info
>     EArmObjLpiInfo,                      ///< 37 - Lpi Info
> +  EArmObjPciAddressMapInfo,            ///< 38 - Pci Address Map Info
> +  EArmObjPciInterruptMapInfo,          ///< 39 - Pci Interrupt Map Info
>     EArmObjMax
>   } EARM_OBJECT_ID;
>   
> @@ -433,6 +435,14 @@ typedef struct CmArmPciConfigSpaceInfo {
>   
>     /// The end bus number
>     UINT8   EndBusNumber;
> +
> +  /// Optional field: Reference Token for address mapping.
> +  /// Token identifying a CM_ARM_OBJ_REF structure.
> +  CM_OBJECT_TOKEN   AddressMapToken;
> +
> +  /// Optional field: Reference Token for interrupt mapping.
> +  /// Token identifying a CM_ARM_OBJ_REF structure.
> +  CM_OBJECT_TOKEN   InterruptMapToken;
>   } CM_ARM_PCI_CONFIG_SPACE_INFO;
>   
>   /** A structure that describes the
> @@ -666,6 +676,10 @@ typedef struct CmArmGenericInterrupt {
>     UINT32    Interrupt;
>   
>     /// Flags
> +  /// BIT0: 0: Interrupt is Level triggered
> +  ///       1: Interrupt is Edge triggered
> +  /// BIT1: 0: Interrupt is Active high
> +  ///       1: Interrupt is Active low
>     UINT32    Flags;
>   } CM_ARM_GENERIC_INTERRUPT;
>   
> @@ -946,6 +960,70 @@ typedef struct CmArmLpiInfo {
>     CHAR8                                   StateName[16];
>   } CM_ARM_LPI_INFO;
>   
> +/** A structure that describes a PCI Address Map.
> +
> +  The memory-ranges used by the PCI bus are described by this object.
> +
> +  ID: EArmObjPciAddressMapInfo
> +*/
> +typedef struct CmArmPciAddressMapInfo {
> +  /** Pci address space code
> +
> +  Available values are:
> +   - 0: Configuration Space
> +   - 1: I/O Space
> +   - 2: 32-bit-address Memory Space
> +   - 3: 64-bit-address Memory Space
> +  */
> +  UINT8                     SpaceCode;
> +
> +  /// PCI address
> +  UINT64                    PciAddress;
> +
> +  /// Cpu address
> +  UINT64                    CpuAddress;
> +
> +  /// Address size
> +  UINT64                    AddressSize;
> +} CM_ARM_PCI_ADDRESS_MAP_INFO;
> +
> +/** A structure that describes a PCI Interrupt Map.
> +
> +  The legacy PCI interrupts used by PCI devices are described by this object.
> +
> +  Cf Devicetree Specification - Release v0.3
> +  s2.4.3 "Interrupt Nexus Properties"
> +
> +  ID: EArmObjPciInterruptMapInfo
> +*/
> +typedef struct CmArmPciInterruptMapInfo {
> +  /// Pci Bus.
> +  /// Value on 8 bits (max 255).
> +  UINT8                       PciBus;
> +
> +  /// Pci Bus.
> +  /// Value on 5 bits (max 31).
> +  UINT8                       PciDevice;
> +
> +  /** PCI interrupt
> +
> +  ACPI bindings are used:
> +  Cf. ACPI 6.4, s6.2.13 _PRT (PCI Routing Table):
> +      "0-INTA, 1-INTB, 2-INTC, 3-INTD"
> +
> +  Device-tree bindings are shifted by 1:
> +      "INTA=1, INTB=2, INTC=3, INTD=4"
> +  */
> +  UINT8                       PciInterrupt;
> +
> +  /** Interrupt controller interrupt.
> +
> +  Cf Devicetree Specification - Release v0.3
> +  s2.4.3 "Interrupt Nexus Properties": "parent interrupt specifier"
> +  */
> +  CM_ARM_GENERIC_INTERRUPT    IntcInterrupt;
> +} CM_ARM_PCI_INTERRUPT_MAP_INFO;
> +
>   #pragma pack()
>   
>   #endif // ARM_NAMESPACE_OBJECTS_H_
> diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
> index da5f5846edd9..0ba4e6e5faff 100644
> --- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
> +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
> @@ -152,7 +152,9 @@ STATIC CONST CM_OBJ_PARSER CmArmPciConfigSpaceInfoParser[] = {
>     {"BaseAddress", 8, "0x%llx", NULL},
>     {"PciSegmentGroupNumber", 2, "0x%x", NULL},
>     {"StartBusNumber", 1, "0x%x", NULL},
> -  {"EndBusNumber", 1, "0x%x", NULL}
> +  {"EndBusNumber", 1, "0x%x", NULL},
> +  {"AddressMapToken", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL},
> +  {"InterruptMapToken", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL},
>   };
>   
>   /** A parser for EArmObjHypervisorVendorIdentity.
> @@ -401,6 +403,26 @@ STATIC CONST CM_OBJ_PARSER CmArmLpiInfoParser[] = {
>     {"StateName", 16, "0x%a", NULL},
>   };
>   
> +/** A parser for EArmObjPciAddressMapInfo.
> +*/
> +STATIC CONST CM_OBJ_PARSER CmArmPciAddressMapInfoParser[] = {
> +  {"SpaceCode", 1, "%d", NULL},
> +  {"PciAddress", 8, "0x%llx", NULL},
> +  {"CpuAddress", 8, "0x%llx", NULL},
> +  {"AddressSize", 8, "0x%llx", NULL},
> +};
> +
> +/** A parser for EArmObjPciInterruptMapInfo.
> +*/
> +STATIC CONST CM_OBJ_PARSER CmPciInterruptMapInfoParser[] = {
> +  {"PciBus", 1, "0x%x", NULL},
> +  {"PciDevice", 1, "0x%x", NULL},
> +  {"PciInterrupt", 1, "0x%x", NULL},
> +  {"IntcInterrupt", sizeof (CM_ARM_GENERIC_INTERRUPT),
> +    NULL, NULL, CmArmGenericInterruptParser,
> +    ARRAY_SIZE (CmArmGenericInterruptParser)},
> +};
> +
>   /** A parser for Arm namespace objects.
>   */
>   STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = {
> @@ -475,6 +497,10 @@ STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = {
>       ARRAY_SIZE (CmArmCmn600InfoParser)},
>     {"EArmObjLpiInfo", CmArmLpiInfoParser,
>         ARRAY_SIZE (CmArmLpiInfoParser)},
> +  {"EArmObjPciAddressMapInfo", CmArmPciAddressMapInfoParser,
> +    ARRAY_SIZE (CmArmPciAddressMapInfoParser)},
> +  {"EArmObjPciInterruptMapInfo", CmPciInterruptMapInfoParser,
> +    ARRAY_SIZE (CmPciInterruptMapInfoParser)},
>     {"EArmObjMax", NULL, 0},
>   };
>   


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

* Re: [PATCH v1 7/7] DynamicTablesPkg: SSDT Pci express generator
  2021-06-23 11:58 ` [PATCH v1 7/7] DynamicTablesPkg: SSDT Pci express generator PierreGondois
@ 2021-10-07 11:11   ` Sami Mujawar
  0 siblings, 0 replies; 15+ messages in thread
From: Sami Mujawar @ 2021-10-07 11:11 UTC (permalink / raw)
  To: Pierre.Gondois, devel, Alexei Fedorov; +Cc: Akanksha Jain, Alexandru Elisei, nd

[-- Attachment #1: Type: text/plain, Size: 58069 bytes --]

Hi Pierre,

Thank you for this patch.

I have some feedback marked inline as [SAMI].

Regards,

Sami Muajwar


On 23/06/2021 12:58 PM, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <Pierre.Gondois@arm.com>
>
> This generator allows to generate a SSDT table describing
> a Pci express Bus. It uses the following CmObj:
> - EArmObjCmRef
> - EArmObjPciConfigSpaceInfo
> - EArmObjPciAddressMapInfo
> - EArmObjPciInterruptMapInfo
>
> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
> ---
>   DynamicTablesPkg/DynamicTables.dsc.inc        |    2 +
>   DynamicTablesPkg/Include/AcpiTableGenerator.h |    5 +
>   .../AcpiSsdtPcieLibArm/SsdtPcieGenerator.c    | 1417 +++++++++++++++++
>   .../AcpiSsdtPcieLibArm/SsdtPcieGenerator.h    |  134 ++
>   .../Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf |   32 +
>   .../SsdtPcieOscTemplate.asl                   |   80 +
>   6 files changed, 1670 insertions(+)
>   create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
>   create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
>   create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
>   create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl
>
> diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
> index 292215c39456..60bcf4b199e8 100644
> --- a/DynamicTablesPkg/DynamicTables.dsc.inc
> +++ b/DynamicTablesPkg/DynamicTables.dsc.inc
> @@ -39,6 +39,7 @@ [Components.common]
>   
>     # AML Codegen
>     DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf
> +  DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
>   
>     #
>     # Dynamic Table Factory Dxe
> @@ -62,6 +63,7 @@ [Components.common]
>   
>         # AML Codegen
>         NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf
> +      NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
>     }
>   
>     #
> diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
> index 45c808ba740d..58ec941f2a35 100644
> --- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
> +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
> @@ -67,6 +67,10 @@ The Dynamic Tables Framework implements the following ACPI table generators:
>               The SSDT Cpu-Topology generator collates the cpu and LPI
>               information from the Configuration Manager and generates a
>               SSDT table describing the CPU hierarchy.
> +  - SSDT Pci-Express:
> +            The SSDT Pci Express generator collates the Pci Express
> +            information from the Configuration Manager and generates a
> +            SSDT table describing a Pci Express bus.
>   */
>   
>   /** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
> @@ -93,6 +97,7 @@ typedef enum StdAcpiTableId {
>     EStdAcpiTableIdSsdtSerialPort,                ///< SSDT Serial-Port Generator
>     EStdAcpiTableIdSsdtCmn600,                    ///< SSDT Cmn-600 Generator
>     EStdAcpiTableIdSsdtCpuTopology,               ///< SSDT Cpu Topology
> +  EStdAcpiTableIdSsdtPciExpress,                ///< SSDT Pci Express Generator
>     EStdAcpiTableIdMax
>   } ESTD_ACPI_TABLE_ID;
>   
> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
> new file mode 100644
> index 000000000000..478bc60ef6f3
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
> @@ -0,0 +1,1417 @@
> +/** @file
> +  SSDT Pcie Table Generator.
> +
> +  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Reference(s):
> +  - PCI Firmware Specification - Revision 3.0
> +  - ACPI 6.4 specification:
> +   - s6.2.13 "_PRT (PCI Routing Table)"
> +   - s6.1.1 "_ADR (Address)"
> +  - linux kernel code
> +**/
> +
> +#include <Library/AcpiLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/AcpiHelperLib.h>
> +#include <Library/AmlLib/AmlLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +
> +#include "SsdtPcieGenerator.h"
> +
> +/** ARM standard SSDT Pcie Table Generator.
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjCmRef
> +  - EArmObjPciConfigSpaceInfo
> +  - EArmObjPciAddressMapInfo
> +  - EArmObjPciInterruptMapInfo
> +*/
> +
> +/** This macro expands to a function that retrieves the cross-CM-object-
> +    reference information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjCmRef,
> +  CM_ARM_OBJ_REF
> +  );
> +
> +/** This macro expands to a function that retrieves the Pci
> +    Configuration Space Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPciConfigSpaceInfo,
> +  CM_ARM_PCI_CONFIG_SPACE_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Pci
> +    Address Mapping Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPciAddressMapInfo,
> +  CM_ARM_PCI_ADDRESS_MAP_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the Pci
> +    Interrupt Mapping Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPciInterruptMapInfo,
> +  CM_ARM_PCI_INTERRUPT_MAP_INFO
> +  );
> +
> +/** Initialize the MappingTable.
> +
> +  @param [in] MappingTable  The mapping table structure.
> +  @param [in] Count         Number of entries to allocate in the
> +                            MappingTable.
> +
> +  @retval EFI_SUCCESS            Success.
> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +MappingTableInitialize (
> +  IN  MAPPING_TABLE   * MappingTable,
> +  IN  UINT32            Count
> +  )
> +{
> +  UINT32  * Table;
> +
> +  if ((MappingTable == NULL)  ||
> +      (Count == 0)) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Table = AllocateZeroPool (sizeof (*Table) * Count);
> +  if (Table == NULL) {
> +    ASSERT (0);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  MappingTable->Table = Table;
> +  MappingTable->LastIndex = 0;
> +  MappingTable->MaxIndex = Count;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Free the MappingTable.
> +
> +  @param [in, out]  MappingTable  The mapping table structure.
> +**/
> +STATIC
> +VOID
> +EFIAPI
> +MappingTableFree (
> +  IN  OUT MAPPING_TABLE   * MappingTable
> +  )
> +{
> +  ASSERT (MappingTable != NULL);
> +  ASSERT (MappingTable->Table != NULL);
> +
> +  if (MappingTable->Table != NULL) {
> +    FreePool (MappingTable->Table);
> +  }
> +}
> +
> +/** Add a new entry to the MappingTable and return its index.
> +
> +  If an entry with [Integer] is already available in the table,
> +  return its index without adding a new entry.
> +
> +  @param [in] MappingTable  The mapping table structure.
> +  @param [in] Integer       New Integer entry to add.
> +
> +  @retval The index of the Integer entry in the MappingTable.
> +**/
> +STATIC
> +UINT32
> +EFIAPI
> +MappingTableAdd (
> +  IN  MAPPING_TABLE   * MappingTable,
> +  IN  UINT32            Integer
> +  )
> +{
> +  UINT32    * Table;
> +  UINT32      Index;
> +  UINT32      LastIndex;
> +
> +  ASSERT (MappingTable != NULL);
> +  ASSERT (MappingTable->Table != NULL);
> +
> +  Table = MappingTable->Table;
> +  LastIndex = MappingTable->LastIndex;
> +
> +  // Search if there is already an entry with this Integer.
> +  for (Index = 0; Index < LastIndex; Index++) {
> +    if (Table[Index] == Integer) {
> +      return Index;
> +    }
> +  }
> +
> +  ASSERT (LastIndex < MAX_PCI_LEGACY_INTERRUPT);
[SAMI] Since the mapping table is used for PCI devices as well. What 
happens if the number of devices are more than MAX_PCI_LEGACY_INTERRUPT 
(which is 4)?
> +  ASSERT (LastIndex < MappingTable->MaxIndex);
> +
> +  // If no, create a new entry.
> +  Table[LastIndex] = Integer;
> +
> +  return MappingTable->LastIndex++;
> +}
> +
> +/** Generate required Pci device information.
> +
> +  ASL code:
> +    Name (_UID, [Uid])                // Uid of the Pci device
> +    Name (_HID, EISAID ("PNP0A08"))   // PCI Express Root Bridge
> +    Name (_CID, EISAID ("PNP0A03"))   // Compatible PCI Root Bridge
> +    Name (_SEG, [Pci segment group])  // PCI Segment Group number
> +    Name (_BBN, [Bus number])         // PCI Base Bus Number
> +    Name (_CCA, 1)                    // Initially mark the PCI coherent
> +
> +  @param [in]       PciInfo         Pci device information.
> +  @param [in]       Uid             Unique Id of the Pci device.
> +  @param [in, out]  PciNode         Pci node to amend.
> +
> +  @retval EFI_SUCCESS            Success.
> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GeneratePciDeviceInfo (
> +  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO  * PciInfo,
> +  IN            UINT32                          Uid,
> +  IN  OUT       AML_OBJECT_NODE_HANDLE          PciNode
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINT32        EisaId;
> +
> +  ASSERT (PciInfo != NULL);
> +  ASSERT (PciNode != NULL);
> +
> +  // ASL: Name (_UID, [Uid])
> +  Status = AmlCodeGenNameInteger ("_UID", Uid, PciNode, NULL);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL: Name (_HID, EISAID ("PNP0A08"))
> +  Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +  Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL: Name (_CID, EISAID ("PNP0A03"))
> +  Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +  Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL: Name (_SEG, [Pci segment group])
[SAMI] I think the comment above should be changed to // ASL: Name 
(_SEG, <Pci segment group>) as the 'Pci segment group' is not an 
optional value. Sam e comment for the 'Bus number' below.
> +  Status = AmlCodeGenNameInteger (
> +             "_SEG",
> +             PciInfo->PciSegmentGroupNumber,
> +             PciNode,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL: Name (_BBN, [Bus number])
> +  Status = AmlCodeGenNameInteger (
> +             "_BBN",
> +             PciInfo->StartBusNumber,
> +             PciNode,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL: Name (_CCA, 1)
> +  // Must be aligned with the IORT CCA property in
> +  // "Table 14 Memory access properties"
> +  Status = AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +  }
> +  return Status;
> +}
> +
> +/** Generate a Link device.
> +
> +  The Link device is added at the beginning of the ASL Pci device definition.
> +
> +  Each Link device represents a Pci legacy interrupt (INTA-...-INTD).
> +
> +  ASL code:
> +  Device ([Link Name]) {
> +    Name (_UID, [Uid]])
> +    Name (_HID, EISAID ("PNP0C0F"))
> +    Name (_PRS, ResourceTemplate () {
> +      Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { [Irq]] }
> +      })
> +    Method (_CRS, 0) { Return (_PRS) }
> +    Method (_SRS, 1) { }
> +    Method (_DIS) { }
> +  }
> +
> +  The list of objects to define is available at:
> +  PCI Firmware Specification - Revision 3.3,
> +  s3.5. "Device State at Firmware/Operating System Handoff"
> +
> +  @param [in]       Irq         Interrupt controller interrupt.
> +  @param [in]       IrqFlags    Interrupt flags.
> +  @param [in]       LinkIndex   Legacy Pci interrupt index.
> +                                Must be between 0-INTA and 3-INTD.
> +  @param [in, out]  PciNode     Pci node to amend.
> +
> +  @retval EFI_SUCCESS            Success.
> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenerateLinkDevice (
> +  IN      UINT32                    Irq,
> +  IN      UINT32                    IrqFlags,
> +  IN      UINT32                    LinkIndex,
> +  IN  OUT AML_OBJECT_NODE_HANDLE    PciNode
> +  )
> +{
> +  EFI_STATUS                Status;
> +  CHAR8                     AslName[AML_NAME_SEG_SIZE + 1];
> +  AML_OBJECT_NODE_HANDLE    LinkNode;
> +  AML_OBJECT_NODE_HANDLE    CrsNode;
> +  UINT32                    EisaId;
> +
> +  ASSERT (LinkIndex < 4);
> +  ASSERT (PciNode != NULL);
> +
> +  CopyMem (AslName, "LNKx", AML_NAME_SEG_SIZE + 1);
> +  AslName[AML_NAME_SEG_SIZE - 1] = 'A' + LinkIndex;
> +
> +  // ASL: Device (LNKx) {}
> +  Status = AmlCodeGenDevice (AslName, NULL, &LinkNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // The LNKx devices must be defined before being referenced.
> +  // Thus add it to the head of the Pci list of variable arguments.
> +  Status = AmlAttachNode (PciNode, LinkNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    // Failed to add.
> +    AmlDeleteTree ((AML_NODE_HANDLE)LinkNode);
> +    return Status;
> +  }
> +
> +  // ASL: Name (_UID, [Uid])
> +  Status = AmlCodeGenNameInteger ("_UID", LinkIndex, LinkNode, NULL);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL: Name (_HID, EISAID ("PNP0C0F"))
> +  Status = AmlGetEisaIdFromString ("PNP0C0F", &EisaId);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +  Status = AmlCodeGenNameInteger ("_HID", EisaId, LinkNode, NULL);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL:
> +  // Name (_PRS, ResourceTemplate () {
> +  //   Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { [Irq] }
> +  // })
> +  Status = AmlCodeGenNameResourceTemplate ("_PRS", LinkNode, &CrsNode);
[SAMI] The Arm BBR specification, version 1.0, section 8.5.2 Device 
methods and objects, states:  "Note: The _PRS (Possible Resource 
Settings) and _SRS (Set Resource Settings) are not supported."
Can you revisit this function again to see what needs to be done, please?
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +  Status = AmlCodeGenRdInterrupt (
> +             FALSE,
> +             (IrqFlags & BIT0) != 0,
> +             (IrqFlags & BIT1) != 0,
> +             FALSE,
> +             &Irq,
> +             1,
> +             CrsNode,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL:
> +  // Method (_CRS, 0) {
> +  //   Return (_PRS)
> +  // }
> +  Status = AmlCodeGenMethodRetNameString (
> +             "_CRS",
> +             "_PRS",
> +             0,
> +             FALSE,
> +             0,
> +             LinkNode,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL: Method (_SRS, 1) {}
> +  // Not possible to set interrupts.
> +  Status = AmlCodeGenMethodRetNameString (
> +             "_SRS",
> +             NULL,
> +             1,
> +             FALSE,
> +             0,
> +             LinkNode,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL:Method (_DIS, 1) {}
> +  // Not possible to disable interrupts.
> +  Status = AmlCodeGenMethodRetNameString (
> +             "_DIS",
> +             NULL,
> +             0,
> +             FALSE,
> +             0,
> +             LinkNode,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // _STA:
> +  // ACPI 6.4, s6.3.7 "_STA (Device Status)":
> +  // If a device object describes a device that is not on an enumerable bus
> +  // and the device object does not have an _STA object, then OSPM assumes
> +  // that the device is present, enabled, shown in the UI, and functioning.
> +
> +  // _MAT:
> +  // Not supported. Mainly used for processors.
> +
> +  return Status;
> +}
> +
> +/** Generate Pci slots devices.
> +
> +  PCI Firmware Specification - Revision 3.3,
> +  s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot
> +  used. It should be possible to enumerate them, but this is additional
> +  information.
> +
> +  @param [in]  MappingTable  The mapping table structure.
> +  @param [in, out]  PciNode     Pci node to amend.
> +
> +  @retval EFI_SUCCESS            Success.
> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GeneratePciSlots (
> +  IN      CONST MAPPING_TABLE           * MappingTable,
> +  IN  OUT       AML_OBJECT_NODE_HANDLE    PciNode
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINT32                    Index;
> +  UINT32                    LastIndex;
> +  UINT32                    DeviceId;
> +  CHAR8                     AslName[AML_NAME_SEG_SIZE + 1];
> +  AML_OBJECT_NODE_HANDLE    DeviceNode;
> +
> +  ASSERT (MappingTable != NULL);
> +  ASSERT (PciNode != NULL);
> +
> +  // Generic device name is "Dxx".
> +  CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);
> +
> +  LastIndex = MappingTable->LastIndex;
> +
> +  // There are at most 32 devices on a Pci bus.
> +  ASSERT (LastIndex < 32);
[SAMI] Return an error if devices are more than 32.
> +
> +  for (Index = 0; Index < LastIndex; Index++) {
> +    DeviceId = MappingTable->Table[Index];
> +    AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);
> +    AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);
> +
> +    // ASL:
> +    // Device (Dxx) {
> +    //   Name (_ADR, [address value])
> +    // }
> +    Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);
> +    if (EFI_ERROR (Status)) {
> +      ASSERT (0);
> +      return Status;
> +    }
> +
> +    /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
> +       High word-Device #, Low word-Function #. (for example, device 3,
> +       function 2 is 0x00030002). To refer to all the functions on a device #,
> +       use a function number of FFFF).
> +    */
> +    Status = AmlCodeGenNameInteger (
> +               "_ADR",
> +               (DeviceId << 16) | 0xFFFF,
> +               DeviceNode,
> +               NULL
> +               );
> +    if (EFI_ERROR (Status)) {
> +      ASSERT (0);
> +      return Status;
> +    }
> +
> +    // _SUN object is not generated as we don't know which slot will be used.
> +  }
> +
> +  return Status;
> +}
> +
> +/** Generate a _PRT object (Pci Routing Table) for the Pci device.
> +
> +  Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)"
> +
> +  @param [in]       Generator       The SSDT Pci generator.
> +  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager
> +                                    Protocol interface.
> +  @param [in]       PciInfo         Pci device information.
> +  @param [in, out]  PciNode         Pci node to amend.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GeneratePrt (
> +  IN            ACPI_PCI_GENERATOR                    *       Generator,
> +  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO          *       PciInfo,
> +  IN  OUT       AML_OBJECT_NODE_HANDLE                        PciNode
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  INT32                             Index;
> +  UINT32                            IrqTableIndex;
> +  AML_OBJECT_NODE_HANDLE            PrtNode;
> +  CHAR8                             AslName[AML_NAME_SEG_SIZE + 1];
> +  CM_ARM_OBJ_REF                  * RefInfo;
> +  UINT32                            RefCount;
> +  CM_ARM_PCI_INTERRUPT_MAP_INFO   * IrqMapInfo;
> +  UINT32                            IrqFlags;
> +  UINT32                            PrevIrqFlags;
> +
> +  ASSERT (Generator != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (PciInfo != NULL);
> +  ASSERT (PciNode != NULL);
> +
> +  // Get the array of CM_ARM_OBJ_REF referencing the
> +  // CM_ARM_PCI_INTERRUPT_MAP_INFO objects.
> +  Status = GetEArmObjCmRef (
> +             CfgMgrProtocol,
> +             PciInfo->InterruptMapToken,
> +             &RefInfo,
> +             &RefCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
[SAMI] What happens if more than 4 CM_ARM_PCI_INTERRUPT_MAP_INFO objects 
are returned?
> +  // Initialized IrqTable.
> +  Status = MappingTableInitialize (&Generator->IrqTable, RefCount);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Initialized DeviceTable.
> +  Status = MappingTableInitialize (&Generator->DeviceTable, RefCount);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto exit_handler;
> +  }
> +
> +  // ASL: Name (_PRT, Package () {})
> +  Status = AmlCodeGenNamePackage ("_PRT", PciNode, &PrtNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto exit_handler;
> +  }
> +
> +  CopyMem (AslName, "LNKx", AML_NAME_SEG_SIZE + 1);
> +
> +  for (Index = 0; Index < RefCount; Index++) {
> +    // Get CM_ARM_PCI_INTERRUPT_MAP_INFO structures one by one.
> +    Status = GetEArmObjPciInterruptMapInfo (
> +               CfgMgrProtocol,
> +               RefInfo[Index].ReferenceToken,
> +               &IrqMapInfo,
> +               NULL
> +               );
> +    if (EFI_ERROR (Status)) {
> +      ASSERT (0);
> +      goto exit_handler;
> +    }
> +
> +    // Add the interrupt in the IrqTable and get the link name.
> +    IrqTableIndex = MappingTableAdd (
> +                      &Generator->IrqTable,
> +                      IrqMapInfo->IntcInterrupt.Interrupt
> +                      );
> +    AslName[AML_NAME_SEG_SIZE - 1] = 'A' + IrqTableIndex;
> +
> +    // Check that the interrupts flags are identical for all interrupts.
> +    PrevIrqFlags = IrqFlags;
> +    IrqFlags = IrqMapInfo->IntcInterrupt.Flags;
> +    if ((Index > 0) && (PrevIrqFlags != IrqFlags)) {
> +      ASSERT (0);
> +      return EFI_INVALID_PARAMETER;
[SAMI] Go to the exit_handler to free the MappingTable memory.
> +    }
> +
> +    // Add the device to the DeviceTable.
> +    MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice);
> +
> +    /* Add a _PRT entry.
> +       ASL
> +       Name (_PRT, Package () {
> +          [OldPrtEntries],
> +         [NewPrtEntry]
> +       })
> +
> +     Address is set as:
> +     ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
> +       High word-Device #, Low word-Function #. (for example, device 3,
> +       function 2 is 0x00030002). To refer to all the functions on a device #,
> +       use a function number of FFFF).
> +    */
> +    Status = AmlAddPrtEntry (
> +               (IrqMapInfo->PciDevice << 16) | 0xFFFF,
> +               IrqMapInfo->PciInterrupt,
> +               AslName,
> +               0,
> +               PrtNode
> +               );
> +    if (EFI_ERROR (Status)) {
> +      ASSERT (0);
> +      goto exit_handler;
> +    }
> +  } // for
> +
> +  // Generate the LNKx devices now that we know all the interrupts used.
> +  // To look nicer, do it in reverse order since LNKx are added to the head.
> +  for (Index = Generator->IrqTable.LastIndex - 1; Index >= 0; Index--) {
> +    Status = GenerateLinkDevice (
> +               Generator->IrqTable.Table[Index],
> +               IrqFlags,
> +               Index,
> +               PciNode
> +               );
> +    if (EFI_ERROR (Status)) {
> +      ASSERT (0);
> +      goto exit_handler;
> +    }
> +  } // for
> +
> +  // Generate the Pci slots once all the device have been added.
> +  Status = GeneratePciSlots (&Generator->DeviceTable, PciNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto exit_handler;
> +  }
> +
> +exit_handler:
> +  MappingTableFree (&Generator->IrqTable);
> +  MappingTableFree (&Generator->DeviceTable);
[SAMI] I think you need to split the exit handler. if initialisation of 
DeviceTable fails it should not be freed.
> +
> +  return Status;
> +}
> +
> +/** Generate a _CRS method for the Pci device.
> +
> +  @param [in]       Generator       The SSDT Pci generator.
> +  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager
> +                                    Protocol interface.
> +  @param [in]       PciInfo         Pci device information.
> +  @param [in, out]  PciNode         Pci node to amend.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GeneratePciCrs (
> +  IN            ACPI_PCI_GENERATOR                    *       Generator,
> +  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO          *       PciInfo,
> +  IN  OUT       AML_OBJECT_NODE_HANDLE                        PciNode
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  BOOLEAN                           Translation;
> +  UINT32                            Index;
> +  CM_ARM_OBJ_REF                  * RefInfo;
> +  UINT32                            RefCount;
> +  CM_ARM_PCI_ADDRESS_MAP_INFO     * AddrMapInfo;
> +  AML_OBJECT_NODE_HANDLE            CrsNode;
> +
> +  ASSERT (Generator != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (PciInfo != NULL);
> +  ASSERT (PciNode != NULL);
> +
> +  // ASL: Name (_CRS, ResourceTemplate () {})
> +  Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // ASL:
> +  // WordBusNumber (          // Bus numbers assigned to this root
> +  //   ResourceProducer, MinFixed, MaxFixed, PosDecode,
> +  //   0,                     // AddressGranularity
> +  //   [Start],               // AddressMinimum - Minimum Bus Number
> +  //   [End],                 // AddressMaximum - Maximum Bus Number
> +  //   0,                     // AddressTranslation - Set to 0
> +  //   [End] - [Start] + 1    // RangeLength - Number of Busses
> +  // )
> +  Status = AmlCodeGenRdWordBusNumber (
> +             FALSE, TRUE, TRUE, TRUE,
[SAMI] Please put parameters on individual lines. Same comment for other 
functions calls below.
> +             0,
> +             PciInfo->StartBusNumber,
> +             PciInfo->EndBusNumber,
> +             0,
> +             PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1,
> +             0,
> +             NULL,
> +             CrsNode,
> +             NULL
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Get the array of CM_ARM_OBJ_REF referencing the
> +  // CM_ARM_PCI_ADDRESS_MAP_INFO objects.
> +  Status = GetEArmObjCmRef (
> +             CfgMgrProtocol,
> +             PciInfo->AddressMapToken,
> +             &RefInfo,
> +             &RefCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  for (Index = 0; Index < RefCount; Index++) {
> +    // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.
> +    Status = GetEArmObjPciAddressMapInfo (
> +               CfgMgrProtocol,
> +               RefInfo[Index].ReferenceToken,
> +               &AddrMapInfo,
> +               NULL
> +               );
> +    if (EFI_ERROR (Status)) {
> +      ASSERT (0);
> +      return Status;
> +    }
> +
> +    Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);
> +
> +    switch (AddrMapInfo->SpaceCode) {
> +      case PCI_SS_IO:
> +        Status = AmlCodeGenRdDWordIo (
> +                   FALSE, TRUE, TRUE, TRUE, 3,
> +                   0,
> +                   AddrMapInfo->PciAddress,
> +                   AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
> +                   Translation ? AddrMapInfo->CpuAddress : 0,
> +                   AddrMapInfo->AddressSize,
> +                   0, NULL,
> +                   TRUE,
> +                   FALSE,
> +                   CrsNode,
> +                   NULL
> +                   );
> +        break;
> +
> +      case PCI_SS_M32:
> +        Status = AmlCodeGenRdDWordMemory (
> +                   FALSE, TRUE, TRUE, TRUE, TRUE, TRUE,
> +                   0,
> +                   AddrMapInfo->PciAddress,
> +                   AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
> +                   Translation ? AddrMapInfo->CpuAddress : 0,
> +                   AddrMapInfo->AddressSize,
> +                   0, NULL,
> +                   0,
> +                   TRUE,
> +                   CrsNode,
> +                   NULL
> +                   );
> +        break;
> +
> +      case PCI_SS_M64:
> +        Status = AmlCodeGenRdQWordMemory (
> +                   FALSE, TRUE, TRUE, TRUE, TRUE, TRUE,
> +                   0,
> +                   AddrMapInfo->PciAddress,
> +                   AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
> +                   Translation ? AddrMapInfo->CpuAddress : 0,
> +                   AddrMapInfo->AddressSize,
> +                   0, NULL,
> +                   0,
> +                   TRUE,
> +                   CrsNode,
> +                   NULL
> +                   );
> +        break;
> +
> +      default:
> +        Status = EFI_INVALID_PARAMETER;
> +    } // switch
> +    if (EFI_ERROR (Status)) {
> +      ASSERT (0);
> +      return Status;
> +    }
> +  } // for
> +  return Status;
> +}
> +
> +/** Add an _OSC template method to the PciNode.
> +
> +  The _OSC method is provided as an AML blob. The blob is
> +  parsed and attached at the end of the PciNode list of variable elements.
> +
> +  @param [in, out]  PciNode     Pci node to amend.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddOscMethod (
> +  IN  OUT   AML_OBJECT_NODE_HANDLE      PciNode
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_STATUS                    Status1;
> +  EFI_ACPI_DESCRIPTION_HEADER * SsdtPcieOscTemplate;
> +  AML_ROOT_NODE_HANDLE          RootNode;
> +  AML_OBJECT_NODE_HANDLE        OscNode;
> +
> +  ASSERT (PciNode != NULL);
> +
> +  // Parse the Ssdt Pci Osc Template.
> +  SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER*)
> +                          ssdtpcieosctemplate_aml_code;
> +
> +  RootNode = NULL;
> +  Status = AmlParseDefinitionBlock (
> +      SsdtPcieOscTemplate,
[SAMI] Align code here.
> +             &RootNode
[SAMI] Can we change the name from RootNode to OscTemplateRoot here, please?
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  Status = AmlFindNode (RootNode, "\\_OSC", &OscNode);
> +  if (EFI_ERROR (Status)) {
> +    goto error_handler;
> +  }
> +
> +  Status = AmlDetachNode (OscNode);
> +  if (EFI_ERROR (Status)) {
> +    goto error_handler;
> +  }
> +
> +  Status = AmlAttachNode (PciNode, OscNode);
> +  if (EFI_ERROR (Status)) {
[SAMI] If attach fails you would need to free the OscNode branch since 
it is no longer in the OscTemplateRoot.
> +    goto error_handler;
> +  }
> +
> +error_handler:
> +  // Cleanup
> +  Status1 = AmlDeleteTree (RootNode);
> +  if (EFI_ERROR (Status1)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."
> +      " Status = %r\n",
> +      Status1
> +      ));
> +    // If Status was success but we failed to delete the AML Tree
> +    // return Status1 else return the original error code, i.e. Status.
> +    if (!EFI_ERROR (Status)) {
> +      return Status1;
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/** Generate a Pci device.
> +
> +  @param [in]       Generator       The SSDT Pci generator.
> +  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager
> +                                    Protocol interface.
> +  @param [in]       PciInfo         Pci device information.
> +  @param [in]       Uid             Unique Id of the Pci device.
> +  @param [in, out]  RootNode        RootNode of the AML tree to populate.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GeneratePciDevice (
> +  IN            ACPI_PCI_GENERATOR                    *       Generator,
> +  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO          *       PciInfo,
> +  IN            UINT32                                        Uid,
> +  IN  OUT       AML_ROOT_NODE_HANDLE                  *       RootNode
> +  )
> +{
> +  EFI_STATUS                Status;
> +
> +  CHAR8                     AslName[AML_NAME_SEG_SIZE + 1];
> +  AML_OBJECT_NODE_HANDLE    ScopeNode;
> +  AML_OBJECT_NODE_HANDLE    PciNode;
> +
> +  ASSERT (Generator != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (PciInfo != NULL);
> +  ASSERT (RootNode != NULL);
> +
> +  PciNode = NULL;
> +
> +  // ASL: Scope (\_SB) {}
> +  Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Write the name of the PCI device.
> +  CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);
> +  AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid);
> +
> +  // ASL: Device (PCIx) {}
> +  Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Populate the PCIx node with some Id values.
> +  Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Generate the Pci Routing Table (_PRT).
> +  if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) {
> +    Status = GeneratePrt (
> +               Generator,
> +               CfgMgrProtocol,
> +               PciInfo,
> +               PciNode
> +               );
> +    if (EFI_ERROR (Status)) {
> +      ASSERT (0);
> +      return Status;
> +    }
> +  }
> +
> +  // Generate the _CRS method.
> +  Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  // Add the template _OSC method.
> +  Status = AddOscMethod (PciNode);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +  }
> +
> +  return Status;
> +}
> +
> +/** Build an Ssdt table describing a Pci device.
> +
> +  @param [in]  Generator        The SSDT Pci generator.
> +  @param [in]  CfgMgrProtocol   Pointer to the Configuration Manager
> +                                Protocol interface.
> +  @param [in]  PciInfo          Pci device information.
> +  @param [in]  Uid              Unique Id of the Pci device.
> +  @param [out] Table            If success, contains the created SSDT table.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildSsdtPciTable (
> +  IN        ACPI_PCI_GENERATOR                    *       Generator,
> +  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  * CONST CfgMgrProtocol,
> +  IN  CONST CM_ARM_PCI_CONFIG_SPACE_INFO          *       PciInfo,
> +  IN        UINT32                                        Uid,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER          **       Table
> +  )
> +{
> +  EFI_STATUS              Status;
> +  EFI_STATUS              Status1;
> +  AML_ROOT_NODE_HANDLE    RootNode;
> +  CHAR8                   OemTableId[9];
> +
> +  ASSERT (Generator != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (PciInfo != NULL);
> +  ASSERT (Table != NULL);
> +
> +  CopyMem (OemTableId, "SSDTPCIx", sizeof (OemTableId) + 1);
> +  OemTableId[7] = AsciiFromHex(Uid);
> +
> +  // Create a new Ssdt table.
> +  Status = AmlCodeGenDefinitionBlock (
> +             "SSDT",
> +             "ARMLTD",
> +             OemTableId,
> +             1,
> +             &RootNode
> +             );
[SAMI] The OemID, OemTableId and OemRevision should be picked 
fromCM_STD_OBJ_CONFIGURATION_MANAGER_INFO 
andCM_STD_OBJ_ACPI_TABLE_INFOwhich is described in the confiuration manager.
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  Status = GeneratePciDevice (
> +             Generator,
> +             CfgMgrProtocol,
> +             PciInfo,
> +             Uid,
> +             RootNode
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    goto exit_handler;
> +  }
> +
> +  // Serialize the tree.
> +  Status = AmlSerializeDefinitionBlock (
> +             RootNode,
> +             Table
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."
> +      " Status = %r\n",
> +      Status
> +      ));
> +  }
> +
> +exit_handler:
> +  // Cleanup
> +  Status1 = AmlDeleteTree (RootNode);
> +  if (EFI_ERROR (Status1)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SSDT-PCI: Failed to cleanup AML tree."
> +      " Status = %r\n",
> +      Status1
> +      ));
> +    // If Status was success but we failed to delete the AML Tree
> +    // return Status1 else return the original error code, i.e. Status.
> +    if (!EFI_ERROR (Status)) {
> +      return Status1;
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/** Construct SSDT tables describing Pci root complexes.
> +
> +  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 FreeXXXXTableResourcesEx function.
> +
> +  @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 a list of generated ACPI table(s).
> +  @param [out] TableCount      Number of generated ACPI table(s).
> +
> +  @retval EFI_SUCCESS            Table generated successfully.
> +  @retval EFI_BAD_BUFFER_SIZE    The size returned by the Configuration
> +                                 Manager is less than the Object size for
> +                                 the requested object.
> +  @retval EFI_INVALID_PARAMETER  A parameter is invalid.
> +  @retval EFI_NOT_FOUND          Could not find information.
> +  @retval EFI_OUT_OF_RESOURCES   Could not allocate memory.
> +  @retval EFI_UNSUPPORTED        Unsupported configuration.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildSsdtPciTableEx (
> +  IN  CONST ACPI_TABLE_GENERATOR                   *       This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO             * CONST AcpiTableInfo,
> +  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL   * CONST CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER          ***       Table,
> +  OUT       UINTN                                  * CONST TableCount
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  CM_ARM_PCI_CONFIG_SPACE_INFO  * PciInfo;
> +  UINT32                          PciCount;
> +  UINTN                           Index;
> +  EFI_ACPI_DESCRIPTION_HEADER  ** TableList;
> +  ACPI_PCI_GENERATOR            * Generator;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (TableCount != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  *TableCount = 0;
> +  Generator = (ACPI_PCI_GENERATOR*)This;
> +
> +  Status = GetEArmObjPciConfigSpaceInfo (
> +             CfgMgrProtocol,
> +             CM_NULL_TOKEN,
> +             &PciInfo,
> +             &PciCount
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SSDT-PCI: Too many Pci root complexes: %d."
> +      " Maximum Pci root complexes supported = %d.\n",
> +      PciCount,
> +      MAX_PCI_ROOT_COMPLEXES_SUPPORTED
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Allocate a table to store pointers to the SSDT tables.
> +  TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
> +              AllocateZeroPool (
> +                (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * PciCount)
> +                );
> +  if (TableList == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: SSDT-PCI: Failed to allocate memory for Table List."
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  // Setup the table list early so that appropriate cleanup
> +  // can be done in case of failure.
> +  *Table = TableList;
> +
> +  for (Index = 0; Index < PciCount; Index++) {
> +    // Build a SSDT table describing the Pci devices.
> +    Status = BuildSsdtPciTable (
> +               Generator,
> +               CfgMgrProtocol,
> +               &PciInfo[Index],
> +               Index,
> +               &TableList[Index]
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: SSDT-PCI: Failed to build associated SSDT table."
> +        " Status = %r\n",
> +        Status
> +        ));
> +      goto error_handler;
> +    }
> +
> +    *TableCount += 1;
> +  } // for
> +
> +error_handler:
> +  // Note: Table list and Table count have been setup. The
> +  // error handler does nothing here as the framework will invoke
> +  // FreeSsdtPciTableEx () even on failure.
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the tables.
> +
> +  @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 an array of pointers
> +                                  to ACPI Table(s).
> +  @param [in]      TableCount     Number of ACPI table(s).
> +
> +  @retval EFI_SUCCESS           The resources were freed successfully.
> +  @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FreeSsdtPciTableEx (
> +  IN      CONST ACPI_TABLE_GENERATOR                   * CONST This,
> +  IN      CONST CM_STD_OBJ_ACPI_TABLE_INFO             * CONST AcpiTableInfo,
> +  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL   * CONST CfgMgrProtocol,
> +  IN OUT        EFI_ACPI_DESCRIPTION_HEADER          *** CONST Table,
> +  IN      CONST UINTN                                          TableCount
> +  )
> +{
> +  EFI_ACPI_DESCRIPTION_HEADER    ** TableList;
> +  UINTN                             Index;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL)   ||
> +      (*Table == NULL)  ||
> +      (TableCount == 0)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TableList = *Table;
> +  for (Index = 0; Index < TableCount; Index++) {
> +    if ((TableList[Index] != NULL) &&
> +        (TableList[Index]->Signature ==
> +         EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
> +      FreePool (TableList[Index]);
> +    } else {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: SSDT-PCI: Could not free SSDT table at index %d.",
> +        Index
> +        ));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +  } //for
> +
> +  // Free the table list.
> +  FreePool (*Table);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the SSDT Pci Table Generator revision.
> +*/
> +#define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0)
> +
> +/** The interface for the SSDT Pci Table Generator.
> +*/
> +STATIC
> +ACPI_PCI_GENERATOR SsdtPcieGenerator = {
> +  // ACPI table generator header
> +  {
> +    // Generator ID
> +    CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress),
> +    // Generator Description
> +    L"ACPI.STD.SSDT.PCI.GENERATOR",
> +    // ACPI Table Signature
> +    EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
> +    // ACPI Table Revision - Unused
> +    0,
> +    // Minimum ACPI Table Revision - Unused
> +    0,
> +    // Creator ID
> +    TABLE_GENERATOR_CREATOR_ID_ARM,
> +    // Creator Revision
> +    SSDT_PCI_GENERATOR_REVISION,
> +    // Build table function. Use the extended version instead.
> +    NULL,
> +    // Free table function. Use the extended version instead.
> +    NULL,
> +    // Extended Build table function.
> +    BuildSsdtPciTableEx,
> +    // Extended free function.
> +    FreeSsdtPciTableEx
> +  },
> +
> +  // Private fields are defined from here.
> +
> +  // IrqTable
> +  {
> +      // Table
> +      NULL,
> +      // LastIndex
> +      0,
> +      // MaxIndex
> +      0
> +  },
> +  // DeviceTable
> +  {
> +      // Table
> +      NULL,
> +      // LastIndex
> +      0,
> +      // MaxIndex
> +      0
> +  },
> +};
> +
> +/** 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
> +AcpiSsdtPcieLibConstructor (
> +  IN  EFI_HANDLE           ImageHandle,
> +  IN  EFI_SYSTEM_TABLE  *  SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +  Status = RegisterAcpiTableGenerator (&SsdtPcieGenerator.Header);
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "SSDT-PCI: 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
> +AcpiSsdtPcieLibDestructor (
> +  IN  EFI_HANDLE           ImageHandle,
> +  IN  EFI_SYSTEM_TABLE  *  SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +  Status = DeregisterAcpiTableGenerator (&SsdtPcieGenerator.Header);
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "SSDT-PCI: Deregister Generator. Status = %r\n",
> +    Status
> +    ));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
> new file mode 100644
> index 000000000000..2b7f40447d87
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
> @@ -0,0 +1,134 @@
> +/** @file
> +  SSDT Pcie Table Generator.
> +
> +  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Reference(s):
> +  - PCI Firmware Specification - Revision 3.0
> +  - ACPI 6.4 specification:
> +   - s6.2.13 "_PRT (PCI Routing Table)"
> +   - s6.1.1 "_ADR (Address)"
> +  - linux kernel code
> +**/
> +
> +#ifndef SSDT_PCIE_GENERATOR_H_
> +#define SSDT_PCIE_GENERATOR_H_
> +
> +/** Pci address attributes.
> +*/
> +#define PCI_SS_CONFIG   0
> +#define PCI_SS_IO       1
> +#define PCI_SS_M32      2
> +#define PCI_SS_M64      3
[SAMI] Please add description of SS in the glossary section in the file 
header.
> +
> +/** Maximum Pci root complexes supported by this generator.
> +
> +  Note: This is not a hard limitation and can be extended if needed.
> +        Corresponding changes would be needed to support the Name and
> +        UID fields describing the Pci root complexes.
> +*/
> +#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED    16
> +
> +/** Maximum number of Pci legacy interrupts.
> +
> +  Currently 4 for INTA-INTB-INTC-INTD.
> +*/
> +#define MAX_PCI_LEGACY_INTERRUPT            4
> +
> +// _SB scope of the AML namespace.
> +#define SB_SCOPE                            "\\_SB_"
> +
> +/** C array containing the compiled AML template.
> +    This symbol is defined in the auto generated C file
> +    containing the AML bytecode array.
> +*/
> +extern CHAR8  ssdtpcieosctemplate_aml_code[];
> +
> +#pragma pack(1)
> +
> +/** Structure used to map integer to an index.
> +*/
> +typedef struct MappingTable {
> +  /// Mapping table.
> +  /// Contains the Index <-> integer mapping
> +  UINT32             * Table;
> +
> +  /// Last used index of the Table.
> +  /// Bound by MaxIndex.
> +  UINT32               LastIndex;
> +
> +  /// Number of entries in the Table.
> +  UINT32               MaxIndex;
> +} MAPPING_TABLE;
> +
> +/** A structure holding the Pcie generator and additional private data.
> +*/
> +typedef struct AcpiPcieGenerator {
> +  /// ACPI Table generator header
> +  ACPI_TABLE_GENERATOR    Header;
> +
> +  // Private fields are defined from here.
> +
> +  /** A structure used to handle the Address and Interrupt Map referencing.
> +
> +    A CM_ARM_PCI_CONFIG_SPACE_INFO structure references two CM_ARM_OBJ_REF:
> +     - one for the address mapping, referencing
> +       CM_ARM_PCI_ADDRESS_MAP_INFO structures.
> +     - one for the address mapping, referencing
[SAMI] I believe this should be 'second for interrupt mapping'
> +       CM_ARM_PCI_INTERRUPT_MAP_INFO structures.
> +
> +    Example (for the interrupt mapping):
> +    (Pci0)
> +    CM_ARM_PCI_CONFIG_SPACE_INFO
> +                |
> +                v
> +    (List of references to address mappings)
> +    CM_ARM_OBJ_REF
> +                |
> +                +----------------------------------------
> +                |                                       |
> +                v                                       v
> +    (A first interrupt mapping)               (A second interrupt mapping)
> +    CM_ARM_PCI_INTERRUPT_MAP_INFO[0]          CM_ARM_PCI_INTERRUPT_MAP_INFO[1]
[SAMI] Please correct the above diagram.
> +
> +    The CM_ARM_PCI_INTERRUPT_MAP_INFO objects cannot be handled individually.
> +    Device's Pci legacy interrupts that are mapped to the same CPU interrupt
> +    are grouped under a Link device.
> +    For instance, the following mapping:
> +     - [INTA of device 0] mapped on [GIC irq 168]
> +     - [INTB of device 1] mapped on [GIC irq 168]
> +    will be represented in an SSDT table as:
> +     - [INTA of device 0] mapped on [Link device A]
> +     - [INTB of device 1] mapped on [Link device A]
> +     - [Link device A] mapped on [GIC irq 168]
> +
> +    Counting the number of Cpu interrupts used and grouping them in Link
> +    devices is done through this IRQ_TABLE.
> +
> +    ASL code:
> +    Scope (_SB) {
> +      Device (LNKA) {
> +        [...]
> +        Name (_PRS, ResourceTemplate () {
> +          Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { 168 }
> +        })
> +      }
> +
> +      Device (PCI0) {
> +        Name (_PRT, Package () {
> +          Package (0x0FFFF, 0, LNKA, 0)  // INTA of device 0 <-> LNKA
> +          Package (0x1FFFF, 1, LNKA, 0)  // INTB of device 1 <-> LNKA
> +          })
> +        }
> +    }
> +  */
> +  MAPPING_TABLE           IrqTable;
> +
> +  /// Table to map: Index <-> Pci device
> +  MAPPING_TABLE           DeviceTable;
> +} ACPI_PCI_GENERATOR;
> +
> +#pragma pack()
> +
> +#endif // SSDT_PCIE_GENERATOR_H_
> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
> new file mode 100644
> index 000000000000..283b5648017c
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
> @@ -0,0 +1,32 @@
> +## @file
> +# Ssdt Serial Port Table Generator
> +#
> +#  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x0001001B
> +  BASE_NAME      = SsdtPcieLibArm
> +  FILE_GUID      = E431D7FD-26BF-4E3D-9064-5B13B0439057
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiSsdtPcieLibConstructor
> +  DESTRUCTOR     = AcpiSsdtPcieLibDestructor
> +
> +[Sources]
> +  SsdtPcieGenerator.c
> +  SsdtPcieGenerator.h
> +  SsdtPcieOscTemplate.asl
> +
> +[Packages]
> +  DynamicTablesPkg/DynamicTablesPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  AcpiHelperLib
> +  AmlLib
> +  BaseLib
> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl
> new file mode 100644
> index 000000000000..feaf56b53384
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl
> @@ -0,0 +1,80 @@
> +/** @file
> +  SSDT Pci Osc (Operating System Capabilities)
> +
> +  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Reference(s):
> +  - PCI Firmware Specification - Revision 3.3
> +  - ACPI 6.4 specification:
> +   - s6.2.13 "_PRT (PCI Routing Table)"
> +   - s6.1.1 "_ADR (Address)"
> +  - linux kernel code
> +**/
> +
> +DefinitionBlock ("SsdtPciOsc.aml", "SSDT", 2, "ARMLTD", "PCI-OSC", 1) {
> +
> +  // This table is just a template and is never installed as a table.
> +  // Pci devices are dynamically created at runtime as:
> +  // ASL:
> +  // Device (PCIx) {
> +  //   ...
> +  // }
> +  // and the _OSC method available below is appended to the PCIx device as:
> +  // ASL:
> +  // Device (PCIx) {
> +  //   ...
> +  //   Method (_OSC, 4 {
> +  //    ...
> +  //   })
> +  // }
> +  Method (_OSC, 4) {
> +    //
> +    // OS Control Handoff
> +    //
> +    Name (SUPP, Zero) // PCI _OSC Support Field value
> +    Name (CTRL, Zero) // PCI _OSC Control Field value
> +
> +    // Create DWord-addressable fields from the Capabilities Buffer
> +    CreateDWordField (Arg3, 0, CDW1)
> +    CreateDWordField (Arg3, 4, CDW2)
> +    CreateDWordField (Arg3, 8, CDW3)
> +
> +    // Check for proper UUID
> +    If (LEqual (Arg0,ToUUID ("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
> +
> +      // Save Capabilities DWord2 & 3
> +      Store (CDW2, SUPP)
> +      Store (CDW3, CTRL)
> +
> +      // Only allow native hot plug control if OS supports:
> +      // * ASPM
> +      // * Clock PM
> +      // * MSI/MSI-X
> +      If (LNotEqual (And (SUPP, 0x16), 0x16)) {
> +        And (CTRL, 0x1E, CTRL) // Mask bit 0 (and undefined bits)
> +      }
> +
> +      // Always allow native PME, AER (no dependencies)
> +
> +      // Never allow SHPC (no SHPC controller in this system)
> +      And (CTRL, 0x1D, CTRL)
> +
> +      If (LNotEqual (Arg1, One)) {  // Unknown revision
> +        Or (CDW1, 0x08, CDW1)
> +      }
> +
> +      If (LNotEqual (CDW3, CTRL)) {  // Capabilities bits were masked
> +        Or (CDW1, 0x10, CDW1)
> +      }
> +
> +      // Update DWORD3 in the buffer
> +      Store (CTRL,CDW3)
> +      Return (Arg3)
> +    } Else {
> +      Or (CDW1, 4, CDW1) // Unrecognized UUID
> +      Return (Arg3)
> +    } // If
> +  } // _OSC
> +}


[-- Attachment #2: Type: text/html, Size: 58684 bytes --]

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

end of thread, other threads:[~2021-10-07 11:11 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-06-23 11:58 [PATCH v1 0/7] Create a SSDT PCIe generator PierreGondois
2021-06-23 11:58 ` [PATCH v1 1/7] DynamicTablesPkg: AML Code generation for memory ranges PierreGondois
2021-10-06 15:14   ` Sami Mujawar
2021-06-23 11:58 ` [PATCH v1 2/7] DynamicTablesPkg: AML Code generation to create a named Package() PierreGondois
2021-10-06 15:15   ` Sami Mujawar
2021-06-23 11:58 ` [PATCH v1 3/7] DynamicTablesPkg: AML Code generation to create a named ResourceTemplate() PierreGondois
2021-10-06 15:16   ` Sami Mujawar
2021-06-23 11:58 ` [PATCH v1 4/7] DynamicTablesPkg: AML Code generation to add _PRT entries PierreGondois
2021-10-06 15:17   ` Sami Mujawar
2021-06-23 11:58 ` [PATCH v1 5/7] DynamicTablesPkg: Add AmlAttachNode() PierreGondois
2021-10-06 15:17   ` Sami Mujawar
2021-06-23 11:58 ` [PATCH v1 6/7] DynamicTablesPkg: Add Pci related objects PierreGondois
2021-10-06 15:18   ` Sami Mujawar
2021-06-23 11:58 ` [PATCH v1 7/7] DynamicTablesPkg: SSDT Pci express generator PierreGondois
2021-10-07 11:11   ` Sami Mujawar

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