1 /******************************************************************************
2  *
3  * Module Name: dsobject - Dispatcher object management routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2004, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 
45 #include <acpi/acpi.h>
46 #include <acpi/acparser.h>
47 #include <acpi/amlcode.h>
48 #include <acpi/acdispat.h>
49 #include <acpi/acnamesp.h>
50 #include <acpi/acinterp.h>
51 
52 #define _COMPONENT          ACPI_DISPATCHER
53 	 ACPI_MODULE_NAME    ("dsobject")
54 
55 
56 #ifndef ACPI_NO_METHOD_EXECUTION
57 /*****************************************************************************
58  *
59  * FUNCTION:    acpi_ds_build_internal_object
60  *
61  * PARAMETERS:  walk_state      - Current walk state
62  *              Op              - Parser object to be translated
63  *              obj_desc_ptr    - Where the ACPI internal object is returned
64  *
65  * RETURN:      Status
66  *
67  * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
68  *              Simple objects are any objects other than a package object!
69  *
70  ****************************************************************************/
71 
72 acpi_status
acpi_ds_build_internal_object(struct acpi_walk_state * walk_state,union acpi_parse_object * op,union acpi_operand_object ** obj_desc_ptr)73 acpi_ds_build_internal_object (
74 	struct acpi_walk_state          *walk_state,
75 	union acpi_parse_object         *op,
76 	union acpi_operand_object       **obj_desc_ptr)
77 {
78 	union acpi_operand_object       *obj_desc;
79 	acpi_status                     status;
80 
81 
82 	ACPI_FUNCTION_TRACE ("ds_build_internal_object");
83 
84 
85 	*obj_desc_ptr = NULL;
86 	if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
87 		/*
88 		 * This is an named object reference.  If this name was
89 		 * previously looked up in the namespace, it was stored in this op.
90 		 * Otherwise, go ahead and look it up now
91 		 */
92 		if (!op->common.node) {
93 			status = acpi_ns_lookup (walk_state->scope_info, op->common.value.string,
94 					  ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
95 					  ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
96 					  (struct acpi_namespace_node **) &(op->common.node));
97 
98 			if (ACPI_FAILURE (status)) {
99 				ACPI_REPORT_NSERROR (op->common.value.string, status);
100 				return_ACPI_STATUS (status);
101 			}
102 		}
103 	}
104 
105 	/* Create and init the internal ACPI object */
106 
107 	obj_desc = acpi_ut_create_internal_object ((acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type);
108 	if (!obj_desc) {
109 		return_ACPI_STATUS (AE_NO_MEMORY);
110 	}
111 
112 	status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode, &obj_desc);
113 	if (ACPI_FAILURE (status)) {
114 		acpi_ut_remove_reference (obj_desc);
115 		return_ACPI_STATUS (status);
116 	}
117 
118 	*obj_desc_ptr = obj_desc;
119 	return_ACPI_STATUS (AE_OK);
120 }
121 
122 
123 /*****************************************************************************
124  *
125  * FUNCTION:    acpi_ds_build_internal_buffer_obj
126  *
127  * PARAMETERS:  walk_state      - Current walk state
128  *              Op              - Parser object to be translated
129  *              buffer_length   - Length of the buffer
130  *              obj_desc_ptr    - Where the ACPI internal object is returned
131  *
132  * RETURN:      Status
133  *
134  * DESCRIPTION: Translate a parser Op package object to the equivalent
135  *              namespace object
136  *
137  ****************************************************************************/
138 
139 acpi_status
acpi_ds_build_internal_buffer_obj(struct acpi_walk_state * walk_state,union acpi_parse_object * op,u32 buffer_length,union acpi_operand_object ** obj_desc_ptr)140 acpi_ds_build_internal_buffer_obj (
141 	struct acpi_walk_state          *walk_state,
142 	union acpi_parse_object         *op,
143 	u32                             buffer_length,
144 	union acpi_operand_object       **obj_desc_ptr)
145 {
146 	union acpi_parse_object         *arg;
147 	union acpi_operand_object       *obj_desc;
148 	union acpi_parse_object         *byte_list;
149 	u32                             byte_list_length = 0;
150 
151 
152 	ACPI_FUNCTION_TRACE ("ds_build_internal_buffer_obj");
153 
154 
155 	obj_desc = *obj_desc_ptr;
156 	if (obj_desc) {
157 		/*
158 		 * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
159 		 * The buffer object already exists (from the NS node)
160 		 */
161 	}
162 	else {
163 		/* Create a new buffer object */
164 
165 		obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
166 		*obj_desc_ptr = obj_desc;
167 		if (!obj_desc) {
168 			return_ACPI_STATUS (AE_NO_MEMORY);
169 		}
170 	}
171 
172 	/*
173 	 * Second arg is the buffer data (optional) byte_list can be either
174 	 * individual bytes or a string initializer.  In either case, a
175 	 * byte_list appears in the AML.
176 	 */
177 	arg = op->common.value.arg;         /* skip first arg */
178 
179 	byte_list = arg->named.next;
180 	if (byte_list) {
181 		if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
182 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
183 				"Expecting bytelist, got AML opcode %X in op %p\n",
184 				byte_list->common.aml_opcode, byte_list));
185 
186 			acpi_ut_remove_reference (obj_desc);
187 			return (AE_TYPE);
188 		}
189 
190 		byte_list_length = (u32) byte_list->common.value.integer;
191 	}
192 
193 	/*
194 	 * The buffer length (number of bytes) will be the larger of:
195 	 * 1) The specified buffer length and
196 	 * 2) The length of the initializer byte list
197 	 */
198 	obj_desc->buffer.length = buffer_length;
199 	if (byte_list_length > buffer_length) {
200 		obj_desc->buffer.length = byte_list_length;
201 	}
202 
203 	/* Allocate the buffer */
204 
205 	if (obj_desc->buffer.length == 0) {
206 		obj_desc->buffer.pointer = NULL;
207 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
208 			"Buffer defined with zero length in AML, creating\n"));
209 	}
210 	else {
211 		obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
212 				   obj_desc->buffer.length);
213 		if (!obj_desc->buffer.pointer) {
214 			acpi_ut_delete_object_desc (obj_desc);
215 			return_ACPI_STATUS (AE_NO_MEMORY);
216 		}
217 
218 		/* Initialize buffer from the byte_list (if present) */
219 
220 		if (byte_list) {
221 			ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data,
222 					  byte_list_length);
223 		}
224 	}
225 
226 	obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
227 	op->common.node = (struct acpi_namespace_node *) obj_desc;
228 	return_ACPI_STATUS (AE_OK);
229 }
230 
231 
232 /*****************************************************************************
233  *
234  * FUNCTION:    acpi_ds_build_internal_package_obj
235  *
236  * PARAMETERS:  walk_state      - Current walk state
237  *              Op              - Parser object to be translated
238  *              package_length  - Number of elements in the package
239  *              obj_desc_ptr    - Where the ACPI internal object is returned
240  *
241  * RETURN:      Status
242  *
243  * DESCRIPTION: Translate a parser Op package object to the equivalent
244  *              namespace object
245  *
246  ****************************************************************************/
247 
248 acpi_status
acpi_ds_build_internal_package_obj(struct acpi_walk_state * walk_state,union acpi_parse_object * op,u32 package_length,union acpi_operand_object ** obj_desc_ptr)249 acpi_ds_build_internal_package_obj (
250 	struct acpi_walk_state          *walk_state,
251 	union acpi_parse_object         *op,
252 	u32                             package_length,
253 	union acpi_operand_object       **obj_desc_ptr)
254 {
255 	union acpi_parse_object         *arg;
256 	union acpi_parse_object         *parent;
257 	union acpi_operand_object       *obj_desc = NULL;
258 	u32                             package_list_length;
259 	acpi_status                     status = AE_OK;
260 	u32                             i;
261 
262 
263 	ACPI_FUNCTION_TRACE ("ds_build_internal_package_obj");
264 
265 
266 	/* Find the parent of a possibly nested package */
267 
268 	parent = op->common.parent;
269 	while ((parent->common.aml_opcode == AML_PACKAGE_OP)    ||
270 		   (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
271 		parent = parent->common.parent;
272 	}
273 
274 	obj_desc = *obj_desc_ptr;
275 	if (obj_desc) {
276 		/*
277 		 * We are evaluating a Named package object "Name (xxxx, Package)".
278 		 * Get the existing package object from the NS node
279 		 */
280 	}
281 	else {
282 		obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
283 		*obj_desc_ptr = obj_desc;
284 		if (!obj_desc) {
285 			return_ACPI_STATUS (AE_NO_MEMORY);
286 		}
287 
288 		obj_desc->package.node = parent->common.node;
289 	}
290 
291 	obj_desc->package.count = package_length;
292 
293 	/* Count the number of items in the package list */
294 
295 	package_list_length = 0;
296 	arg = op->common.value.arg;
297 	arg = arg->common.next;
298 	while (arg) {
299 		package_list_length++;
300 		arg = arg->common.next;
301 	}
302 
303 	/*
304 	 * The package length (number of elements) will be the greater
305 	 * of the specified length and the length of the initializer list
306 	 */
307 	if (package_list_length > package_length) {
308 		obj_desc->package.count = package_list_length;
309 	}
310 
311 	/*
312 	 * Allocate the pointer array (array of pointers to the
313 	 * individual objects). Add an extra pointer slot so
314 	 * that the list is always null terminated.
315 	 */
316 	obj_desc->package.elements = ACPI_MEM_CALLOCATE (
317 			 ((acpi_size) obj_desc->package.count + 1) * sizeof (void *));
318 
319 	if (!obj_desc->package.elements) {
320 		acpi_ut_delete_object_desc (obj_desc);
321 		return_ACPI_STATUS (AE_NO_MEMORY);
322 	}
323 
324 	/*
325 	 * Now init the elements of the package
326 	 */
327 	i = 0;
328 	arg = op->common.value.arg;
329 	arg = arg->common.next;
330 	while (arg) {
331 		if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
332 			/* Object (package or buffer) is already built */
333 
334 			obj_desc->package.elements[i] = ACPI_CAST_PTR (union acpi_operand_object, arg->common.node);
335 		}
336 		else {
337 			status = acpi_ds_build_internal_object (walk_state, arg,
338 					  &obj_desc->package.elements[i]);
339 		}
340 
341 		i++;
342 		arg = arg->common.next;
343 	}
344 
345 	obj_desc->package.flags |= AOPOBJ_DATA_VALID;
346 	op->common.node = (struct acpi_namespace_node *) obj_desc;
347 	return_ACPI_STATUS (status);
348 }
349 
350 
351 /*****************************************************************************
352  *
353  * FUNCTION:    acpi_ds_create_node
354  *
355  * PARAMETERS:  walk_state      - Current walk state
356  *              Node            - NS Node to be initialized
357  *              Op              - Parser object to be translated
358  *
359  * RETURN:      Status
360  *
361  * DESCRIPTION: Create the object to be associated with a namespace node
362  *
363  ****************************************************************************/
364 
365 acpi_status
acpi_ds_create_node(struct acpi_walk_state * walk_state,struct acpi_namespace_node * node,union acpi_parse_object * op)366 acpi_ds_create_node (
367 	struct acpi_walk_state          *walk_state,
368 	struct acpi_namespace_node      *node,
369 	union acpi_parse_object         *op)
370 {
371 	acpi_status                     status;
372 	union acpi_operand_object       *obj_desc;
373 
374 
375 	ACPI_FUNCTION_TRACE_PTR ("ds_create_node", op);
376 
377 
378 	/*
379 	 * Because of the execution pass through the non-control-method
380 	 * parts of the table, we can arrive here twice.  Only init
381 	 * the named object node the first time through
382 	 */
383 	if (acpi_ns_get_attached_object (node)) {
384 		return_ACPI_STATUS (AE_OK);
385 	}
386 
387 	if (!op->common.value.arg) {
388 		/* No arguments, there is nothing to do */
389 
390 		return_ACPI_STATUS (AE_OK);
391 	}
392 
393 	/* Build an internal object for the argument(s) */
394 
395 	status = acpi_ds_build_internal_object (walk_state, op->common.value.arg, &obj_desc);
396 	if (ACPI_FAILURE (status)) {
397 		return_ACPI_STATUS (status);
398 	}
399 
400 	/* Re-type the object according to its argument */
401 
402 	node->type = ACPI_GET_OBJECT_TYPE (obj_desc);
403 
404 	/* Attach obj to node */
405 
406 	status = acpi_ns_attach_object (node, obj_desc, node->type);
407 
408 	/* Remove local reference to the object */
409 
410 	acpi_ut_remove_reference (obj_desc);
411 	return_ACPI_STATUS (status);
412 }
413 
414 #endif /* ACPI_NO_METHOD_EXECUTION */
415 
416 
417 /*****************************************************************************
418  *
419  * FUNCTION:    acpi_ds_init_object_from_op
420  *
421  * PARAMETERS:  walk_state      - Current walk state
422  *              Op              - Parser op used to init the internal object
423  *              Opcode          - AML opcode associated with the object
424  *              ret_obj_desc    - Namespace object to be initialized
425  *
426  * RETURN:      Status
427  *
428  * DESCRIPTION: Initialize a namespace object from a parser Op and its
429  *              associated arguments.  The namespace object is a more compact
430  *              representation of the Op and its arguments.
431  *
432  ****************************************************************************/
433 
434 acpi_status
acpi_ds_init_object_from_op(struct acpi_walk_state * walk_state,union acpi_parse_object * op,u16 opcode,union acpi_operand_object ** ret_obj_desc)435 acpi_ds_init_object_from_op (
436 	struct acpi_walk_state          *walk_state,
437 	union acpi_parse_object         *op,
438 	u16                             opcode,
439 	union acpi_operand_object       **ret_obj_desc)
440 {
441 	const struct acpi_opcode_info   *op_info;
442 	union acpi_operand_object       *obj_desc;
443 	acpi_status                     status = AE_OK;
444 
445 
446 	ACPI_FUNCTION_TRACE ("ds_init_object_from_op");
447 
448 
449 	obj_desc = *ret_obj_desc;
450 	op_info = acpi_ps_get_opcode_info (opcode);
451 	if (op_info->class == AML_CLASS_UNKNOWN) {
452 		/* Unknown opcode */
453 
454 		return_ACPI_STATUS (AE_TYPE);
455 	}
456 
457 	/* Perform per-object initialization */
458 
459 	switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
460 	case ACPI_TYPE_BUFFER:
461 
462 		/*
463 		 * Defer evaluation of Buffer term_arg operand
464 		 */
465 		obj_desc->buffer.node     = (struct acpi_namespace_node *) walk_state->operands[0];
466 		obj_desc->buffer.aml_start = op->named.data;
467 		obj_desc->buffer.aml_length = op->named.length;
468 		break;
469 
470 
471 	case ACPI_TYPE_PACKAGE:
472 
473 		/*
474 		 * Defer evaluation of Package term_arg operand
475 		 */
476 		obj_desc->package.node     = (struct acpi_namespace_node *) walk_state->operands[0];
477 		obj_desc->package.aml_start = op->named.data;
478 		obj_desc->package.aml_length = op->named.length;
479 		break;
480 
481 
482 	case ACPI_TYPE_INTEGER:
483 
484 		switch (op_info->type) {
485 		case AML_TYPE_CONSTANT:
486 			/*
487 			 * Resolve AML Constants here - AND ONLY HERE!
488 			 * All constants are integers.
489 			 * We mark the integer with a flag that indicates that it started life
490 			 * as a constant -- so that stores to constants will perform as expected (noop).
491 			 * (zero_op is used as a placeholder for optional target operands.)
492 			 */
493 			obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
494 
495 			switch (opcode) {
496 			case AML_ZERO_OP:
497 
498 				obj_desc->integer.value = 0;
499 				break;
500 
501 			case AML_ONE_OP:
502 
503 				obj_desc->integer.value = 1;
504 				break;
505 
506 			case AML_ONES_OP:
507 
508 				obj_desc->integer.value = ACPI_INTEGER_MAX;
509 
510 				/* Truncate value if we are executing from a 32-bit ACPI table */
511 
512 #ifndef ACPI_NO_METHOD_EXECUTION
513 				acpi_ex_truncate_for32bit_table (obj_desc);
514 #endif
515 				break;
516 
517 			case AML_REVISION_OP:
518 
519 				obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL;
520 				break;
521 
522 			default:
523 
524 				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown constant opcode %X\n", opcode));
525 				status = AE_AML_OPERAND_TYPE;
526 				break;
527 			}
528 			break;
529 
530 
531 		case AML_TYPE_LITERAL:
532 
533 			obj_desc->integer.value = op->common.value.integer;
534 			break;
535 
536 
537 		default:
538 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n", op_info->type));
539 			status = AE_AML_OPERAND_TYPE;
540 			break;
541 		}
542 		break;
543 
544 
545 	case ACPI_TYPE_STRING:
546 
547 		obj_desc->string.pointer = op->common.value.string;
548 		obj_desc->string.length = (u32) ACPI_STRLEN (op->common.value.string);
549 
550 		/*
551 		 * The string is contained in the ACPI table, don't ever try
552 		 * to delete it
553 		 */
554 		obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
555 		break;
556 
557 
558 	case ACPI_TYPE_METHOD:
559 		break;
560 
561 
562 	case ACPI_TYPE_LOCAL_REFERENCE:
563 
564 		switch (op_info->type) {
565 		case AML_TYPE_LOCAL_VARIABLE:
566 
567 			/* Split the opcode into a base opcode + offset */
568 
569 			obj_desc->reference.opcode = AML_LOCAL_OP;
570 			obj_desc->reference.offset = opcode - AML_LOCAL_OP;
571 
572 #ifndef ACPI_NO_METHOD_EXECUTION
573 			status = acpi_ds_method_data_get_node (AML_LOCAL_OP, obj_desc->reference.offset,
574 					 walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
575 #endif
576 			break;
577 
578 
579 		case AML_TYPE_METHOD_ARGUMENT:
580 
581 			/* Split the opcode into a base opcode + offset */
582 
583 			obj_desc->reference.opcode = AML_ARG_OP;
584 			obj_desc->reference.offset = opcode - AML_ARG_OP;
585 
586 #ifndef ACPI_NO_METHOD_EXECUTION
587 			status = acpi_ds_method_data_get_node (AML_ARG_OP, obj_desc->reference.offset,
588 					 walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
589 #endif
590 			break;
591 
592 		default: /* Other literals, etc.. */
593 
594 			if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
595 				/* Node was saved in Op */
596 
597 				obj_desc->reference.node = op->common.node;
598 			}
599 
600 			obj_desc->reference.opcode = opcode;
601 			break;
602 		}
603 		break;
604 
605 
606 	default:
607 
608 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
609 			ACPI_GET_OBJECT_TYPE (obj_desc)));
610 
611 		status = AE_AML_OPERAND_TYPE;
612 		break;
613 	}
614 
615 	return_ACPI_STATUS (status);
616 }
617 
618 
619