0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acparser.h"
0013 #include "acinterp.h"
0014 #include "acevents.h"
0015 #include "amlcode.h"
0016
0017 #define _COMPONENT ACPI_EXECUTER
0018 ACPI_MODULE_NAME("exoparg2")
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
0056 {
0057 union acpi_operand_object **operand = &walk_state->operands[0];
0058 struct acpi_namespace_node *node;
0059 u32 value;
0060 acpi_status status = AE_OK;
0061
0062 ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
0063 acpi_ps_get_opcode_name(walk_state->opcode));
0064
0065
0066
0067 switch (walk_state->opcode) {
0068 case AML_NOTIFY_OP:
0069
0070
0071
0072 node = (struct acpi_namespace_node *)operand[0];
0073
0074
0075
0076 value = (u32) operand[1]->integer.value;
0077
0078
0079
0080 if (!acpi_ev_is_notify_object(node)) {
0081 ACPI_ERROR((AE_INFO,
0082 "Unexpected notify object type [%s]",
0083 acpi_ut_get_type_name(node->type)));
0084
0085 status = AE_AML_OPERAND_TYPE;
0086 break;
0087 }
0088
0089
0090
0091
0092
0093
0094
0095
0096 status = acpi_ev_queue_notify_request(node, value);
0097 break;
0098
0099 default:
0100
0101 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0102 walk_state->opcode));
0103 status = AE_AML_BAD_OPCODE;
0104 }
0105
0106 return_ACPI_STATUS(status);
0107 }
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
0123 {
0124 union acpi_operand_object **operand = &walk_state->operands[0];
0125 union acpi_operand_object *return_desc1 = NULL;
0126 union acpi_operand_object *return_desc2 = NULL;
0127 acpi_status status;
0128
0129 ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
0130 acpi_ps_get_opcode_name(walk_state->opcode));
0131
0132
0133
0134 switch (walk_state->opcode) {
0135 case AML_DIVIDE_OP:
0136
0137
0138
0139 return_desc1 =
0140 acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0141 if (!return_desc1) {
0142 status = AE_NO_MEMORY;
0143 goto cleanup;
0144 }
0145
0146 return_desc2 =
0147 acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0148 if (!return_desc2) {
0149 status = AE_NO_MEMORY;
0150 goto cleanup;
0151 }
0152
0153
0154
0155 status = acpi_ut_divide(operand[0]->integer.value,
0156 operand[1]->integer.value,
0157 &return_desc1->integer.value,
0158 &return_desc2->integer.value);
0159 if (ACPI_FAILURE(status)) {
0160 goto cleanup;
0161 }
0162 break;
0163
0164 default:
0165
0166 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0167 walk_state->opcode));
0168
0169 status = AE_AML_BAD_OPCODE;
0170 goto cleanup;
0171 }
0172
0173
0174
0175 status = acpi_ex_store(return_desc2, operand[2], walk_state);
0176 if (ACPI_FAILURE(status)) {
0177 goto cleanup;
0178 }
0179
0180 status = acpi_ex_store(return_desc1, operand[3], walk_state);
0181 if (ACPI_FAILURE(status)) {
0182 goto cleanup;
0183 }
0184
0185 cleanup:
0186
0187
0188
0189
0190 acpi_ut_remove_reference(return_desc2);
0191
0192 if (ACPI_FAILURE(status)) {
0193
0194
0195
0196 acpi_ut_remove_reference(return_desc1);
0197 }
0198
0199
0200
0201 else {
0202 walk_state->result_obj = return_desc1;
0203 }
0204
0205 return_ACPI_STATUS(status);
0206 }
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221 acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
0222 {
0223 union acpi_operand_object **operand = &walk_state->operands[0];
0224 union acpi_operand_object *return_desc = NULL;
0225 u64 index;
0226 acpi_status status = AE_OK;
0227 acpi_size length = 0;
0228
0229 ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
0230 acpi_ps_get_opcode_name(walk_state->opcode));
0231
0232
0233
0234 if (walk_state->op_info->flags & AML_MATH) {
0235
0236
0237
0238 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0239 if (!return_desc) {
0240 status = AE_NO_MEMORY;
0241 goto cleanup;
0242 }
0243
0244 return_desc->integer.value =
0245 acpi_ex_do_math_op(walk_state->opcode,
0246 operand[0]->integer.value,
0247 operand[1]->integer.value);
0248 goto store_result_to_target;
0249 }
0250
0251 switch (walk_state->opcode) {
0252 case AML_MOD_OP:
0253
0254 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0255 if (!return_desc) {
0256 status = AE_NO_MEMORY;
0257 goto cleanup;
0258 }
0259
0260
0261
0262 status = acpi_ut_divide(operand[0]->integer.value,
0263 operand[1]->integer.value,
0264 NULL, &return_desc->integer.value);
0265 break;
0266
0267 case AML_CONCATENATE_OP:
0268
0269 status =
0270 acpi_ex_do_concatenate(operand[0], operand[1], &return_desc,
0271 walk_state);
0272 break;
0273
0274 case AML_TO_STRING_OP:
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290 while ((length < operand[0]->buffer.length) &&
0291 (length < operand[1]->integer.value) &&
0292 (operand[0]->buffer.pointer[length])) {
0293 length++;
0294 }
0295
0296
0297
0298 return_desc = acpi_ut_create_string_object(length);
0299 if (!return_desc) {
0300 status = AE_NO_MEMORY;
0301 goto cleanup;
0302 }
0303
0304
0305
0306
0307
0308 memcpy(return_desc->string.pointer,
0309 operand[0]->buffer.pointer, length);
0310 break;
0311
0312 case AML_CONCATENATE_TEMPLATE_OP:
0313
0314
0315
0316 status =
0317 acpi_ex_concat_template(operand[0], operand[1],
0318 &return_desc, walk_state);
0319 break;
0320
0321 case AML_INDEX_OP:
0322
0323
0324
0325 return_desc =
0326 acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
0327 if (!return_desc) {
0328 status = AE_NO_MEMORY;
0329 goto cleanup;
0330 }
0331
0332
0333
0334 index = operand[1]->integer.value;
0335 return_desc->reference.value = (u32) index;
0336 return_desc->reference.class = ACPI_REFCLASS_INDEX;
0337
0338
0339
0340
0341
0342 switch ((operand[0])->common.type) {
0343 case ACPI_TYPE_STRING:
0344
0345 if (index >= operand[0]->string.length) {
0346 length = operand[0]->string.length;
0347 status = AE_AML_STRING_LIMIT;
0348 }
0349
0350 return_desc->reference.target_type =
0351 ACPI_TYPE_BUFFER_FIELD;
0352 return_desc->reference.index_pointer =
0353 &(operand[0]->buffer.pointer[index]);
0354 break;
0355
0356 case ACPI_TYPE_BUFFER:
0357
0358 if (index >= operand[0]->buffer.length) {
0359 length = operand[0]->buffer.length;
0360 status = AE_AML_BUFFER_LIMIT;
0361 }
0362
0363 return_desc->reference.target_type =
0364 ACPI_TYPE_BUFFER_FIELD;
0365 return_desc->reference.index_pointer =
0366 &(operand[0]->buffer.pointer[index]);
0367 break;
0368
0369 case ACPI_TYPE_PACKAGE:
0370
0371 if (index >= operand[0]->package.count) {
0372 length = operand[0]->package.count;
0373 status = AE_AML_PACKAGE_LIMIT;
0374 }
0375
0376 return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
0377 return_desc->reference.where =
0378 &operand[0]->package.elements[index];
0379 break;
0380
0381 default:
0382
0383 ACPI_ERROR((AE_INFO,
0384 "Invalid object type: %X",
0385 (operand[0])->common.type));
0386 status = AE_AML_INTERNAL;
0387 goto cleanup;
0388 }
0389
0390
0391
0392 if (ACPI_FAILURE(status)) {
0393 ACPI_BIOS_EXCEPTION((AE_INFO, status,
0394 "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
0395 ACPI_FORMAT_UINT64(index),
0396 (u32)length));
0397 goto cleanup;
0398 }
0399
0400
0401
0402
0403
0404 return_desc->reference.object = operand[0];
0405 acpi_ut_add_reference(operand[0]);
0406
0407
0408
0409 status = acpi_ex_store(return_desc, operand[2], walk_state);
0410
0411
0412
0413 walk_state->result_obj = return_desc;
0414 goto cleanup;
0415
0416 default:
0417
0418 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0419 walk_state->opcode));
0420 status = AE_AML_BAD_OPCODE;
0421 break;
0422 }
0423
0424 store_result_to_target:
0425
0426 if (ACPI_SUCCESS(status)) {
0427
0428
0429
0430
0431 status = acpi_ex_store(return_desc, operand[2], walk_state);
0432 if (ACPI_FAILURE(status)) {
0433 goto cleanup;
0434 }
0435
0436 if (!walk_state->result_obj) {
0437 walk_state->result_obj = return_desc;
0438 }
0439 }
0440
0441 cleanup:
0442
0443
0444
0445 if (ACPI_FAILURE(status)) {
0446 acpi_ut_remove_reference(return_desc);
0447 walk_state->result_obj = NULL;
0448 }
0449
0450 return_ACPI_STATUS(status);
0451 }
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465 acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
0466 {
0467 union acpi_operand_object **operand = &walk_state->operands[0];
0468 union acpi_operand_object *return_desc = NULL;
0469 acpi_status status = AE_OK;
0470 u8 logical_result = FALSE;
0471
0472 ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
0473 acpi_ps_get_opcode_name(walk_state->opcode));
0474
0475
0476
0477 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
0478 if (!return_desc) {
0479 status = AE_NO_MEMORY;
0480 goto cleanup;
0481 }
0482
0483
0484
0485 if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
0486
0487
0488
0489 status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
0490 operand[0]->integer.
0491 value,
0492 operand[1]->integer.
0493 value, &logical_result);
0494 goto store_logical_result;
0495 } else if (walk_state->op_info->flags & AML_LOGICAL) {
0496
0497
0498
0499 status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
0500 operand[1], &logical_result);
0501 goto store_logical_result;
0502 }
0503
0504 switch (walk_state->opcode) {
0505 case AML_ACQUIRE_OP:
0506
0507 status =
0508 acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
0509 if (status == AE_TIME) {
0510 logical_result = TRUE;
0511 status = AE_OK;
0512 }
0513 break;
0514
0515 case AML_WAIT_OP:
0516
0517 status = acpi_ex_system_wait_event(operand[1], operand[0]);
0518 if (status == AE_TIME) {
0519 logical_result = TRUE;
0520 status = AE_OK;
0521 }
0522 break;
0523
0524 default:
0525
0526 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0527 walk_state->opcode));
0528
0529 status = AE_AML_BAD_OPCODE;
0530 goto cleanup;
0531 }
0532
0533 store_logical_result:
0534
0535
0536
0537
0538 if (logical_result) {
0539 return_desc->integer.value = ACPI_UINT64_MAX;
0540 }
0541
0542 cleanup:
0543
0544
0545
0546 if (ACPI_FAILURE(status)) {
0547 acpi_ut_remove_reference(return_desc);
0548 }
0549
0550
0551
0552 else {
0553 walk_state->result_obj = return_desc;
0554 }
0555
0556 return_ACPI_STATUS(status);
0557 }