1
2/******************************************************************************
3 *
4 * Module Name: exresolv - AML Interpreter object resolution
5 *              $Revision: 1.1.1.1 $
6 *
7 *****************************************************************************/
8
9/*
10 *  Copyright (C) 2000, 2001 R. Byron Moore
11 *
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.
16 *
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.
21 *
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
25 */
26
27
28#include "acpi.h"
29#include "amlcode.h"
30#include "acparser.h"
31#include "acdispat.h"
32#include "acinterp.h"
33#include "acnamesp.h"
34#include "actables.h"
35#include "acevents.h"
36
37
38#define _COMPONENT          ACPI_EXECUTER
39	 MODULE_NAME         ("exresolv")
40
41
42/*******************************************************************************
43 *
44 * FUNCTION:    Acpi_ex_get_buffer_field_value
45 *
46 * PARAMETERS:  *Obj_desc           - Pointer to a Buffer_field
47 *              *Result_desc        - Pointer to an empty descriptor which will
48 *                                    become an Integer with the field's value
49 *
50 * RETURN:      Status
51 *
52 * DESCRIPTION: Retrieve the value from a Buffer_field
53 *
54 ******************************************************************************/
55
56acpi_status
57acpi_ex_get_buffer_field_value (
58	acpi_operand_object     *obj_desc,
59	acpi_operand_object     *result_desc)
60{
61	acpi_status             status;
62	u32                     mask;
63	u8                      *location;
64
65
66	FUNCTION_TRACE ("Ex_get_buffer_field_value");
67
68
69	/*
70	 * Parameter validation
71	 */
72	if (!obj_desc) {
73		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null field pointer\n"));
74		return_ACPI_STATUS (AE_AML_NO_OPERAND);
75	}
76
77	if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
78		status = acpi_ds_get_buffer_field_arguments (obj_desc);
79		if (ACPI_FAILURE (status)) {
80			return_ACPI_STATUS (status);
81		}
82	}
83
84	if (!obj_desc->buffer_field.buffer_obj) {
85		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null container pointer\n"));
86		return_ACPI_STATUS (AE_AML_INTERNAL);
87	}
88
89	if (ACPI_TYPE_BUFFER != obj_desc->buffer_field.buffer_obj->common.type) {
90		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - container is not a Buffer\n"));
91		return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
92	}
93
94	if (!result_desc) {
95		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null result pointer\n"));
96		return_ACPI_STATUS (AE_AML_INTERNAL);
97	}
98
99
100	/* Field location is (base of buffer) + (byte offset) */
101
102	location = obj_desc->buffer_field.buffer_obj->buffer.pointer
103			 + obj_desc->buffer_field.base_byte_offset;
104
105	/*
106	 * Construct Mask with as many 1 bits as the field width
107	 *
108	 * NOTE: Only the bottom 5 bits are valid for a shift operation, so
109	 *  special care must be taken for any shift greater than 31 bits.
110	 *
111	 * TBD: [Unhandled] Fields greater than 32 bits will not work.
112	 */
113	if (obj_desc->buffer_field.bit_length < 32) {
114		mask = ((u32) 1 << obj_desc->buffer_field.bit_length) - (u32) 1;
115	}
116	else {
117		mask = ACPI_UINT32_MAX;
118	}
119
120	result_desc->integer.type = (u8) ACPI_TYPE_INTEGER;
121
122	/* Get the 32 bit value at the location */
123
124	MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location);
125
126	/*
127	 * Shift the 32-bit word containing the field, and mask off the
128	 * resulting value
129	 */
130	result_desc->integer.value =
131		(result_desc->integer.value >> obj_desc->buffer_field.start_field_bit_offset) & mask;
132
133	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
134		"** Read from buffer %p byte %d bit %d width %d addr %p mask %08X val %8.8X%8.8X\n",
135		obj_desc->buffer_field.buffer_obj->buffer.pointer,
136		obj_desc->buffer_field.base_byte_offset,
137		obj_desc->buffer_field.start_field_bit_offset,
138		obj_desc->buffer_field.bit_length,
139		location, mask,
140		HIDWORD(result_desc->integer.value),
141		LODWORD(result_desc->integer.value)));
142
143	return_ACPI_STATUS (AE_OK);
144}
145
146
147/*******************************************************************************
148 *
149 * FUNCTION:    Acpi_ex_resolve_to_value
150 *
151 * PARAMETERS:  **Stack_ptr         - Points to entry on Obj_stack, which can
152 *                                    be either an (acpi_operand_object *)
153 *                                    or an acpi_handle.
154 *              Walk_state          - Current method state
155 *
156 * RETURN:      Status
157 *
158 * DESCRIPTION: Convert Reference objects to values
159 *
160 ******************************************************************************/
161
162acpi_status
163acpi_ex_resolve_to_value (
164	acpi_operand_object     **stack_ptr,
165	acpi_walk_state         *walk_state)
166{
167	acpi_status             status;
168
169
170	FUNCTION_TRACE_PTR ("Ex_resolve_to_value", stack_ptr);
171
172
173	if (!stack_ptr || !*stack_ptr) {
174		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n"));
175		return_ACPI_STATUS (AE_AML_NO_OPERAND);
176	}
177
178
179	/*
180	 * The entity pointed to by the Stack_ptr can be either
181	 * 1) A valid acpi_operand_object, or
182	 * 2) A acpi_namespace_node (Named_obj)
183	 */
184	if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) {
185		status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state);
186		if (ACPI_FAILURE (status)) {
187			return_ACPI_STATUS (status);
188		}
189	}
190
191	/*
192	 * Object on the stack may have changed if Acpi_ex_resolve_object_to_value()
193	 * was called (i.e., we can't use an _else_ here.)
194	 */
195	if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) {
196		status = acpi_ex_resolve_node_to_value ((acpi_namespace_node **) stack_ptr,
197				  walk_state);
198		if (ACPI_FAILURE (status)) {
199			return_ACPI_STATUS (status);
200		}
201	}
202
203
204	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Resolved object %p\n", *stack_ptr));
205	return_ACPI_STATUS (AE_OK);
206}
207
208
209/*******************************************************************************
210 *
211 * FUNCTION:    Acpi_ex_resolve_object_to_value
212 *
213 * PARAMETERS:  Stack_ptr       - Pointer to a stack location that contains a
214 *                                ptr to an internal object.
215 *              Walk_state      - Current method state
216 *
217 * RETURN:      Status
218 *
219 * DESCRIPTION: Retrieve the value from an internal object.  The Reference type
220 *              uses the associated AML opcode to determine the value.
221 *
222 ******************************************************************************/
223
224acpi_status
225acpi_ex_resolve_object_to_value (
226	acpi_operand_object     **stack_ptr,
227	acpi_walk_state         *walk_state)
228{
229	acpi_status             status = AE_OK;
230	acpi_operand_object     *stack_desc;
231	void                    *temp_node;
232	acpi_operand_object     *obj_desc;
233	u16                     opcode;
234
235
236	FUNCTION_TRACE ("Ex_resolve_object_to_value");
237
238
239	stack_desc = *stack_ptr;
240
241	/* This is an acpi_operand_object  */
242
243	switch (stack_desc->common.type) {
244
245	case INTERNAL_TYPE_REFERENCE:
246
247		opcode = stack_desc->reference.opcode;
248
249		switch (opcode) {
250
251		case AML_NAME_OP:
252
253			/*
254			 * Convert indirect name ptr to a direct name ptr.
255			 * Then, Acpi_ex_resolve_node_to_value can be used to get the value
256			 */
257			temp_node = stack_desc->reference.object;
258
259			/* Delete the Reference Object */
260
261			acpi_ut_remove_reference (stack_desc);
262
263			/* Put direct name pointer onto stack and exit */
264
265			(*stack_ptr) = temp_node;
266			break;
267
268
269		case AML_LOCAL_OP:
270		case AML_ARG_OP:
271
272			/*
273			 * Get the local from the method's state info
274			 * Note: this increments the local's object reference count
275			 */
276			status = acpi_ds_method_data_get_value (opcode,
277					  stack_desc->reference.offset, walk_state, &obj_desc);
278			if (ACPI_FAILURE (status)) {
279				return_ACPI_STATUS (status);
280			}
281
282			/*
283			 * Now we can delete the original Reference Object and
284			 * replace it with the resolve value
285			 */
286			acpi_ut_remove_reference (stack_desc);
287			*stack_ptr = obj_desc;
288
289			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[Arg/Local %d] Value_obj is %p\n",
290				stack_desc->reference.offset, obj_desc));
291			break;
292
293
294		/*
295		 * For constants, we must change the reference/constant object
296		 * to a real integer object
297		 */
298		case AML_ZERO_OP:
299		case AML_ONE_OP:
300		case AML_ONES_OP:
301		case AML_REVISION_OP:
302
303			/* Create a new integer object */
304
305			obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
306			if (!obj_desc) {
307				return_ACPI_STATUS (AE_NO_MEMORY);
308			}
309
310			switch (opcode) {
311			case AML_ZERO_OP:
312				obj_desc->integer.value = 0;
313				break;
314
315			case AML_ONE_OP:
316				obj_desc->integer.value = 1;
317				break;
318
319			case AML_ONES_OP:
320				obj_desc->integer.value = ACPI_INTEGER_MAX;
321
322				/* Truncate value if we are executing from a 32-bit ACPI table */
323
324				acpi_ex_truncate_for32bit_table (obj_desc, walk_state);
325				break;
326
327			case AML_REVISION_OP:
328				obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL;
329				break;
330			}
331
332			/*
333			 * Remove a reference from the original reference object
334			 * and put the new object in its place
335			 */
336			acpi_ut_remove_reference (stack_desc);
337			*stack_ptr = obj_desc;
338			break;
339
340
341		case AML_INDEX_OP:
342
343			switch (stack_desc->reference.target_type) {
344			case ACPI_TYPE_BUFFER_FIELD:
345
346				/* Just return - leave the Reference on the stack */
347				break;
348
349
350			case ACPI_TYPE_PACKAGE:
351				obj_desc = *stack_desc->reference.where;
352				if (obj_desc) {
353					/*
354					 * Valid obj descriptor, copy pointer to return value
355					 * (i.e., dereference the package index)
356					 * Delete the ref object, increment the returned object
357					 */
358					acpi_ut_remove_reference (stack_desc);
359					acpi_ut_add_reference (obj_desc);
360					*stack_ptr = obj_desc;
361				}
362
363				else {
364					/*
365					 * A NULL object descriptor means an unitialized element of
366					 * the package, can't dereference it
367					 */
368					ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
369						"Attempt to deref an Index to NULL pkg element Idx=%p\n",
370						stack_desc));
371					status = AE_AML_UNINITIALIZED_ELEMENT;
372				}
373				break;
374
375			default:
376				/* Invalid reference object */
377
378				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
379					"Unknown Target_type %X in Index/Reference obj %p\n",
380					stack_desc->reference.target_type, stack_desc));
381				status = AE_AML_INTERNAL;
382				break;
383			}
384
385			break;
386
387
388		case AML_DEBUG_OP:
389
390			/* Just leave the object as-is */
391			break;
392
393
394		default:
395
396			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference object subtype %02X in %p\n",
397				opcode, stack_desc));
398			status = AE_AML_INTERNAL;
399			break;
400
401		}   /* switch (Opcode) */
402
403		break; /* case INTERNAL_TYPE_REFERENCE */
404
405
406	case ACPI_TYPE_BUFFER_FIELD:
407
408		obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_ANY);
409		if (!obj_desc) {
410			return_ACPI_STATUS (AE_NO_MEMORY);
411		}
412
413		status = acpi_ex_get_buffer_field_value (stack_desc, obj_desc);
414		if (ACPI_FAILURE (status)) {
415			acpi_ut_remove_reference (obj_desc);
416			obj_desc = NULL;
417		}
418
419		*stack_ptr = (void *) obj_desc;
420		break;
421
422
423	case INTERNAL_TYPE_BANK_FIELD:
424
425		obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_ANY);
426		if (!obj_desc) {
427			return_ACPI_STATUS (AE_NO_MEMORY);
428		}
429
430		/* TBD: WRONG! */
431
432		status = acpi_ex_get_buffer_field_value (stack_desc, obj_desc);
433		if (ACPI_FAILURE (status)) {
434			acpi_ut_remove_reference (obj_desc);
435			obj_desc = NULL;
436		}
437
438		*stack_ptr = (void *) obj_desc;
439		break;
440
441
442	/* TBD: [Future] - may need to handle Index_field, and Def_field someday */
443
444	default:
445
446		break;
447
448	}   /* switch (Stack_desc->Common.Type) */
449
450
451	return_ACPI_STATUS (status);
452}
453
454
455