2 AML Update Resource Data.
4 Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 /* Even though this file has access to the internal Node definition,
10 i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. Only the external node
11 handle types should be used, i.e. AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE,
13 Indeed, the functions in the "Api" folder should be implemented only
14 using the "safe" functions available in the "Include" folder. This
15 makes the functions available in the "Api" folder easy to export.
17 #include <AmlNodeDefines.h>
19 #include <AmlCoreInterface.h>
20 #include <AmlInclude.h>
21 #include <Api/AmlApiHelper.h>
22 #include <CodeGen/AmlResourceDataCodeGen.h>
24 /** Update the first interrupt of an Interrupt resource data node.
26 The flags of the Interrupt resource data are left unchanged.
28 The InterruptRdNode corresponds to the Resource Data created by the
29 "Interrupt ()" ASL macro. It is an Extended Interrupt Resource Data.
30 See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
31 for more information about Extended Interrupt Resource Data.
33 @param [in] InterruptRdNode Pointer to the an extended interrupt
35 @param [in] Irq Interrupt value to update.
37 @retval EFI_SUCCESS The function completed successfully.
38 @retval EFI_INVALID_PARAMETER Invalid parameter.
39 @retval EFI_OUT_OF_RESOURCES Out of resources.
43 AmlUpdateRdInterrupt (
44 IN AML_DATA_NODE_HANDLE InterruptRdNode
,
49 UINT32
* FirstInterrupt
;
51 UINT32 QueryBufferSize
;
53 if ((InterruptRdNode
== NULL
) ||
54 (AmlGetNodeType ((AML_NODE_HANDLE
)InterruptRdNode
) != EAmlNodeData
) ||
55 (!AmlNodeHasDataType (
57 EAmlNodeDataTypeResourceData
)) ||
58 (!AmlNodeHasRdDataType (
60 AML_RD_BUILD_LARGE_DESC_ID (
61 ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME
)))) {
63 return EFI_INVALID_PARAMETER
;
68 // Get the size of the InterruptRdNode buffer.
69 Status
= AmlGetDataNodeBuffer (
74 if (EFI_ERROR (Status
)) {
79 // Check the Buffer is large enough.
80 if (QueryBufferSize
< sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR
)) {
82 return EFI_INVALID_PARAMETER
;
85 // Allocate a buffer to fetch the data.
86 QueryBuffer
= AllocatePool (QueryBufferSize
);
87 if (QueryBuffer
== NULL
) {
89 return EFI_OUT_OF_RESOURCES
;
93 Status
= AmlGetDataNodeBuffer (
98 if (EFI_ERROR (Status
)) {
103 // Get the address of the first interrupt field.
105 ((EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR
*)QueryBuffer
)->InterruptNumber
;
107 *FirstInterrupt
= Irq
;
109 // Update the InterruptRdNode buffer.
110 Status
= AmlUpdateDataNode (
112 EAmlNodeDataTypeResourceData
,
116 if (EFI_ERROR (Status
)) {
121 if (QueryBuffer
!= NULL
) {
122 FreePool (QueryBuffer
);
127 /** Update the interrupt list of an interrupt resource data node.
129 The InterruptRdNode corresponds to the Resource Data created by the
130 "Interrupt ()" ASL function. It is an Extended Interrupt Resource Data.
131 See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
132 for more information about Extended Interrupt Resource Data.
134 @param [in] InterruptRdNode Pointer to the an extended interrupt
136 @param [in] ResourceConsumer The device consumes the specified interrupt
137 or produces it for use by a child device.
138 @param [in] EdgeTriggered The interrupt is edge triggered or
140 @param [in] ActiveLow The interrupt is active-high or active-low.
141 @param [in] Shared The interrupt can be shared with other
142 devices or not (Exclusive).
143 @param [in] IrqList Interrupt list. Must be non-NULL.
144 @param [in] IrqCount Interrupt count. Must be non-zero.
147 @retval EFI_SUCCESS The function completed successfully.
148 @retval EFI_INVALID_PARAMETER Invalid parameter.
149 @retval EFI_OUT_OF_RESOURCES Out of resources.
153 AmlUpdateRdInterruptEx (
154 IN AML_DATA_NODE_HANDLE InterruptRdNode
,
155 IN BOOLEAN ResourceConsumer
,
156 IN BOOLEAN EdgeTriggered
,
157 IN BOOLEAN ActiveLow
,
165 EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR
* RdInterrupt
;
166 UINT32
* FirstInterrupt
;
167 UINT8
* UpdateBuffer
;
168 UINT16 UpdateBufferSize
;
170 if ((InterruptRdNode
== NULL
) ||
171 (AmlGetNodeType ((AML_NODE_HANDLE
)InterruptRdNode
) != EAmlNodeData
) ||
172 (!AmlNodeHasDataType (
174 EAmlNodeDataTypeResourceData
)) ||
175 (!AmlNodeHasRdDataType (
177 AML_RD_BUILD_LARGE_DESC_ID (
178 ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME
))) ||
182 return EFI_INVALID_PARAMETER
;
186 UpdateBufferSize
= sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR
) +
187 ((IrqCount
- 1) * sizeof (UINT32
));
189 // Allocate a buffer to update the data.
190 UpdateBuffer
= AllocatePool (UpdateBufferSize
);
191 if (UpdateBuffer
== NULL
) {
193 return EFI_OUT_OF_RESOURCES
;
196 // Update the Resource Data information (structure size, interrupt count).
197 RdInterrupt
= (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR
*)UpdateBuffer
;
198 RdInterrupt
->Header
.Header
.Byte
=
199 AML_RD_BUILD_LARGE_DESC_ID (ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME
);
200 RdInterrupt
->Header
.Length
=
201 UpdateBufferSize
- sizeof (ACPI_LARGE_RESOURCE_HEADER
);
202 RdInterrupt
->InterruptTableLength
= IrqCount
;
203 RdInterrupt
->InterruptVectorFlags
= (ResourceConsumer
? BIT0
: 0) |
204 (EdgeTriggered
? BIT1
: 0) |
205 (ActiveLow
? BIT2
: 0) |
208 // Get the address of the first interrupt field.
210 ((EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR
*)UpdateBuffer
)->InterruptNumber
;
212 // Copy the input list of interrupts.
213 CopyMem (FirstInterrupt
, IrqList
, (sizeof (UINT32
) * IrqCount
));
215 // Update the InterruptRdNode buffer.
216 Status
= AmlUpdateDataNode (
218 EAmlNodeDataTypeResourceData
,
222 if (EFI_ERROR (Status
)) {
227 FreePool (UpdateBuffer
);
232 /** Update the base address and length of a QWord resource data node.
234 @param [in] QWordRdNode Pointer a QWord resource data
236 @param [in] BaseAddress Base address.
237 @param [in] BaseAddressLength Base address length.
239 @retval EFI_SUCCESS The function completed successfully.
240 @retval EFI_INVALID_PARAMETER Invalid parameter.
241 @retval EFI_OUT_OF_RESOURCES Out of resources.
246 IN AML_DATA_NODE_HANDLE QWordRdNode
,
247 IN UINT64 BaseAddress
,
248 IN UINT64 BaseAddressLength
252 EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR
* RdQWord
;
255 UINT32 QueryBufferSize
;
257 if ((QWordRdNode
== NULL
) ||
258 (AmlGetNodeType ((AML_NODE_HANDLE
)QWordRdNode
) != EAmlNodeData
) ||
259 (!AmlNodeHasDataType (QWordRdNode
, EAmlNodeDataTypeResourceData
)) ||
260 (!AmlNodeHasRdDataType (
262 AML_RD_BUILD_LARGE_DESC_ID (
263 ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME
)))) {
265 return EFI_INVALID_PARAMETER
;
268 // Get the size of the QWordRdNode's buffer.
269 Status
= AmlGetDataNodeBuffer (
274 if (EFI_ERROR (Status
)) {
279 // Allocate a buffer to fetch the data.
280 QueryBuffer
= AllocatePool (QueryBufferSize
);
281 if (QueryBuffer
== NULL
) {
283 return EFI_OUT_OF_RESOURCES
;
287 Status
= AmlGetDataNodeBuffer (
292 if (EFI_ERROR (Status
)) {
297 RdQWord
= (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR
*)QueryBuffer
;
299 // Update the Base Address and Length.
300 RdQWord
->AddrRangeMin
= BaseAddress
;
301 RdQWord
->AddrRangeMax
= BaseAddress
+ BaseAddressLength
- 1;
302 RdQWord
->AddrLen
= BaseAddressLength
;
304 // Update Base Address Resource Data node.
305 Status
= AmlUpdateDataNode (
307 EAmlNodeDataTypeResourceData
,
311 if (EFI_ERROR (Status
)) {
316 if (QueryBuffer
!= NULL
) {
317 FreePool (QueryBuffer
);