1 
2 /******************************************************************************
3  *
4  * Module Name: exstore - AML Interpreter object store support
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2004, R. Byron Moore
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 
46 #include <acpi/acpi.h>
47 #include <acpi/acdispat.h>
48 #include <acpi/acinterp.h>
49 #include <acpi/amlcode.h>
50 #include <acpi/acnamesp.h>
51 
52 
53 #define _COMPONENT          ACPI_EXECUTER
54 	 ACPI_MODULE_NAME    ("exstore")
55 
56 
57 /*******************************************************************************
58  *
59  * FUNCTION:    acpi_ex_store
60  *
61  * PARAMETERS:  *source_desc        - Value to be stored
62  *              *dest_desc          - Where to store it.  Must be an NS node
63  *                                    or an union acpi_operand_object of type
64  *                                    Reference;
65  *              walk_state          - Current walk state
66  *
67  * RETURN:      Status
68  *
69  * DESCRIPTION: Store the value described by source_desc into the location
70  *              described by dest_desc. Called by various interpreter
71  *              functions to store the result of an operation into
72  *              the destination operand -- not just simply the actual "Store"
73  *              ASL operator.
74  *
75  ******************************************************************************/
76 
77 acpi_status
acpi_ex_store(union acpi_operand_object * source_desc,union acpi_operand_object * dest_desc,struct acpi_walk_state * walk_state)78 acpi_ex_store (
79 	union acpi_operand_object       *source_desc,
80 	union acpi_operand_object       *dest_desc,
81 	struct acpi_walk_state          *walk_state)
82 {
83 	acpi_status                     status = AE_OK;
84 	union acpi_operand_object       *ref_desc = dest_desc;
85 
86 
87 	ACPI_FUNCTION_TRACE_PTR ("ex_store", dest_desc);
88 
89 
90 	/* Validate parameters */
91 
92 	if (!source_desc || !dest_desc) {
93 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null parameter\n"));
94 		return_ACPI_STATUS (AE_AML_NO_OPERAND);
95 	}
96 
97 	/* dest_desc can be either a namespace node or an ACPI object */
98 
99 	if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) {
100 		/*
101 		 * Dest is a namespace node,
102 		 * Storing an object into a Named node.
103 		 */
104 		status = acpi_ex_store_object_to_node (source_desc,
105 				 (struct acpi_namespace_node *) dest_desc, walk_state);
106 
107 		return_ACPI_STATUS (status);
108 	}
109 
110 	/* Destination object must be a Reference or a Constant object */
111 
112 	switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
113 	case ACPI_TYPE_LOCAL_REFERENCE:
114 		break;
115 
116 	case ACPI_TYPE_INTEGER:
117 
118 		/* Allow stores to Constants -- a Noop as per ACPI spec */
119 
120 		if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
121 			return_ACPI_STATUS (AE_OK);
122 		}
123 
124 		/*lint -fallthrough */
125 
126 	default:
127 
128 		/* Destination is not a Reference object */
129 
130 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
131 			"Destination is not a Reference or Constant object [%p]\n", dest_desc));
132 
133 		ACPI_DUMP_STACK_ENTRY (source_desc);
134 		ACPI_DUMP_STACK_ENTRY (dest_desc);
135 		ACPI_DUMP_OPERANDS (&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
136 				  2, "Target is not a Reference or Constant object");
137 
138 		return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
139 	}
140 
141 	/*
142 	 * Examine the Reference opcode.  These cases are handled:
143 	 *
144 	 * 1) Store to Name (Change the object associated with a name)
145 	 * 2) Store to an indexed area of a Buffer or Package
146 	 * 3) Store to a Method Local or Arg
147 	 * 4) Store to the debug object
148 	 */
149 	switch (ref_desc->reference.opcode) {
150 	case AML_NAME_OP:
151 	case AML_REF_OF_OP:
152 
153 		/* Storing an object into a Name "container" */
154 
155 		status = acpi_ex_store_object_to_node (source_desc, ref_desc->reference.object,
156 				  walk_state);
157 		break;
158 
159 
160 	case AML_INDEX_OP:
161 
162 		/* Storing to an Index (pointer into a packager or buffer) */
163 
164 		status = acpi_ex_store_object_to_index (source_desc, ref_desc, walk_state);
165 		break;
166 
167 
168 	case AML_LOCAL_OP:
169 	case AML_ARG_OP:
170 
171 		/* Store to a method local/arg  */
172 
173 		status = acpi_ds_store_object_to_local (ref_desc->reference.opcode,
174 				  ref_desc->reference.offset, source_desc, walk_state);
175 		break;
176 
177 
178 	case AML_DEBUG_OP:
179 
180 		/*
181 		 * Storing to the Debug object causes the value stored to be
182 		 * displayed and otherwise has no effect -- see ACPI Specification
183 		 */
184 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Write to Debug Object: ****:\n\n"));
185 
186 		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %s: ",
187 				  acpi_ut_get_object_type_name (source_desc)));
188 
189 		switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
190 		case ACPI_TYPE_INTEGER:
191 
192 			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n",
193 					ACPI_FORMAT_UINT64 (source_desc->integer.value)));
194 			break;
195 
196 
197 		case ACPI_TYPE_BUFFER:
198 
199 			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X",
200 					(u32) source_desc->buffer.length));
201 			ACPI_DUMP_BUFFER (source_desc->buffer.pointer,
202 				(source_desc->buffer.length < 32) ? source_desc->buffer.length : 32);
203 			break;
204 
205 
206 		case ACPI_TYPE_STRING:
207 
208 			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X, \"%s\"\n",
209 					source_desc->string.length, source_desc->string.pointer));
210 			break;
211 
212 
213 		case ACPI_TYPE_PACKAGE:
214 
215 			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Size 0x%.2X Elements Ptr - %p\n",
216 					source_desc->package.count, source_desc->package.elements));
217 			break;
218 
219 
220 		default:
221 
222 			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n",
223 					source_desc));
224 			break;
225 		}
226 
227 		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n"));
228 		break;
229 
230 
231 	default:
232 
233 		ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n",
234 			ref_desc->reference.opcode));
235 		ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR);
236 
237 		status = AE_AML_INTERNAL;
238 		break;
239 	}
240 
241 	return_ACPI_STATUS (status);
242 }
243 
244 
245 /*******************************************************************************
246  *
247  * FUNCTION:    acpi_ex_store_object_to_index
248  *
249  * PARAMETERS:  *source_desc            - Value to be stored
250  *              *dest_desc              - Named object to receive the value
251  *              walk_state              - Current walk state
252  *
253  * RETURN:      Status
254  *
255  * DESCRIPTION: Store the object to indexed Buffer or Package element
256  *
257  ******************************************************************************/
258 
259 acpi_status
acpi_ex_store_object_to_index(union acpi_operand_object * source_desc,union acpi_operand_object * index_desc,struct acpi_walk_state * walk_state)260 acpi_ex_store_object_to_index (
261 	union acpi_operand_object       *source_desc,
262 	union acpi_operand_object       *index_desc,
263 	struct acpi_walk_state          *walk_state)
264 {
265 	acpi_status                     status = AE_OK;
266 	union acpi_operand_object       *obj_desc;
267 	union acpi_operand_object       *new_desc;
268 	u8                              value = 0;
269 	u32                             i;
270 
271 
272 	ACPI_FUNCTION_TRACE ("ex_store_object_to_index");
273 
274 
275 	/*
276 	 * Destination must be a reference pointer, and
277 	 * must point to either a buffer or a package
278 	 */
279 	switch (index_desc->reference.target_type) {
280 	case ACPI_TYPE_PACKAGE:
281 		/*
282 		 * Storing to a package element is not simple.  The source must be
283 		 * evaluated and converted to the type of the destination and then the
284 		 * source is copied into the destination - we can't just point to the
285 		 * source object.
286 		 */
287 		/*
288 		 * The object at *(index_desc->Reference.Where) is the
289 		 * element within the package that is to be modified.
290 		 * The parent package object is at index_desc->Reference.Object
291 		 */
292 		obj_desc = *(index_desc->reference.where);
293 
294 		/* Do the conversion/store */
295 
296 		status = acpi_ex_store_object_to_object (source_desc, obj_desc, &new_desc,
297 				  walk_state);
298 		if (ACPI_FAILURE (status)) {
299 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
300 				"Could not store object to indexed package element\n"));
301 			return_ACPI_STATUS (status);
302 		}
303 
304 		/*
305 		 * If a new object was created, we must install it as the new
306 		 * package element
307 		 */
308 		if (new_desc != obj_desc) {
309 			acpi_ut_remove_reference (obj_desc);
310 			*(index_desc->reference.where) = new_desc;
311 
312 			/* If same as the original source, add a reference */
313 
314 			if (new_desc == source_desc) {
315 				acpi_ut_add_reference (new_desc);
316 			}
317 
318 			/* Increment reference count by the ref count of the parent package -1 */
319 
320 			for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
321 				acpi_ut_add_reference (new_desc);
322 			}
323 		}
324 		break;
325 
326 
327 	case ACPI_TYPE_BUFFER_FIELD:
328 
329 		/*
330 		 * Store into a Buffer (not actually a real buffer_field) at a
331 		 * location defined by an Index.
332 		 *
333 		 * The first 8-bit element of the source object is written to the
334 		 * 8-bit Buffer location defined by the Index destination object,
335 		 * according to the ACPI 2.0 specification.
336 		 */
337 
338 		/*
339 		 * Make sure the target is a Buffer
340 		 */
341 		obj_desc = index_desc->reference.object;
342 		if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_BUFFER) {
343 			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
344 		}
345 
346 		/*
347 		 * The assignment of the individual elements will be slightly
348 		 * different for each source type.
349 		 */
350 		switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
351 		case ACPI_TYPE_INTEGER:
352 
353 			/* Use the least-significant byte of the integer */
354 
355 			value = (u8) (source_desc->integer.value);
356 			break;
357 
358 		case ACPI_TYPE_BUFFER:
359 
360 			value = source_desc->buffer.pointer[0];
361 			break;
362 
363 		case ACPI_TYPE_STRING:
364 
365 			value = (u8) source_desc->string.pointer[0];
366 			break;
367 
368 		default:
369 
370 			/* All other types are invalid */
371 
372 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
373 				"Source must be Integer/Buffer/String type, not %s\n",
374 				acpi_ut_get_object_type_name (source_desc)));
375 			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
376 		}
377 
378 		/* Store the source value into the target buffer byte */
379 
380 		obj_desc->buffer.pointer[index_desc->reference.offset] = value;
381 		break;
382 
383 
384 	default:
385 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
386 			"Target is not a Package or buffer_field\n"));
387 		status = AE_AML_OPERAND_TYPE;
388 		break;
389 	}
390 
391 	return_ACPI_STATUS (status);
392 }
393 
394 
395 /*******************************************************************************
396  *
397  * FUNCTION:    acpi_ex_store_object_to_node
398  *
399  * PARAMETERS:  source_desc             - Value to be stored
400  *              Node                    - Named object to receive the value
401  *              walk_state              - Current walk state
402  *
403  * RETURN:      Status
404  *
405  * DESCRIPTION: Store the object to the named object.
406  *
407  *              The Assignment of an object to a named object is handled here
408  *              The value passed in will replace the current value (if any)
409  *              with the input value.
410  *
411  *              When storing into an object the data is converted to the
412  *              target object type then stored in the object.  This means
413  *              that the target object type (for an initialized target) will
414  *              not be changed by a store operation.
415  *
416  *              Assumes parameters are already validated.
417  *
418  ******************************************************************************/
419 
420 acpi_status
acpi_ex_store_object_to_node(union acpi_operand_object * source_desc,struct acpi_namespace_node * node,struct acpi_walk_state * walk_state)421 acpi_ex_store_object_to_node (
422 	union acpi_operand_object       *source_desc,
423 	struct acpi_namespace_node      *node,
424 	struct acpi_walk_state          *walk_state)
425 {
426 	acpi_status                     status = AE_OK;
427 	union acpi_operand_object       *target_desc;
428 	union acpi_operand_object       *new_desc;
429 	acpi_object_type                target_type;
430 
431 
432 	ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_node", source_desc);
433 
434 
435 	/*
436 	 * Get current type of the node, and object attached to Node
437 	 */
438 	target_type = acpi_ns_get_type (node);
439 	target_desc = acpi_ns_get_attached_object (node);
440 
441 	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
442 		source_desc, acpi_ut_get_object_type_name (source_desc),
443 			  node, acpi_ut_get_type_name (target_type)));
444 
445 	/*
446 	 * Resolve the source object to an actual value
447 	 * (If it is a reference object)
448 	 */
449 	status = acpi_ex_resolve_object (&source_desc, target_type, walk_state);
450 	if (ACPI_FAILURE (status)) {
451 		return_ACPI_STATUS (status);
452 	}
453 
454 	/*
455 	 * Do the actual store operation
456 	 */
457 	switch (target_type) {
458 	case ACPI_TYPE_BUFFER_FIELD:
459 	case ACPI_TYPE_LOCAL_REGION_FIELD:
460 	case ACPI_TYPE_LOCAL_BANK_FIELD:
461 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
462 
463 		/*
464 		 * For fields, copy the source data to the target field.
465 		 */
466 		status = acpi_ex_write_data_to_field (source_desc, target_desc, &walk_state->result_obj);
467 		break;
468 
469 
470 	case ACPI_TYPE_INTEGER:
471 	case ACPI_TYPE_STRING:
472 	case ACPI_TYPE_BUFFER:
473 
474 		/*
475 		 * These target types are all of type Integer/String/Buffer, and
476 		 * therefore support implicit conversion before the store.
477 		 *
478 		 * Copy and/or convert the source object to a new target object
479 		 */
480 		status = acpi_ex_store_object_to_object (source_desc, target_desc, &new_desc, walk_state);
481 		if (ACPI_FAILURE (status)) {
482 			return_ACPI_STATUS (status);
483 		}
484 
485 		if (new_desc != target_desc) {
486 			/*
487 			 * Store the new new_desc as the new value of the Name, and set
488 			 * the Name's type to that of the value being stored in it.
489 			 * source_desc reference count is incremented by attach_object.
490 			 *
491 			 * Note: This may change the type of the node if an explicit store
492 			 * has been performed such that the node/object type has been
493 			 * changed.
494 			 */
495 			status = acpi_ns_attach_object (node, new_desc, new_desc->common.type);
496 
497 			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
498 				"Store %s into %s via Convert/Attach\n",
499 				acpi_ut_get_object_type_name (source_desc),
500 				acpi_ut_get_object_type_name (new_desc)));
501 		}
502 		break;
503 
504 
505 	default:
506 
507 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
508 			"Storing %s (%p) directly into node (%p), no implicit conversion\n",
509 			acpi_ut_get_object_type_name (source_desc), source_desc, node));
510 
511 		/* No conversions for all other types.  Just attach the source object */
512 
513 		status = acpi_ns_attach_object (node, source_desc, ACPI_GET_OBJECT_TYPE (source_desc));
514 		break;
515 	}
516 
517 	return_ACPI_STATUS (status);
518 }
519 
520 
521