Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: exresolv - AML Interpreter object resolution
5 : : *
6 : : * Copyright (C) 2000 - 2020, Intel Corp.
7 : : *
8 : : *****************************************************************************/
9 : :
10 : : #include <acpi/acpi.h>
11 : : #include "accommon.h"
12 : : #include "amlcode.h"
13 : : #include "acdispat.h"
14 : : #include "acinterp.h"
15 : : #include "acnamesp.h"
16 : :
17 : : #define _COMPONENT ACPI_EXECUTER
18 : : ACPI_MODULE_NAME("exresolv")
19 : :
20 : : /* Local prototypes */
21 : : static acpi_status
22 : : acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
23 : : struct acpi_walk_state *walk_state);
24 : :
25 : : /*******************************************************************************
26 : : *
27 : : * FUNCTION: acpi_ex_resolve_to_value
28 : : *
29 : : * PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can
30 : : * be either an (union acpi_operand_object *)
31 : : * or an acpi_handle.
32 : : * walk_state - Current method state
33 : : *
34 : : * RETURN: Status
35 : : *
36 : : * DESCRIPTION: Convert Reference objects to values
37 : : *
38 : : ******************************************************************************/
39 : :
40 : : acpi_status
41 : 156806 : acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
42 : : struct acpi_walk_state *walk_state)
43 : : {
44 : 156806 : acpi_status status;
45 : :
46 : 156806 : ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
47 : :
48 [ + - - + ]: 156806 : if (!stack_ptr || !*stack_ptr) {
49 : 0 : ACPI_ERROR((AE_INFO, "Internal - null pointer"));
50 : 0 : return_ACPI_STATUS(AE_AML_NO_OPERAND);
51 : : }
52 : :
53 : : /*
54 : : * The entity pointed to by the stack_ptr can be either
55 : : * 1) A valid union acpi_operand_object, or
56 : : * 2) A struct acpi_namespace_node (named_obj)
57 : : */
58 [ + + ]: 156806 : if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
59 : 154650 : status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
60 [ + - ]: 154650 : if (ACPI_FAILURE(status)) {
61 : : return_ACPI_STATUS(status);
62 : : }
63 : :
64 [ - + ]: 154650 : if (!*stack_ptr) {
65 : 0 : ACPI_ERROR((AE_INFO, "Internal - null pointer"));
66 : 0 : return_ACPI_STATUS(AE_AML_NO_OPERAND);
67 : : }
68 : : }
69 : :
70 : : /*
71 : : * Object on the stack may have changed if acpi_ex_resolve_object_to_value()
72 : : * was called (i.e., we can't use an _else_ here.)
73 : : */
74 [ + + ]: 156806 : if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
75 : 2156 : status =
76 : 2156 : acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
77 : : (struct acpi_namespace_node,
78 : : stack_ptr), walk_state);
79 : 2156 : if (ACPI_FAILURE(status)) {
80 : : return_ACPI_STATUS(status);
81 : : }
82 : : }
83 : :
84 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
85 : : return_ACPI_STATUS(AE_OK);
86 : : }
87 : :
88 : : /*******************************************************************************
89 : : *
90 : : * FUNCTION: acpi_ex_resolve_object_to_value
91 : : *
92 : : * PARAMETERS: stack_ptr - Pointer to an internal object
93 : : * walk_state - Current method state
94 : : *
95 : : * RETURN: Status
96 : : *
97 : : * DESCRIPTION: Retrieve the value from an internal object. The Reference type
98 : : * uses the associated AML opcode to determine the value.
99 : : *
100 : : ******************************************************************************/
101 : :
102 : : static acpi_status
103 : 154650 : acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
104 : : struct acpi_walk_state *walk_state)
105 : : {
106 : 154650 : acpi_status status = AE_OK;
107 : 154650 : union acpi_operand_object *stack_desc;
108 : 154650 : union acpi_operand_object *obj_desc = NULL;
109 : 154650 : u8 ref_type;
110 : :
111 : 154650 : ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
112 : :
113 : 154650 : stack_desc = *stack_ptr;
114 : :
115 : : /* This is an object of type union acpi_operand_object */
116 : :
117 [ + + + - : 154650 : switch (stack_desc->common.type) {
+ ]
118 : 66558 : case ACPI_TYPE_LOCAL_REFERENCE:
119 : :
120 : 66558 : ref_type = stack_desc->reference.class;
121 : :
122 [ + - - - : 66558 : switch (ref_type) {
- ]
123 : 66558 : case ACPI_REFCLASS_LOCAL:
124 : : case ACPI_REFCLASS_ARG:
125 : : /*
126 : : * Get the local from the method's state info
127 : : * Note: this increments the local's object reference count
128 : : */
129 : 66558 : status = acpi_ds_method_data_get_value(ref_type,
130 : : stack_desc->
131 : : reference.value,
132 : : walk_state,
133 : : &obj_desc);
134 [ + - ]: 66558 : if (ACPI_FAILURE(status)) {
135 : : return_ACPI_STATUS(status);
136 : : }
137 : :
138 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
139 : : "[Arg/Local %X] ValueObj is %p\n",
140 : : stack_desc->reference.value,
141 : 66558 : obj_desc));
142 : :
143 : : /*
144 : : * Now we can delete the original Reference Object and
145 : : * replace it with the resolved value
146 : : */
147 : 66558 : acpi_ut_remove_reference(stack_desc);
148 : 66558 : *stack_ptr = obj_desc;
149 : 66558 : break;
150 : :
151 : 0 : case ACPI_REFCLASS_INDEX:
152 : :
153 [ # # # ]: 0 : switch (stack_desc->reference.target_type) {
154 : : case ACPI_TYPE_BUFFER_FIELD:
155 : :
156 : : /* Just return - do not dereference */
157 : : break;
158 : :
159 : 0 : case ACPI_TYPE_PACKAGE:
160 : :
161 : : /* If method call or copy_object - do not dereference */
162 : :
163 : 0 : if ((walk_state->opcode ==
164 : : AML_INT_METHODCALL_OP)
165 [ # # ]: 0 : || (walk_state->opcode ==
166 : : AML_COPY_OBJECT_OP)) {
167 : : break;
168 : : }
169 : :
170 : : /* Otherwise, dereference the package_index to a package element */
171 : :
172 : 0 : obj_desc = *stack_desc->reference.where;
173 [ # # ]: 0 : if (obj_desc) {
174 : : /*
175 : : * Valid object descriptor, copy pointer to return value
176 : : * (i.e., dereference the package index)
177 : : * Delete the ref object, increment the returned object
178 : : */
179 : 0 : acpi_ut_add_reference(obj_desc);
180 : 0 : *stack_ptr = obj_desc;
181 : : } else {
182 : : /*
183 : : * A NULL object descriptor means an uninitialized element of
184 : : * the package, can't dereference it
185 : : */
186 : 0 : ACPI_ERROR((AE_INFO,
187 : : "Attempt to dereference an Index to "
188 : : "NULL package element Idx=%p",
189 : : stack_desc));
190 : 0 : status = AE_AML_UNINITIALIZED_ELEMENT;
191 : : }
192 : : break;
193 : :
194 : 0 : default:
195 : :
196 : : /* Invalid reference object */
197 : :
198 : 0 : ACPI_ERROR((AE_INFO,
199 : : "Unknown TargetType 0x%X in Index/Reference object %p",
200 : : stack_desc->reference.target_type,
201 : : stack_desc));
202 : 0 : status = AE_AML_INTERNAL;
203 : 0 : break;
204 : : }
205 : 0 : break;
206 : :
207 : : case ACPI_REFCLASS_REFOF:
208 : : case ACPI_REFCLASS_DEBUG:
209 : : case ACPI_REFCLASS_TABLE:
210 : :
211 : : /* Just leave the object as-is, do not dereference */
212 : :
213 : : break;
214 : :
215 : 0 : case ACPI_REFCLASS_NAME: /* Reference to a named object */
216 : :
217 : : /* Dereference the name */
218 : :
219 : 0 : if ((stack_desc->reference.node->type ==
220 : : ACPI_TYPE_DEVICE)
221 [ # # ]: 0 : || (stack_desc->reference.node->type ==
222 : : ACPI_TYPE_THERMAL)) {
223 : :
224 : : /* These node types do not have 'real' subobjects */
225 : :
226 : 0 : *stack_ptr = (void *)stack_desc->reference.node;
227 : : } else {
228 : : /* Get the object pointed to by the namespace node */
229 : :
230 : 0 : *stack_ptr =
231 : 0 : (stack_desc->reference.node)->object;
232 : 0 : acpi_ut_add_reference(*stack_ptr);
233 : : }
234 : :
235 : 0 : acpi_ut_remove_reference(stack_desc);
236 : 0 : break;
237 : :
238 : 0 : default:
239 : :
240 : 0 : ACPI_ERROR((AE_INFO,
241 : : "Unknown Reference type 0x%X in %p",
242 : : ref_type, stack_desc));
243 : 0 : status = AE_AML_INTERNAL;
244 : 0 : break;
245 : : }
246 : : break;
247 : :
248 : 560 : case ACPI_TYPE_BUFFER:
249 : :
250 : 560 : status = acpi_ds_get_buffer_arguments(stack_desc);
251 : 560 : break;
252 : :
253 : 3999 : case ACPI_TYPE_PACKAGE:
254 : :
255 : 3999 : status = acpi_ds_get_package_arguments(stack_desc);
256 : 3999 : break;
257 : :
258 : 0 : case ACPI_TYPE_BUFFER_FIELD:
259 : : case ACPI_TYPE_LOCAL_REGION_FIELD:
260 : : case ACPI_TYPE_LOCAL_BANK_FIELD:
261 : : case ACPI_TYPE_LOCAL_INDEX_FIELD:
262 : :
263 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
264 : : "FieldRead SourceDesc=%p Type=%X\n",
265 : 0 : stack_desc, stack_desc->common.type));
266 : :
267 : 0 : status =
268 : 0 : acpi_ex_read_data_from_field(walk_state, stack_desc,
269 : : &obj_desc);
270 : :
271 : : /* Remove a reference to the original operand, then override */
272 : :
273 : 0 : acpi_ut_remove_reference(*stack_ptr);
274 : 0 : *stack_ptr = (void *)obj_desc;
275 : 0 : break;
276 : :
277 : : default:
278 : :
279 : : break;
280 : : }
281 : :
282 : : return_ACPI_STATUS(status);
283 : : }
284 : :
285 : : /*******************************************************************************
286 : : *
287 : : * FUNCTION: acpi_ex_resolve_multiple
288 : : *
289 : : * PARAMETERS: walk_state - Current state (contains AML opcode)
290 : : * operand - Starting point for resolution
291 : : * return_type - Where the object type is returned
292 : : * return_desc - Where the resolved object is returned
293 : : *
294 : : * RETURN: Status
295 : : *
296 : : * DESCRIPTION: Return the base object and type. Traverse a reference list if
297 : : * necessary to get to the base object.
298 : : *
299 : : ******************************************************************************/
300 : :
301 : : acpi_status
302 : 0 : acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
303 : : union acpi_operand_object *operand,
304 : : acpi_object_type *return_type,
305 : : union acpi_operand_object **return_desc)
306 : : {
307 : 0 : union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
308 : 0 : struct acpi_namespace_node *node =
309 : : ACPI_CAST_PTR(struct acpi_namespace_node, operand);
310 : 0 : acpi_object_type type;
311 : 0 : acpi_status status;
312 : :
313 : 0 : ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
314 : :
315 : : /* Operand can be either a namespace node or an operand descriptor */
316 : :
317 [ # # # ]: 0 : switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
318 : 0 : case ACPI_DESC_TYPE_OPERAND:
319 : :
320 : 0 : type = obj_desc->common.type;
321 : 0 : break;
322 : :
323 : 0 : case ACPI_DESC_TYPE_NAMED:
324 : :
325 : 0 : type = ((struct acpi_namespace_node *)obj_desc)->type;
326 : 0 : obj_desc = acpi_ns_get_attached_object(node);
327 : :
328 : : /* If we had an Alias node, use the attached object for type info */
329 : :
330 [ # # ]: 0 : if (type == ACPI_TYPE_LOCAL_ALIAS) {
331 : 0 : type = ((struct acpi_namespace_node *)obj_desc)->type;
332 : 0 : obj_desc = acpi_ns_get_attached_object((struct
333 : : acpi_namespace_node
334 : : *)obj_desc);
335 : : }
336 : :
337 [ # # ]: 0 : switch (type) {
338 : : case ACPI_TYPE_DEVICE:
339 : : case ACPI_TYPE_THERMAL:
340 : :
341 : : /* These types have no attached subobject */
342 : : break;
343 : :
344 : 0 : default:
345 : :
346 : : /* All other types require a subobject */
347 : :
348 [ # # ]: 0 : if (!obj_desc) {
349 : 0 : ACPI_ERROR((AE_INFO,
350 : : "[%4.4s] Node is unresolved or uninitialized",
351 : : acpi_ut_get_node_name(node)));
352 : 0 : return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
353 : : }
354 : : break;
355 : : }
356 : : break;
357 : :
358 : : default:
359 : : return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
360 : : }
361 : :
362 : : /* If type is anything other than a reference, we are done */
363 : :
364 [ # # ]: 0 : if (type != ACPI_TYPE_LOCAL_REFERENCE) {
365 : 0 : goto exit;
366 : : }
367 : :
368 : : /*
369 : : * For reference objects created via the ref_of, Index, or Load/load_table
370 : : * operators, we need to get to the base object (as per the ACPI
371 : : * specification of the object_type and size_of operators). This means
372 : : * traversing the list of possibly many nested references.
373 : : */
374 [ # # ]: 0 : while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
375 [ # # # # : 0 : switch (obj_desc->reference.class) {
# # ]
376 : 0 : case ACPI_REFCLASS_REFOF:
377 : : case ACPI_REFCLASS_NAME:
378 : :
379 : : /* Dereference the reference pointer */
380 : :
381 [ # # ]: 0 : if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
382 : 0 : node = obj_desc->reference.object;
383 : : } else { /* AML_INT_NAMEPATH_OP */
384 : :
385 : 0 : node = obj_desc->reference.node;
386 : : }
387 : :
388 : : /* All "References" point to a NS node */
389 : :
390 [ # # ]: 0 : if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
391 : : ACPI_DESC_TYPE_NAMED) {
392 : 0 : ACPI_ERROR((AE_INFO,
393 : : "Not a namespace node %p [%s]",
394 : : node,
395 : : acpi_ut_get_descriptor_name(node)));
396 : 0 : return_ACPI_STATUS(AE_AML_INTERNAL);
397 : : }
398 : :
399 : : /* Get the attached object */
400 : :
401 : 0 : obj_desc = acpi_ns_get_attached_object(node);
402 [ # # ]: 0 : if (!obj_desc) {
403 : :
404 : : /* No object, use the NS node type */
405 : :
406 : 0 : type = acpi_ns_get_type(node);
407 : 0 : goto exit;
408 : : }
409 : :
410 : : /* Check for circular references */
411 : :
412 [ # # ]: 0 : if (obj_desc == operand) {
413 : : return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
414 : : }
415 : : break;
416 : :
417 : 0 : case ACPI_REFCLASS_INDEX:
418 : :
419 : : /* Get the type of this reference (index into another object) */
420 : :
421 : 0 : type = obj_desc->reference.target_type;
422 [ # # ]: 0 : if (type != ACPI_TYPE_PACKAGE) {
423 : 0 : goto exit;
424 : : }
425 : :
426 : : /*
427 : : * The main object is a package, we want to get the type
428 : : * of the individual package element that is referenced by
429 : : * the index.
430 : : *
431 : : * This could of course in turn be another reference object.
432 : : */
433 : 0 : obj_desc = *(obj_desc->reference.where);
434 [ # # ]: 0 : if (!obj_desc) {
435 : :
436 : : /* NULL package elements are allowed */
437 : :
438 : 0 : type = 0; /* Uninitialized */
439 : 0 : goto exit;
440 : : }
441 : : break;
442 : :
443 : 0 : case ACPI_REFCLASS_TABLE:
444 : :
445 : 0 : type = ACPI_TYPE_DDB_HANDLE;
446 : 0 : goto exit;
447 : :
448 : 0 : case ACPI_REFCLASS_LOCAL:
449 : : case ACPI_REFCLASS_ARG:
450 : :
451 [ # # ]: 0 : if (return_desc) {
452 : 0 : status =
453 : 0 : acpi_ds_method_data_get_value(obj_desc->
454 : : reference.
455 : : class,
456 : : obj_desc->
457 : : reference.
458 : : value,
459 : : walk_state,
460 : : &obj_desc);
461 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
462 : 0 : return_ACPI_STATUS(status);
463 : : }
464 : 0 : acpi_ut_remove_reference(obj_desc);
465 : : } else {
466 : 0 : status =
467 : 0 : acpi_ds_method_data_get_node(obj_desc->
468 : : reference.
469 : : class,
470 : : obj_desc->
471 : : reference.
472 : : value,
473 : : walk_state,
474 : : &node);
475 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
476 : 0 : return_ACPI_STATUS(status);
477 : : }
478 : :
479 : 0 : obj_desc = acpi_ns_get_attached_object(node);
480 [ # # ]: 0 : if (!obj_desc) {
481 : 0 : type = ACPI_TYPE_ANY;
482 : 0 : goto exit;
483 : : }
484 : : }
485 : : break;
486 : :
487 : 0 : case ACPI_REFCLASS_DEBUG:
488 : :
489 : : /* The Debug Object is of type "DebugObject" */
490 : :
491 : 0 : type = ACPI_TYPE_DEBUG_OBJECT;
492 : 0 : goto exit;
493 : :
494 : 0 : default:
495 : :
496 : 0 : ACPI_ERROR((AE_INFO,
497 : : "Unknown Reference Class 0x%2.2X",
498 : : obj_desc->reference.class));
499 : 0 : return_ACPI_STATUS(AE_AML_INTERNAL);
500 : : }
501 : : }
502 : :
503 : : /*
504 : : * Now we are guaranteed to have an object that has not been created
505 : : * via the ref_of or Index operators.
506 : : */
507 : 0 : type = obj_desc->common.type;
508 : :
509 : 0 : exit:
510 : : /* Convert internal types to external types */
511 : :
512 [ # # # ]: 0 : switch (type) {
513 : 0 : case ACPI_TYPE_LOCAL_REGION_FIELD:
514 : : case ACPI_TYPE_LOCAL_BANK_FIELD:
515 : : case ACPI_TYPE_LOCAL_INDEX_FIELD:
516 : :
517 : 0 : type = ACPI_TYPE_FIELD_UNIT;
518 : 0 : break;
519 : :
520 : 0 : case ACPI_TYPE_LOCAL_SCOPE:
521 : :
522 : : /* Per ACPI Specification, Scope is untyped */
523 : :
524 : 0 : type = ACPI_TYPE_ANY;
525 : 0 : break;
526 : :
527 : : default:
528 : :
529 : : /* No change to Type required */
530 : :
531 : : break;
532 : : }
533 : :
534 : 0 : *return_type = type;
535 [ # # ]: 0 : if (return_desc) {
536 : 0 : *return_desc = obj_desc;
537 : : }
538 : : return_ACPI_STATUS(AE_OK);
539 : : }
|