Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/acpi/acpica/dsutils.c
26285 views
1
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2
/*******************************************************************************
3
*
4
* Module Name: dsutils - Dispatcher utilities
5
*
6
******************************************************************************/
7
8
#include <acpi/acpi.h>
9
#include "accommon.h"
10
#include "acparser.h"
11
#include "amlcode.h"
12
#include "acdispat.h"
13
#include "acinterp.h"
14
#include "acnamesp.h"
15
#include "acdebug.h"
16
17
#define _COMPONENT ACPI_DISPATCHER
18
ACPI_MODULE_NAME("dsutils")
19
20
/*******************************************************************************
21
*
22
* FUNCTION: acpi_ds_clear_implicit_return
23
*
24
* PARAMETERS: walk_state - Current State
25
*
26
* RETURN: None.
27
*
28
* DESCRIPTION: Clear and remove a reference on an implicit return value. Used
29
* to delete "stale" return values (if enabled, the return value
30
* from every operator is saved at least momentarily, in case the
31
* parent method exits.)
32
*
33
******************************************************************************/
34
void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
35
{
36
ACPI_FUNCTION_NAME(ds_clear_implicit_return);
37
38
/*
39
* Slack must be enabled for this feature
40
*/
41
if (!acpi_gbl_enable_interpreter_slack) {
42
return;
43
}
44
45
if (walk_state->implicit_return_obj) {
46
/*
47
* Delete any "stale" implicit return. However, in
48
* complex statements, the implicit return value can be
49
* bubbled up several levels.
50
*/
51
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
52
"Removing reference on stale implicit return obj %p\n",
53
walk_state->implicit_return_obj));
54
55
acpi_ut_remove_reference(walk_state->implicit_return_obj);
56
walk_state->implicit_return_obj = NULL;
57
}
58
}
59
60
/*******************************************************************************
61
*
62
* FUNCTION: acpi_ds_do_implicit_return
63
*
64
* PARAMETERS: return_desc - The return value
65
* walk_state - Current State
66
* add_reference - True if a reference should be added to the
67
* return object
68
*
69
* RETURN: TRUE if implicit return enabled, FALSE otherwise
70
*
71
* DESCRIPTION: Implements the optional "implicit return". We save the result
72
* of every ASL operator and control method invocation in case the
73
* parent method exit. Before storing a new return value, we
74
* delete the previous return value.
75
*
76
******************************************************************************/
77
78
u8
79
acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
80
struct acpi_walk_state *walk_state, u8 add_reference)
81
{
82
ACPI_FUNCTION_NAME(ds_do_implicit_return);
83
84
/*
85
* Slack must be enabled for this feature, and we must
86
* have a valid return object
87
*/
88
if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
89
return (FALSE);
90
}
91
92
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
93
"Result %p will be implicitly returned; Prev=%p\n",
94
return_desc, walk_state->implicit_return_obj));
95
96
/*
97
* Delete any "stale" implicit return value first. However, in
98
* complex statements, the implicit return value can be
99
* bubbled up several levels, so we don't clear the value if it
100
* is the same as the return_desc.
101
*/
102
if (walk_state->implicit_return_obj) {
103
if (walk_state->implicit_return_obj == return_desc) {
104
return (TRUE);
105
}
106
acpi_ds_clear_implicit_return(walk_state);
107
}
108
109
/* Save the implicit return value, add a reference if requested */
110
111
walk_state->implicit_return_obj = return_desc;
112
if (add_reference) {
113
acpi_ut_add_reference(return_desc);
114
}
115
116
return (TRUE);
117
}
118
119
/*******************************************************************************
120
*
121
* FUNCTION: acpi_ds_is_result_used
122
*
123
* PARAMETERS: op - Current Op
124
* walk_state - Current State
125
*
126
* RETURN: TRUE if result is used, FALSE otherwise
127
*
128
* DESCRIPTION: Check if a result object will be used by the parent
129
*
130
******************************************************************************/
131
132
u8
133
acpi_ds_is_result_used(union acpi_parse_object * op,
134
struct acpi_walk_state * walk_state)
135
{
136
const struct acpi_opcode_info *parent_info;
137
138
ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
139
140
/* Must have both an Op and a Result Object */
141
142
if (!op) {
143
ACPI_ERROR((AE_INFO, "Null Op"));
144
return_UINT8(TRUE);
145
}
146
147
/*
148
* We know that this operator is not a
149
* Return() operator (would not come here.) The following code is the
150
* optional support for a so-called "implicit return". Some AML code
151
* assumes that the last value of the method is "implicitly" returned
152
* to the caller. Just save the last result as the return value.
153
* NOTE: this is optional because the ASL language does not actually
154
* support this behavior.
155
*/
156
(void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
157
TRUE);
158
159
/*
160
* Now determine if the parent will use the result
161
*
162
* If there is no parent, or the parent is a scope_op, we are executing
163
* at the method level. An executing method typically has no parent,
164
* since each method is parsed separately. A method invoked externally
165
* via execute_control_method has a scope_op as the parent.
166
*/
167
if ((!op->common.parent) ||
168
(op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
169
170
/* No parent, the return value cannot possibly be used */
171
172
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
173
"At Method level, result of [%s] not used\n",
174
acpi_ps_get_opcode_name(op->common.
175
aml_opcode)));
176
return_UINT8(FALSE);
177
}
178
179
/* Get info on the parent. The root_op is AML_SCOPE */
180
181
parent_info =
182
acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
183
if (parent_info->class == AML_CLASS_UNKNOWN) {
184
ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
185
return_UINT8(FALSE);
186
}
187
188
/*
189
* Decide what to do with the result based on the parent. If
190
* the parent opcode will not use the result, delete the object.
191
* Otherwise leave it as is, it will be deleted when it is used
192
* as an operand later.
193
*/
194
switch (parent_info->class) {
195
case AML_CLASS_CONTROL:
196
197
switch (op->common.parent->common.aml_opcode) {
198
case AML_RETURN_OP:
199
200
/* Never delete the return value associated with a return opcode */
201
202
goto result_used;
203
204
case AML_IF_OP:
205
case AML_WHILE_OP:
206
/*
207
* If we are executing the predicate AND this is the predicate op,
208
* we will use the return value
209
*/
210
if ((walk_state->control_state->common.state ==
211
ACPI_CONTROL_PREDICATE_EXECUTING) &&
212
(walk_state->control_state->control.predicate_op ==
213
op)) {
214
goto result_used;
215
}
216
break;
217
218
default:
219
220
/* Ignore other control opcodes */
221
222
break;
223
}
224
225
/* The general control opcode returns no result */
226
227
goto result_not_used;
228
229
case AML_CLASS_CREATE:
230
/*
231
* These opcodes allow term_arg(s) as operands and therefore
232
* the operands can be method calls. The result is used.
233
*/
234
goto result_used;
235
236
case AML_CLASS_NAMED_OBJECT:
237
238
if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
239
(op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
240
|| (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
241
|| (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
242
|| (op->common.parent->common.aml_opcode ==
243
AML_VARIABLE_PACKAGE_OP)
244
|| (op->common.parent->common.aml_opcode ==
245
AML_INT_EVAL_SUBTREE_OP)
246
|| (op->common.parent->common.aml_opcode ==
247
AML_BANK_FIELD_OP)) {
248
/*
249
* These opcodes allow term_arg(s) as operands and therefore
250
* the operands can be method calls. The result is used.
251
*/
252
goto result_used;
253
}
254
255
goto result_not_used;
256
257
default:
258
/*
259
* In all other cases. the parent will actually use the return
260
* object, so keep it.
261
*/
262
goto result_used;
263
}
264
265
result_used:
266
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
267
"Result of [%s] used by Parent [%s] Op=%p\n",
268
acpi_ps_get_opcode_name(op->common.aml_opcode),
269
acpi_ps_get_opcode_name(op->common.parent->common.
270
aml_opcode), op));
271
272
return_UINT8(TRUE);
273
274
result_not_used:
275
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
276
"Result of [%s] not used by Parent [%s] Op=%p\n",
277
acpi_ps_get_opcode_name(op->common.aml_opcode),
278
acpi_ps_get_opcode_name(op->common.parent->common.
279
aml_opcode), op));
280
281
return_UINT8(FALSE);
282
}
283
284
/*******************************************************************************
285
*
286
* FUNCTION: acpi_ds_delete_result_if_not_used
287
*
288
* PARAMETERS: op - Current parse Op
289
* result_obj - Result of the operation
290
* walk_state - Current state
291
*
292
* RETURN: Status
293
*
294
* DESCRIPTION: Used after interpretation of an opcode. If there is an internal
295
* result descriptor, check if the parent opcode will actually use
296
* this result. If not, delete the result now so that it will
297
* not become orphaned.
298
*
299
******************************************************************************/
300
301
void
302
acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
303
union acpi_operand_object *result_obj,
304
struct acpi_walk_state *walk_state)
305
{
306
union acpi_operand_object *obj_desc;
307
acpi_status status;
308
309
ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
310
311
if (!op) {
312
ACPI_ERROR((AE_INFO, "Null Op"));
313
return_VOID;
314
}
315
316
if (!result_obj) {
317
return_VOID;
318
}
319
320
if (!acpi_ds_is_result_used(op, walk_state)) {
321
322
/* Must pop the result stack (obj_desc should be equal to result_obj) */
323
324
status = acpi_ds_result_pop(&obj_desc, walk_state);
325
if (ACPI_SUCCESS(status)) {
326
acpi_ut_remove_reference(result_obj);
327
}
328
}
329
330
return_VOID;
331
}
332
333
/*******************************************************************************
334
*
335
* FUNCTION: acpi_ds_resolve_operands
336
*
337
* PARAMETERS: walk_state - Current walk state with operands on stack
338
*
339
* RETURN: Status
340
*
341
* DESCRIPTION: Resolve all operands to their values. Used to prepare
342
* arguments to a control method invocation (a call from one
343
* method to another.)
344
*
345
******************************************************************************/
346
347
acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
348
{
349
u32 i;
350
acpi_status status = AE_OK;
351
352
ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
353
354
/*
355
* Attempt to resolve each of the valid operands
356
* Method arguments are passed by reference, not by value. This means
357
* that the actual objects are passed, not copies of the objects.
358
*/
359
for (i = 0; i < walk_state->num_operands; i++) {
360
status =
361
acpi_ex_resolve_to_value(&walk_state->operands[i],
362
walk_state);
363
if (ACPI_FAILURE(status)) {
364
break;
365
}
366
}
367
368
return_ACPI_STATUS(status);
369
}
370
371
/*******************************************************************************
372
*
373
* FUNCTION: acpi_ds_clear_operands
374
*
375
* PARAMETERS: walk_state - Current walk state with operands on stack
376
*
377
* RETURN: None
378
*
379
* DESCRIPTION: Clear all operands on the current walk state operand stack.
380
*
381
******************************************************************************/
382
383
void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
384
{
385
u32 i;
386
387
ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
388
389
/* Remove a reference on each operand on the stack */
390
391
for (i = 0; i < walk_state->num_operands; i++) {
392
/*
393
* Remove a reference to all operands, including both
394
* "Arguments" and "Targets".
395
*/
396
acpi_ut_remove_reference(walk_state->operands[i]);
397
walk_state->operands[i] = NULL;
398
}
399
400
walk_state->num_operands = 0;
401
return_VOID;
402
}
403
404
/*******************************************************************************
405
*
406
* FUNCTION: acpi_ds_create_operand
407
*
408
* PARAMETERS: walk_state - Current walk state
409
* arg - Parse object for the argument
410
* arg_index - Which argument (zero based)
411
*
412
* RETURN: Status
413
*
414
* DESCRIPTION: Translate a parse tree object that is an argument to an AML
415
* opcode to the equivalent interpreter object. This may include
416
* looking up a name or entering a new name into the internal
417
* namespace.
418
*
419
******************************************************************************/
420
421
acpi_status
422
acpi_ds_create_operand(struct acpi_walk_state *walk_state,
423
union acpi_parse_object *arg, u32 arg_index)
424
{
425
acpi_status status = AE_OK;
426
char *name_string;
427
u32 name_length;
428
union acpi_operand_object *obj_desc;
429
union acpi_parse_object *parent_op;
430
u16 opcode;
431
acpi_interpreter_mode interpreter_mode;
432
const struct acpi_opcode_info *op_info;
433
434
ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
435
436
/* A valid name must be looked up in the namespace */
437
438
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
439
(arg->common.value.string) &&
440
!(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
441
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
442
arg));
443
444
/* Get the entire name string from the AML stream */
445
446
status = acpi_ex_get_name_string(ACPI_TYPE_ANY,
447
arg->common.value.buffer,
448
&name_string, &name_length);
449
450
if (ACPI_FAILURE(status)) {
451
return_ACPI_STATUS(status);
452
}
453
454
/* All prefixes have been handled, and the name is in name_string */
455
456
/*
457
* Special handling for buffer_field declarations. This is a deferred
458
* opcode that unfortunately defines the field name as the last
459
* parameter instead of the first. We get here when we are performing
460
* the deferred execution, so the actual name of the field is already
461
* in the namespace. We don't want to attempt to look it up again
462
* because we may be executing in a different scope than where the
463
* actual opcode exists.
464
*/
465
if ((walk_state->deferred_node) &&
466
(walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
467
&& (arg_index == (u32)
468
((walk_state->opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) {
469
obj_desc =
470
ACPI_CAST_PTR(union acpi_operand_object,
471
walk_state->deferred_node);
472
status = AE_OK;
473
} else { /* All other opcodes */
474
475
/*
476
* Differentiate between a namespace "create" operation
477
* versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
478
* IMODE_EXECUTE) in order to support the creation of
479
* namespace objects during the execution of control methods.
480
*/
481
parent_op = arg->common.parent;
482
op_info =
483
acpi_ps_get_opcode_info(parent_op->common.
484
aml_opcode);
485
486
if ((op_info->flags & AML_NSNODE) &&
487
(parent_op->common.aml_opcode !=
488
AML_INT_METHODCALL_OP)
489
&& (parent_op->common.aml_opcode != AML_REGION_OP)
490
&& (parent_op->common.aml_opcode !=
491
AML_INT_NAMEPATH_OP)) {
492
493
/* Enter name into namespace if not found */
494
495
interpreter_mode = ACPI_IMODE_LOAD_PASS2;
496
} else {
497
/* Return a failure if name not found */
498
499
interpreter_mode = ACPI_IMODE_EXECUTE;
500
}
501
502
status =
503
acpi_ns_lookup(walk_state->scope_info, name_string,
504
ACPI_TYPE_ANY, interpreter_mode,
505
ACPI_NS_SEARCH_PARENT |
506
ACPI_NS_DONT_OPEN_SCOPE, walk_state,
507
ACPI_CAST_INDIRECT_PTR(struct
508
acpi_namespace_node,
509
&obj_desc));
510
/*
511
* The only case where we pass through (ignore) a NOT_FOUND
512
* error is for the cond_ref_of opcode.
513
*/
514
if (status == AE_NOT_FOUND) {
515
if (parent_op->common.aml_opcode ==
516
AML_CONDITIONAL_REF_OF_OP) {
517
/*
518
* For the Conditional Reference op, it's OK if
519
* the name is not found; We just need a way to
520
* indicate this to the interpreter, set the
521
* object to the root
522
*/
523
obj_desc =
524
ACPI_CAST_PTR(union
525
acpi_operand_object,
526
acpi_gbl_root_node);
527
status = AE_OK;
528
} else if (parent_op->common.aml_opcode ==
529
AML_EXTERNAL_OP) {
530
/*
531
* This opcode should never appear here. It is used only
532
* by AML disassemblers and is surrounded by an If(0)
533
* by the ASL compiler.
534
*
535
* Therefore, if we see it here, it is a serious error.
536
*/
537
status = AE_AML_BAD_OPCODE;
538
} else {
539
/*
540
* We just plain didn't find it -- which is a
541
* very serious error at this point
542
*/
543
status = AE_AML_NAME_NOT_FOUND;
544
}
545
}
546
547
if (ACPI_FAILURE(status)) {
548
ACPI_ERROR_NAMESPACE(walk_state->scope_info,
549
name_string, status);
550
}
551
}
552
553
/* Free the namestring created above */
554
555
ACPI_FREE(name_string);
556
557
/* Check status from the lookup */
558
559
if (ACPI_FAILURE(status)) {
560
return_ACPI_STATUS(status);
561
}
562
563
/* Put the resulting object onto the current object stack */
564
565
status = acpi_ds_obj_stack_push(obj_desc, walk_state);
566
if (ACPI_FAILURE(status)) {
567
return_ACPI_STATUS(status);
568
}
569
570
acpi_db_display_argument_object(obj_desc, walk_state);
571
} else {
572
/* Check for null name case */
573
574
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
575
!(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
576
/*
577
* If the name is null, this means that this is an
578
* optional result parameter that was not specified
579
* in the original ASL. Create a Zero Constant for a
580
* placeholder. (Store to a constant is a Noop.)
581
*/
582
opcode = AML_ZERO_OP; /* Has no arguments! */
583
584
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
585
"Null namepath: Arg=%p\n", arg));
586
} else {
587
opcode = arg->common.aml_opcode;
588
}
589
590
/* Get the object type of the argument */
591
592
op_info = acpi_ps_get_opcode_info(opcode);
593
if (op_info->object_type == ACPI_TYPE_INVALID) {
594
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
595
}
596
597
if ((op_info->flags & AML_HAS_RETVAL) ||
598
(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
599
/*
600
* Use value that was already previously returned
601
* by the evaluation of this argument
602
*/
603
status = acpi_ds_result_pop(&obj_desc, walk_state);
604
if (ACPI_FAILURE(status)) {
605
/*
606
* Only error is underflow, and this indicates
607
* a missing or null operand!
608
*/
609
ACPI_EXCEPTION((AE_INFO, status,
610
"Missing or null operand"));
611
return_ACPI_STATUS(status);
612
}
613
} else {
614
/* Create an ACPI_INTERNAL_OBJECT for the argument */
615
616
obj_desc =
617
acpi_ut_create_internal_object(op_info->
618
object_type);
619
if (!obj_desc) {
620
return_ACPI_STATUS(AE_NO_MEMORY);
621
}
622
623
/* Initialize the new object */
624
625
status =
626
acpi_ds_init_object_from_op(walk_state, arg, opcode,
627
&obj_desc);
628
if (ACPI_FAILURE(status)) {
629
acpi_ut_delete_object_desc(obj_desc);
630
return_ACPI_STATUS(status);
631
}
632
}
633
634
/* Put the operand object on the object stack */
635
636
status = acpi_ds_obj_stack_push(obj_desc, walk_state);
637
if (ACPI_FAILURE(status)) {
638
return_ACPI_STATUS(status);
639
}
640
641
acpi_db_display_argument_object(obj_desc, walk_state);
642
}
643
644
return_ACPI_STATUS(AE_OK);
645
}
646
647
/*******************************************************************************
648
*
649
* FUNCTION: acpi_ds_create_operands
650
*
651
* PARAMETERS: walk_state - Current state
652
* first_arg - First argument of a parser argument tree
653
*
654
* RETURN: Status
655
*
656
* DESCRIPTION: Convert an operator's arguments from a parse tree format to
657
* namespace objects and place those argument object on the object
658
* stack in preparation for evaluation by the interpreter.
659
*
660
******************************************************************************/
661
662
acpi_status
663
acpi_ds_create_operands(struct acpi_walk_state *walk_state,
664
union acpi_parse_object *first_arg)
665
{
666
acpi_status status = AE_OK;
667
union acpi_parse_object *arg;
668
union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
669
u32 arg_count = 0;
670
u32 index = walk_state->num_operands;
671
u32 prev_num_operands = walk_state->num_operands;
672
u32 new_num_operands;
673
u32 i;
674
675
ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
676
677
/* Get all arguments in the list */
678
679
arg = first_arg;
680
while (arg) {
681
if (index >= ACPI_OBJ_NUM_OPERANDS) {
682
return_ACPI_STATUS(AE_BAD_DATA);
683
}
684
685
arguments[index] = arg;
686
walk_state->operands[index] = NULL;
687
688
/* Move on to next argument, if any */
689
690
arg = arg->common.next;
691
arg_count++;
692
index++;
693
}
694
695
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
696
"NumOperands %d, ArgCount %d, Index %d\n",
697
walk_state->num_operands, arg_count, index));
698
699
/* Create the interpreter arguments, in reverse order */
700
701
new_num_operands = index;
702
index--;
703
for (i = 0; i < arg_count; i++) {
704
arg = arguments[index];
705
walk_state->operand_index = (u8)index;
706
707
status = acpi_ds_create_operand(walk_state, arg, index);
708
if (ACPI_FAILURE(status)) {
709
goto cleanup;
710
}
711
712
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
713
"Created Arg #%u (%p) %u args total\n",
714
index, arg, arg_count));
715
index--;
716
}
717
718
return_ACPI_STATUS(status);
719
720
cleanup:
721
/*
722
* We must undo everything done above; meaning that we must
723
* pop everything off of the operand stack and delete those
724
* objects
725
*/
726
walk_state->num_operands = (u8)(i);
727
acpi_ds_obj_stack_pop_and_delete(new_num_operands, walk_state);
728
729
/* Restore operand count */
730
walk_state->num_operands = (u8)(prev_num_operands);
731
732
ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
733
return_ACPI_STATUS(status);
734
}
735
736
/*****************************************************************************
737
*
738
* FUNCTION: acpi_ds_evaluate_name_path
739
*
740
* PARAMETERS: walk_state - Current state of the parse tree walk,
741
* the opcode of current operation should be
742
* AML_INT_NAMEPATH_OP
743
*
744
* RETURN: Status
745
*
746
* DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
747
* interpreter object, convert it to value, if needed, duplicate
748
* it, if needed, and push it onto the current result stack.
749
*
750
****************************************************************************/
751
752
acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
753
{
754
acpi_status status = AE_OK;
755
union acpi_parse_object *op = walk_state->op;
756
union acpi_operand_object **operand = &walk_state->operands[0];
757
union acpi_operand_object *new_obj_desc;
758
u8 type;
759
760
ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
761
762
if (!op->common.parent) {
763
764
/* This happens after certain exception processing */
765
766
goto exit;
767
}
768
769
if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
770
(op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP) ||
771
(op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
772
773
/* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
774
775
goto exit;
776
}
777
778
status = acpi_ds_create_operand(walk_state, op, 0);
779
if (ACPI_FAILURE(status)) {
780
goto exit;
781
}
782
783
if (op->common.flags & ACPI_PARSEOP_TARGET) {
784
new_obj_desc = *operand;
785
goto push_result;
786
}
787
788
type = (*operand)->common.type;
789
790
status = acpi_ex_resolve_to_value(operand, walk_state);
791
if (ACPI_FAILURE(status)) {
792
goto exit;
793
}
794
795
if (type == ACPI_TYPE_INTEGER) {
796
797
/* It was incremented by acpi_ex_resolve_to_value */
798
799
acpi_ut_remove_reference(*operand);
800
801
status =
802
acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
803
walk_state);
804
if (ACPI_FAILURE(status)) {
805
goto exit;
806
}
807
} else {
808
/*
809
* The object either was anew created or is
810
* a Namespace node - don't decrement it.
811
*/
812
new_obj_desc = *operand;
813
}
814
815
/* Cleanup for name-path operand */
816
817
status = acpi_ds_obj_stack_pop(1, walk_state);
818
if (ACPI_FAILURE(status)) {
819
walk_state->result_obj = new_obj_desc;
820
goto exit;
821
}
822
823
push_result:
824
825
walk_state->result_obj = new_obj_desc;
826
827
status = acpi_ds_result_push(walk_state->result_obj, walk_state);
828
if (ACPI_SUCCESS(status)) {
829
830
/* Force to take it from stack */
831
832
op->common.flags |= ACPI_PARSEOP_IN_STACK;
833
}
834
835
exit:
836
837
return_ACPI_STATUS(status);
838
}
839
840