]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
cba942c0fd1a4a251aaf8cd7c0de69cd53867e2a
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AmlLib / CodeGen / AmlResourceDataCodeGen.c
1 /** @file
2 AML Resource Data Code Generation.
3
4 Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 @par Glossary:
9 - Rd or RD - Resource Data
10 - Rds or RDS - Resource Data Small
11 - Rdl or RDL - Resource Data Large
12 **/
13
14 #include <AmlNodeDefines.h>
15 #include <CodeGen/AmlResourceDataCodeGen.h>
16
17 #include <AmlCoreInterface.h>
18 #include <AmlDefines.h>
19 #include <Api/AmlApiHelper.h>
20 #include <Tree/AmlNode.h>
21 #include <ResourceData/AmlResourceData.h>
22
23 /** If ParentNode is not NULL, append RdNode.
24 If NewRdNode is not NULL, update its value to RdNode.
25
26 @param [in] RdNode Newly created Resource Data node.
27 RdNode is deleted if an error occurs.
28 @param [in] ParentNode If not NULL, ParentNode must:
29 - be a NameOp node, i.e. have the AML_NAME_OP
30 opcode (cf "Name ()" ASL statement)
31 - contain a list of resource data elements
32 (cf "ResourceTemplate ()" ASL statement)
33 RdNode is then added at the end of the variable
34 list of resource data elements, but before the
35 "End Tag" Resource Data.
36 @param [out] NewRdNode If not NULL:
37 - and Success, contains RdNode.
38 - and Error, reset to NULL.
39
40 @retval EFI_SUCCESS The function completed successfully.
41 @retval EFI_INVALID_PARAMETER Invalid parameter.
42 **/
43 STATIC
44 EFI_STATUS
45 EFIAPI
46 LinkRdNode (
47 IN AML_DATA_NODE * RdNode,
48 IN AML_OBJECT_NODE * ParentNode,
49 OUT AML_DATA_NODE ** NewRdNode
50 )
51 {
52 EFI_STATUS Status;
53 EFI_STATUS Status1;
54 AML_OBJECT_NODE *BufferOpNode;
55
56 if (NewRdNode != NULL) {
57 *NewRdNode = NULL;
58 }
59
60 if (ParentNode != NULL) {
61 // Check this is a NameOp node.
62 if ((!AmlNodeHasOpCode (ParentNode, AML_NAME_OP, 0))) {
63 ASSERT (0);
64 Status = EFI_INVALID_PARAMETER;
65 goto error_handler;
66 }
67
68 // Get the value which is represented as a BufferOp object node
69 // which is the 2nd fixed argument (i.e. index 1).
70 BufferOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
71 ParentNode,
72 EAmlParseIndexTerm1
73 );
74 if ((BufferOpNode == NULL) ||
75 (AmlGetNodeType ((AML_NODE_HANDLE)BufferOpNode) != EAmlNodeObject) ||
76 (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0))) {
77 ASSERT (0);
78 Status = EFI_INVALID_PARAMETER;
79 goto error_handler;
80 }
81
82 // Add RdNode as the last element, but before the EndTag.
83 Status = AmlAppendRdNode (BufferOpNode, RdNode);
84 if (EFI_ERROR (Status)) {
85 ASSERT (0);
86 goto error_handler;
87 }
88 }
89
90 if (NewRdNode != NULL) {
91 *NewRdNode = RdNode;
92 }
93
94 return Status;
95
96 error_handler:
97 Status1 = AmlDeleteTree ((AML_NODE_HEADER*)RdNode);
98 ASSERT_EFI_ERROR (Status1);
99 // Return original error.
100 return Status;
101 }
102
103 /** Code generation for the "Interrupt ()" ASL function.
104
105 The Resource Data effectively created is an Extended Interrupt Resource
106 Data. Cf ACPI 6.4:
107 - s6.4.3.6 "Extended Interrupt Descriptor"
108 - s19.6.64 "Interrupt (Interrupt Resource Descriptor Macro)"
109
110 The created resource data node can be:
111 - appended to the list of resource data elements of the NameOpNode.
112 In such case NameOpNode must be defined by a the "Name ()" ASL statement
113 and initially contain a "ResourceTemplate ()".
114 - returned through the NewRdNode parameter.
115
116 @param [in] ResourceConsumer The device consumes the specified interrupt
117 or produces it for use by a child device.
118 @param [in] EdgeTriggered The interrupt is edge triggered or
119 level triggered.
120 @param [in] ActiveLow The interrupt is active-high or active-low.
121 @param [in] Shared The interrupt can be shared with other
122 devices or not (Exclusive).
123 @param [in] IrqList Interrupt list. Must be non-NULL.
124 @param [in] IrqCount Interrupt count. Must be non-zero.
125 @param [in] NameOpNode NameOp object node defining a named object.
126 If provided, append the new resource data node
127 to the list of resource data elements of this
128 node.
129 @param [out] NewRdNode If provided and success,
130 contain the created node.
131
132 @retval EFI_SUCCESS The function completed successfully.
133 @retval EFI_INVALID_PARAMETER Invalid parameter.
134 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
135 **/
136 EFI_STATUS
137 EFIAPI
138 AmlCodeGenRdInterrupt (
139 IN BOOLEAN ResourceConsumer,
140 IN BOOLEAN EdgeTriggered,
141 IN BOOLEAN ActiveLow,
142 IN BOOLEAN Shared,
143 IN UINT32 *IrqList,
144 IN UINT8 IrqCount,
145 IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
146 OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
147 )
148 {
149 EFI_STATUS Status;
150
151 AML_DATA_NODE * RdNode;
152 EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR RdInterrupt;
153 UINT32 * FirstInterrupt;
154
155 if ((IrqList == NULL) ||
156 (IrqCount == 0) ||
157 ((NameOpNode == NULL) && (NewRdNode == NULL))) {
158 ASSERT (0);
159 return EFI_INVALID_PARAMETER;
160 }
161
162 // Header
163 RdInterrupt.Header.Header.Bits.Name =
164 ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME;
165 RdInterrupt.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
166 RdInterrupt.Header.Length = sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR) -
167 sizeof (ACPI_LARGE_RESOURCE_HEADER);
168
169 // Body
170 RdInterrupt.InterruptVectorFlags = (ResourceConsumer ? BIT0 : 0) |
171 (EdgeTriggered ? BIT1 : 0) |
172 (ActiveLow ? BIT2 : 0) |
173 (Shared ? BIT3 : 0);
174 RdInterrupt.InterruptTableLength = IrqCount;
175
176 // Get the address of the first interrupt field.
177 FirstInterrupt = RdInterrupt.InterruptNumber;
178
179 // Copy the list of interrupts.
180 CopyMem (FirstInterrupt, IrqList, (sizeof (UINT32) * IrqCount));
181
182 Status = AmlCreateDataNode (
183 EAmlNodeDataTypeResourceData,
184 (UINT8*)&RdInterrupt,
185 sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR),
186 &RdNode
187 );
188 if (EFI_ERROR (Status)) {
189 ASSERT (0);
190 return Status;
191 }
192
193 return LinkRdNode (RdNode, NameOpNode, NewRdNode);
194 }
195
196 // DEPRECATED APIS
197 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
198
199 /** DEPRECATED API
200
201 Add an Interrupt Resource Data node.
202
203 This function creates a Resource Data element corresponding to the
204 "Interrupt ()" ASL function, stores it in an AML Data Node.
205
206 It then adds it after the input CurrRdNode in the list of resource data
207 element.
208
209 The Resource Data effectively created is an Extended Interrupt Resource
210 Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
211 for more information about Extended Interrupt Resource Data.
212
213 The Extended Interrupt contains one single interrupt.
214
215 This function allocates memory to create a data node. It is the caller's
216 responsibility to either:
217 - attach this node to an AML tree;
218 - delete this node.
219
220 Note: The _CRS node must be defined using the ASL Name () function.
221 e.g. Name (_CRS, ResourceTemplate () {
222 ...
223 }
224
225 @ingroup UserApis
226
227 @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object.
228 Must have an OpCode=AML_NAME_OP, SubOpCode=0.
229 NameOp object nodes are defined in ASL
230 using the "Name ()" function.
231 @param [in] ResourceConsumer The device consumes the specified interrupt
232 or produces it for use by a child device.
233 @param [in] EdgeTriggered The interrupt is edge triggered or
234 level triggered.
235 @param [in] ActiveLow The interrupt is active-high or active-low.
236 @param [in] Shared The interrupt can be shared with other
237 devices or not (Exclusive).
238 @param [in] IrqList Interrupt list. Must be non-NULL.
239 @param [in] IrqCount Interrupt count. Must be non-zero.
240
241
242 @retval EFI_SUCCESS The function completed successfully.
243 @retval EFI_INVALID_PARAMETER Invalid parameter.
244 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
245 **/
246 EFI_STATUS
247 EFIAPI
248 AmlCodeGenCrsAddRdInterrupt (
249 IN AML_OBJECT_NODE_HANDLE NameOpCrsNode,
250 IN BOOLEAN ResourceConsumer,
251 IN BOOLEAN EdgeTriggered,
252 IN BOOLEAN ActiveLow,
253 IN BOOLEAN Shared,
254 IN UINT32 * IrqList,
255 IN UINT8 IrqCount
256 )
257 {
258 return AmlCodeGenRdInterrupt (
259 ResourceConsumer,
260 EdgeTriggered,
261 ActiveLow,
262 Shared,
263 IrqList,
264 IrqCount,
265 NameOpCrsNode,
266 NULL
267 );
268 }
269
270 #endif // DISABLE_NEW_DEPRECATED_INTERFACES