]> git.proxmox.com Git - mirror_edk2.git/commitdiff
DynamicTablesPkg: AML Resource Data Codegen
authorPierre Gondois <pierre.gondois@arm.com>
Wed, 5 Aug 2020 13:54:51 +0000 (14:54 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 13 Aug 2020 18:00:06 +0000 (18:00 +0000)
AML Codegen is a Dynamic AML technique that facilitates
generation of small segments of AML code. The AML code
generated using AML Codegen is represented as nodes in
the AML Tree.

AML Resource Data Codegen implements interfaces required
for generating Resource Data elements that can be attached
to an AML tree.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c [new file with mode: 0644]
DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.h [new file with mode: 0644]

diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
new file mode 100644 (file)
index 0000000..9e7a508
--- /dev/null
@@ -0,0 +1,256 @@
+/** @file\r
+  AML Resource Data Code Generation.\r
+\r
+  Copyright (c) 2020, Arm Limited. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+  @par Glossary:\r
+  - Rd or RD   - Resource Data\r
+  - Rds or RDS - Resource Data Small\r
+  - Rdl or RDL - Resource Data Large\r
+**/\r
+\r
+#include <AmlNodeDefines.h>\r
+#include <CodeGen/AmlResourceDataCodeGen.h>\r
+\r
+#include <AmlCoreInterface.h>\r
+#include <AmlDefines.h>\r
+#include <Api/AmlApiHelper.h>\r
+#include <Tree/AmlNode.h>\r
+#include <ResourceData/AmlResourceData.h>\r
+\r
+/** If ParentNode is not NULL, append RdNode.\r
+    If NewRdNode is not NULL, update its value to RdNode.\r
+\r
+  @param [in]  RdNode       Newly created Resource Data node.\r
+  @param [in]  ParentNode   If not NULL, add the generated node\r
+                            to the end of the variable list of\r
+                            argument of the ParentNode, but\r
+                            before the "End Tag" Resource Data.\r
+                            Must be a BufferOpNode.\r
+  @param [out] NewRdNode    If not NULL, update the its value to RdNode.\r
+\r
+  @retval  EFI_SUCCESS            The function completed successfully.\r
+  @retval  EFI_INVALID_PARAMETER  Invalid parameter.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+LinkRdNode (\r
+  IN  AML_DATA_NODE      * RdNode,\r
+  IN  AML_OBJECT_NODE    * ParentNode,\r
+  IN  AML_DATA_NODE     ** NewRdNode\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_STATUS    Status1;\r
+\r
+  if (NewRdNode != NULL) {\r
+    *NewRdNode = RdNode;\r
+  }\r
+\r
+  // Add RdNode as the last element, but before the EndTag.\r
+  if (ParentNode != NULL) {\r
+    Status = AmlAppendRdNode (ParentNode, RdNode);\r
+    if (EFI_ERROR (Status)) {\r
+      ASSERT (0);\r
+      Status1 = AmlDeleteTree ((AML_NODE_HEADER*)RdNode);\r
+      ASSERT_EFI_ERROR (Status1);\r
+      // Return original error.\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/** Code generation for the "Interrupt ()" ASL function.\r
+\r
+  This function creates a Resource Data element corresponding to the\r
+  "Interrupt ()" ASL function and stores it in an AML Data Node.\r
+\r
+  The Resource Data effectively created is an Extended Interrupt Resource\r
+  Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"\r
+  for more information about Extended Interrupt Resource Data.\r
+\r
+  This function allocates memory to create a data node. It is the caller's\r
+  responsibility to either:\r
+   - attach this node to an AML tree;\r
+   - delete this node.\r
+\r
+  @param [in]  ResourceConsumer    The device consumes the specified interrupt\r
+                                   or produces it for use by a child device.\r
+  @param [in]  EdgeTriggered       The interrupt is edge triggered or\r
+                                   level triggered.\r
+  @param [in]  ActiveLow           The interrupt is active-high or active-low.\r
+  @param [in]  Shared              The interrupt can be shared with other\r
+                                   devices or not (Exclusive).\r
+  @param [in]  IrqList             Interrupt list. Must be non-NULL.\r
+  @param [in]  IrqCount            Interrupt count. Must be non-zero.\r
+  @param [in]  ParentNode          If not NULL, add the generated node\r
+                                   to the end of the variable list of\r
+                                   argument of the ParentNode, but\r
+                                   before the "End Tag" Resource Data.\r
+                                   Must be a BufferOpNode.\r
+  @param  [out] NewRdNode          If success, contains the generated node.\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenInterrupt (\r
+  IN  BOOLEAN             ResourceConsumer,\r
+  IN  BOOLEAN             EdgeTriggered,\r
+  IN  BOOLEAN             ActiveLow,\r
+  IN  BOOLEAN             Shared,\r
+  IN  UINT32            * IrqList,\r
+  IN  UINT8               IrqCount,\r
+  IN  AML_OBJECT_NODE   * ParentNode,   OPTIONAL\r
+  OUT AML_DATA_NODE    ** NewRdNode     OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                               Status;\r
+\r
+  AML_DATA_NODE                          * RdNode;\r
+  EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR   RdInterrupt;\r
+  UINT32                                 * FirstInterrupt;\r
+\r
+  if ((IrqList == NULL) ||\r
+      (IrqCount == 0)   ||\r
+      ((ParentNode == NULL) && (NewRdNode == NULL))) {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  RdInterrupt.Header.Header.Bits.Name =\r
+    ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME;\r
+  RdInterrupt.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;\r
+  RdInterrupt.Header.Length = sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR) -\r
+                                sizeof (ACPI_LARGE_RESOURCE_HEADER);\r
+  RdInterrupt.InterruptVectorFlags = (ResourceConsumer ? BIT0 : 0) |\r
+                                     (EdgeTriggered ? BIT1 : 0)    |\r
+                                     (ActiveLow ? BIT2 : 0)        |\r
+                                     (Shared ? BIT3 : 0);\r
+  RdInterrupt.InterruptTableLength = IrqCount;\r
+\r
+  // Get the address of the first interrupt field.\r
+  FirstInterrupt = RdInterrupt.InterruptNumber;\r
+\r
+  // Copy the list of interrupts.\r
+  CopyMem (FirstInterrupt, IrqList, (sizeof (UINT32) * IrqCount));\r
+\r
+  Status = AmlCreateDataNode (\r
+             EAmlNodeDataTypeResourceData,\r
+             (UINT8*)&RdInterrupt,\r
+             sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR),\r
+             &RdNode\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    return Status;\r
+  }\r
+\r
+  return LinkRdNode (RdNode, ParentNode, NewRdNode);\r
+}\r
+\r
+/** Add an Interrupt Resource Data node.\r
+\r
+  This function creates a Resource Data element corresponding to the\r
+  "Interrupt ()" ASL function, stores it in an AML Data Node.\r
+\r
+  It then adds it after the input CurrRdNode in the list of resource data\r
+  element.\r
+\r
+  The Resource Data effectively created is an Extended Interrupt Resource\r
+  Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"\r
+  for more information about Extended Interrupt Resource Data.\r
+\r
+  The Extended Interrupt contains one single interrupt.\r
+\r
+  This function allocates memory to create a data node. It is the caller's\r
+  responsibility to either:\r
+   - attach this node to an AML tree;\r
+   - delete this node.\r
+\r
+  Note: The _CRS node must be defined using the ASL Name () function.\r
+        e.g. Name (_CRS, ResourceTemplate () {\r
+               ...\r
+             }\r
+\r
+  @param  [in]  NameOpCrsNode    NameOp object node defining a "_CRS" object.\r
+                                 Must have an OpCode=AML_NAME_OP, SubOpCode=0.\r
+                                 NameOp object nodes are defined in ASL\r
+                                 using the "Name ()" function.\r
+  @param  [in]  ResourceConsumer The device consumes the specified interrupt\r
+                                 or produces it for use by a child device.\r
+  @param  [in]  EdgeTriggered    The interrupt is edge triggered or\r
+                                 level triggered.\r
+  @param  [in]  ActiveLow        The interrupt is active-high or active-low.\r
+  @param  [in]  Shared           The interrupt can be shared with other\r
+                                 devices or not (Exclusive).\r
+  @param  [in]  IrqList          Interrupt list. Must be non-NULL.\r
+  @param  [in]  IrqCount         Interrupt count. Must be non-zero.\r
+\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenCrsAddRdInterrupt (\r
+  IN  AML_OBJECT_NODE_HANDLE  NameOpCrsNode,\r
+  IN  BOOLEAN                 ResourceConsumer,\r
+  IN  BOOLEAN                 EdgeTriggered,\r
+  IN  BOOLEAN                 ActiveLow,\r
+  IN  BOOLEAN                 Shared,\r
+  IN  UINT32                * IrqList,\r
+  IN  UINT8                   IrqCount\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  AML_OBJECT_NODE_HANDLE  BufferOpNode;\r
+\r
+  if ((IrqList == NULL)                                                   ||\r
+      (IrqCount == 0)                                                     ||\r
+      (!AmlNodeHasOpCode (NameOpCrsNode, AML_NAME_OP, 0))                 ||\r
+      (!AmlNameOpCompareName (NameOpCrsNode, "_CRS"))) {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  // Get the _CRS value which is represented as a BufferOp object node\r
+  // which is the 2nd fixed argument (i.e. index 1).\r
+  BufferOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (\r
+                                           NameOpCrsNode,\r
+                                           EAmlParseIndexTerm1\r
+                                           );\r
+  if ((BufferOpNode == NULL)                                             ||\r
+      (AmlGetNodeType ((AML_NODE_HANDLE)BufferOpNode) != EAmlNodeObject) ||\r
+      (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0))) {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  // Generate the Extended Interrupt Resource Data node,\r
+  // and attach it as the last variable argument of the BufferOpNode.\r
+  Status = AmlCodeGenInterrupt (\r
+             ResourceConsumer,\r
+             EdgeTriggered,\r
+             ActiveLow,\r
+             Shared,\r
+             IrqList,\r
+             IrqCount,\r
+             BufferOpNode,\r
+             NULL\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.h b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.h
new file mode 100644 (file)
index 0000000..08364db
--- /dev/null
@@ -0,0 +1,59 @@
+/** @file\r
+  AML Resource Data Code Generation.\r
+\r
+  Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#ifndef AML_RESOURCE_DATA_CODE_GEN_H_\r
+#define AML_RESOURCE_DATA_CODE_GEN_H_\r
+\r
+/** Code generation for the "Interrupt ()" ASL function.\r
+\r
+  This function creates a Resource Data element corresponding to the\r
+  "Interrupt ()" ASL function and stores it in an AML Data Node.\r
+\r
+  The Resource Data effectively created is an Extended Interrupt Resource\r
+  Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"\r
+  for more information about Extended Interrupt Resource Data.\r
+\r
+  This function allocates memory to create a data node. It is the caller's\r
+  responsibility to either:\r
+   - attach this node to an AML tree;\r
+   - delete this node.\r
+\r
+  @param [in]  ResourceConsumer    The device consumes the specified interrupt\r
+                                   or produces it for use by a child device.\r
+  @param [in]  EdgeTriggered       The interrupt is edge triggered or\r
+                                   level triggered.\r
+  @param [in]  ActiveLow           The interrupt is active-high or active-low.\r
+  @param [in]  Shared              The interrupt can be shared with other\r
+                                   devices or not (Exclusive).\r
+  @param [in]  IrqList             Interrupt list. Must be non-NULL.\r
+  @param [in]  IrqCount            Interrupt count. Must be non-zero.\r
+  @param [in]  ParentNode          If not NULL, add the generated node\r
+                                   to the end of the variable list of\r
+                                   argument of the ParentNode, but\r
+                                   before the "End Tag" Resource Data.\r
+                                   Must be a BufferOpNode.\r
+  @param  [out] NewRdNode          If success, contains the generated node.\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenInterrupt (\r
+  IN  BOOLEAN             ResourceConsumer,\r
+  IN  BOOLEAN             EdgeTriggered,\r
+  IN  BOOLEAN             ActiveLow,\r
+  IN  BOOLEAN             Shared,\r
+  IN  UINT32            * IrqList,\r
+  IN  UINT8               IrqCount,\r
+  IN  AML_OBJECT_NODE   * ParentNode,   OPTIONAL\r
+  OUT AML_DATA_NODE    ** NewRdNode     OPTIONAL\r
+  );\r
+\r
+#endif // AML_RESOURCE_DATA_CODE_GEN_H_\r