0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "amlcode.h"
0013 #include "acdispat.h"
0014 #include "acinterp.h"
0015 #include "acnamesp.h"
0016 #include "acparser.h"
0017
0018 #ifdef ACPI_EXEC_APP
0019 #include "aecommon.h"
0020 #endif
0021
0022 #define _COMPONENT ACPI_DISPATCHER
0023 ACPI_MODULE_NAME("dsfield")
0024
0025
0026 #ifdef ACPI_ASL_COMPILER
0027 #include "acdisasm.h"
0028 static acpi_status
0029 acpi_ds_create_external_region(acpi_status lookup_status,
0030 union acpi_parse_object *op,
0031 char *path,
0032 struct acpi_walk_state *walk_state,
0033 struct acpi_namespace_node **node);
0034 #endif
0035
0036 static acpi_status
0037 acpi_ds_get_field_names(struct acpi_create_field_info *info,
0038 struct acpi_walk_state *walk_state,
0039 union acpi_parse_object *arg);
0040
0041 #ifdef ACPI_ASL_COMPILER
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 static acpi_status
0060 acpi_ds_create_external_region(acpi_status lookup_status,
0061 union acpi_parse_object *op,
0062 char *path,
0063 struct acpi_walk_state *walk_state,
0064 struct acpi_namespace_node **node)
0065 {
0066 acpi_status status;
0067 union acpi_operand_object *obj_desc;
0068
0069 if (lookup_status != AE_NOT_FOUND) {
0070 return (lookup_status);
0071 }
0072
0073
0074
0075
0076
0077
0078 acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0);
0079
0080 status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
0081 ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
0082 walk_state, node);
0083 if (ACPI_FAILURE(status)) {
0084 return (status);
0085 }
0086
0087
0088
0089 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
0090 if (!obj_desc) {
0091 return (AE_NO_MEMORY);
0092 }
0093
0094 obj_desc->region.node = *node;
0095 status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION);
0096 return (status);
0097 }
0098 #endif
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119 acpi_status
0120 acpi_ds_create_buffer_field(union acpi_parse_object *op,
0121 struct acpi_walk_state *walk_state)
0122 {
0123 union acpi_parse_object *arg;
0124 struct acpi_namespace_node *node;
0125 acpi_status status;
0126 union acpi_operand_object *obj_desc;
0127 union acpi_operand_object *second_desc = NULL;
0128 u32 flags;
0129
0130 ACPI_FUNCTION_TRACE(ds_create_buffer_field);
0131
0132
0133
0134
0135 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
0136
0137
0138
0139 arg = acpi_ps_get_arg(op, 3);
0140 } else {
0141
0142
0143 arg = acpi_ps_get_arg(op, 2);
0144 }
0145
0146 if (!arg) {
0147 return_ACPI_STATUS(AE_AML_NO_OPERAND);
0148 }
0149
0150 if (walk_state->deferred_node) {
0151 node = walk_state->deferred_node;
0152 } else {
0153
0154
0155 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
0156 ACPI_ERROR((AE_INFO, "Parse execute mode is not set"));
0157 return_ACPI_STATUS(AE_AML_INTERNAL);
0158 }
0159
0160
0161
0162 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
0163 ACPI_NS_ERROR_IF_FOUND;
0164
0165
0166
0167
0168
0169 if (walk_state->method_node &&
0170 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
0171 flags |= ACPI_NS_TEMPORARY;
0172 }
0173
0174
0175
0176 status = acpi_ns_lookup(walk_state->scope_info,
0177 arg->common.value.string, ACPI_TYPE_ANY,
0178 ACPI_IMODE_LOAD_PASS1, flags,
0179 walk_state, &node);
0180 if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE)
0181 && status == AE_ALREADY_EXISTS) {
0182 status = AE_OK;
0183 } else if (ACPI_FAILURE(status)) {
0184 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0185 arg->common.value.string, status);
0186 return_ACPI_STATUS(status);
0187 }
0188 }
0189
0190
0191
0192
0193
0194
0195 op->common.node = node;
0196
0197
0198
0199
0200
0201
0202 obj_desc = acpi_ns_get_attached_object(node);
0203 if (obj_desc) {
0204 return_ACPI_STATUS(AE_OK);
0205 }
0206
0207
0208
0209
0210
0211
0212
0213
0214 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD);
0215 if (!obj_desc) {
0216 status = AE_NO_MEMORY;
0217 goto cleanup;
0218 }
0219
0220
0221
0222
0223
0224 second_desc = obj_desc->common.next_object;
0225 second_desc->extra.aml_start = op->named.data;
0226 second_desc->extra.aml_length = op->named.length;
0227 obj_desc->buffer_field.node = node;
0228
0229
0230
0231 status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
0232 if (ACPI_FAILURE(status)) {
0233 goto cleanup;
0234 }
0235
0236 cleanup:
0237
0238
0239
0240 acpi_ut_remove_reference(obj_desc);
0241 return_ACPI_STATUS(status);
0242 }
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 static acpi_status
0260 acpi_ds_get_field_names(struct acpi_create_field_info *info,
0261 struct acpi_walk_state *walk_state,
0262 union acpi_parse_object *arg)
0263 {
0264 acpi_status status;
0265 u64 position;
0266 union acpi_parse_object *child;
0267
0268 #ifdef ACPI_EXEC_APP
0269 union acpi_operand_object *result_desc;
0270 union acpi_operand_object *obj_desc;
0271 char *name_path;
0272 #endif
0273
0274 ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
0275
0276
0277
0278 info->field_bit_position = 0;
0279
0280
0281
0282 while (arg) {
0283
0284
0285
0286
0287
0288
0289
0290 switch (arg->common.aml_opcode) {
0291 case AML_INT_RESERVEDFIELD_OP:
0292
0293 position = (u64)info->field_bit_position +
0294 (u64)arg->common.value.size;
0295
0296 if (position > ACPI_UINT32_MAX) {
0297 ACPI_ERROR((AE_INFO,
0298 "Bit offset within field too large (> 0xFFFFFFFF)"));
0299 return_ACPI_STATUS(AE_SUPPORT);
0300 }
0301
0302 info->field_bit_position = (u32) position;
0303 break;
0304
0305 case AML_INT_ACCESSFIELD_OP:
0306 case AML_INT_EXTACCESSFIELD_OP:
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 info->field_flags = (u8)
0321 ((info->
0322 field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
0323 ((u8)((u32)(arg->common.value.integer & 0x07))));
0324
0325
0326
0327 info->attribute = (u8)
0328 ((arg->common.value.integer >> 8) & 0xFF);
0329
0330
0331
0332 info->access_length = (u8)
0333 ((arg->common.value.integer >> 16) & 0xFF);
0334 break;
0335
0336 case AML_INT_CONNECTION_OP:
0337
0338
0339
0340
0341 info->resource_buffer = NULL;
0342 info->connection_node = NULL;
0343 info->pin_number_index = 0;
0344
0345
0346
0347
0348
0349 child = arg->common.value.arg;
0350 if (child->common.aml_opcode == AML_INT_BYTELIST_OP) {
0351 info->resource_buffer = child->named.data;
0352 info->resource_length =
0353 (u16)child->named.value.integer;
0354 } else {
0355
0356
0357 status = acpi_ns_lookup(walk_state->scope_info,
0358 child->common.value.
0359 name, ACPI_TYPE_ANY,
0360 ACPI_IMODE_EXECUTE,
0361 ACPI_NS_DONT_OPEN_SCOPE,
0362 walk_state,
0363 &info->connection_node);
0364 if (ACPI_FAILURE(status)) {
0365 ACPI_ERROR_NAMESPACE(walk_state->
0366 scope_info,
0367 child->common.
0368 value.name,
0369 status);
0370 return_ACPI_STATUS(status);
0371 }
0372 }
0373 break;
0374
0375 case AML_INT_NAMEDFIELD_OP:
0376
0377
0378
0379 status = acpi_ns_lookup(walk_state->scope_info,
0380 (char *)&arg->named.name,
0381 info->field_type,
0382 ACPI_IMODE_EXECUTE,
0383 ACPI_NS_DONT_OPEN_SCOPE,
0384 walk_state, &info->field_node);
0385 if (ACPI_FAILURE(status)) {
0386 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0387 (char *)&arg->named.name,
0388 status);
0389 return_ACPI_STATUS(status);
0390 } else {
0391 arg->common.node = info->field_node;
0392 info->field_bit_length = arg->common.value.size;
0393
0394
0395
0396
0397
0398
0399
0400 if (!acpi_ns_get_attached_object
0401 (info->field_node)) {
0402 status = acpi_ex_prep_field_value(info);
0403 if (ACPI_FAILURE(status)) {
0404 return_ACPI_STATUS(status);
0405 }
0406 #ifdef ACPI_EXEC_APP
0407 name_path =
0408 acpi_ns_get_external_pathname(info->
0409 field_node);
0410 if (ACPI_SUCCESS
0411 (ae_lookup_init_file_entry
0412 (name_path, &obj_desc))) {
0413 acpi_ex_write_data_to_field
0414 (obj_desc,
0415 acpi_ns_get_attached_object
0416 (info->field_node),
0417 &result_desc);
0418 acpi_ut_remove_reference
0419 (obj_desc);
0420 }
0421 ACPI_FREE(name_path);
0422 #endif
0423 }
0424 }
0425
0426
0427
0428 position = (u64)info->field_bit_position +
0429 (u64)arg->common.value.size;
0430
0431 if (position > ACPI_UINT32_MAX) {
0432 ACPI_ERROR((AE_INFO,
0433 "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
0434 ACPI_CAST_PTR(char,
0435 &info->field_node->
0436 name)));
0437 return_ACPI_STATUS(AE_SUPPORT);
0438 }
0439
0440 info->field_bit_position += info->field_bit_length;
0441 info->pin_number_index++;
0442 break;
0443
0444 default:
0445
0446 ACPI_ERROR((AE_INFO,
0447 "Invalid opcode in field list: 0x%X",
0448 arg->common.aml_opcode));
0449 return_ACPI_STATUS(AE_AML_BAD_OPCODE);
0450 }
0451
0452 arg = arg->common.next;
0453 }
0454
0455 return_ACPI_STATUS(AE_OK);
0456 }
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472 acpi_status
0473 acpi_ds_create_field(union acpi_parse_object *op,
0474 struct acpi_namespace_node *region_node,
0475 struct acpi_walk_state *walk_state)
0476 {
0477 acpi_status status;
0478 union acpi_parse_object *arg;
0479 struct acpi_create_field_info info;
0480
0481 ACPI_FUNCTION_TRACE_PTR(ds_create_field, op);
0482
0483
0484
0485 arg = op->common.value.arg;
0486
0487 if (!region_node) {
0488 status =
0489 acpi_ns_lookup(walk_state->scope_info,
0490 arg->common.value.name, ACPI_TYPE_REGION,
0491 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
0492 walk_state, ®ion_node);
0493 #ifdef ACPI_ASL_COMPILER
0494 status = acpi_ds_create_external_region(status, arg,
0495 arg->common.value.name,
0496 walk_state,
0497 ®ion_node);
0498 #endif
0499 if (ACPI_FAILURE(status)) {
0500 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0501 arg->common.value.name, status);
0502 return_ACPI_STATUS(status);
0503 }
0504 }
0505
0506 memset(&info, 0, sizeof(struct acpi_create_field_info));
0507
0508
0509
0510 arg = arg->common.next;
0511 info.field_flags = (u8) arg->common.value.integer;
0512 info.attribute = 0;
0513
0514
0515
0516 info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
0517 info.region_node = region_node;
0518
0519 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
0520 if (ACPI_FAILURE(status)) {
0521 return_ACPI_STATUS(status);
0522 }
0523
0524 if (info.region_node->object->region.space_id ==
0525 ACPI_ADR_SPACE_PLATFORM_COMM) {
0526 region_node->object->field.internal_pcc_buffer =
0527 ACPI_ALLOCATE_ZEROED(info.region_node->object->region.
0528 length);
0529 if (!region_node->object->field.internal_pcc_buffer) {
0530 return_ACPI_STATUS(AE_NO_MEMORY);
0531 }
0532 }
0533
0534 return_ACPI_STATUS(status);
0535 }
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552 acpi_status
0553 acpi_ds_init_field_objects(union acpi_parse_object *op,
0554 struct acpi_walk_state *walk_state)
0555 {
0556 acpi_status status;
0557 union acpi_parse_object *arg = NULL;
0558 struct acpi_namespace_node *node;
0559 u8 type = 0;
0560 u32 flags;
0561
0562 ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
0563
0564
0565
0566 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
0567 if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
0568
0569
0570
0571 return_ACPI_STATUS(AE_OK);
0572 }
0573
0574 ACPI_ERROR((AE_INFO, "Parse deferred mode is not set"));
0575 return_ACPI_STATUS(AE_AML_INTERNAL);
0576 }
0577
0578
0579
0580
0581
0582 switch (walk_state->opcode) {
0583 case AML_FIELD_OP:
0584
0585 arg = acpi_ps_get_arg(op, 2);
0586 type = ACPI_TYPE_LOCAL_REGION_FIELD;
0587 break;
0588
0589 case AML_BANK_FIELD_OP:
0590
0591 arg = acpi_ps_get_arg(op, 4);
0592 type = ACPI_TYPE_LOCAL_BANK_FIELD;
0593 break;
0594
0595 case AML_INDEX_FIELD_OP:
0596
0597 arg = acpi_ps_get_arg(op, 3);
0598 type = ACPI_TYPE_LOCAL_INDEX_FIELD;
0599 break;
0600
0601 default:
0602
0603 return_ACPI_STATUS(AE_BAD_PARAMETER);
0604 }
0605
0606
0607
0608 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
0609 ACPI_NS_ERROR_IF_FOUND;
0610
0611
0612
0613
0614
0615 if (walk_state->method_node &&
0616 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
0617 flags |= ACPI_NS_TEMPORARY;
0618 }
0619 #ifdef ACPI_EXEC_APP
0620 flags |= ACPI_NS_OVERRIDE_IF_FOUND;
0621 #endif
0622
0623
0624
0625
0626 while (arg) {
0627
0628
0629
0630
0631 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
0632 status = acpi_ns_lookup(walk_state->scope_info,
0633 (char *)&arg->named.name, type,
0634 ACPI_IMODE_LOAD_PASS1, flags,
0635 walk_state, &node);
0636 if (ACPI_FAILURE(status)) {
0637 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0638 (char *)&arg->named.name,
0639 status);
0640 if (status != AE_ALREADY_EXISTS) {
0641 return_ACPI_STATUS(status);
0642 }
0643
0644
0645 }
0646
0647 arg->common.node = node;
0648 }
0649
0650
0651
0652 arg = arg->common.next;
0653 }
0654
0655 return_ACPI_STATUS(AE_OK);
0656 }
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672 acpi_status
0673 acpi_ds_create_bank_field(union acpi_parse_object *op,
0674 struct acpi_namespace_node *region_node,
0675 struct acpi_walk_state *walk_state)
0676 {
0677 acpi_status status;
0678 union acpi_parse_object *arg;
0679 struct acpi_create_field_info info;
0680
0681 ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op);
0682
0683
0684
0685 arg = op->common.value.arg;
0686 if (!region_node) {
0687 status =
0688 acpi_ns_lookup(walk_state->scope_info,
0689 arg->common.value.name, ACPI_TYPE_REGION,
0690 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
0691 walk_state, ®ion_node);
0692 #ifdef ACPI_ASL_COMPILER
0693 status = acpi_ds_create_external_region(status, arg,
0694 arg->common.value.name,
0695 walk_state,
0696 ®ion_node);
0697 #endif
0698 if (ACPI_FAILURE(status)) {
0699 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0700 arg->common.value.name, status);
0701 return_ACPI_STATUS(status);
0702 }
0703 }
0704
0705
0706
0707 arg = arg->common.next;
0708 status =
0709 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
0710 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
0711 ACPI_NS_SEARCH_PARENT, walk_state,
0712 &info.register_node);
0713 if (ACPI_FAILURE(status)) {
0714 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0715 arg->common.value.string, status);
0716 return_ACPI_STATUS(status);
0717 }
0718
0719
0720
0721
0722
0723
0724 arg = arg->common.next;
0725
0726
0727
0728 arg = arg->common.next;
0729 info.field_flags = (u8) arg->common.value.integer;
0730
0731
0732
0733 info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
0734 info.region_node = region_node;
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745 info.data_register_node = (struct acpi_namespace_node *)op;
0746
0747 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
0748 return_ACPI_STATUS(status);
0749 }
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765 acpi_status
0766 acpi_ds_create_index_field(union acpi_parse_object *op,
0767 struct acpi_namespace_node *region_node,
0768 struct acpi_walk_state *walk_state)
0769 {
0770 acpi_status status;
0771 union acpi_parse_object *arg;
0772 struct acpi_create_field_info info;
0773
0774 ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op);
0775
0776
0777
0778 arg = op->common.value.arg;
0779 status =
0780 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
0781 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
0782 ACPI_NS_SEARCH_PARENT, walk_state,
0783 &info.register_node);
0784 if (ACPI_FAILURE(status)) {
0785 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0786 arg->common.value.string, status);
0787 return_ACPI_STATUS(status);
0788 }
0789
0790
0791
0792 arg = arg->common.next;
0793 status =
0794 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
0795 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
0796 ACPI_NS_SEARCH_PARENT, walk_state,
0797 &info.data_register_node);
0798 if (ACPI_FAILURE(status)) {
0799 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0800 arg->common.value.string, status);
0801 return_ACPI_STATUS(status);
0802 }
0803
0804
0805
0806 arg = arg->common.next;
0807 info.field_flags = (u8) arg->common.value.integer;
0808
0809
0810
0811 info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
0812 info.region_node = region_node;
0813
0814 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
0815 return_ACPI_STATUS(status);
0816 }