1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: dswexec - Dispatcher method execution callbacks; |
5 | * dispatch to interpreter. |
6 | * |
7 | * Copyright (C) 2000 - 2023, Intel Corp. |
8 | * |
9 | *****************************************************************************/ |
10 | |
11 | #include <acpi/acpi.h> |
12 | #include "accommon.h" |
13 | #include "acparser.h" |
14 | #include "amlcode.h" |
15 | #include "acdispat.h" |
16 | #include "acinterp.h" |
17 | #include "acnamesp.h" |
18 | #include "acdebug.h" |
19 | #ifdef ACPI_EXEC_APP |
20 | #include "aecommon.h" |
21 | #endif |
22 | |
23 | #define _COMPONENT ACPI_DISPATCHER |
24 | ACPI_MODULE_NAME("dswexec" ) |
25 | |
26 | /* |
27 | * Dispatch table for opcode classes |
28 | */ |
29 | static acpi_execute_op acpi_gbl_op_type_dispatch[] = { |
30 | acpi_ex_opcode_0A_0T_1R, |
31 | acpi_ex_opcode_1A_0T_0R, |
32 | acpi_ex_opcode_1A_0T_1R, |
33 | NULL, /* Was: acpi_ex_opcode_1A_0T_0R (Was for Load operator) */ |
34 | acpi_ex_opcode_1A_1T_1R, |
35 | acpi_ex_opcode_2A_0T_0R, |
36 | acpi_ex_opcode_2A_0T_1R, |
37 | acpi_ex_opcode_2A_1T_1R, |
38 | acpi_ex_opcode_2A_2T_1R, |
39 | acpi_ex_opcode_3A_0T_0R, |
40 | acpi_ex_opcode_3A_1T_1R, |
41 | acpi_ex_opcode_6A_0T_1R |
42 | }; |
43 | |
44 | /***************************************************************************** |
45 | * |
46 | * FUNCTION: acpi_ds_get_predicate_value |
47 | * |
48 | * PARAMETERS: walk_state - Current state of the parse tree walk |
49 | * result_obj - if non-zero, pop result from result stack |
50 | * |
51 | * RETURN: Status |
52 | * |
53 | * DESCRIPTION: Get the result of a predicate evaluation |
54 | * |
55 | ****************************************************************************/ |
56 | |
57 | acpi_status |
58 | acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, |
59 | union acpi_operand_object *result_obj) |
60 | { |
61 | acpi_status status = AE_OK; |
62 | union acpi_operand_object *obj_desc; |
63 | union acpi_operand_object *local_obj_desc = NULL; |
64 | |
65 | ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state); |
66 | |
67 | walk_state->control_state->common.state = 0; |
68 | |
69 | if (result_obj) { |
70 | status = acpi_ds_result_pop(object: &obj_desc, walk_state); |
71 | if (ACPI_FAILURE(status)) { |
72 | ACPI_EXCEPTION((AE_INFO, status, |
73 | "Could not get result from predicate evaluation" )); |
74 | |
75 | return_ACPI_STATUS(status); |
76 | } |
77 | } else { |
78 | status = acpi_ds_create_operand(walk_state, arg: walk_state->op, args_remaining: 0); |
79 | if (ACPI_FAILURE(status)) { |
80 | return_ACPI_STATUS(status); |
81 | } |
82 | |
83 | status = |
84 | acpi_ex_resolve_to_value(stack_ptr: &walk_state->operands[0], |
85 | walk_state); |
86 | if (ACPI_FAILURE(status)) { |
87 | return_ACPI_STATUS(status); |
88 | } |
89 | |
90 | obj_desc = walk_state->operands[0]; |
91 | } |
92 | |
93 | if (!obj_desc) { |
94 | ACPI_ERROR((AE_INFO, |
95 | "No predicate ObjDesc=%p State=%p" , |
96 | obj_desc, walk_state)); |
97 | |
98 | return_ACPI_STATUS(AE_AML_NO_OPERAND); |
99 | } |
100 | |
101 | /* |
102 | * Result of predicate evaluation must be an Integer |
103 | * object. Implicitly convert the argument if necessary. |
104 | */ |
105 | status = acpi_ex_convert_to_integer(obj_desc, result_desc: &local_obj_desc, |
106 | ACPI_IMPLICIT_CONVERSION); |
107 | if (ACPI_FAILURE(status)) { |
108 | goto cleanup; |
109 | } |
110 | |
111 | if (local_obj_desc->common.type != ACPI_TYPE_INTEGER) { |
112 | ACPI_ERROR((AE_INFO, |
113 | "Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X" , |
114 | obj_desc, walk_state, obj_desc->common.type)); |
115 | |
116 | status = AE_AML_OPERAND_TYPE; |
117 | goto cleanup; |
118 | } |
119 | |
120 | /* Truncate the predicate to 32-bits if necessary */ |
121 | |
122 | (void)acpi_ex_truncate_for32bit_table(obj_desc: local_obj_desc); |
123 | |
124 | /* |
125 | * Save the result of the predicate evaluation on |
126 | * the control stack |
127 | */ |
128 | if (local_obj_desc->integer.value) { |
129 | walk_state->control_state->common.value = TRUE; |
130 | } else { |
131 | /* |
132 | * Predicate is FALSE, we will just toss the |
133 | * rest of the package |
134 | */ |
135 | walk_state->control_state->common.value = FALSE; |
136 | status = AE_CTRL_FALSE; |
137 | } |
138 | |
139 | /* Predicate can be used for an implicit return value */ |
140 | |
141 | (void)acpi_ds_do_implicit_return(return_desc: local_obj_desc, walk_state, TRUE); |
142 | |
143 | cleanup: |
144 | |
145 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
146 | "Completed a predicate eval=%X Op=%p\n" , |
147 | walk_state->control_state->common.value, |
148 | walk_state->op)); |
149 | |
150 | /* Break to debugger to display result */ |
151 | |
152 | acpi_db_display_result_object(obj_desc: local_obj_desc, walk_state); |
153 | |
154 | /* |
155 | * Delete the predicate result object (we know that |
156 | * we don't need it anymore) |
157 | */ |
158 | if (local_obj_desc != obj_desc) { |
159 | acpi_ut_remove_reference(object: local_obj_desc); |
160 | } |
161 | acpi_ut_remove_reference(object: obj_desc); |
162 | |
163 | walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; |
164 | return_ACPI_STATUS(status); |
165 | } |
166 | |
167 | /***************************************************************************** |
168 | * |
169 | * FUNCTION: acpi_ds_exec_begin_op |
170 | * |
171 | * PARAMETERS: walk_state - Current state of the parse tree walk |
172 | * out_op - Where to return op if a new one is created |
173 | * |
174 | * RETURN: Status |
175 | * |
176 | * DESCRIPTION: Descending callback used during the execution of control |
177 | * methods. This is where most operators and operands are |
178 | * dispatched to the interpreter. |
179 | * |
180 | ****************************************************************************/ |
181 | |
182 | acpi_status |
183 | acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, |
184 | union acpi_parse_object **out_op) |
185 | { |
186 | union acpi_parse_object *op; |
187 | acpi_status status = AE_OK; |
188 | u32 opcode_class; |
189 | |
190 | ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state); |
191 | |
192 | op = walk_state->op; |
193 | if (!op) { |
194 | status = acpi_ds_load2_begin_op(walk_state, out_op); |
195 | if (ACPI_FAILURE(status)) { |
196 | goto error_exit; |
197 | } |
198 | |
199 | op = *out_op; |
200 | walk_state->op = op; |
201 | walk_state->opcode = op->common.aml_opcode; |
202 | walk_state->op_info = |
203 | acpi_ps_get_opcode_info(opcode: op->common.aml_opcode); |
204 | |
205 | if (acpi_ns_opens_scope(type: walk_state->op_info->object_type)) { |
206 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
207 | "(%s) Popping scope for Op %p\n" , |
208 | acpi_ut_get_type_name(walk_state-> |
209 | op_info-> |
210 | object_type), |
211 | op)); |
212 | |
213 | status = acpi_ds_scope_stack_pop(walk_state); |
214 | if (ACPI_FAILURE(status)) { |
215 | goto error_exit; |
216 | } |
217 | } |
218 | } |
219 | |
220 | if (op == walk_state->origin) { |
221 | if (out_op) { |
222 | *out_op = op; |
223 | } |
224 | |
225 | return_ACPI_STATUS(AE_OK); |
226 | } |
227 | |
228 | /* |
229 | * If the previous opcode was a conditional, this opcode |
230 | * must be the beginning of the associated predicate. |
231 | * Save this knowledge in the current scope descriptor |
232 | */ |
233 | if ((walk_state->control_state) && |
234 | (walk_state->control_state->common.state == |
235 | ACPI_CONTROL_CONDITIONAL_EXECUTING)) { |
236 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
237 | "Exec predicate Op=%p State=%p\n" , |
238 | op, walk_state)); |
239 | |
240 | walk_state->control_state->common.state = |
241 | ACPI_CONTROL_PREDICATE_EXECUTING; |
242 | |
243 | /* Save start of predicate */ |
244 | |
245 | walk_state->control_state->control.predicate_op = op; |
246 | } |
247 | |
248 | opcode_class = walk_state->op_info->class; |
249 | |
250 | /* We want to send namepaths to the load code */ |
251 | |
252 | if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { |
253 | opcode_class = AML_CLASS_NAMED_OBJECT; |
254 | } |
255 | |
256 | /* |
257 | * Handle the opcode based upon the opcode type |
258 | */ |
259 | switch (opcode_class) { |
260 | case AML_CLASS_CONTROL: |
261 | |
262 | status = acpi_ds_exec_begin_control_op(walk_state, op); |
263 | break; |
264 | |
265 | case AML_CLASS_NAMED_OBJECT: |
266 | |
267 | if (walk_state->walk_type & ACPI_WALK_METHOD) { |
268 | /* |
269 | * Found a named object declaration during method execution; |
270 | * we must enter this object into the namespace. The created |
271 | * object is temporary and will be deleted upon completion of |
272 | * the execution of this method. |
273 | * |
274 | * Note 10/2010: Except for the Scope() op. This opcode does |
275 | * not actually create a new object, it refers to an existing |
276 | * object. However, for Scope(), we want to indeed open a |
277 | * new scope. |
278 | */ |
279 | if (op->common.aml_opcode != AML_SCOPE_OP) { |
280 | status = |
281 | acpi_ds_load2_begin_op(walk_state, NULL); |
282 | } else { |
283 | status = |
284 | acpi_ds_scope_stack_push(node: op->named.node, |
285 | type: op->named.node-> |
286 | type, walk_state); |
287 | if (ACPI_FAILURE(status)) { |
288 | return_ACPI_STATUS(status); |
289 | } |
290 | } |
291 | } |
292 | break; |
293 | |
294 | case AML_CLASS_EXECUTE: |
295 | case AML_CLASS_CREATE: |
296 | |
297 | break; |
298 | |
299 | default: |
300 | |
301 | break; |
302 | } |
303 | |
304 | /* Nothing to do here during method execution */ |
305 | |
306 | return_ACPI_STATUS(status); |
307 | |
308 | error_exit: |
309 | status = acpi_ds_method_error(status, walk_state); |
310 | return_ACPI_STATUS(status); |
311 | } |
312 | |
313 | /***************************************************************************** |
314 | * |
315 | * FUNCTION: acpi_ds_exec_end_op |
316 | * |
317 | * PARAMETERS: walk_state - Current state of the parse tree walk |
318 | * |
319 | * RETURN: Status |
320 | * |
321 | * DESCRIPTION: Ascending callback used during the execution of control |
322 | * methods. The only thing we really need to do here is to |
323 | * notice the beginning of IF, ELSE, and WHILE blocks. |
324 | * |
325 | ****************************************************************************/ |
326 | |
327 | acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) |
328 | { |
329 | union acpi_parse_object *op; |
330 | acpi_status status = AE_OK; |
331 | u32 op_type; |
332 | u32 op_class; |
333 | union acpi_parse_object *next_op; |
334 | union acpi_parse_object *first_arg; |
335 | #ifdef ACPI_EXEC_APP |
336 | char *namepath; |
337 | union acpi_operand_object *obj_desc; |
338 | #endif |
339 | |
340 | ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state); |
341 | |
342 | op = walk_state->op; |
343 | op_type = walk_state->op_info->type; |
344 | op_class = walk_state->op_info->class; |
345 | |
346 | if (op_class == AML_CLASS_UNKNOWN) { |
347 | ACPI_ERROR((AE_INFO, "Unknown opcode 0x%X" , |
348 | op->common.aml_opcode)); |
349 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); |
350 | } |
351 | |
352 | first_arg = op->common.value.arg; |
353 | |
354 | /* Init the walk state */ |
355 | |
356 | walk_state->num_operands = 0; |
357 | walk_state->operand_index = 0; |
358 | walk_state->return_desc = NULL; |
359 | walk_state->result_obj = NULL; |
360 | |
361 | /* Call debugger for single step support (DEBUG build only) */ |
362 | |
363 | status = acpi_db_single_step(walk_state, op, op_type: op_class); |
364 | if (ACPI_FAILURE(status)) { |
365 | return_ACPI_STATUS(status); |
366 | } |
367 | |
368 | /* Decode the Opcode Class */ |
369 | |
370 | switch (op_class) { |
371 | case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ |
372 | |
373 | if (walk_state->opcode == AML_INT_NAMEPATH_OP) { |
374 | status = acpi_ds_evaluate_name_path(walk_state); |
375 | if (ACPI_FAILURE(status)) { |
376 | goto cleanup; |
377 | } |
378 | } |
379 | break; |
380 | |
381 | case AML_CLASS_EXECUTE: /* Most operators with arguments */ |
382 | |
383 | /* Build resolved operand stack */ |
384 | |
385 | status = acpi_ds_create_operands(walk_state, first_arg); |
386 | if (ACPI_FAILURE(status)) { |
387 | goto cleanup; |
388 | } |
389 | |
390 | /* |
391 | * All opcodes require operand resolution, with the only exceptions |
392 | * being the object_type and size_of operators as well as opcodes that |
393 | * take no arguments. |
394 | */ |
395 | if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE) && |
396 | (walk_state->op_info->flags & AML_HAS_ARGS)) { |
397 | |
398 | /* Resolve all operands */ |
399 | |
400 | status = acpi_ex_resolve_operands(opcode: walk_state->opcode, |
401 | stack_ptr: &(walk_state-> |
402 | operands |
403 | [walk_state-> |
404 | num_operands - 1]), |
405 | walk_state); |
406 | } |
407 | |
408 | if (ACPI_SUCCESS(status)) { |
409 | /* |
410 | * Dispatch the request to the appropriate interpreter handler |
411 | * routine. There is one routine per opcode "type" based upon the |
412 | * number of opcode arguments and return type. |
413 | */ |
414 | status = |
415 | acpi_gbl_op_type_dispatch[op_type] (walk_state); |
416 | } else { |
417 | /* |
418 | * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the |
419 | * Local is uninitialized. |
420 | */ |
421 | if ((status == AE_AML_UNINITIALIZED_LOCAL) && |
422 | (walk_state->opcode == AML_STORE_OP) && |
423 | (walk_state->operands[0]->common.type == |
424 | ACPI_TYPE_LOCAL_REFERENCE) |
425 | && (walk_state->operands[1]->common.type == |
426 | ACPI_TYPE_LOCAL_REFERENCE) |
427 | && (walk_state->operands[0]->reference.class == |
428 | walk_state->operands[1]->reference.class) |
429 | && (walk_state->operands[0]->reference.value == |
430 | walk_state->operands[1]->reference.value)) { |
431 | status = AE_OK; |
432 | } else { |
433 | ACPI_EXCEPTION((AE_INFO, status, |
434 | "While resolving operands for [%s]" , |
435 | acpi_ps_get_opcode_name |
436 | (walk_state->opcode))); |
437 | } |
438 | } |
439 | |
440 | /* Always delete the argument objects and clear the operand stack */ |
441 | |
442 | acpi_ds_clear_operands(walk_state); |
443 | |
444 | /* |
445 | * If a result object was returned from above, push it on the |
446 | * current result stack |
447 | */ |
448 | if (ACPI_SUCCESS(status) && walk_state->result_obj) { |
449 | status = |
450 | acpi_ds_result_push(object: walk_state->result_obj, |
451 | walk_state); |
452 | } |
453 | break; |
454 | |
455 | default: |
456 | |
457 | switch (op_type) { |
458 | case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ |
459 | |
460 | /* 1 Operand, 0 external_result, 0 internal_result */ |
461 | |
462 | status = acpi_ds_exec_end_control_op(walk_state, op); |
463 | |
464 | break; |
465 | |
466 | case AML_TYPE_METHOD_CALL: |
467 | /* |
468 | * If the method is referenced from within a package |
469 | * declaration, it is not a invocation of the method, just |
470 | * a reference to it. |
471 | */ |
472 | if ((op->asl.parent) && |
473 | ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) |
474 | || (op->asl.parent->asl.aml_opcode == |
475 | AML_VARIABLE_PACKAGE_OP))) { |
476 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
477 | "Method Reference in a Package, Op=%p\n" , |
478 | op)); |
479 | |
480 | op->common.node = (struct acpi_namespace_node *) |
481 | op->asl.value.arg->asl.node; |
482 | acpi_ut_add_reference(object: op->asl.value.arg->asl. |
483 | node->object); |
484 | return_ACPI_STATUS(AE_OK); |
485 | } |
486 | |
487 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
488 | "Method invocation, Op=%p\n" , op)); |
489 | |
490 | /* |
491 | * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains |
492 | * the method Node pointer |
493 | */ |
494 | /* next_op points to the op that holds the method name */ |
495 | |
496 | next_op = first_arg; |
497 | |
498 | /* next_op points to first argument op */ |
499 | |
500 | next_op = next_op->common.next; |
501 | |
502 | /* |
503 | * Get the method's arguments and put them on the operand stack |
504 | */ |
505 | status = acpi_ds_create_operands(walk_state, first_arg: next_op); |
506 | if (ACPI_FAILURE(status)) { |
507 | break; |
508 | } |
509 | |
510 | /* |
511 | * Since the operands will be passed to another control method, |
512 | * we must resolve all local references here (Local variables, |
513 | * arguments to *this* method, etc.) |
514 | */ |
515 | status = acpi_ds_resolve_operands(walk_state); |
516 | if (ACPI_FAILURE(status)) { |
517 | |
518 | /* On error, clear all resolved operands */ |
519 | |
520 | acpi_ds_clear_operands(walk_state); |
521 | break; |
522 | } |
523 | |
524 | /* |
525 | * Tell the walk loop to preempt this running method and |
526 | * execute the new method |
527 | */ |
528 | status = AE_CTRL_TRANSFER; |
529 | |
530 | /* |
531 | * Return now; we don't want to disturb anything, |
532 | * especially the operand count! |
533 | */ |
534 | return_ACPI_STATUS(status); |
535 | |
536 | case AML_TYPE_CREATE_FIELD: |
537 | |
538 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
539 | "Executing CreateField Buffer/Index Op=%p\n" , |
540 | op)); |
541 | |
542 | status = acpi_ds_load2_end_op(walk_state); |
543 | if (ACPI_FAILURE(status)) { |
544 | break; |
545 | } |
546 | |
547 | status = |
548 | acpi_ds_eval_buffer_field_operands(walk_state, op); |
549 | if (ACPI_FAILURE(status)) { |
550 | break; |
551 | } |
552 | #ifdef ACPI_EXEC_APP |
553 | /* |
554 | * acpi_exec support for namespace initialization file (initialize |
555 | * buffer_fields in this code.) |
556 | */ |
557 | namepath = |
558 | acpi_ns_get_external_pathname(op->common.node); |
559 | status = ae_lookup_init_file_entry(namepath, &obj_desc); |
560 | if (ACPI_SUCCESS(status)) { |
561 | status = |
562 | acpi_ex_write_data_to_field(obj_desc, |
563 | op->common. |
564 | node->object, |
565 | NULL); |
566 | if (ACPI_FAILURE(status)) { |
567 | ACPI_EXCEPTION((AE_INFO, status, |
568 | "While writing to buffer field" )); |
569 | } |
570 | } |
571 | ACPI_FREE(namepath); |
572 | status = AE_OK; |
573 | #endif |
574 | break; |
575 | |
576 | case AML_TYPE_CREATE_OBJECT: |
577 | |
578 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
579 | "Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n" , |
580 | op, op->named.value.arg, |
581 | op->common.parent->common. |
582 | aml_opcode)); |
583 | |
584 | switch (op->common.parent->common.aml_opcode) { |
585 | case AML_NAME_OP: |
586 | /* |
587 | * Put the Node on the object stack (Contains the ACPI Name |
588 | * of this object) |
589 | */ |
590 | walk_state->operands[0] = (void *) |
591 | op->common.parent->common.node; |
592 | walk_state->num_operands = 1; |
593 | |
594 | status = acpi_ds_create_node(walk_state, |
595 | node: op->common.parent-> |
596 | common.node, |
597 | op: op->common.parent); |
598 | if (ACPI_FAILURE(status)) { |
599 | break; |
600 | } |
601 | |
602 | ACPI_FALLTHROUGH; |
603 | |
604 | case AML_INT_EVAL_SUBTREE_OP: |
605 | |
606 | status = |
607 | acpi_ds_eval_data_object_operands |
608 | (walk_state, op, |
609 | obj_desc: acpi_ns_get_attached_object(node: op->common. |
610 | parent->common. |
611 | node)); |
612 | break; |
613 | |
614 | default: |
615 | |
616 | status = |
617 | acpi_ds_eval_data_object_operands |
618 | (walk_state, op, NULL); |
619 | break; |
620 | } |
621 | |
622 | /* |
623 | * If a result object was returned from above, push it on the |
624 | * current result stack |
625 | */ |
626 | if (walk_state->result_obj) { |
627 | status = |
628 | acpi_ds_result_push(object: walk_state->result_obj, |
629 | walk_state); |
630 | } |
631 | break; |
632 | |
633 | case AML_TYPE_NAMED_FIELD: |
634 | case AML_TYPE_NAMED_COMPLEX: |
635 | case AML_TYPE_NAMED_SIMPLE: |
636 | case AML_TYPE_NAMED_NO_OBJ: |
637 | |
638 | status = acpi_ds_load2_end_op(walk_state); |
639 | if (ACPI_FAILURE(status)) { |
640 | break; |
641 | } |
642 | |
643 | if (op->common.aml_opcode == AML_REGION_OP) { |
644 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
645 | "Executing OpRegion Address/Length Op=%p\n" , |
646 | op)); |
647 | |
648 | status = |
649 | acpi_ds_eval_region_operands(walk_state, |
650 | op); |
651 | if (ACPI_FAILURE(status)) { |
652 | break; |
653 | } |
654 | } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { |
655 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
656 | "Executing DataTableRegion Strings Op=%p\n" , |
657 | op)); |
658 | |
659 | status = |
660 | acpi_ds_eval_table_region_operands |
661 | (walk_state, op); |
662 | if (ACPI_FAILURE(status)) { |
663 | break; |
664 | } |
665 | } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { |
666 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
667 | "Executing BankField Op=%p\n" , |
668 | op)); |
669 | |
670 | status = |
671 | acpi_ds_eval_bank_field_operands(walk_state, |
672 | op); |
673 | if (ACPI_FAILURE(status)) { |
674 | break; |
675 | } |
676 | } |
677 | break; |
678 | |
679 | case AML_TYPE_UNDEFINED: |
680 | |
681 | ACPI_ERROR((AE_INFO, |
682 | "Undefined opcode type Op=%p" , op)); |
683 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); |
684 | |
685 | case AML_TYPE_BOGUS: |
686 | |
687 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
688 | "Internal opcode=%X type Op=%p\n" , |
689 | walk_state->opcode, op)); |
690 | break; |
691 | |
692 | default: |
693 | |
694 | ACPI_ERROR((AE_INFO, |
695 | "Unimplemented opcode, class=0x%X " |
696 | "type=0x%X Opcode=0x%X Op=%p" , |
697 | op_class, op_type, op->common.aml_opcode, |
698 | op)); |
699 | |
700 | status = AE_NOT_IMPLEMENTED; |
701 | break; |
702 | } |
703 | } |
704 | |
705 | /* |
706 | * ACPI 2.0 support for 64-bit integers: Truncate numeric |
707 | * result value if we are executing from a 32-bit ACPI table |
708 | */ |
709 | (void)acpi_ex_truncate_for32bit_table(obj_desc: walk_state->result_obj); |
710 | |
711 | /* |
712 | * Check if we just completed the evaluation of a |
713 | * conditional predicate |
714 | */ |
715 | if ((ACPI_SUCCESS(status)) && |
716 | (walk_state->control_state) && |
717 | (walk_state->control_state->common.state == |
718 | ACPI_CONTROL_PREDICATE_EXECUTING) && |
719 | (walk_state->control_state->control.predicate_op == op)) { |
720 | status = |
721 | acpi_ds_get_predicate_value(walk_state, |
722 | result_obj: walk_state->result_obj); |
723 | walk_state->result_obj = NULL; |
724 | } |
725 | |
726 | cleanup: |
727 | |
728 | if (walk_state->result_obj) { |
729 | |
730 | /* Break to debugger to display result */ |
731 | |
732 | acpi_db_display_result_object(obj_desc: walk_state->result_obj, |
733 | walk_state); |
734 | |
735 | /* |
736 | * Delete the result op if and only if: |
737 | * Parent will not use the result -- such as any |
738 | * non-nested type2 op in a method (parent will be method) |
739 | */ |
740 | acpi_ds_delete_result_if_not_used(op, result_obj: walk_state->result_obj, |
741 | walk_state); |
742 | } |
743 | #ifdef _UNDER_DEVELOPMENT |
744 | |
745 | if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) { |
746 | acpi_db_method_end(walk_state); |
747 | } |
748 | #endif |
749 | |
750 | /* Invoke exception handler on error */ |
751 | |
752 | if (ACPI_FAILURE(status)) { |
753 | status = acpi_ds_method_error(status, walk_state); |
754 | } |
755 | |
756 | /* Always clear the object stack */ |
757 | |
758 | walk_state->num_operands = 0; |
759 | return_ACPI_STATUS(status); |
760 | } |
761 | |