0001
0002
0003
0004
0005
0006
0007
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 #include "acparser.h"
0011 #include "amlcode.h"
0012 #include "acdispat.h"
0013 #include "acinterp.h"
0014 #include "acnamesp.h"
0015 #include "acdebug.h"
0016
0017 #define _COMPONENT ACPI_DISPATCHER
0018 ACPI_MODULE_NAME("dsutils")
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
0035 {
0036 ACPI_FUNCTION_NAME(ds_clear_implicit_return);
0037
0038
0039
0040
0041 if (!acpi_gbl_enable_interpreter_slack) {
0042 return;
0043 }
0044
0045 if (walk_state->implicit_return_obj) {
0046
0047
0048
0049
0050
0051 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0052 "Removing reference on stale implicit return obj %p\n",
0053 walk_state->implicit_return_obj));
0054
0055 acpi_ut_remove_reference(walk_state->implicit_return_obj);
0056 walk_state->implicit_return_obj = NULL;
0057 }
0058 }
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 u8
0079 acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
0080 struct acpi_walk_state *walk_state, u8 add_reference)
0081 {
0082 ACPI_FUNCTION_NAME(ds_do_implicit_return);
0083
0084
0085
0086
0087
0088 if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
0089 return (FALSE);
0090 }
0091
0092 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0093 "Result %p will be implicitly returned; Prev=%p\n",
0094 return_desc, walk_state->implicit_return_obj));
0095
0096
0097
0098
0099
0100
0101
0102 if (walk_state->implicit_return_obj) {
0103 if (walk_state->implicit_return_obj == return_desc) {
0104 return (TRUE);
0105 }
0106 acpi_ds_clear_implicit_return(walk_state);
0107 }
0108
0109
0110
0111 walk_state->implicit_return_obj = return_desc;
0112 if (add_reference) {
0113 acpi_ut_add_reference(return_desc);
0114 }
0115
0116 return (TRUE);
0117 }
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 u8
0133 acpi_ds_is_result_used(union acpi_parse_object * op,
0134 struct acpi_walk_state * walk_state)
0135 {
0136 const struct acpi_opcode_info *parent_info;
0137
0138 ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
0139
0140
0141
0142 if (!op) {
0143 ACPI_ERROR((AE_INFO, "Null Op"));
0144 return_UINT8(TRUE);
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
0157 TRUE);
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 if ((!op->common.parent) ||
0168 (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
0169
0170
0171
0172 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0173 "At Method level, result of [%s] not used\n",
0174 acpi_ps_get_opcode_name(op->common.
0175 aml_opcode)));
0176 return_UINT8(FALSE);
0177 }
0178
0179
0180
0181 parent_info =
0182 acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
0183 if (parent_info->class == AML_CLASS_UNKNOWN) {
0184 ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
0185 return_UINT8(FALSE);
0186 }
0187
0188
0189
0190
0191
0192
0193
0194 switch (parent_info->class) {
0195 case AML_CLASS_CONTROL:
0196
0197 switch (op->common.parent->common.aml_opcode) {
0198 case AML_RETURN_OP:
0199
0200
0201
0202 goto result_used;
0203
0204 case AML_IF_OP:
0205 case AML_WHILE_OP:
0206
0207
0208
0209
0210 if ((walk_state->control_state->common.state ==
0211 ACPI_CONTROL_PREDICATE_EXECUTING) &&
0212 (walk_state->control_state->control.predicate_op ==
0213 op)) {
0214 goto result_used;
0215 }
0216 break;
0217
0218 default:
0219
0220
0221
0222 break;
0223 }
0224
0225
0226
0227 goto result_not_used;
0228
0229 case AML_CLASS_CREATE:
0230
0231
0232
0233
0234 goto result_used;
0235
0236 case AML_CLASS_NAMED_OBJECT:
0237
0238 if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
0239 (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
0240 || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
0241 || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
0242 || (op->common.parent->common.aml_opcode ==
0243 AML_VARIABLE_PACKAGE_OP)
0244 || (op->common.parent->common.aml_opcode ==
0245 AML_INT_EVAL_SUBTREE_OP)
0246 || (op->common.parent->common.aml_opcode ==
0247 AML_BANK_FIELD_OP)) {
0248
0249
0250
0251
0252 goto result_used;
0253 }
0254
0255 goto result_not_used;
0256
0257 default:
0258
0259
0260
0261
0262 goto result_used;
0263 }
0264
0265 result_used:
0266 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0267 "Result of [%s] used by Parent [%s] Op=%p\n",
0268 acpi_ps_get_opcode_name(op->common.aml_opcode),
0269 acpi_ps_get_opcode_name(op->common.parent->common.
0270 aml_opcode), op));
0271
0272 return_UINT8(TRUE);
0273
0274 result_not_used:
0275 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0276 "Result of [%s] not used by Parent [%s] Op=%p\n",
0277 acpi_ps_get_opcode_name(op->common.aml_opcode),
0278 acpi_ps_get_opcode_name(op->common.parent->common.
0279 aml_opcode), op));
0280
0281 return_UINT8(FALSE);
0282 }
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 void
0302 acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
0303 union acpi_operand_object *result_obj,
0304 struct acpi_walk_state *walk_state)
0305 {
0306 union acpi_operand_object *obj_desc;
0307 acpi_status status;
0308
0309 ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
0310
0311 if (!op) {
0312 ACPI_ERROR((AE_INFO, "Null Op"));
0313 return_VOID;
0314 }
0315
0316 if (!result_obj) {
0317 return_VOID;
0318 }
0319
0320 if (!acpi_ds_is_result_used(op, walk_state)) {
0321
0322
0323
0324 status = acpi_ds_result_pop(&obj_desc, walk_state);
0325 if (ACPI_SUCCESS(status)) {
0326 acpi_ut_remove_reference(result_obj);
0327 }
0328 }
0329
0330 return_VOID;
0331 }
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347 acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
0348 {
0349 u32 i;
0350 acpi_status status = AE_OK;
0351
0352 ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
0353
0354
0355
0356
0357
0358
0359 for (i = 0; i < walk_state->num_operands; i++) {
0360 status =
0361 acpi_ex_resolve_to_value(&walk_state->operands[i],
0362 walk_state);
0363 if (ACPI_FAILURE(status)) {
0364 break;
0365 }
0366 }
0367
0368 return_ACPI_STATUS(status);
0369 }
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
0384 {
0385 u32 i;
0386
0387 ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
0388
0389
0390
0391 for (i = 0; i < walk_state->num_operands; i++) {
0392
0393
0394
0395
0396 acpi_ut_remove_reference(walk_state->operands[i]);
0397 walk_state->operands[i] = NULL;
0398 }
0399
0400 walk_state->num_operands = 0;
0401 return_VOID;
0402 }
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421 acpi_status
0422 acpi_ds_create_operand(struct acpi_walk_state *walk_state,
0423 union acpi_parse_object *arg, u32 arg_index)
0424 {
0425 acpi_status status = AE_OK;
0426 char *name_string;
0427 u32 name_length;
0428 union acpi_operand_object *obj_desc;
0429 union acpi_parse_object *parent_op;
0430 u16 opcode;
0431 acpi_interpreter_mode interpreter_mode;
0432 const struct acpi_opcode_info *op_info;
0433
0434 ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
0435
0436
0437
0438 if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
0439 (arg->common.value.string) &&
0440 !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
0441 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
0442 arg));
0443
0444
0445
0446 status = acpi_ex_get_name_string(ACPI_TYPE_ANY,
0447 arg->common.value.buffer,
0448 &name_string, &name_length);
0449
0450 if (ACPI_FAILURE(status)) {
0451 return_ACPI_STATUS(status);
0452 }
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465 if ((walk_state->deferred_node) &&
0466 (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
0467 && (arg_index == (u32)
0468 ((walk_state->opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) {
0469 obj_desc =
0470 ACPI_CAST_PTR(union acpi_operand_object,
0471 walk_state->deferred_node);
0472 status = AE_OK;
0473 } else {
0474
0475
0476
0477
0478
0479
0480
0481 parent_op = arg->common.parent;
0482 op_info =
0483 acpi_ps_get_opcode_info(parent_op->common.
0484 aml_opcode);
0485
0486 if ((op_info->flags & AML_NSNODE) &&
0487 (parent_op->common.aml_opcode !=
0488 AML_INT_METHODCALL_OP)
0489 && (parent_op->common.aml_opcode != AML_REGION_OP)
0490 && (parent_op->common.aml_opcode !=
0491 AML_INT_NAMEPATH_OP)) {
0492
0493
0494
0495 interpreter_mode = ACPI_IMODE_LOAD_PASS2;
0496 } else {
0497
0498
0499 interpreter_mode = ACPI_IMODE_EXECUTE;
0500 }
0501
0502 status =
0503 acpi_ns_lookup(walk_state->scope_info, name_string,
0504 ACPI_TYPE_ANY, interpreter_mode,
0505 ACPI_NS_SEARCH_PARENT |
0506 ACPI_NS_DONT_OPEN_SCOPE, walk_state,
0507 ACPI_CAST_INDIRECT_PTR(struct
0508 acpi_namespace_node,
0509 &obj_desc));
0510
0511
0512
0513
0514 if (status == AE_NOT_FOUND) {
0515 if (parent_op->common.aml_opcode ==
0516 AML_CONDITIONAL_REF_OF_OP) {
0517
0518
0519
0520
0521
0522
0523 obj_desc =
0524 ACPI_CAST_PTR(union
0525 acpi_operand_object,
0526 acpi_gbl_root_node);
0527 status = AE_OK;
0528 } else if (parent_op->common.aml_opcode ==
0529 AML_EXTERNAL_OP) {
0530
0531
0532
0533
0534
0535
0536
0537 status = AE_AML_BAD_OPCODE;
0538 } else {
0539
0540
0541
0542
0543 status = AE_AML_NAME_NOT_FOUND;
0544 }
0545 }
0546
0547 if (ACPI_FAILURE(status)) {
0548 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0549 name_string, status);
0550 }
0551 }
0552
0553
0554
0555 ACPI_FREE(name_string);
0556
0557
0558
0559 if (ACPI_FAILURE(status)) {
0560 return_ACPI_STATUS(status);
0561 }
0562
0563
0564
0565 status = acpi_ds_obj_stack_push(obj_desc, walk_state);
0566 if (ACPI_FAILURE(status)) {
0567 return_ACPI_STATUS(status);
0568 }
0569
0570 acpi_db_display_argument_object(obj_desc, walk_state);
0571 } else {
0572
0573
0574 if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
0575 !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
0576
0577
0578
0579
0580
0581
0582 opcode = AML_ZERO_OP;
0583
0584 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0585 "Null namepath: Arg=%p\n", arg));
0586 } else {
0587 opcode = arg->common.aml_opcode;
0588 }
0589
0590
0591
0592 op_info = acpi_ps_get_opcode_info(opcode);
0593 if (op_info->object_type == ACPI_TYPE_INVALID) {
0594 return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
0595 }
0596
0597 if ((op_info->flags & AML_HAS_RETVAL) ||
0598 (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
0599
0600
0601
0602
0603 status = acpi_ds_result_pop(&obj_desc, walk_state);
0604 if (ACPI_FAILURE(status)) {
0605
0606
0607
0608
0609 ACPI_EXCEPTION((AE_INFO, status,
0610 "Missing or null operand"));
0611 return_ACPI_STATUS(status);
0612 }
0613 } else {
0614
0615
0616 obj_desc =
0617 acpi_ut_create_internal_object(op_info->
0618 object_type);
0619 if (!obj_desc) {
0620 return_ACPI_STATUS(AE_NO_MEMORY);
0621 }
0622
0623
0624
0625 status =
0626 acpi_ds_init_object_from_op(walk_state, arg, opcode,
0627 &obj_desc);
0628 if (ACPI_FAILURE(status)) {
0629 acpi_ut_delete_object_desc(obj_desc);
0630 return_ACPI_STATUS(status);
0631 }
0632 }
0633
0634
0635
0636 status = acpi_ds_obj_stack_push(obj_desc, walk_state);
0637 if (ACPI_FAILURE(status)) {
0638 return_ACPI_STATUS(status);
0639 }
0640
0641 acpi_db_display_argument_object(obj_desc, walk_state);
0642 }
0643
0644 return_ACPI_STATUS(AE_OK);
0645 }
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662 acpi_status
0663 acpi_ds_create_operands(struct acpi_walk_state *walk_state,
0664 union acpi_parse_object *first_arg)
0665 {
0666 acpi_status status = AE_OK;
0667 union acpi_parse_object *arg;
0668 union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
0669 u32 arg_count = 0;
0670 u32 index = walk_state->num_operands;
0671 u32 i;
0672
0673 ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
0674
0675
0676
0677 arg = first_arg;
0678 while (arg) {
0679 if (index >= ACPI_OBJ_NUM_OPERANDS) {
0680 return_ACPI_STATUS(AE_BAD_DATA);
0681 }
0682
0683 arguments[index] = arg;
0684 walk_state->operands[index] = NULL;
0685
0686
0687
0688 arg = arg->common.next;
0689 arg_count++;
0690 index++;
0691 }
0692
0693 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0694 "NumOperands %d, ArgCount %d, Index %d\n",
0695 walk_state->num_operands, arg_count, index));
0696
0697
0698
0699 index--;
0700 for (i = 0; i < arg_count; i++) {
0701 arg = arguments[index];
0702 walk_state->operand_index = (u8)index;
0703
0704 status = acpi_ds_create_operand(walk_state, arg, index);
0705 if (ACPI_FAILURE(status)) {
0706 goto cleanup;
0707 }
0708
0709 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0710 "Created Arg #%u (%p) %u args total\n",
0711 index, arg, arg_count));
0712 index--;
0713 }
0714
0715 return_ACPI_STATUS(status);
0716
0717 cleanup:
0718
0719
0720
0721
0722
0723 acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
0724
0725 ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
0726 return_ACPI_STATUS(status);
0727 }
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745 acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
0746 {
0747 acpi_status status = AE_OK;
0748 union acpi_parse_object *op = walk_state->op;
0749 union acpi_operand_object **operand = &walk_state->operands[0];
0750 union acpi_operand_object *new_obj_desc;
0751 u8 type;
0752
0753 ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
0754
0755 if (!op->common.parent) {
0756
0757
0758
0759 goto exit;
0760 }
0761
0762 if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
0763 (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP) ||
0764 (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
0765
0766
0767
0768 goto exit;
0769 }
0770
0771 status = acpi_ds_create_operand(walk_state, op, 0);
0772 if (ACPI_FAILURE(status)) {
0773 goto exit;
0774 }
0775
0776 if (op->common.flags & ACPI_PARSEOP_TARGET) {
0777 new_obj_desc = *operand;
0778 goto push_result;
0779 }
0780
0781 type = (*operand)->common.type;
0782
0783 status = acpi_ex_resolve_to_value(operand, walk_state);
0784 if (ACPI_FAILURE(status)) {
0785 goto exit;
0786 }
0787
0788 if (type == ACPI_TYPE_INTEGER) {
0789
0790
0791
0792 acpi_ut_remove_reference(*operand);
0793
0794 status =
0795 acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
0796 walk_state);
0797 if (ACPI_FAILURE(status)) {
0798 goto exit;
0799 }
0800 } else {
0801
0802
0803
0804
0805 new_obj_desc = *operand;
0806 }
0807
0808
0809
0810 status = acpi_ds_obj_stack_pop(1, walk_state);
0811 if (ACPI_FAILURE(status)) {
0812 walk_state->result_obj = new_obj_desc;
0813 goto exit;
0814 }
0815
0816 push_result:
0817
0818 walk_state->result_obj = new_obj_desc;
0819
0820 status = acpi_ds_result_push(walk_state->result_obj, walk_state);
0821 if (ACPI_SUCCESS(status)) {
0822
0823
0824
0825 op->common.flags |= ACPI_PARSEOP_IN_STACK;
0826 }
0827
0828 exit:
0829
0830 return_ACPI_STATUS(status);
0831 }