0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acparser.h"
0013 #include "amlcode.h"
0014 #include "acdispat.h"
0015 #include "acinterp.h"
0016 #include "acnamesp.h"
0017 #include "acevents.h"
0018 #include "actables.h"
0019
0020 #define _COMPONENT ACPI_DISPATCHER
0021 ACPI_MODULE_NAME("dsopcode")
0022
0023
0024 static acpi_status
0025 acpi_ds_init_buffer_field(u16 aml_opcode,
0026 union acpi_operand_object *obj_desc,
0027 union acpi_operand_object *buffer_desc,
0028 union acpi_operand_object *offset_desc,
0029 union acpi_operand_object *length_desc,
0030 union acpi_operand_object *result_desc);
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
0045 {
0046 union acpi_operand_object *obj_desc;
0047 acpi_status status;
0048
0049 obj_desc = acpi_ns_get_attached_object(obj_handle);
0050
0051
0052
0053 status = acpi_ev_initialize_region(obj_desc);
0054 return (status);
0055 }
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 static acpi_status
0075 acpi_ds_init_buffer_field(u16 aml_opcode,
0076 union acpi_operand_object *obj_desc,
0077 union acpi_operand_object *buffer_desc,
0078 union acpi_operand_object *offset_desc,
0079 union acpi_operand_object *length_desc,
0080 union acpi_operand_object *result_desc)
0081 {
0082 u32 offset;
0083 u32 bit_offset;
0084 u32 bit_count;
0085 u8 field_flags;
0086 acpi_status status;
0087
0088 ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
0089
0090
0091
0092 if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
0093 ACPI_ERROR((AE_INFO,
0094 "Target of Create Field is not a Buffer object - %s",
0095 acpi_ut_get_object_type_name(buffer_desc)));
0096
0097 status = AE_AML_OPERAND_TYPE;
0098 goto cleanup;
0099 }
0100
0101
0102
0103
0104
0105
0106 if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
0107 ACPI_ERROR((AE_INFO,
0108 "(%s) destination not a NS Node [%s]",
0109 acpi_ps_get_opcode_name(aml_opcode),
0110 acpi_ut_get_descriptor_name(result_desc)));
0111
0112 status = AE_AML_OPERAND_TYPE;
0113 goto cleanup;
0114 }
0115
0116 offset = (u32) offset_desc->integer.value;
0117
0118
0119
0120
0121 switch (aml_opcode) {
0122 case AML_CREATE_FIELD_OP:
0123
0124
0125
0126 field_flags = AML_FIELD_ACCESS_BYTE;
0127 bit_offset = offset;
0128 bit_count = (u32) length_desc->integer.value;
0129
0130
0131
0132 if (bit_count == 0) {
0133 ACPI_BIOS_ERROR((AE_INFO,
0134 "Attempt to CreateField of length zero"));
0135 status = AE_AML_OPERAND_VALUE;
0136 goto cleanup;
0137 }
0138 break;
0139
0140 case AML_CREATE_BIT_FIELD_OP:
0141
0142
0143
0144 bit_offset = offset;
0145 bit_count = 1;
0146 field_flags = AML_FIELD_ACCESS_BYTE;
0147 break;
0148
0149 case AML_CREATE_BYTE_FIELD_OP:
0150
0151
0152
0153 bit_offset = 8 * offset;
0154 bit_count = 8;
0155 field_flags = AML_FIELD_ACCESS_BYTE;
0156 break;
0157
0158 case AML_CREATE_WORD_FIELD_OP:
0159
0160
0161
0162 bit_offset = 8 * offset;
0163 bit_count = 16;
0164 field_flags = AML_FIELD_ACCESS_WORD;
0165 break;
0166
0167 case AML_CREATE_DWORD_FIELD_OP:
0168
0169
0170
0171 bit_offset = 8 * offset;
0172 bit_count = 32;
0173 field_flags = AML_FIELD_ACCESS_DWORD;
0174 break;
0175
0176 case AML_CREATE_QWORD_FIELD_OP:
0177
0178
0179
0180 bit_offset = 8 * offset;
0181 bit_count = 64;
0182 field_flags = AML_FIELD_ACCESS_QWORD;
0183 break;
0184
0185 default:
0186
0187 ACPI_ERROR((AE_INFO,
0188 "Unknown field creation opcode 0x%02X",
0189 aml_opcode));
0190 status = AE_AML_BAD_OPCODE;
0191 goto cleanup;
0192 }
0193
0194
0195
0196 if ((bit_offset + bit_count) > (8 * (u32)buffer_desc->buffer.length)) {
0197 status = AE_AML_BUFFER_LIMIT;
0198 ACPI_BIOS_EXCEPTION((AE_INFO, status,
0199 "Field [%4.4s] at bit offset/length %u/%u "
0200 "exceeds size of target Buffer (%u bits)",
0201 acpi_ut_get_node_name(result_desc),
0202 bit_offset, bit_count,
0203 8 * (u32)buffer_desc->buffer.length));
0204 goto cleanup;
0205 }
0206
0207
0208
0209
0210
0211
0212 status =
0213 acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
0214 bit_offset, bit_count);
0215 if (ACPI_FAILURE(status)) {
0216 goto cleanup;
0217 }
0218
0219 obj_desc->buffer_field.buffer_obj = buffer_desc;
0220 obj_desc->buffer_field.is_create_field =
0221 aml_opcode == AML_CREATE_FIELD_OP;
0222
0223
0224
0225 buffer_desc->common.reference_count = (u16)
0226 (buffer_desc->common.reference_count +
0227 obj_desc->common.reference_count);
0228
0229 cleanup:
0230
0231
0232
0233 acpi_ut_remove_reference(offset_desc);
0234 acpi_ut_remove_reference(buffer_desc);
0235
0236 if (aml_opcode == AML_CREATE_FIELD_OP) {
0237 acpi_ut_remove_reference(length_desc);
0238 }
0239
0240
0241
0242 if (ACPI_FAILURE(status)) {
0243 acpi_ut_remove_reference(result_desc);
0244 } else {
0245
0246
0247 obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
0248 }
0249
0250 return_ACPI_STATUS(status);
0251 }
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 acpi_status
0268 acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
0269 union acpi_parse_object *op)
0270 {
0271 acpi_status status;
0272 union acpi_operand_object *obj_desc;
0273 struct acpi_namespace_node *node;
0274 union acpi_parse_object *next_op;
0275
0276 ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
0277
0278
0279
0280
0281
0282 node = op->common.node;
0283
0284
0285
0286 next_op = op->common.value.arg;
0287
0288
0289
0290 status = acpi_ds_create_operands(walk_state, next_op);
0291 if (ACPI_FAILURE(status)) {
0292 return_ACPI_STATUS(status);
0293 }
0294
0295 obj_desc = acpi_ns_get_attached_object(node);
0296 if (!obj_desc) {
0297 return_ACPI_STATUS(AE_NOT_EXIST);
0298 }
0299
0300
0301
0302 status =
0303 acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
0304 walk_state);
0305 if (ACPI_FAILURE(status)) {
0306 ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
0307 acpi_ps_get_opcode_name(op->common.aml_opcode),
0308 status));
0309
0310 return_ACPI_STATUS(status);
0311 }
0312
0313
0314
0315 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
0316
0317
0318
0319 status =
0320 acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
0321 walk_state->operands[0],
0322 walk_state->operands[1],
0323 walk_state->operands[2],
0324 walk_state->operands[3]);
0325 } else {
0326
0327
0328 status =
0329 acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
0330 walk_state->operands[0],
0331 walk_state->operands[1], NULL,
0332 walk_state->operands[2]);
0333 }
0334
0335 return_ACPI_STATUS(status);
0336 }
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 acpi_status
0353 acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
0354 union acpi_parse_object *op)
0355 {
0356 acpi_status status;
0357 union acpi_operand_object *obj_desc;
0358 union acpi_operand_object *operand_desc;
0359 struct acpi_namespace_node *node;
0360 union acpi_parse_object *next_op;
0361 acpi_adr_space_type space_id;
0362
0363 ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
0364
0365
0366
0367
0368
0369 node = op->common.node;
0370
0371
0372
0373 next_op = op->common.value.arg;
0374 space_id = (acpi_adr_space_type)next_op->common.value.integer;
0375
0376
0377
0378 next_op = next_op->common.next;
0379
0380
0381
0382 status = acpi_ds_create_operands(walk_state, next_op);
0383 if (ACPI_FAILURE(status)) {
0384 return_ACPI_STATUS(status);
0385 }
0386
0387
0388
0389 status =
0390 acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
0391 walk_state);
0392 if (ACPI_FAILURE(status)) {
0393 return_ACPI_STATUS(status);
0394 }
0395
0396 obj_desc = acpi_ns_get_attached_object(node);
0397 if (!obj_desc) {
0398 return_ACPI_STATUS(AE_NOT_EXIST);
0399 }
0400
0401
0402
0403
0404
0405 operand_desc = walk_state->operands[walk_state->num_operands - 1];
0406
0407 obj_desc->region.length = (u32) operand_desc->integer.value;
0408 acpi_ut_remove_reference(operand_desc);
0409
0410
0411
0412 if (!obj_desc->region.length
0413 && (space_id < ACPI_NUM_PREDEFINED_REGIONS)) {
0414 ACPI_WARNING((AE_INFO,
0415 "Operation Region [%4.4s] has zero length (SpaceId %X)",
0416 node->name.ascii, space_id));
0417 }
0418
0419
0420
0421
0422
0423 operand_desc = walk_state->operands[walk_state->num_operands - 2];
0424
0425 obj_desc->region.address = (acpi_physical_address)
0426 operand_desc->integer.value;
0427 acpi_ut_remove_reference(operand_desc);
0428
0429 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
0430 obj_desc,
0431 ACPI_FORMAT_UINT64(obj_desc->region.address),
0432 obj_desc->region.length));
0433
0434 status = acpi_ut_add_address_range(obj_desc->region.space_id,
0435 obj_desc->region.address,
0436 obj_desc->region.length, node);
0437
0438
0439
0440 obj_desc->region.flags |= AOPOBJ_DATA_VALID;
0441 return_ACPI_STATUS(status);
0442 }
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459 acpi_status
0460 acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
0461 union acpi_parse_object *op)
0462 {
0463 acpi_status status;
0464 union acpi_operand_object *obj_desc;
0465 union acpi_operand_object **operand;
0466 struct acpi_namespace_node *node;
0467 union acpi_parse_object *next_op;
0468 struct acpi_table_header *table;
0469 u32 table_index;
0470
0471 ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
0472
0473
0474
0475
0476
0477 node = op->common.node;
0478
0479
0480
0481 next_op = op->common.value.arg;
0482
0483
0484
0485
0486
0487 status = acpi_ds_create_operands(walk_state, next_op);
0488 if (ACPI_FAILURE(status)) {
0489 return_ACPI_STATUS(status);
0490 }
0491
0492 operand = &walk_state->operands[0];
0493
0494
0495
0496
0497
0498 status =
0499 acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
0500 walk_state);
0501 if (ACPI_FAILURE(status)) {
0502 goto cleanup;
0503 }
0504
0505
0506
0507 status = acpi_tb_find_table(operand[0]->string.pointer,
0508 operand[1]->string.pointer,
0509 operand[2]->string.pointer, &table_index);
0510 if (ACPI_FAILURE(status)) {
0511 if (status == AE_NOT_FOUND) {
0512 ACPI_ERROR((AE_INFO,
0513 "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT",
0514 operand[0]->string.pointer,
0515 operand[1]->string.pointer,
0516 operand[2]->string.pointer));
0517 }
0518 goto cleanup;
0519 }
0520
0521 status = acpi_get_table_by_index(table_index, &table);
0522 if (ACPI_FAILURE(status)) {
0523 goto cleanup;
0524 }
0525
0526 obj_desc = acpi_ns_get_attached_object(node);
0527 if (!obj_desc) {
0528 status = AE_NOT_EXIST;
0529 goto cleanup;
0530 }
0531
0532 obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
0533 obj_desc->region.length = table->length;
0534 obj_desc->region.pointer = table;
0535
0536 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
0537 obj_desc,
0538 ACPI_FORMAT_UINT64(obj_desc->region.address),
0539 obj_desc->region.length));
0540
0541
0542
0543 obj_desc->region.flags |= AOPOBJ_DATA_VALID;
0544
0545 cleanup:
0546 acpi_ut_remove_reference(operand[0]);
0547 acpi_ut_remove_reference(operand[1]);
0548 acpi_ut_remove_reference(operand[2]);
0549
0550 return_ACPI_STATUS(status);
0551 }
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568 acpi_status
0569 acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
0570 union acpi_parse_object *op,
0571 union acpi_operand_object *obj_desc)
0572 {
0573 acpi_status status;
0574 union acpi_operand_object *arg_desc;
0575 u32 length;
0576
0577 ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
0578
0579
0580
0581
0582
0583
0584
0585 walk_state->operand_index = walk_state->num_operands;
0586
0587
0588
0589 if (!op->common.value.arg) {
0590 ACPI_ERROR((AE_INFO,
0591 "Missing child while evaluating opcode %4.4X, Op %p",
0592 op->common.aml_opcode, op));
0593 return_ACPI_STATUS(AE_OK);
0594 }
0595
0596 status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
0597 if (ACPI_FAILURE(status)) {
0598 return_ACPI_STATUS(status);
0599 }
0600
0601 status = acpi_ex_resolve_operands(walk_state->opcode,
0602 &(walk_state->
0603 operands[walk_state->num_operands -
0604 1]), walk_state);
0605 if (ACPI_FAILURE(status)) {
0606 return_ACPI_STATUS(status);
0607 }
0608
0609
0610
0611 arg_desc = walk_state->operands[walk_state->num_operands - 1];
0612 length = (u32) arg_desc->integer.value;
0613
0614
0615
0616 status = acpi_ds_obj_stack_pop(1, walk_state);
0617 if (ACPI_FAILURE(status)) {
0618 return_ACPI_STATUS(status);
0619 }
0620
0621 acpi_ut_remove_reference(arg_desc);
0622
0623
0624
0625
0626 switch (op->common.aml_opcode) {
0627 case AML_BUFFER_OP:
0628
0629 status =
0630 acpi_ds_build_internal_buffer_obj(walk_state, op, length,
0631 &obj_desc);
0632 break;
0633
0634 case AML_PACKAGE_OP:
0635 case AML_VARIABLE_PACKAGE_OP:
0636
0637 status =
0638 acpi_ds_build_internal_package_obj(walk_state, op, length,
0639 &obj_desc);
0640 break;
0641
0642 default:
0643
0644 return_ACPI_STATUS(AE_AML_BAD_OPCODE);
0645 }
0646
0647 if (ACPI_SUCCESS(status)) {
0648
0649
0650
0651
0652
0653 if ((!op->common.parent) ||
0654 ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
0655 (op->common.parent->common.aml_opcode !=
0656 AML_VARIABLE_PACKAGE_OP)
0657 && (op->common.parent->common.aml_opcode !=
0658 AML_NAME_OP))) {
0659 walk_state->result_obj = obj_desc;
0660 }
0661 }
0662
0663 return_ACPI_STATUS(status);
0664 }
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680 acpi_status
0681 acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
0682 union acpi_parse_object *op)
0683 {
0684 acpi_status status;
0685 union acpi_operand_object *obj_desc;
0686 union acpi_operand_object *operand_desc;
0687 struct acpi_namespace_node *node;
0688 union acpi_parse_object *next_op;
0689 union acpi_parse_object *arg;
0690
0691 ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);
0692
0693
0694
0695
0696
0697
0698
0699
0700 next_op = op->common.value.arg;
0701
0702
0703
0704 next_op = next_op->common.next;
0705
0706
0707
0708 next_op = next_op->common.next;
0709
0710
0711
0712
0713
0714
0715
0716 walk_state->operand_index = 0;
0717
0718 status = acpi_ds_create_operand(walk_state, next_op, 0);
0719 if (ACPI_FAILURE(status)) {
0720 return_ACPI_STATUS(status);
0721 }
0722
0723 status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
0724 if (ACPI_FAILURE(status)) {
0725 return_ACPI_STATUS(status);
0726 }
0727
0728 ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
0729 acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
0730
0731
0732
0733
0734 operand_desc = walk_state->operands[0];
0735
0736
0737
0738 arg = acpi_ps_get_arg(op, 4);
0739 while (arg) {
0740
0741
0742
0743 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
0744 node = arg->common.node;
0745
0746 obj_desc = acpi_ns_get_attached_object(node);
0747 if (!obj_desc) {
0748 return_ACPI_STATUS(AE_NOT_EXIST);
0749 }
0750
0751 obj_desc->bank_field.value =
0752 (u32) operand_desc->integer.value;
0753 }
0754
0755
0756
0757 arg = arg->common.next;
0758 }
0759
0760 acpi_ut_remove_reference(operand_desc);
0761 return_ACPI_STATUS(status);
0762 }