2 /******************************************************************************
4 * Module Name: amstore - AML Interpreter object store support
7 *****************************************************************************/
10 * Copyright (C) 2000 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 #define _COMPONENT INTERPRETER
38 MODULE_NAME ("amstore")
41 /*******************************************************************************
43 * FUNCTION: Acpi_aml_exec_store
45 * PARAMETERS: *Val_desc - Value to be stored
46 * *Dest_desc - Where to store it 0 Must be (ACPI_HANDLE)
47 * or an ACPI_OPERAND_OBJECT of type
48 * Reference; if the latter the descriptor
49 * will be either reused or deleted.
53 * DESCRIPTION: Store the value described by Val_desc into the location
54 * described by Dest_desc. Called by various interpreter
55 * functions to store the result of an operation into
56 * the destination operand.
58 ******************************************************************************/
62 ACPI_OPERAND_OBJECT
*val_desc
,
63 ACPI_OPERAND_OBJECT
*dest_desc
,
64 ACPI_WALK_STATE
*walk_state
)
66 ACPI_STATUS status
= AE_OK
;
67 ACPI_OPERAND_OBJECT
*delete_dest_desc
= NULL
;
68 ACPI_OPERAND_OBJECT
*tmp_desc
;
69 ACPI_NAMESPACE_NODE
*node
= NULL
;
75 /* Validate parameters */
77 if (!val_desc
|| !dest_desc
) {
78 return (AE_AML_NO_OPERAND
);
81 /* Examine the datatype of the Dest_desc */
83 if (VALID_DESCRIPTOR_TYPE (dest_desc
, ACPI_DESC_TYPE_NAMED
)) {
84 /* Dest is an ACPI_HANDLE, create a new object */
86 node
= (ACPI_NAMESPACE_NODE
*) dest_desc
;
87 dest_desc
= acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE
);
89 /* Allocation failure */
91 return (AE_NO_MEMORY
);
94 /* Build a new Reference wrapper around the handle */
96 dest_desc
->reference
.op_code
= AML_NAME_OP
;
97 dest_desc
->reference
.object
= node
;
101 /* Destination object must be of type Reference */
103 if (dest_desc
->common
.type
!= INTERNAL_TYPE_REFERENCE
) {
104 /* Destination is not an Reference */
106 return (AE_AML_OPERAND_TYPE
);
109 /* Examine the Reference opcode */
111 switch (dest_desc
->reference
.op_code
)
117 * Storing into a Name
119 delete_dest_desc
= dest_desc
;
120 status
= acpi_aml_store_object_to_node (val_desc
, dest_desc
->reference
.object
,
123 break; /* Case Name_op */
128 delete_dest_desc
= dest_desc
;
131 * Valid source value and destination reference pointer.
133 * ACPI Specification 1.0B section 15.2.3.4.2.13:
134 * Destination should point to either a buffer or a package
138 * Actually, storing to a package is not so simple. The source must be
139 * evaluated and converted to the type of the destination and then the
140 * source is copied into the destination - we can't just point to the
143 if (dest_desc
->reference
.target_type
== ACPI_TYPE_PACKAGE
) {
145 * The object at *(Dest_desc->Reference.Where) is the
146 * element within the package that is to be modified.
148 tmp_desc
= *(dest_desc
->reference
.where
);
151 * If the Destination element is a package, we will delete
152 * that object and construct a new one.
154 * TBD: [Investigate] Should both the src and dest be required
156 * && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE)
158 if (tmp_desc
->common
.type
== ACPI_TYPE_PACKAGE
) {
160 * Take away the reference for being part of a package and
163 acpi_cm_remove_reference (tmp_desc
);
164 acpi_cm_remove_reference (tmp_desc
);
172 * If the Tmp_desc is NULL, that means an uninitialized package
173 * has been used as a destination, therefore, we must create
174 * the destination element to match the type of the source
175 * element NOTE: Val_desc can be of any type.
177 tmp_desc
= acpi_cm_create_internal_object (val_desc
->common
.type
);
179 status
= AE_NO_MEMORY
;
184 * If the source is a package, copy the source to the new dest
186 if (ACPI_TYPE_PACKAGE
== tmp_desc
->common
.type
) {
187 status
= acpi_aml_build_copy_internal_package_object (
188 val_desc
, tmp_desc
, walk_state
);
189 if (ACPI_FAILURE (status
)) {
190 acpi_cm_remove_reference (tmp_desc
);
197 * Install the new descriptor into the package and add a
198 * reference to the newly created descriptor for now being
199 * part of the parent package
202 *(dest_desc
->reference
.where
) = tmp_desc
;
203 acpi_cm_add_reference (tmp_desc
);
206 if (ACPI_TYPE_PACKAGE
!= tmp_desc
->common
.type
) {
208 * The destination element is not a package, so we need to
209 * convert the contents of the source (Val_desc) and copy into
210 * the destination (Tmp_desc)
212 status
= acpi_aml_store_object_to_object (val_desc
, tmp_desc
,
214 if (ACPI_FAILURE (status
)) {
216 * An error occurrered when copying the internal object
217 * so delete the reference.
219 status
= AE_AML_OPERAND_TYPE
;
227 * Check that the destination is a Buffer Field type
229 if (dest_desc
->reference
.target_type
!= ACPI_TYPE_BUFFER_FIELD
) {
230 status
= AE_AML_OPERAND_TYPE
;
235 * Storing into a buffer at a location defined by an Index.
237 * Each 8-bit element of the source object is written to the
238 * 8-bit Buffer Field of the Index destination object.
242 * Set the Tmp_desc to the destination object and type check.
244 tmp_desc
= dest_desc
->reference
.object
;
246 if (tmp_desc
->common
.type
!= ACPI_TYPE_BUFFER
) {
247 status
= AE_AML_OPERAND_TYPE
;
252 * The assignment of the individual elements will be slightly
253 * different for each source type.
256 switch (val_desc
->common
.type
)
259 * If the type is Integer, the Length is 4.
260 * This loop to assign each of the elements is somewhat
261 * backward because of the Big Endian-ness of IA-64
263 case ACPI_TYPE_NUMBER
:
265 for (i
= length
; i
!= 0; i
--) {
266 value
= (u8
)(val_desc
->number
.value
>> (MUL_8 (i
- 1)));
267 tmp_desc
->buffer
.pointer
[dest_desc
->reference
.offset
] = value
;
272 * If the type is Buffer, the Length is in the structure.
273 * Just loop through the elements and assign each one in turn.
275 case ACPI_TYPE_BUFFER
:
276 length
= val_desc
->buffer
.length
;
277 for (i
= 0; i
< length
; i
++) {
278 value
= *(val_desc
->buffer
.pointer
+ i
);
279 tmp_desc
->buffer
.pointer
[dest_desc
->reference
.offset
] = value
;
284 * If the type is String, the Length is in the structure.
285 * Just loop through the elements and assign each one in turn.
287 case ACPI_TYPE_STRING
:
288 length
= val_desc
->string
.length
;
289 for (i
= 0; i
< length
; i
++) {
290 value
= *(val_desc
->string
.pointer
+ i
);
291 tmp_desc
->buffer
.pointer
[dest_desc
->reference
.offset
] = value
;
296 * If source is not a valid type so return an error.
299 status
= AE_AML_OPERAND_TYPE
;
304 * If we had an error, break out of this case statement.
306 if (ACPI_FAILURE (status
)) {
311 * Set the return pointer
313 dest_desc
= tmp_desc
;
322 * Storing to a constant is a no-op -- see ACPI Specification
323 * Delete the result descriptor.
326 delete_dest_desc
= dest_desc
;
332 status
= acpi_ds_method_data_set_value (MTH_TYPE_LOCAL
,
333 (dest_desc
->reference
.offset
), val_desc
, walk_state
);
334 delete_dest_desc
= dest_desc
;
340 status
= acpi_ds_method_data_set_value (MTH_TYPE_ARG
,
341 (dest_desc
->reference
.offset
), val_desc
, walk_state
);
342 delete_dest_desc
= dest_desc
;
349 * Storing to the Debug object causes the value stored to be
350 * displayed and otherwise has no effect -- see ACPI Specification
353 delete_dest_desc
= dest_desc
;
359 /* TBD: [Restructure] use object dump routine !! */
361 delete_dest_desc
= dest_desc
;
362 status
= AE_AML_INTERNAL
;
364 } /* switch(Dest_desc->Reference.Op_code) */
369 /* Cleanup and exit*/
371 if (delete_dest_desc
) {
372 acpi_cm_remove_reference (delete_dest_desc
);