Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.13 739 lines 20 kB view raw
1 2/****************************************************************************** 3 * 4 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2005, 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 46#include <acpi/acpi.h> 47#include <acpi/acinterp.h> 48#include <acpi/amlcode.h> 49 50 51#define _COMPONENT ACPI_EXECUTER 52 ACPI_MODULE_NAME ("exmisc") 53 54 55/******************************************************************************* 56 * 57 * FUNCTION: acpi_ex_get_object_reference 58 * 59 * PARAMETERS: obj_desc - Create a reference to this object 60 * return_desc - Where to store the reference 61 * walk_state - Current state 62 * 63 * RETURN: Status 64 * 65 * DESCRIPTION: Obtain and return a "reference" to the target object 66 * Common code for the ref_of_op and the cond_ref_of_op. 67 * 68 ******************************************************************************/ 69 70acpi_status 71acpi_ex_get_object_reference ( 72 union acpi_operand_object *obj_desc, 73 union acpi_operand_object **return_desc, 74 struct acpi_walk_state *walk_state) 75{ 76 union acpi_operand_object *reference_obj; 77 union acpi_operand_object *referenced_obj; 78 79 80 ACPI_FUNCTION_TRACE_PTR ("ex_get_object_reference", obj_desc); 81 82 83 *return_desc = NULL; 84 85 switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { 86 case ACPI_DESC_TYPE_OPERAND: 87 88 if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { 89 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 90 } 91 92 /* 93 * Must be a reference to a Local or Arg 94 */ 95 switch (obj_desc->reference.opcode) { 96 case AML_LOCAL_OP: 97 case AML_ARG_OP: 98 case AML_DEBUG_OP: 99 100 /* The referenced object is the pseudo-node for the local/arg */ 101 102 referenced_obj = obj_desc->reference.object; 103 break; 104 105 default: 106 107 ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n", 108 obj_desc->reference.opcode)); 109 return_ACPI_STATUS (AE_AML_INTERNAL); 110 } 111 break; 112 113 114 case ACPI_DESC_TYPE_NAMED: 115 116 /* 117 * A named reference that has already been resolved to a Node 118 */ 119 referenced_obj = obj_desc; 120 break; 121 122 123 default: 124 125 ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n", 126 ACPI_GET_DESCRIPTOR_TYPE (obj_desc))); 127 return_ACPI_STATUS (AE_TYPE); 128 } 129 130 131 /* Create a new reference object */ 132 133 reference_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE); 134 if (!reference_obj) { 135 return_ACPI_STATUS (AE_NO_MEMORY); 136 } 137 138 reference_obj->reference.opcode = AML_REF_OF_OP; 139 reference_obj->reference.object = referenced_obj; 140 *return_desc = reference_obj; 141 142 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 143 "Object %p Type [%s], returning Reference %p\n", 144 obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc)); 145 146 return_ACPI_STATUS (AE_OK); 147} 148 149 150/******************************************************************************* 151 * 152 * FUNCTION: acpi_ex_concat_template 153 * 154 * PARAMETERS: Operand0 - First source object 155 * Operand1 - Second source object 156 * actual_return_desc - Where to place the return object 157 * walk_state - Current walk state 158 * 159 * RETURN: Status 160 * 161 * DESCRIPTION: Concatenate two resource templates 162 * 163 ******************************************************************************/ 164 165acpi_status 166acpi_ex_concat_template ( 167 union acpi_operand_object *operand0, 168 union acpi_operand_object *operand1, 169 union acpi_operand_object **actual_return_desc, 170 struct acpi_walk_state *walk_state) 171{ 172 union acpi_operand_object *return_desc; 173 u8 *new_buf; 174 u8 *end_tag1; 175 u8 *end_tag2; 176 acpi_size length1; 177 acpi_size length2; 178 179 180 ACPI_FUNCTION_TRACE ("ex_concat_template"); 181 182 183 /* Find the end_tags in each resource template */ 184 185 end_tag1 = acpi_ut_get_resource_end_tag (operand0); 186 end_tag2 = acpi_ut_get_resource_end_tag (operand1); 187 if (!end_tag1 || !end_tag2) { 188 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 189 } 190 191 /* Compute the length of each part */ 192 193 length1 = ACPI_PTR_DIFF (end_tag1, operand0->buffer.pointer); 194 length2 = ACPI_PTR_DIFF (end_tag2, operand1->buffer.pointer) + 195 2; /* Size of END_TAG */ 196 197 /* Create a new buffer object for the result */ 198 199 return_desc = acpi_ut_create_buffer_object (length1 + length2); 200 if (!return_desc) { 201 return_ACPI_STATUS (AE_NO_MEMORY); 202 } 203 204 /* Copy the templates to the new descriptor */ 205 206 new_buf = return_desc->buffer.pointer; 207 ACPI_MEMCPY (new_buf, operand0->buffer.pointer, length1); 208 ACPI_MEMCPY (new_buf + length1, operand1->buffer.pointer, length2); 209 210 /* Compute the new checksum */ 211 212 new_buf[return_desc->buffer.length - 1] = 213 acpi_ut_generate_checksum (return_desc->buffer.pointer, 214 (return_desc->buffer.length - 1)); 215 216 /* Return the completed template descriptor */ 217 218 *actual_return_desc = return_desc; 219 return_ACPI_STATUS (AE_OK); 220} 221 222 223/******************************************************************************* 224 * 225 * FUNCTION: acpi_ex_do_concatenate 226 * 227 * PARAMETERS: Operand0 - First source object 228 * Operand1 - Second source object 229 * actual_return_desc - Where to place the return object 230 * walk_state - Current walk state 231 * 232 * RETURN: Status 233 * 234 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. 235 * 236 ******************************************************************************/ 237 238acpi_status 239acpi_ex_do_concatenate ( 240 union acpi_operand_object *operand0, 241 union acpi_operand_object *operand1, 242 union acpi_operand_object **actual_return_desc, 243 struct acpi_walk_state *walk_state) 244{ 245 union acpi_operand_object *local_operand1 = operand1; 246 union acpi_operand_object *return_desc; 247 char *new_buf; 248 acpi_status status; 249 acpi_size new_length; 250 251 252 ACPI_FUNCTION_TRACE ("ex_do_concatenate"); 253 254 255 /* 256 * Convert the second operand if necessary. The first operand 257 * determines the type of the second operand, (See the Data Types 258 * section of the ACPI specification.) Both object types are 259 * guaranteed to be either Integer/String/Buffer by the operand 260 * resolution mechanism. 261 */ 262 switch (ACPI_GET_OBJECT_TYPE (operand0)) { 263 case ACPI_TYPE_INTEGER: 264 status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16); 265 break; 266 267 case ACPI_TYPE_STRING: 268 status = acpi_ex_convert_to_string (operand1, &local_operand1, 269 ACPI_IMPLICIT_CONVERT_HEX); 270 break; 271 272 case ACPI_TYPE_BUFFER: 273 status = acpi_ex_convert_to_buffer (operand1, &local_operand1); 274 break; 275 276 default: 277 ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", 278 ACPI_GET_OBJECT_TYPE (operand0))); 279 status = AE_AML_INTERNAL; 280 } 281 282 if (ACPI_FAILURE (status)) { 283 goto cleanup; 284 } 285 286 /* 287 * Both operands are now known to be the same object type 288 * (Both are Integer, String, or Buffer), and we can now perform the 289 * concatenation. 290 */ 291 292 /* 293 * There are three cases to handle: 294 * 295 * 1) Two Integers concatenated to produce a new Buffer 296 * 2) Two Strings concatenated to produce a new String 297 * 3) Two Buffers concatenated to produce a new Buffer 298 */ 299 switch (ACPI_GET_OBJECT_TYPE (operand0)) { 300 case ACPI_TYPE_INTEGER: 301 302 /* Result of two Integers is a Buffer */ 303 /* Need enough buffer space for two integers */ 304 305 return_desc = acpi_ut_create_buffer_object ( 306 ACPI_MUL_2 (acpi_gbl_integer_byte_width)); 307 if (!return_desc) { 308 status = AE_NO_MEMORY; 309 goto cleanup; 310 } 311 312 new_buf = (char *) return_desc->buffer.pointer; 313 314 /* Copy the first integer, LSB first */ 315 316 ACPI_MEMCPY (new_buf, 317 &operand0->integer.value, 318 acpi_gbl_integer_byte_width); 319 320 /* Copy the second integer (LSB first) after the first */ 321 322 ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width, 323 &local_operand1->integer.value, 324 acpi_gbl_integer_byte_width); 325 break; 326 327 case ACPI_TYPE_STRING: 328 329 /* Result of two Strings is a String */ 330 331 new_length = (acpi_size) operand0->string.length + 332 (acpi_size) local_operand1->string.length; 333 if (new_length > ACPI_MAX_STRING_CONVERSION) { 334 status = AE_AML_STRING_LIMIT; 335 goto cleanup; 336 } 337 338 return_desc = acpi_ut_create_string_object (new_length); 339 if (!return_desc) { 340 status = AE_NO_MEMORY; 341 goto cleanup; 342 } 343 344 new_buf = return_desc->string.pointer; 345 346 /* Concatenate the strings */ 347 348 ACPI_STRCPY (new_buf, 349 operand0->string.pointer); 350 ACPI_STRCPY (new_buf + operand0->string.length, 351 local_operand1->string.pointer); 352 break; 353 354 case ACPI_TYPE_BUFFER: 355 356 /* Result of two Buffers is a Buffer */ 357 358 return_desc = acpi_ut_create_buffer_object ( 359 (acpi_size) operand0->buffer.length + 360 (acpi_size) local_operand1->buffer.length); 361 if (!return_desc) { 362 status = AE_NO_MEMORY; 363 goto cleanup; 364 } 365 366 new_buf = (char *) return_desc->buffer.pointer; 367 368 /* Concatenate the buffers */ 369 370 ACPI_MEMCPY (new_buf, 371 operand0->buffer.pointer, 372 operand0->buffer.length); 373 ACPI_MEMCPY (new_buf + operand0->buffer.length, 374 local_operand1->buffer.pointer, 375 local_operand1->buffer.length); 376 break; 377 378 default: 379 380 /* Invalid object type, should not happen here */ 381 382 ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n", 383 ACPI_GET_OBJECT_TYPE (operand0))); 384 status =AE_AML_INTERNAL; 385 goto cleanup; 386 } 387 388 *actual_return_desc = return_desc; 389 390cleanup: 391 if (local_operand1 != operand1) { 392 acpi_ut_remove_reference (local_operand1); 393 } 394 return_ACPI_STATUS (status); 395} 396 397 398/******************************************************************************* 399 * 400 * FUNCTION: acpi_ex_do_math_op 401 * 402 * PARAMETERS: Opcode - AML opcode 403 * Integer0 - Integer operand #0 404 * Integer1 - Integer operand #1 405 * 406 * RETURN: Integer result of the operation 407 * 408 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the 409 * math functions here is to prevent a lot of pointer dereferencing 410 * to obtain the operands. 411 * 412 ******************************************************************************/ 413 414acpi_integer 415acpi_ex_do_math_op ( 416 u16 opcode, 417 acpi_integer integer0, 418 acpi_integer integer1) 419{ 420 421 ACPI_FUNCTION_ENTRY (); 422 423 424 switch (opcode) { 425 case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ 426 427 return (integer0 + integer1); 428 429 430 case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ 431 432 return (integer0 & integer1); 433 434 435 case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ 436 437 return (~(integer0 & integer1)); 438 439 440 case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ 441 442 return (integer0 | integer1); 443 444 445 case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ 446 447 return (~(integer0 | integer1)); 448 449 450 case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ 451 452 return (integer0 ^ integer1); 453 454 455 case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ 456 457 return (integer0 * integer1); 458 459 460 case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result)*/ 461 462 return (integer0 << integer1); 463 464 465 case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ 466 467 return (integer0 >> integer1); 468 469 470 case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ 471 472 return (integer0 - integer1); 473 474 default: 475 476 return (0); 477 } 478} 479 480 481/******************************************************************************* 482 * 483 * FUNCTION: acpi_ex_do_logical_numeric_op 484 * 485 * PARAMETERS: Opcode - AML opcode 486 * Integer0 - Integer operand #0 487 * Integer1 - Integer operand #1 488 * logical_result - TRUE/FALSE result of the operation 489 * 490 * RETURN: Status 491 * 492 * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric 493 * operators (LAnd and LOr), both operands must be integers. 494 * 495 * Note: cleanest machine code seems to be produced by the code 496 * below, rather than using statements of the form: 497 * Result = (Integer0 && Integer1); 498 * 499 ******************************************************************************/ 500 501acpi_status 502acpi_ex_do_logical_numeric_op ( 503 u16 opcode, 504 acpi_integer integer0, 505 acpi_integer integer1, 506 u8 *logical_result) 507{ 508 acpi_status status = AE_OK; 509 u8 local_result = FALSE; 510 511 512 ACPI_FUNCTION_TRACE ("ex_do_logical_numeric_op"); 513 514 515 switch (opcode) { 516 case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ 517 518 if (integer0 && integer1) { 519 local_result = TRUE; 520 } 521 break; 522 523 case AML_LOR_OP: /* LOr (Integer0, Integer1) */ 524 525 if (integer0 || integer1) { 526 local_result = TRUE; 527 } 528 break; 529 530 default: 531 status = AE_AML_INTERNAL; 532 break; 533 } 534 535 /* Return the logical result and status */ 536 537 *logical_result = local_result; 538 return_ACPI_STATUS (status); 539} 540 541 542/******************************************************************************* 543 * 544 * FUNCTION: acpi_ex_do_logical_op 545 * 546 * PARAMETERS: Opcode - AML opcode 547 * Operand0 - operand #0 548 * Operand1 - operand #1 549 * logical_result - TRUE/FALSE result of the operation 550 * 551 * RETURN: Status 552 * 553 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 554 * functions here is to prevent a lot of pointer dereferencing 555 * to obtain the operands and to simplify the generation of the 556 * logical value. For the Numeric operators (LAnd and LOr), both 557 * operands must be integers. For the other logical operators, 558 * operands can be any combination of Integer/String/Buffer. The 559 * first operand determines the type to which the second operand 560 * will be converted. 561 * 562 * Note: cleanest machine code seems to be produced by the code 563 * below, rather than using statements of the form: 564 * Result = (Operand0 == Operand1); 565 * 566 ******************************************************************************/ 567 568acpi_status 569acpi_ex_do_logical_op ( 570 u16 opcode, 571 union acpi_operand_object *operand0, 572 union acpi_operand_object *operand1, 573 u8 *logical_result) 574{ 575 union acpi_operand_object *local_operand1 = operand1; 576 acpi_integer integer0; 577 acpi_integer integer1; 578 u32 length0; 579 u32 length1; 580 acpi_status status = AE_OK; 581 u8 local_result = FALSE; 582 int compare; 583 584 585 ACPI_FUNCTION_TRACE ("ex_do_logical_op"); 586 587 588 /* 589 * Convert the second operand if necessary. The first operand 590 * determines the type of the second operand, (See the Data Types 591 * section of the ACPI 3.0+ specification.) Both object types are 592 * guaranteed to be either Integer/String/Buffer by the operand 593 * resolution mechanism. 594 */ 595 switch (ACPI_GET_OBJECT_TYPE (operand0)) { 596 case ACPI_TYPE_INTEGER: 597 status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16); 598 break; 599 600 case ACPI_TYPE_STRING: 601 status = acpi_ex_convert_to_string (operand1, &local_operand1, 602 ACPI_IMPLICIT_CONVERT_HEX); 603 break; 604 605 case ACPI_TYPE_BUFFER: 606 status = acpi_ex_convert_to_buffer (operand1, &local_operand1); 607 break; 608 609 default: 610 status = AE_AML_INTERNAL; 611 break; 612 } 613 614 if (ACPI_FAILURE (status)) { 615 goto cleanup; 616 } 617 618 /* 619 * Two cases: 1) Both Integers, 2) Both Strings or Buffers 620 */ 621 if (ACPI_GET_OBJECT_TYPE (operand0) == ACPI_TYPE_INTEGER) { 622 /* 623 * 1) Both operands are of type integer 624 * Note: local_operand1 may have changed above 625 */ 626 integer0 = operand0->integer.value; 627 integer1 = local_operand1->integer.value; 628 629 switch (opcode) { 630 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 631 632 if (integer0 == integer1) { 633 local_result = TRUE; 634 } 635 break; 636 637 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 638 639 if (integer0 > integer1) { 640 local_result = TRUE; 641 } 642 break; 643 644 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 645 646 if (integer0 < integer1) { 647 local_result = TRUE; 648 } 649 break; 650 651 default: 652 status = AE_AML_INTERNAL; 653 break; 654 } 655 } 656 else { 657 /* 658 * 2) Both operands are Strings or both are Buffers 659 * Note: Code below takes advantage of common Buffer/String 660 * object fields. local_operand1 may have changed above. Use 661 * memcmp to handle nulls in buffers. 662 */ 663 length0 = operand0->buffer.length; 664 length1 = local_operand1->buffer.length; 665 666 /* Lexicographic compare: compare the data bytes */ 667 668 compare = ACPI_MEMCMP ((const char * ) operand0->buffer.pointer, 669 (const char * ) local_operand1->buffer.pointer, 670 (length0 > length1) ? length1 : length0); 671 672 switch (opcode) { 673 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 674 675 /* Length and all bytes must be equal */ 676 677 if ((length0 == length1) && 678 (compare == 0)) { 679 /* Length and all bytes match ==> TRUE */ 680 681 local_result = TRUE; 682 } 683 break; 684 685 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 686 687 if (compare > 0) { 688 local_result = TRUE; 689 goto cleanup; /* TRUE */ 690 } 691 if (compare < 0) { 692 goto cleanup; /* FALSE */ 693 } 694 695 /* Bytes match (to shortest length), compare lengths */ 696 697 if (length0 > length1) { 698 local_result = TRUE; 699 } 700 break; 701 702 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 703 704 if (compare > 0) { 705 goto cleanup; /* FALSE */ 706 } 707 if (compare < 0) { 708 local_result = TRUE; 709 goto cleanup; /* TRUE */ 710 } 711 712 /* Bytes match (to shortest length), compare lengths */ 713 714 if (length0 < length1) { 715 local_result = TRUE; 716 } 717 break; 718 719 default: 720 status = AE_AML_INTERNAL; 721 break; 722 } 723 } 724 725cleanup: 726 727 /* New object was created if implicit conversion performed - delete */ 728 729 if (local_operand1 != operand1) { 730 acpi_ut_remove_reference (local_operand1); 731 } 732 733 /* Return the logical result and status */ 734 735 *logical_result = local_result; 736 return_ACPI_STATUS (status); 737} 738 739