2 AML Resource Data Code Generation.
4 Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 - Rd or RD - Resource Data
10 - Rds or RDS - Resource Data Small
11 - Rdl or RDL - Resource Data Large
14 #include <AmlNodeDefines.h>
15 #include <CodeGen/AmlResourceDataCodeGen.h>
17 #include <AmlCoreInterface.h>
18 #include <AmlDefines.h>
19 #include <Api/AmlApiHelper.h>
20 #include <Tree/AmlNode.h>
21 #include <ResourceData/AmlResourceData.h>
23 /** If ParentNode is not NULL, append RdNode.
24 If NewRdNode is not NULL, update its value to RdNode.
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.
40 @retval EFI_SUCCESS The function completed successfully.
41 @retval EFI_INVALID_PARAMETER Invalid parameter.
47 IN AML_DATA_NODE
* RdNode
,
48 IN AML_OBJECT_NODE
* ParentNode
,
49 OUT AML_DATA_NODE
** NewRdNode
54 AML_OBJECT_NODE
*BufferOpNode
;
56 if (NewRdNode
!= NULL
) {
60 if (ParentNode
!= NULL
) {
61 // Check this is a NameOp node.
62 if ((!AmlNodeHasOpCode (ParentNode
, AML_NAME_OP
, 0))) {
64 Status
= EFI_INVALID_PARAMETER
;
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 (
74 if ((BufferOpNode
== NULL
) ||
75 (AmlGetNodeType ((AML_NODE_HANDLE
)BufferOpNode
) != EAmlNodeObject
) ||
76 (!AmlNodeHasOpCode (BufferOpNode
, AML_BUFFER_OP
, 0))) {
78 Status
= EFI_INVALID_PARAMETER
;
82 // Add RdNode as the last element, but before the EndTag.
83 Status
= AmlAppendRdNode (BufferOpNode
, RdNode
);
84 if (EFI_ERROR (Status
)) {
90 if (NewRdNode
!= NULL
) {
97 Status1
= AmlDeleteTree ((AML_NODE_HEADER
*)RdNode
);
98 ASSERT_EFI_ERROR (Status1
);
99 // Return original error.
103 /** Code generation for the "Interrupt ()" ASL function.
105 The Resource Data effectively created is an Extended Interrupt Resource
107 - s6.4.3.6 "Extended Interrupt Descriptor"
108 - s19.6.64 "Interrupt (Interrupt Resource Descriptor Macro)"
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.
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
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
129 @param [out] NewRdNode If provided and success,
130 contain the created node.
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.
138 AmlCodeGenRdInterrupt (
139 IN BOOLEAN ResourceConsumer
,
140 IN BOOLEAN EdgeTriggered
,
141 IN BOOLEAN ActiveLow
,
145 IN AML_OBJECT_NODE_HANDLE NameOpNode
, OPTIONAL
146 OUT AML_DATA_NODE_HANDLE
*NewRdNode OPTIONAL
151 AML_DATA_NODE
* RdNode
;
152 EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR RdInterrupt
;
153 UINT32
* FirstInterrupt
;
155 if ((IrqList
== NULL
) ||
157 ((NameOpNode
== NULL
) && (NewRdNode
== NULL
))) {
159 return EFI_INVALID_PARAMETER
;
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
);
170 RdInterrupt
.InterruptVectorFlags
= (ResourceConsumer
? BIT0
: 0) |
171 (EdgeTriggered
? BIT1
: 0) |
172 (ActiveLow
? BIT2
: 0) |
174 RdInterrupt
.InterruptTableLength
= IrqCount
;
176 // Get the address of the first interrupt field.
177 FirstInterrupt
= RdInterrupt
.InterruptNumber
;
179 // Copy the list of interrupts.
180 CopyMem (FirstInterrupt
, IrqList
, (sizeof (UINT32
) * IrqCount
));
182 Status
= AmlCreateDataNode (
183 EAmlNodeDataTypeResourceData
,
184 (UINT8
*)&RdInterrupt
,
185 sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR
),
188 if (EFI_ERROR (Status
)) {
193 return LinkRdNode (RdNode
, NameOpNode
, NewRdNode
);
196 /** Code generation for the "Register ()" ASL function.
198 The Resource Data effectively created is a Generic Register Descriptor.
200 - s6.4.3.7 "Generic Register Descriptor".
201 - s19.6.114 "Register".
203 The created resource data node can be:
204 - appended to the list of resource data elements of the NameOpNode.
205 In such case NameOpNode must be defined by a the "Name ()" ASL statement
206 and initially contain a "ResourceTemplate ()".
207 - returned through the NewRdNode parameter.
209 @param [in] AddressSpace Address space where the register exists.
210 Can be one of I/O space, System Memory, etc.
211 @param [in] BitWidth Number of bits in the register.
212 @param [in] BitOffset Offset in bits from the start of the register
213 indicated by the Address.
214 @param [in] Address Register address.
215 @param [in] AccessSize Size of data values used when accessing the
216 address space. Can be one of:
217 0 - Undefined, legacy (EFI_ACPI_6_4_UNDEFINED)
218 1 - Byte access (EFI_ACPI_6_4_BYTE)
219 2 - Word access (EFI_ACPI_6_4_WORD)
220 3 - DWord access (EFI_ACPI_6_4_DWORD)
221 4 - QWord access (EFI_ACPI_6_4_QWORD)
222 @param [in] NameOpNode NameOp object node defining a named object.
223 If provided, append the new resource data node
224 to the list of resource data elements of this
226 @param [out] NewRdNode If provided and success,
227 contain the created node.
229 @retval EFI_SUCCESS The function completed successfully.
230 @retval EFI_INVALID_PARAMETER Invalid parameter.
231 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
235 AmlCodeGenRdRegister (
236 IN UINT8 AddressSpace
,
241 IN AML_OBJECT_NODE_HANDLE NameOpNode
, OPTIONAL
242 OUT AML_DATA_NODE_HANDLE
*NewRdNode OPTIONAL
246 AML_DATA_NODE
* RdNode
;
247 EFI_ACPI_GENERIC_REGISTER_DESCRIPTOR RdRegister
;
249 if ((AccessSize
> EFI_ACPI_6_4_QWORD
) ||
250 ((NameOpNode
== NULL
) && (NewRdNode
== NULL
))) {
252 return EFI_INVALID_PARAMETER
;
256 RdRegister
.Header
.Header
.Bits
.Name
=
257 ACPI_LARGE_GENERIC_REGISTER_DESCRIPTOR_NAME
;
258 RdRegister
.Header
.Header
.Bits
.Type
= ACPI_LARGE_ITEM_FLAG
;
259 RdRegister
.Header
.Length
= sizeof (EFI_ACPI_GENERIC_REGISTER_DESCRIPTOR
) -
260 sizeof (ACPI_LARGE_RESOURCE_HEADER
);
263 RdRegister
.AddressSpaceId
= AddressSpace
;
264 RdRegister
.RegisterBitWidth
= BitWidth
;
265 RdRegister
.RegisterBitOffset
= BitOffset
;
266 RdRegister
.AddressSize
= AccessSize
;
267 RdRegister
.RegisterAddress
= Address
;
269 Status
= AmlCreateDataNode (
270 EAmlNodeDataTypeResourceData
,
272 sizeof (EFI_ACPI_GENERIC_REGISTER_DESCRIPTOR
),
275 if (EFI_ERROR (Status
)) {
280 return LinkRdNode (RdNode
, NameOpNode
, NewRdNode
);
284 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
288 Add an Interrupt Resource Data node.
290 This function creates a Resource Data element corresponding to the
291 "Interrupt ()" ASL function, stores it in an AML Data Node.
293 It then adds it after the input CurrRdNode in the list of resource data
296 The Resource Data effectively created is an Extended Interrupt Resource
297 Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
298 for more information about Extended Interrupt Resource Data.
300 The Extended Interrupt contains one single interrupt.
302 This function allocates memory to create a data node. It is the caller's
303 responsibility to either:
304 - attach this node to an AML tree;
307 Note: The _CRS node must be defined using the ASL Name () function.
308 e.g. Name (_CRS, ResourceTemplate () {
314 @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object.
315 Must have an OpCode=AML_NAME_OP, SubOpCode=0.
316 NameOp object nodes are defined in ASL
317 using the "Name ()" function.
318 @param [in] ResourceConsumer The device consumes the specified interrupt
319 or produces it for use by a child device.
320 @param [in] EdgeTriggered The interrupt is edge triggered or
322 @param [in] ActiveLow The interrupt is active-high or active-low.
323 @param [in] Shared The interrupt can be shared with other
324 devices or not (Exclusive).
325 @param [in] IrqList Interrupt list. Must be non-NULL.
326 @param [in] IrqCount Interrupt count. Must be non-zero.
329 @retval EFI_SUCCESS The function completed successfully.
330 @retval EFI_INVALID_PARAMETER Invalid parameter.
331 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
335 AmlCodeGenCrsAddRdInterrupt (
336 IN AML_OBJECT_NODE_HANDLE NameOpCrsNode
,
337 IN BOOLEAN ResourceConsumer
,
338 IN BOOLEAN EdgeTriggered
,
339 IN BOOLEAN ActiveLow
,
345 return AmlCodeGenRdInterrupt (
357 #endif // DISABLE_NEW_DEPRECATED_INTERFACES