at v2.6.12 19 kB view raw
1/****************************************************************************** 2 * 3 * Module Name: psargs - Parse AML opcode arguments 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2005, R. Byron Moore 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 45#include <acpi/acpi.h> 46#include <acpi/acparser.h> 47#include <acpi/amlcode.h> 48#include <acpi/acnamesp.h> 49 50#define _COMPONENT ACPI_PARSER 51 ACPI_MODULE_NAME ("psargs") 52 53 54/******************************************************************************* 55 * 56 * FUNCTION: acpi_ps_get_next_package_length 57 * 58 * PARAMETERS: parser_state - Current parser state object 59 * 60 * RETURN: Decoded package length. On completion, the AML pointer points 61 * past the length byte or bytes. 62 * 63 * DESCRIPTION: Decode and return a package length field 64 * 65 ******************************************************************************/ 66 67u32 68acpi_ps_get_next_package_length ( 69 struct acpi_parse_state *parser_state) 70{ 71 u32 encoded_length; 72 u32 length = 0; 73 74 75 ACPI_FUNCTION_TRACE ("ps_get_next_package_length"); 76 77 78 encoded_length = (u32) ACPI_GET8 (parser_state->aml); 79 parser_state->aml++; 80 81 82 switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ { 83 case 0: /* 1-byte encoding (bits 0-5) */ 84 85 length = (encoded_length & 0x3F); 86 break; 87 88 89 case 1: /* 2-byte encoding (next byte + bits 0-3) */ 90 91 length = ((ACPI_GET8 (parser_state->aml) << 04) | 92 (encoded_length & 0x0F)); 93 parser_state->aml++; 94 break; 95 96 97 case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */ 98 99 length = ((ACPI_GET8 (parser_state->aml + 1) << 12) | 100 (ACPI_GET8 (parser_state->aml) << 04) | 101 (encoded_length & 0x0F)); 102 parser_state->aml += 2; 103 break; 104 105 106 case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */ 107 108 length = ((ACPI_GET8 (parser_state->aml + 2) << 20) | 109 (ACPI_GET8 (parser_state->aml + 1) << 12) | 110 (ACPI_GET8 (parser_state->aml) << 04) | 111 (encoded_length & 0x0F)); 112 parser_state->aml += 3; 113 break; 114 115 default: 116 117 /* Can't get here, only 2 bits / 4 cases */ 118 break; 119 } 120 121 return_VALUE (length); 122} 123 124 125/******************************************************************************* 126 * 127 * FUNCTION: acpi_ps_get_next_package_end 128 * 129 * PARAMETERS: parser_state - Current parser state object 130 * 131 * RETURN: Pointer to end-of-package +1 132 * 133 * DESCRIPTION: Get next package length and return a pointer past the end of 134 * the package. Consumes the package length field 135 * 136 ******************************************************************************/ 137 138u8 * 139acpi_ps_get_next_package_end ( 140 struct acpi_parse_state *parser_state) 141{ 142 u8 *start = parser_state->aml; 143 acpi_native_uint length; 144 145 146 ACPI_FUNCTION_TRACE ("ps_get_next_package_end"); 147 148 149 /* Function below changes parser_state->Aml */ 150 151 length = (acpi_native_uint) acpi_ps_get_next_package_length (parser_state); 152 153 return_PTR (start + length); /* end of package */ 154} 155 156 157/******************************************************************************* 158 * 159 * FUNCTION: acpi_ps_get_next_namestring 160 * 161 * PARAMETERS: parser_state - Current parser state object 162 * 163 * RETURN: Pointer to the start of the name string (pointer points into 164 * the AML. 165 * 166 * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name 167 * prefix characters. Set parser state to point past the string. 168 * (Name is consumed from the AML.) 169 * 170 ******************************************************************************/ 171 172char * 173acpi_ps_get_next_namestring ( 174 struct acpi_parse_state *parser_state) 175{ 176 u8 *start = parser_state->aml; 177 u8 *end = parser_state->aml; 178 179 180 ACPI_FUNCTION_TRACE ("ps_get_next_namestring"); 181 182 183 /* Handle multiple prefix characters */ 184 185 while (acpi_ps_is_prefix_char (ACPI_GET8 (end))) { 186 /* Include prefix '\\' or '^' */ 187 188 end++; 189 } 190 191 /* Decode the path */ 192 193 switch (ACPI_GET8 (end)) { 194 case 0: 195 196 /* null_name */ 197 198 if (end == start) { 199 start = NULL; 200 } 201 end++; 202 break; 203 204 case AML_DUAL_NAME_PREFIX: 205 206 /* Two name segments */ 207 208 end += 1 + (2 * ACPI_NAME_SIZE); 209 break; 210 211 case AML_MULTI_NAME_PREFIX_OP: 212 213 /* Multiple name segments, 4 chars each */ 214 215 end += 2 + ((acpi_size) ACPI_GET8 (end + 1) * ACPI_NAME_SIZE); 216 break; 217 218 default: 219 220 /* Single name segment */ 221 222 end += ACPI_NAME_SIZE; 223 break; 224 } 225 226 parser_state->aml = (u8*) end; 227 return_PTR ((char *) start); 228} 229 230 231/******************************************************************************* 232 * 233 * FUNCTION: acpi_ps_get_next_namepath 234 * 235 * PARAMETERS: parser_state - Current parser state object 236 * Arg - Where the namepath will be stored 237 * arg_count - If the namepath points to a control method 238 * the method's argument is returned here. 239 * method_call - Whether the namepath can possibly be the 240 * start of a method call 241 * 242 * RETURN: Status 243 * 244 * DESCRIPTION: Get next name (if method call, return # of required args). 245 * Names are looked up in the internal namespace to determine 246 * if the name represents a control method. If a method 247 * is found, the number of arguments to the method is returned. 248 * This information is critical for parsing to continue correctly. 249 * 250 ******************************************************************************/ 251 252acpi_status 253acpi_ps_get_next_namepath ( 254 struct acpi_walk_state *walk_state, 255 struct acpi_parse_state *parser_state, 256 union acpi_parse_object *arg, 257 u8 method_call) 258{ 259 char *path; 260 union acpi_parse_object *name_op; 261 acpi_status status = AE_OK; 262 union acpi_operand_object *method_desc; 263 struct acpi_namespace_node *node; 264 union acpi_generic_state scope_info; 265 266 267 ACPI_FUNCTION_TRACE ("ps_get_next_namepath"); 268 269 270 path = acpi_ps_get_next_namestring (parser_state); 271 272 /* Null path case is allowed */ 273 274 if (path) { 275 /* 276 * Lookup the name in the internal namespace 277 */ 278 scope_info.scope.node = NULL; 279 node = parser_state->start_node; 280 if (node) { 281 scope_info.scope.node = node; 282 } 283 284 /* 285 * Lookup object. We don't want to add anything new to the namespace 286 * here, however. So we use MODE_EXECUTE. Allow searching of the 287 * parent tree, but don't open a new scope -- we just want to lookup the 288 * object (MUST BE mode EXECUTE to perform upsearch) 289 */ 290 status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 291 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &node); 292 if (ACPI_SUCCESS (status) && method_call) { 293 if (node->type == ACPI_TYPE_METHOD) { 294 /* 295 * This name is actually a control method invocation 296 */ 297 method_desc = acpi_ns_get_attached_object (node); 298 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 299 "Control Method - %p Desc %p Path=%p\n", 300 node, method_desc, path)); 301 302 name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP); 303 if (!name_op) { 304 return_ACPI_STATUS (AE_NO_MEMORY); 305 } 306 307 /* Change arg into a METHOD CALL and attach name to it */ 308 309 acpi_ps_init_op (arg, AML_INT_METHODCALL_OP); 310 name_op->common.value.name = path; 311 312 /* Point METHODCALL/NAME to the METHOD Node */ 313 314 name_op->common.node = node; 315 acpi_ps_append_arg (arg, name_op); 316 317 if (!method_desc) { 318 ACPI_REPORT_ERROR (( 319 "ps_get_next_namepath: Control Method %p has no attached object\n", 320 node)); 321 return_ACPI_STATUS (AE_AML_INTERNAL); 322 } 323 324 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 325 "Control Method - %p Args %X\n", 326 node, method_desc->method.param_count)); 327 328 /* Get the number of arguments to expect */ 329 330 walk_state->arg_count = method_desc->method.param_count; 331 return_ACPI_STATUS (AE_OK); 332 } 333 334 /* 335 * Else this is normal named object reference. 336 * Just init the NAMEPATH object with the pathname. 337 * (See code below) 338 */ 339 } 340 341 if (ACPI_FAILURE (status)) { 342 /* 343 * 1) Any error other than NOT_FOUND is always severe 344 * 2) NOT_FOUND is only important if we are executing a method. 345 * 3) If executing a cond_ref_of opcode, NOT_FOUND is ok. 346 */ 347 if ((((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) && 348 (status == AE_NOT_FOUND) && 349 (walk_state->op->common.aml_opcode != AML_COND_REF_OF_OP)) || 350 351 (status != AE_NOT_FOUND)) { 352 ACPI_REPORT_NSERROR (path, status); 353 354 acpi_os_printf ("search_node %p start_node %p return_node %p\n", 355 scope_info.scope.node, parser_state->start_node, node); 356 357 358 } 359 else { 360 /* 361 * We got a NOT_FOUND during table load or we encountered 362 * a cond_ref_of(x) where the target does not exist. 363 * -- either case is ok 364 */ 365 status = AE_OK; 366 } 367 } 368 } 369 370 /* 371 * Regardless of success/failure above, 372 * Just initialize the Op with the pathname. 373 */ 374 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); 375 arg->common.value.name = path; 376 377 return_ACPI_STATUS (status); 378} 379 380 381/******************************************************************************* 382 * 383 * FUNCTION: acpi_ps_get_next_simple_arg 384 * 385 * PARAMETERS: parser_state - Current parser state object 386 * arg_type - The argument type (AML_*_ARG) 387 * Arg - Where the argument is returned 388 * 389 * RETURN: None 390 * 391 * DESCRIPTION: Get the next simple argument (constant, string, or namestring) 392 * 393 ******************************************************************************/ 394 395void 396acpi_ps_get_next_simple_arg ( 397 struct acpi_parse_state *parser_state, 398 u32 arg_type, 399 union acpi_parse_object *arg) 400{ 401 402 ACPI_FUNCTION_TRACE_U32 ("ps_get_next_simple_arg", arg_type); 403 404 405 switch (arg_type) { 406 case ARGP_BYTEDATA: 407 408 acpi_ps_init_op (arg, AML_BYTE_OP); 409 arg->common.value.integer = (u32) ACPI_GET8 (parser_state->aml); 410 parser_state->aml++; 411 break; 412 413 414 case ARGP_WORDDATA: 415 416 acpi_ps_init_op (arg, AML_WORD_OP); 417 418 /* Get 2 bytes from the AML stream */ 419 420 ACPI_MOVE_16_TO_32 (&arg->common.value.integer, parser_state->aml); 421 parser_state->aml += 2; 422 break; 423 424 425 case ARGP_DWORDDATA: 426 427 acpi_ps_init_op (arg, AML_DWORD_OP); 428 429 /* Get 4 bytes from the AML stream */ 430 431 ACPI_MOVE_32_TO_32 (&arg->common.value.integer, parser_state->aml); 432 parser_state->aml += 4; 433 break; 434 435 436 case ARGP_QWORDDATA: 437 438 acpi_ps_init_op (arg, AML_QWORD_OP); 439 440 /* Get 8 bytes from the AML stream */ 441 442 ACPI_MOVE_64_TO_64 (&arg->common.value.integer, parser_state->aml); 443 parser_state->aml += 8; 444 break; 445 446 447 case ARGP_CHARLIST: 448 449 acpi_ps_init_op (arg, AML_STRING_OP); 450 arg->common.value.string = (char *) parser_state->aml; 451 452 while (ACPI_GET8 (parser_state->aml) != '\0') { 453 parser_state->aml++; 454 } 455 parser_state->aml++; 456 break; 457 458 459 case ARGP_NAME: 460 case ARGP_NAMESTRING: 461 462 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); 463 arg->common.value.name = acpi_ps_get_next_namestring (parser_state); 464 break; 465 466 467 default: 468 469 ACPI_REPORT_ERROR (("Invalid arg_type %X\n", arg_type)); 470 break; 471 } 472 473 return_VOID; 474} 475 476 477/******************************************************************************* 478 * 479 * FUNCTION: acpi_ps_get_next_field 480 * 481 * PARAMETERS: parser_state - Current parser state object 482 * 483 * RETURN: A newly allocated FIELD op 484 * 485 * DESCRIPTION: Get next field (named_field, reserved_field, or access_field) 486 * 487 ******************************************************************************/ 488 489union acpi_parse_object * 490acpi_ps_get_next_field ( 491 struct acpi_parse_state *parser_state) 492{ 493 u32 aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, 494 parser_state->aml_start); 495 union acpi_parse_object *field; 496 u16 opcode; 497 u32 name; 498 499 500 ACPI_FUNCTION_TRACE ("ps_get_next_field"); 501 502 503 /* determine field type */ 504 505 switch (ACPI_GET8 (parser_state->aml)) { 506 default: 507 508 opcode = AML_INT_NAMEDFIELD_OP; 509 break; 510 511 case 0x00: 512 513 opcode = AML_INT_RESERVEDFIELD_OP; 514 parser_state->aml++; 515 break; 516 517 case 0x01: 518 519 opcode = AML_INT_ACCESSFIELD_OP; 520 parser_state->aml++; 521 break; 522 } 523 524 525 /* Allocate a new field op */ 526 527 field = acpi_ps_alloc_op (opcode); 528 if (!field) { 529 return_PTR (NULL); 530 } 531 532 field->common.aml_offset = aml_offset; 533 534 /* Decode the field type */ 535 536 switch (opcode) { 537 case AML_INT_NAMEDFIELD_OP: 538 539 /* Get the 4-character name */ 540 541 ACPI_MOVE_32_TO_32 (&name, parser_state->aml); 542 acpi_ps_set_name (field, name); 543 parser_state->aml += ACPI_NAME_SIZE; 544 545 /* Get the length which is encoded as a package length */ 546 547 field->common.value.size = acpi_ps_get_next_package_length (parser_state); 548 break; 549 550 551 case AML_INT_RESERVEDFIELD_OP: 552 553 /* Get the length which is encoded as a package length */ 554 555 field->common.value.size = acpi_ps_get_next_package_length (parser_state); 556 break; 557 558 559 case AML_INT_ACCESSFIELD_OP: 560 561 /* 562 * Get access_type and access_attrib and merge into the field Op 563 * access_type is first operand, access_attribute is second 564 */ 565 field->common.value.integer = (ACPI_GET8 (parser_state->aml) << 8); 566 parser_state->aml++; 567 field->common.value.integer |= ACPI_GET8 (parser_state->aml); 568 parser_state->aml++; 569 break; 570 571 default: 572 573 /* Opcode was set in previous switch */ 574 break; 575 } 576 577 return_PTR (field); 578} 579 580 581/******************************************************************************* 582 * 583 * FUNCTION: acpi_ps_get_next_arg 584 * 585 * PARAMETERS: parser_state - Current parser state object 586 * arg_type - The argument type (AML_*_ARG) 587 * arg_count - If the argument points to a control method 588 * the method's argument is returned here. 589 * 590 * RETURN: Status, and an op object containing the next argument. 591 * 592 * DESCRIPTION: Get next argument (including complex list arguments that require 593 * pushing the parser stack) 594 * 595 ******************************************************************************/ 596 597acpi_status 598acpi_ps_get_next_arg ( 599 struct acpi_walk_state *walk_state, 600 struct acpi_parse_state *parser_state, 601 u32 arg_type, 602 union acpi_parse_object **return_arg) 603{ 604 union acpi_parse_object *arg = NULL; 605 union acpi_parse_object *prev = NULL; 606 union acpi_parse_object *field; 607 u32 subop; 608 acpi_status status = AE_OK; 609 610 611 ACPI_FUNCTION_TRACE_PTR ("ps_get_next_arg", parser_state); 612 613 614 switch (arg_type) { 615 case ARGP_BYTEDATA: 616 case ARGP_WORDDATA: 617 case ARGP_DWORDDATA: 618 case ARGP_CHARLIST: 619 case ARGP_NAME: 620 case ARGP_NAMESTRING: 621 622 /* constants, strings, and namestrings are all the same size */ 623 624 arg = acpi_ps_alloc_op (AML_BYTE_OP); 625 if (!arg) { 626 return_ACPI_STATUS (AE_NO_MEMORY); 627 } 628 acpi_ps_get_next_simple_arg (parser_state, arg_type, arg); 629 break; 630 631 632 case ARGP_PKGLENGTH: 633 634 /* Package length, nothing returned */ 635 636 parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state); 637 break; 638 639 640 case ARGP_FIELDLIST: 641 642 if (parser_state->aml < parser_state->pkg_end) { 643 /* Non-empty list */ 644 645 while (parser_state->aml < parser_state->pkg_end) { 646 field = acpi_ps_get_next_field (parser_state); 647 if (!field) { 648 return_ACPI_STATUS (AE_NO_MEMORY); 649 } 650 651 if (prev) { 652 prev->common.next = field; 653 } 654 else { 655 arg = field; 656 } 657 658 prev = field; 659 } 660 661 /* Skip to End of byte data */ 662 663 parser_state->aml = parser_state->pkg_end; 664 } 665 break; 666 667 668 case ARGP_BYTELIST: 669 670 if (parser_state->aml < parser_state->pkg_end) { 671 /* Non-empty list */ 672 673 arg = acpi_ps_alloc_op (AML_INT_BYTELIST_OP); 674 if (!arg) { 675 return_ACPI_STATUS (AE_NO_MEMORY); 676 } 677 678 /* Fill in bytelist data */ 679 680 arg->common.value.size = (u32) ACPI_PTR_DIFF (parser_state->pkg_end, 681 parser_state->aml); 682 arg->named.data = parser_state->aml; 683 684 /* Skip to End of byte data */ 685 686 parser_state->aml = parser_state->pkg_end; 687 } 688 break; 689 690 691 case ARGP_TARGET: 692 case ARGP_SUPERNAME: 693 case ARGP_SIMPLENAME: 694 695 subop = acpi_ps_peek_opcode (parser_state); 696 if (subop == 0 || 697 acpi_ps_is_leading_char (subop) || 698 acpi_ps_is_prefix_char (subop)) { 699 /* null_name or name_string */ 700 701 arg = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP); 702 if (!arg) { 703 return_ACPI_STATUS (AE_NO_MEMORY); 704 } 705 706 status = acpi_ps_get_next_namepath (walk_state, parser_state, arg, 0); 707 } 708 else { 709 /* single complex argument, nothing returned */ 710 711 walk_state->arg_count = 1; 712 } 713 break; 714 715 716 case ARGP_DATAOBJ: 717 case ARGP_TERMARG: 718 719 /* single complex argument, nothing returned */ 720 721 walk_state->arg_count = 1; 722 break; 723 724 725 case ARGP_DATAOBJLIST: 726 case ARGP_TERMLIST: 727 case ARGP_OBJLIST: 728 729 if (parser_state->aml < parser_state->pkg_end) { 730 /* non-empty list of variable arguments, nothing returned */ 731 732 walk_state->arg_count = ACPI_VAR_ARGS; 733 } 734 break; 735 736 737 default: 738 739 ACPI_REPORT_ERROR (("Invalid arg_type: %X\n", arg_type)); 740 status = AE_AML_OPERAND_TYPE; 741 break; 742 } 743 744 *return_arg = arg; 745 return_ACPI_STATUS (status); 746}