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