1/****************************************************************************** 2 * 3 * Module Name: dsopcode - Dispatcher Op Region support and handling of 4 * "control" opcodes 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2007, R. Byron Moore 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45#include <acpi/acpi.h> 46#include <acpi/acparser.h> 47#include <acpi/amlcode.h> 48#include <acpi/acdispat.h> 49#include <acpi/acinterp.h> 50#include <acpi/acnamesp.h> 51#include <acpi/acevents.h> 52 53#define _COMPONENT ACPI_DISPATCHER 54ACPI_MODULE_NAME("dsopcode") 55 56/* Local prototypes */ 57static acpi_status 58acpi_ds_execute_arguments(struct acpi_namespace_node *node, 59 struct acpi_namespace_node *scope_node, 60 u32 aml_length, u8 * aml_start); 61 62static acpi_status 63acpi_ds_init_buffer_field(u16 aml_opcode, 64 union acpi_operand_object *obj_desc, 65 union acpi_operand_object *buffer_desc, 66 union acpi_operand_object *offset_desc, 67 union acpi_operand_object *length_desc, 68 union acpi_operand_object *result_desc); 69 70/******************************************************************************* 71 * 72 * FUNCTION: acpi_ds_execute_arguments 73 * 74 * PARAMETERS: Node - Object NS node 75 * scope_node - Parent NS node 76 * aml_length - Length of executable AML 77 * aml_start - Pointer to the AML 78 * 79 * RETURN: Status. 80 * 81 * DESCRIPTION: Late (deferred) execution of region or field arguments 82 * 83 ******************************************************************************/ 84 85static acpi_status 86acpi_ds_execute_arguments(struct acpi_namespace_node *node, 87 struct acpi_namespace_node *scope_node, 88 u32 aml_length, u8 * aml_start) 89{ 90 acpi_status status; 91 union acpi_parse_object *op; 92 struct acpi_walk_state *walk_state; 93 94 ACPI_FUNCTION_TRACE(ds_execute_arguments); 95 96 /* 97 * Allocate a new parser op to be the root of the parsed tree 98 */ 99 op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); 100 if (!op) { 101 return_ACPI_STATUS(AE_NO_MEMORY); 102 } 103 104 /* Save the Node for use in acpi_ps_parse_aml */ 105 106 op->common.node = scope_node; 107 108 /* Create and initialize a new parser state */ 109 110 walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); 111 if (!walk_state) { 112 status = AE_NO_MEMORY; 113 goto cleanup; 114 } 115 116 status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, 117 aml_length, NULL, ACPI_IMODE_LOAD_PASS1); 118 if (ACPI_FAILURE(status)) { 119 acpi_ds_delete_walk_state(walk_state); 120 goto cleanup; 121 } 122 123 /* Mark this parse as a deferred opcode */ 124 125 walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; 126 walk_state->deferred_node = node; 127 128 /* Pass1: Parse the entire declaration */ 129 130 status = acpi_ps_parse_aml(walk_state); 131 if (ACPI_FAILURE(status)) { 132 goto cleanup; 133 } 134 135 /* Get and init the Op created above */ 136 137 op->common.node = node; 138 acpi_ps_delete_parse_tree(op); 139 140 /* Evaluate the deferred arguments */ 141 142 op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); 143 if (!op) { 144 return_ACPI_STATUS(AE_NO_MEMORY); 145 } 146 147 op->common.node = scope_node; 148 149 /* Create and initialize a new parser state */ 150 151 walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); 152 if (!walk_state) { 153 status = AE_NO_MEMORY; 154 goto cleanup; 155 } 156 157 /* Execute the opcode and arguments */ 158 159 status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, 160 aml_length, NULL, ACPI_IMODE_EXECUTE); 161 if (ACPI_FAILURE(status)) { 162 acpi_ds_delete_walk_state(walk_state); 163 goto cleanup; 164 } 165 166 /* Mark this execution as a deferred opcode */ 167 168 walk_state->deferred_node = node; 169 status = acpi_ps_parse_aml(walk_state); 170 171 cleanup: 172 acpi_ps_delete_parse_tree(op); 173 return_ACPI_STATUS(status); 174} 175 176/******************************************************************************* 177 * 178 * FUNCTION: acpi_ds_get_buffer_field_arguments 179 * 180 * PARAMETERS: obj_desc - A valid buffer_field object 181 * 182 * RETURN: Status. 183 * 184 * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late 185 * evaluation of these field attributes. 186 * 187 ******************************************************************************/ 188 189acpi_status 190acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) 191{ 192 union acpi_operand_object *extra_desc; 193 struct acpi_namespace_node *node; 194 acpi_status status; 195 196 ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); 197 198 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { 199 return_ACPI_STATUS(AE_OK); 200 } 201 202 /* Get the AML pointer (method object) and buffer_field node */ 203 204 extra_desc = acpi_ns_get_secondary_object(obj_desc); 205 node = obj_desc->buffer_field.node; 206 207 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname 208 (ACPI_TYPE_BUFFER_FIELD, node, NULL)); 209 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", 210 acpi_ut_get_node_name(node))); 211 212 /* Execute the AML code for the term_arg arguments */ 213 214 status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), 215 extra_desc->extra.aml_length, 216 extra_desc->extra.aml_start); 217 return_ACPI_STATUS(status); 218} 219 220/******************************************************************************* 221 * 222 * FUNCTION: acpi_ds_get_buffer_arguments 223 * 224 * PARAMETERS: obj_desc - A valid Buffer object 225 * 226 * RETURN: Status. 227 * 228 * DESCRIPTION: Get Buffer length and initializer byte list. This implements 229 * the late evaluation of these attributes. 230 * 231 ******************************************************************************/ 232 233acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) 234{ 235 struct acpi_namespace_node *node; 236 acpi_status status; 237 238 ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); 239 240 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { 241 return_ACPI_STATUS(AE_OK); 242 } 243 244 /* Get the Buffer node */ 245 246 node = obj_desc->buffer.node; 247 if (!node) { 248 ACPI_ERROR((AE_INFO, 249 "No pointer back to NS node in buffer obj %p", 250 obj_desc)); 251 return_ACPI_STATUS(AE_AML_INTERNAL); 252 } 253 254 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); 255 256 /* Execute the AML code for the term_arg arguments */ 257 258 status = acpi_ds_execute_arguments(node, node, 259 obj_desc->buffer.aml_length, 260 obj_desc->buffer.aml_start); 261 return_ACPI_STATUS(status); 262} 263 264/******************************************************************************* 265 * 266 * FUNCTION: acpi_ds_get_package_arguments 267 * 268 * PARAMETERS: obj_desc - A valid Package object 269 * 270 * RETURN: Status. 271 * 272 * DESCRIPTION: Get Package length and initializer byte list. This implements 273 * the late evaluation of these attributes. 274 * 275 ******************************************************************************/ 276 277acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) 278{ 279 struct acpi_namespace_node *node; 280 acpi_status status; 281 282 ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); 283 284 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { 285 return_ACPI_STATUS(AE_OK); 286 } 287 288 /* Get the Package node */ 289 290 node = obj_desc->package.node; 291 if (!node) { 292 ACPI_ERROR((AE_INFO, 293 "No pointer back to NS node in package %p", 294 obj_desc)); 295 return_ACPI_STATUS(AE_AML_INTERNAL); 296 } 297 298 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); 299 300 /* Execute the AML code for the term_arg arguments */ 301 302 status = acpi_ds_execute_arguments(node, node, 303 obj_desc->package.aml_length, 304 obj_desc->package.aml_start); 305 return_ACPI_STATUS(status); 306} 307 308/***************************************************************************** 309 * 310 * FUNCTION: acpi_ds_get_region_arguments 311 * 312 * PARAMETERS: obj_desc - A valid region object 313 * 314 * RETURN: Status. 315 * 316 * DESCRIPTION: Get region address and length. This implements the late 317 * evaluation of these region attributes. 318 * 319 ****************************************************************************/ 320 321acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) 322{ 323 struct acpi_namespace_node *node; 324 acpi_status status; 325 union acpi_operand_object *extra_desc; 326 327 ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); 328 329 if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { 330 return_ACPI_STATUS(AE_OK); 331 } 332 333 extra_desc = acpi_ns_get_secondary_object(obj_desc); 334 if (!extra_desc) { 335 return_ACPI_STATUS(AE_NOT_EXIST); 336 } 337 338 /* Get the Region node */ 339 340 node = obj_desc->region.node; 341 342 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname 343 (ACPI_TYPE_REGION, node, NULL)); 344 345 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", 346 acpi_ut_get_node_name(node), 347 extra_desc->extra.aml_start)); 348 349 /* Execute the argument AML */ 350 351 status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), 352 extra_desc->extra.aml_length, 353 extra_desc->extra.aml_start); 354 if (ACPI_FAILURE(status)) { 355 return_ACPI_STATUS(status); 356 } 357 358 /* Validate the region address/length via the host OS */ 359 360 status = acpi_os_validate_address(obj_desc->region.space_id, 361 obj_desc->region.address, 362 (acpi_size) obj_desc->region.length); 363 if (ACPI_FAILURE(status)) { 364 /* 365 * Invalid address/length. We will emit an error message and mark 366 * the region as invalid, so that it will cause an additional error if 367 * it is ever used. Then return AE_OK. 368 */ 369 ACPI_EXCEPTION((AE_INFO, status, 370 "During address validation of OpRegion [%4.4s]", 371 node->name.ascii)); 372 obj_desc->common.flags |= AOPOBJ_INVALID; 373 status = AE_OK; 374 } 375 376 return_ACPI_STATUS(status); 377} 378 379/******************************************************************************* 380 * 381 * FUNCTION: acpi_ds_initialize_region 382 * 383 * PARAMETERS: obj_handle - Region namespace node 384 * 385 * RETURN: Status 386 * 387 * DESCRIPTION: Front end to ev_initialize_region 388 * 389 ******************************************************************************/ 390 391acpi_status acpi_ds_initialize_region(acpi_handle obj_handle) 392{ 393 union acpi_operand_object *obj_desc; 394 acpi_status status; 395 396 obj_desc = acpi_ns_get_attached_object(obj_handle); 397 398 /* Namespace is NOT locked */ 399 400 status = acpi_ev_initialize_region(obj_desc, FALSE); 401 return (status); 402} 403 404/******************************************************************************* 405 * 406 * FUNCTION: acpi_ds_init_buffer_field 407 * 408 * PARAMETERS: aml_opcode - create_xxx_field 409 * obj_desc - buffer_field object 410 * buffer_desc - Host Buffer 411 * offset_desc - Offset into buffer 412 * length_desc - Length of field (CREATE_FIELD_OP only) 413 * result_desc - Where to store the result 414 * 415 * RETURN: Status 416 * 417 * DESCRIPTION: Perform actual initialization of a buffer field 418 * 419 ******************************************************************************/ 420 421static acpi_status 422acpi_ds_init_buffer_field(u16 aml_opcode, 423 union acpi_operand_object *obj_desc, 424 union acpi_operand_object *buffer_desc, 425 union acpi_operand_object *offset_desc, 426 union acpi_operand_object *length_desc, 427 union acpi_operand_object *result_desc) 428{ 429 u32 offset; 430 u32 bit_offset; 431 u32 bit_count; 432 u8 field_flags; 433 acpi_status status; 434 435 ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); 436 437 /* Host object must be a Buffer */ 438 439 if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) { 440 ACPI_ERROR((AE_INFO, 441 "Target of Create Field is not a Buffer object - %s", 442 acpi_ut_get_object_type_name(buffer_desc))); 443 444 status = AE_AML_OPERAND_TYPE; 445 goto cleanup; 446 } 447 448 /* 449 * The last parameter to all of these opcodes (result_desc) started 450 * out as a name_string, and should therefore now be a NS node 451 * after resolution in acpi_ex_resolve_operands(). 452 */ 453 if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) { 454 ACPI_ERROR((AE_INFO, 455 "(%s) destination not a NS Node [%s]", 456 acpi_ps_get_opcode_name(aml_opcode), 457 acpi_ut_get_descriptor_name(result_desc))); 458 459 status = AE_AML_OPERAND_TYPE; 460 goto cleanup; 461 } 462 463 offset = (u32) offset_desc->integer.value; 464 465 /* 466 * Setup the Bit offsets and counts, according to the opcode 467 */ 468 switch (aml_opcode) { 469 case AML_CREATE_FIELD_OP: 470 471 /* Offset is in bits, count is in bits */ 472 473 field_flags = AML_FIELD_ACCESS_BYTE; 474 bit_offset = offset; 475 bit_count = (u32) length_desc->integer.value; 476 477 /* Must have a valid (>0) bit count */ 478 479 if (bit_count == 0) { 480 ACPI_ERROR((AE_INFO, 481 "Attempt to CreateField of length zero")); 482 status = AE_AML_OPERAND_VALUE; 483 goto cleanup; 484 } 485 break; 486 487 case AML_CREATE_BIT_FIELD_OP: 488 489 /* Offset is in bits, Field is one bit */ 490 491 bit_offset = offset; 492 bit_count = 1; 493 field_flags = AML_FIELD_ACCESS_BYTE; 494 break; 495 496 case AML_CREATE_BYTE_FIELD_OP: 497 498 /* Offset is in bytes, field is one byte */ 499 500 bit_offset = 8 * offset; 501 bit_count = 8; 502 field_flags = AML_FIELD_ACCESS_BYTE; 503 break; 504 505 case AML_CREATE_WORD_FIELD_OP: 506 507 /* Offset is in bytes, field is one word */ 508 509 bit_offset = 8 * offset; 510 bit_count = 16; 511 field_flags = AML_FIELD_ACCESS_WORD; 512 break; 513 514 case AML_CREATE_DWORD_FIELD_OP: 515 516 /* Offset is in bytes, field is one dword */ 517 518 bit_offset = 8 * offset; 519 bit_count = 32; 520 field_flags = AML_FIELD_ACCESS_DWORD; 521 break; 522 523 case AML_CREATE_QWORD_FIELD_OP: 524 525 /* Offset is in bytes, field is one qword */ 526 527 bit_offset = 8 * offset; 528 bit_count = 64; 529 field_flags = AML_FIELD_ACCESS_QWORD; 530 break; 531 532 default: 533 534 ACPI_ERROR((AE_INFO, 535 "Unknown field creation opcode %02x", aml_opcode)); 536 status = AE_AML_BAD_OPCODE; 537 goto cleanup; 538 } 539 540 /* Entire field must fit within the current length of the buffer */ 541 542 if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { 543 ACPI_ERROR((AE_INFO, 544 "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)", 545 acpi_ut_get_node_name(result_desc), 546 bit_offset + bit_count, 547 acpi_ut_get_node_name(buffer_desc->buffer.node), 548 8 * (u32) buffer_desc->buffer.length)); 549 status = AE_AML_BUFFER_LIMIT; 550 goto cleanup; 551 } 552 553 /* 554 * Initialize areas of the field object that are common to all fields 555 * For field_flags, use LOCK_RULE = 0 (NO_LOCK), 556 * UPDATE_RULE = 0 (UPDATE_PRESERVE) 557 */ 558 status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, 559 bit_offset, bit_count); 560 if (ACPI_FAILURE(status)) { 561 goto cleanup; 562 } 563 564 obj_desc->buffer_field.buffer_obj = buffer_desc; 565 566 /* Reference count for buffer_desc inherits obj_desc count */ 567 568 buffer_desc->common.reference_count = (u16) 569 (buffer_desc->common.reference_count + 570 obj_desc->common.reference_count); 571 572 cleanup: 573 574 /* Always delete the operands */ 575 576 acpi_ut_remove_reference(offset_desc); 577 acpi_ut_remove_reference(buffer_desc); 578 579 if (aml_opcode == AML_CREATE_FIELD_OP) { 580 acpi_ut_remove_reference(length_desc); 581 } 582 583 /* On failure, delete the result descriptor */ 584 585 if (ACPI_FAILURE(status)) { 586 acpi_ut_remove_reference(result_desc); /* Result descriptor */ 587 } else { 588 /* Now the address and length are valid for this buffer_field */ 589 590 obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; 591 } 592 593 return_ACPI_STATUS(status); 594} 595 596/******************************************************************************* 597 * 598 * FUNCTION: acpi_ds_eval_buffer_field_operands 599 * 600 * PARAMETERS: walk_state - Current walk 601 * Op - A valid buffer_field Op object 602 * 603 * RETURN: Status 604 * 605 * DESCRIPTION: Get buffer_field Buffer and Index 606 * Called from acpi_ds_exec_end_op during buffer_field parse tree walk 607 * 608 ******************************************************************************/ 609 610acpi_status 611acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, 612 union acpi_parse_object *op) 613{ 614 acpi_status status; 615 union acpi_operand_object *obj_desc; 616 struct acpi_namespace_node *node; 617 union acpi_parse_object *next_op; 618 619 ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); 620 621 /* 622 * This is where we evaluate the address and length fields of the 623 * create_xxx_field declaration 624 */ 625 node = op->common.node; 626 627 /* next_op points to the op that holds the Buffer */ 628 629 next_op = op->common.value.arg; 630 631 /* Evaluate/create the address and length operands */ 632 633 status = acpi_ds_create_operands(walk_state, next_op); 634 if (ACPI_FAILURE(status)) { 635 return_ACPI_STATUS(status); 636 } 637 638 obj_desc = acpi_ns_get_attached_object(node); 639 if (!obj_desc) { 640 return_ACPI_STATUS(AE_NOT_EXIST); 641 } 642 643 /* Resolve the operands */ 644 645 status = acpi_ex_resolve_operands(op->common.aml_opcode, 646 ACPI_WALK_OPERANDS, walk_state); 647 648 ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, 649 acpi_ps_get_opcode_name(op->common.aml_opcode), 650 walk_state->num_operands, 651 "after AcpiExResolveOperands"); 652 653 if (ACPI_FAILURE(status)) { 654 ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)", 655 acpi_ps_get_opcode_name(op->common.aml_opcode), 656 status)); 657 658 return_ACPI_STATUS(status); 659 } 660 661 /* Initialize the Buffer Field */ 662 663 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { 664 665 /* NOTE: Slightly different operands for this opcode */ 666 667 status = 668 acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, 669 walk_state->operands[0], 670 walk_state->operands[1], 671 walk_state->operands[2], 672 walk_state->operands[3]); 673 } else { 674 /* All other, create_xxx_field opcodes */ 675 676 status = 677 acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, 678 walk_state->operands[0], 679 walk_state->operands[1], NULL, 680 walk_state->operands[2]); 681 } 682 683 return_ACPI_STATUS(status); 684} 685 686/******************************************************************************* 687 * 688 * FUNCTION: acpi_ds_eval_region_operands 689 * 690 * PARAMETERS: walk_state - Current walk 691 * Op - A valid region Op object 692 * 693 * RETURN: Status 694 * 695 * DESCRIPTION: Get region address and length 696 * Called from acpi_ds_exec_end_op during op_region parse tree walk 697 * 698 ******************************************************************************/ 699 700acpi_status 701acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, 702 union acpi_parse_object *op) 703{ 704 acpi_status status; 705 union acpi_operand_object *obj_desc; 706 union acpi_operand_object *operand_desc; 707 struct acpi_namespace_node *node; 708 union acpi_parse_object *next_op; 709 710 ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); 711 712 /* 713 * This is where we evaluate the address and length fields of the 714 * op_region declaration 715 */ 716 node = op->common.node; 717 718 /* next_op points to the op that holds the space_iD */ 719 720 next_op = op->common.value.arg; 721 722 /* next_op points to address op */ 723 724 next_op = next_op->common.next; 725 726 /* Evaluate/create the address and length operands */ 727 728 status = acpi_ds_create_operands(walk_state, next_op); 729 if (ACPI_FAILURE(status)) { 730 return_ACPI_STATUS(status); 731 } 732 733 /* Resolve the length and address operands to numbers */ 734 735 status = acpi_ex_resolve_operands(op->common.aml_opcode, 736 ACPI_WALK_OPERANDS, walk_state); 737 if (ACPI_FAILURE(status)) { 738 return_ACPI_STATUS(status); 739 } 740 741 ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, 742 acpi_ps_get_opcode_name(op->common.aml_opcode), 743 1, "after AcpiExResolveOperands"); 744 745 obj_desc = acpi_ns_get_attached_object(node); 746 if (!obj_desc) { 747 return_ACPI_STATUS(AE_NOT_EXIST); 748 } 749 750 /* 751 * Get the length operand and save it 752 * (at Top of stack) 753 */ 754 operand_desc = walk_state->operands[walk_state->num_operands - 1]; 755 756 obj_desc->region.length = (u32) operand_desc->integer.value; 757 acpi_ut_remove_reference(operand_desc); 758 759 /* 760 * Get the address and save it 761 * (at top of stack - 1) 762 */ 763 operand_desc = walk_state->operands[walk_state->num_operands - 2]; 764 765 obj_desc->region.address = (acpi_physical_address) 766 operand_desc->integer.value; 767 acpi_ut_remove_reference(operand_desc); 768 769 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", 770 obj_desc, 771 ACPI_FORMAT_UINT64(obj_desc->region.address), 772 obj_desc->region.length)); 773 774 /* Now the address and length are valid for this opregion */ 775 776 obj_desc->region.flags |= AOPOBJ_DATA_VALID; 777 778 return_ACPI_STATUS(status); 779} 780 781/******************************************************************************* 782 * 783 * FUNCTION: acpi_ds_eval_data_object_operands 784 * 785 * PARAMETERS: walk_state - Current walk 786 * Op - A valid data_object Op object 787 * obj_desc - data_object 788 * 789 * RETURN: Status 790 * 791 * DESCRIPTION: Get the operands and complete the following data object types: 792 * Buffer, Package. 793 * 794 ******************************************************************************/ 795 796acpi_status 797acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, 798 union acpi_parse_object *op, 799 union acpi_operand_object *obj_desc) 800{ 801 acpi_status status; 802 union acpi_operand_object *arg_desc; 803 u32 length; 804 805 ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); 806 807 /* The first operand (for all of these data objects) is the length */ 808 809 status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); 810 if (ACPI_FAILURE(status)) { 811 return_ACPI_STATUS(status); 812 } 813 814 status = acpi_ex_resolve_operands(walk_state->opcode, 815 &(walk_state-> 816 operands[walk_state->num_operands - 817 1]), walk_state); 818 if (ACPI_FAILURE(status)) { 819 return_ACPI_STATUS(status); 820 } 821 822 /* Extract length operand */ 823 824 arg_desc = walk_state->operands[walk_state->num_operands - 1]; 825 length = (u32) arg_desc->integer.value; 826 827 /* Cleanup for length operand */ 828 829 status = acpi_ds_obj_stack_pop(1, walk_state); 830 if (ACPI_FAILURE(status)) { 831 return_ACPI_STATUS(status); 832 } 833 834 acpi_ut_remove_reference(arg_desc); 835 836 /* 837 * Create the actual data object 838 */ 839 switch (op->common.aml_opcode) { 840 case AML_BUFFER_OP: 841 842 status = 843 acpi_ds_build_internal_buffer_obj(walk_state, op, length, 844 &obj_desc); 845 break; 846 847 case AML_PACKAGE_OP: 848 case AML_VAR_PACKAGE_OP: 849 850 status = 851 acpi_ds_build_internal_package_obj(walk_state, op, length, 852 &obj_desc); 853 break; 854 855 default: 856 return_ACPI_STATUS(AE_AML_BAD_OPCODE); 857 } 858 859 if (ACPI_SUCCESS(status)) { 860 /* 861 * Return the object in the walk_state, unless the parent is a package - 862 * in this case, the return object will be stored in the parse tree 863 * for the package. 864 */ 865 if ((!op->common.parent) || 866 ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && 867 (op->common.parent->common.aml_opcode != 868 AML_VAR_PACKAGE_OP) 869 && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { 870 walk_state->result_obj = obj_desc; 871 } 872 } 873 874 return_ACPI_STATUS(status); 875} 876 877/******************************************************************************* 878 * 879 * FUNCTION: acpi_ds_exec_begin_control_op 880 * 881 * PARAMETERS: walk_list - The list that owns the walk stack 882 * Op - The control Op 883 * 884 * RETURN: Status 885 * 886 * DESCRIPTION: Handles all control ops encountered during control method 887 * execution. 888 * 889 ******************************************************************************/ 890 891acpi_status 892acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, 893 union acpi_parse_object *op) 894{ 895 acpi_status status = AE_OK; 896 union acpi_generic_state *control_state; 897 898 ACPI_FUNCTION_NAME(ds_exec_begin_control_op); 899 900 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, 901 op->common.aml_opcode, walk_state)); 902 903 switch (op->common.aml_opcode) { 904 case AML_IF_OP: 905 case AML_WHILE_OP: 906 907 /* 908 * IF/WHILE: Create a new control state to manage these 909 * constructs. We need to manage these as a stack, in order 910 * to handle nesting. 911 */ 912 control_state = acpi_ut_create_control_state(); 913 if (!control_state) { 914 status = AE_NO_MEMORY; 915 break; 916 } 917 /* 918 * Save a pointer to the predicate for multiple executions 919 * of a loop 920 */ 921 control_state->control.aml_predicate_start = 922 walk_state->parser_state.aml - 1; 923 control_state->control.package_end = 924 walk_state->parser_state.pkg_end; 925 control_state->control.opcode = op->common.aml_opcode; 926 927 /* Push the control state on this walk's control stack */ 928 929 acpi_ut_push_generic_state(&walk_state->control_state, 930 control_state); 931 break; 932 933 case AML_ELSE_OP: 934 935 /* Predicate is in the state object */ 936 /* If predicate is true, the IF was executed, ignore ELSE part */ 937 938 if (walk_state->last_predicate) { 939 status = AE_CTRL_TRUE; 940 } 941 942 break; 943 944 case AML_RETURN_OP: 945 946 break; 947 948 default: 949 break; 950 } 951 952 return (status); 953} 954 955/******************************************************************************* 956 * 957 * FUNCTION: acpi_ds_exec_end_control_op 958 * 959 * PARAMETERS: walk_list - The list that owns the walk stack 960 * Op - The control Op 961 * 962 * RETURN: Status 963 * 964 * DESCRIPTION: Handles all control ops encountered during control method 965 * execution. 966 * 967 ******************************************************************************/ 968 969acpi_status 970acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, 971 union acpi_parse_object * op) 972{ 973 acpi_status status = AE_OK; 974 union acpi_generic_state *control_state; 975 976 ACPI_FUNCTION_NAME(ds_exec_end_control_op); 977 978 switch (op->common.aml_opcode) { 979 case AML_IF_OP: 980 981 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); 982 983 /* 984 * Save the result of the predicate in case there is an 985 * ELSE to come 986 */ 987 walk_state->last_predicate = 988 (u8) walk_state->control_state->common.value; 989 990 /* 991 * Pop the control state that was created at the start 992 * of the IF and free it 993 */ 994 control_state = 995 acpi_ut_pop_generic_state(&walk_state->control_state); 996 acpi_ut_delete_generic_state(control_state); 997 break; 998 999 case AML_ELSE_OP: 1000 1001 break; 1002 1003 case AML_WHILE_OP: 1004 1005 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); 1006 1007 if (walk_state->control_state->common.value) { 1008 1009 /* Predicate was true, go back and evaluate it again! */ 1010 1011 status = AE_CTRL_PENDING; 1012 } 1013 1014 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 1015 "[WHILE_OP] termination! Op=%p\n", op)); 1016 1017 /* Pop this control state and free it */ 1018 1019 control_state = 1020 acpi_ut_pop_generic_state(&walk_state->control_state); 1021 1022 walk_state->aml_last_while = 1023 control_state->control.aml_predicate_start; 1024 acpi_ut_delete_generic_state(control_state); 1025 break; 1026 1027 case AML_RETURN_OP: 1028 1029 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 1030 "[RETURN_OP] Op=%p Arg=%p\n", op, 1031 op->common.value.arg)); 1032 1033 /* 1034 * One optional operand -- the return value 1035 * It can be either an immediate operand or a result that 1036 * has been bubbled up the tree 1037 */ 1038 if (op->common.value.arg) { 1039 1040 /* Since we have a real Return(), delete any implicit return */ 1041 1042 acpi_ds_clear_implicit_return(walk_state); 1043 1044 /* Return statement has an immediate operand */ 1045 1046 status = 1047 acpi_ds_create_operands(walk_state, 1048 op->common.value.arg); 1049 if (ACPI_FAILURE(status)) { 1050 return (status); 1051 } 1052 1053 /* 1054 * If value being returned is a Reference (such as 1055 * an arg or local), resolve it now because it may 1056 * cease to exist at the end of the method. 1057 */ 1058 status = 1059 acpi_ex_resolve_to_value(&walk_state->operands[0], 1060 walk_state); 1061 if (ACPI_FAILURE(status)) { 1062 return (status); 1063 } 1064 1065 /* 1066 * Get the return value and save as the last result 1067 * value. This is the only place where walk_state->return_desc 1068 * is set to anything other than zero! 1069 */ 1070 walk_state->return_desc = walk_state->operands[0]; 1071 } else if ((walk_state->results) && 1072 (walk_state->results->results.num_results > 0)) { 1073 1074 /* Since we have a real Return(), delete any implicit return */ 1075 1076 acpi_ds_clear_implicit_return(walk_state); 1077 1078 /* 1079 * The return value has come from a previous calculation. 1080 * 1081 * If value being returned is a Reference (such as 1082 * an arg or local), resolve it now because it may 1083 * cease to exist at the end of the method. 1084 * 1085 * Allow references created by the Index operator to return unchanged. 1086 */ 1087 if ((ACPI_GET_DESCRIPTOR_TYPE 1088 (walk_state->results->results.obj_desc[0]) == 1089 ACPI_DESC_TYPE_OPERAND) 1090 && 1091 (ACPI_GET_OBJECT_TYPE 1092 (walk_state->results->results.obj_desc[0]) == 1093 ACPI_TYPE_LOCAL_REFERENCE) 1094 && ((walk_state->results->results.obj_desc[0])-> 1095 reference.opcode != AML_INDEX_OP)) { 1096 status = 1097 acpi_ex_resolve_to_value(&walk_state-> 1098 results->results. 1099 obj_desc[0], 1100 walk_state); 1101 if (ACPI_FAILURE(status)) { 1102 return (status); 1103 } 1104 } 1105 1106 walk_state->return_desc = 1107 walk_state->results->results.obj_desc[0]; 1108 } else { 1109 /* No return operand */ 1110 1111 if (walk_state->num_operands) { 1112 acpi_ut_remove_reference(walk_state-> 1113 operands[0]); 1114 } 1115 1116 walk_state->operands[0] = NULL; 1117 walk_state->num_operands = 0; 1118 walk_state->return_desc = NULL; 1119 } 1120 1121 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 1122 "Completed RETURN_OP State=%p, RetVal=%p\n", 1123 walk_state, walk_state->return_desc)); 1124 1125 /* End the control method execution right now */ 1126 1127 status = AE_CTRL_TERMINATE; 1128 break; 1129 1130 case AML_NOOP_OP: 1131 1132 /* Just do nothing! */ 1133 break; 1134 1135 case AML_BREAK_POINT_OP: 1136 1137 /* Call up to the OS service layer to handle this */ 1138 1139 status = 1140 acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, 1141 "Executed AML Breakpoint opcode"); 1142 1143 /* If and when it returns, all done. */ 1144 1145 break; 1146 1147 case AML_BREAK_OP: 1148 case AML_CONTINUE_OP: /* ACPI 2.0 */ 1149 1150 /* Pop and delete control states until we find a while */ 1151 1152 while (walk_state->control_state && 1153 (walk_state->control_state->control.opcode != 1154 AML_WHILE_OP)) { 1155 control_state = 1156 acpi_ut_pop_generic_state(&walk_state-> 1157 control_state); 1158 acpi_ut_delete_generic_state(control_state); 1159 } 1160 1161 /* No while found? */ 1162 1163 if (!walk_state->control_state) { 1164 return (AE_AML_NO_WHILE); 1165 } 1166 1167 /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ 1168 1169 walk_state->aml_last_while = 1170 walk_state->control_state->control.package_end; 1171 1172 /* Return status depending on opcode */ 1173 1174 if (op->common.aml_opcode == AML_BREAK_OP) { 1175 status = AE_CTRL_BREAK; 1176 } else { 1177 status = AE_CTRL_CONTINUE; 1178 } 1179 break; 1180 1181 default: 1182 1183 ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p", 1184 op->common.aml_opcode, op)); 1185 1186 status = AE_AML_BAD_OPCODE; 1187 break; 1188 } 1189 1190 return (status); 1191} 1192