1 /******************************************************************************* 2 * 3 * Module Name: dmopcode - AML disassembler, specific AML opcodes 4 * 5 ******************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #include "acpi.h" 153 #include "accommon.h" 154 #include "acparser.h" 155 #include "amlcode.h" 156 #include "acinterp.h" 157 #include "acnamesp.h" 158 #include "acdebug.h" 159 #include "acconvert.h" 160 161 #ifdef ACPI_DISASSEMBLER 162 163 #define _COMPONENT ACPI_CA_DEBUGGER 164 ACPI_MODULE_NAME ("dmopcode") 165 166 167 /* Local prototypes */ 168 169 static void 170 AcpiDmMatchKeyword ( 171 ACPI_PARSE_OBJECT *Op); 172 173 static void 174 AcpiDmConvertToElseIf ( 175 ACPI_PARSE_OBJECT *Op); 176 177 static void 178 AcpiDmPromoteSubtree ( 179 ACPI_PARSE_OBJECT *StartOp); 180 181 static BOOLEAN 182 AcpiDmIsSwitchBlock ( 183 ACPI_PARSE_OBJECT *Op, 184 char *Temp); 185 186 static BOOLEAN 187 AcpiDmIsCaseBlock ( 188 ACPI_PARSE_OBJECT *Op); 189 190 /******************************************************************************* 191 * 192 * FUNCTION: AcpiDmDisplayTargetPathname 193 * 194 * PARAMETERS: Op - Parse object 195 * 196 * RETURN: None 197 * 198 * DESCRIPTION: For AML opcodes that have a target operand, display the full 199 * pathname for the target, in a comment field. Handles Return() 200 * statements also. 201 * 202 ******************************************************************************/ 203 204 void 205 AcpiDmDisplayTargetPathname ( 206 ACPI_PARSE_OBJECT *Op) 207 { 208 ACPI_PARSE_OBJECT *NextOp; 209 ACPI_PARSE_OBJECT *PrevOp = NULL; 210 char *Pathname; 211 const ACPI_OPCODE_INFO *OpInfo; 212 213 214 if (Op->Common.AmlOpcode == AML_RETURN_OP) 215 { 216 PrevOp = Op->Asl.Value.Arg; 217 } 218 else 219 { 220 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 221 if (!(OpInfo->Flags & AML_HAS_TARGET)) 222 { 223 return; 224 } 225 226 /* Target is the last Op in the arg list */ 227 228 NextOp = Op->Asl.Value.Arg; 229 while (NextOp) 230 { 231 PrevOp = NextOp; 232 NextOp = PrevOp->Asl.Next; 233 } 234 } 235 236 if (!PrevOp) 237 { 238 return; 239 } 240 241 /* We must have a namepath AML opcode */ 242 243 if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP) 244 { 245 return; 246 } 247 248 /* A null string is the "no target specified" case */ 249 250 if (!PrevOp->Asl.Value.String) 251 { 252 return; 253 } 254 255 /* No node means "unresolved external reference" */ 256 257 if (!PrevOp->Asl.Node) 258 { 259 AcpiOsPrintf (" /* External reference */"); 260 return; 261 } 262 263 /* Ignore if path is already from the root */ 264 265 if (*PrevOp->Asl.Value.String == '\\') 266 { 267 return; 268 } 269 270 /* Now: we can get the full pathname */ 271 272 Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node); 273 if (!Pathname) 274 { 275 return; 276 } 277 278 AcpiOsPrintf (" /* %s */", Pathname); 279 ACPI_FREE (Pathname); 280 } 281 282 283 /******************************************************************************* 284 * 285 * FUNCTION: AcpiDmNotifyDescription 286 * 287 * PARAMETERS: Op - Name() parse object 288 * 289 * RETURN: None 290 * 291 * DESCRIPTION: Emit a description comment for the value associated with a 292 * Notify() operator. 293 * 294 ******************************************************************************/ 295 296 void 297 AcpiDmNotifyDescription ( 298 ACPI_PARSE_OBJECT *Op) 299 { 300 ACPI_PARSE_OBJECT *NextOp; 301 ACPI_NAMESPACE_NODE *Node; 302 UINT8 NotifyValue; 303 UINT8 Type = ACPI_TYPE_ANY; 304 305 306 /* The notify value is the second argument */ 307 308 NextOp = Op->Asl.Value.Arg; 309 NextOp = NextOp->Asl.Next; 310 311 switch (NextOp->Common.AmlOpcode) 312 { 313 case AML_ZERO_OP: 314 case AML_ONE_OP: 315 316 NotifyValue = (UINT8) NextOp->Common.AmlOpcode; 317 break; 318 319 case AML_BYTE_OP: 320 321 NotifyValue = (UINT8) NextOp->Asl.Value.Integer; 322 break; 323 324 default: 325 return; 326 } 327 328 /* 329 * Attempt to get the namespace node so we can determine the object type. 330 * Some notify values are dependent on the object type (Device, Thermal, 331 * or Processor). 332 */ 333 Node = Op->Asl.Node; 334 if (Node) 335 { 336 Type = Node->Type; 337 } 338 339 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type)); 340 } 341 342 343 /******************************************************************************* 344 * 345 * FUNCTION: AcpiDmPredefinedDescription 346 * 347 * PARAMETERS: Op - Name() parse object 348 * 349 * RETURN: None 350 * 351 * DESCRIPTION: Emit a description comment for a predefined ACPI name. 352 * Used for iASL compiler only. 353 * 354 ******************************************************************************/ 355 356 void 357 AcpiDmPredefinedDescription ( 358 ACPI_PARSE_OBJECT *Op) 359 { 360 #ifdef ACPI_ASL_COMPILER 361 const AH_PREDEFINED_NAME *Info; 362 char *NameString; 363 int LastCharIsDigit; 364 int LastCharsAreHex; 365 366 367 if (!Op) 368 { 369 return; 370 } 371 372 /* Ensure that the comment field is emitted only once */ 373 374 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED) 375 { 376 return; 377 } 378 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED; 379 380 /* Predefined name must start with an underscore */ 381 382 NameString = ACPI_CAST_PTR (char, &Op->Named.Name); 383 if (NameString[0] != '_') 384 { 385 return; 386 } 387 388 /* 389 * Check for the special ACPI names: 390 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a 391 * (where d=decimal_digit, x=hex_digit, a=anything) 392 * 393 * Convert these to the generic name for table lookup. 394 * Note: NameString is guaranteed to be upper case here. 395 */ 396 LastCharIsDigit = 397 (isdigit ((int) NameString[3])); /* d */ 398 LastCharsAreHex = 399 (isxdigit ((int) NameString[2]) && /* xx */ 400 isxdigit ((int) NameString[3])); 401 402 switch (NameString[1]) 403 { 404 case 'A': 405 406 if ((NameString[2] == 'C') && (LastCharIsDigit)) 407 { 408 NameString = "_ACx"; 409 } 410 else if ((NameString[2] == 'L') && (LastCharIsDigit)) 411 { 412 NameString = "_ALx"; 413 } 414 break; 415 416 case 'E': 417 418 if ((NameString[2] == 'J') && (LastCharIsDigit)) 419 { 420 NameString = "_EJx"; 421 } 422 else if (LastCharsAreHex) 423 { 424 NameString = "_Exx"; 425 } 426 break; 427 428 case 'L': 429 430 if (LastCharsAreHex) 431 { 432 NameString = "_Lxx"; 433 } 434 break; 435 436 case 'Q': 437 438 if (LastCharsAreHex) 439 { 440 NameString = "_Qxx"; 441 } 442 break; 443 444 case 'T': 445 446 if (NameString[2] == '_') 447 { 448 NameString = "_T_x"; 449 } 450 break; 451 452 case 'W': 453 454 if (LastCharsAreHex) 455 { 456 NameString = "_Wxx"; 457 } 458 break; 459 460 default: 461 462 break; 463 } 464 465 /* Match the name in the info table */ 466 467 Info = AcpiAhMatchPredefinedName (NameString); 468 if (Info) 469 { 470 AcpiOsPrintf (" // %4.4s: %s", 471 NameString, ACPI_CAST_PTR (char, Info->Description)); 472 } 473 474 #endif 475 return; 476 } 477 478 479 /******************************************************************************* 480 * 481 * FUNCTION: AcpiDmFieldPredefinedDescription 482 * 483 * PARAMETERS: Op - Parse object 484 * 485 * RETURN: None 486 * 487 * DESCRIPTION: Emit a description comment for a resource descriptor tag 488 * (which is a predefined ACPI name.) Used for iASL compiler only. 489 * 490 ******************************************************************************/ 491 492 void 493 AcpiDmFieldPredefinedDescription ( 494 ACPI_PARSE_OBJECT *Op) 495 { 496 #ifdef ACPI_ASL_COMPILER 497 ACPI_PARSE_OBJECT *IndexOp; 498 char *Tag; 499 const ACPI_OPCODE_INFO *OpInfo; 500 const AH_PREDEFINED_NAME *Info; 501 502 503 if (!Op) 504 { 505 return; 506 } 507 508 /* Ensure that the comment field is emitted only once */ 509 510 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED) 511 { 512 return; 513 } 514 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED; 515 516 /* 517 * Op must be one of the Create* operators: CreateField, CreateBitField, 518 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField 519 */ 520 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 521 if (!(OpInfo->Flags & AML_CREATE)) 522 { 523 return; 524 } 525 526 /* Second argument is the Index argument */ 527 528 IndexOp = Op->Common.Value.Arg; 529 IndexOp = IndexOp->Common.Next; 530 531 /* Index argument must be a namepath */ 532 533 if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP) 534 { 535 return; 536 } 537 538 /* Major cheat: We previously put the Tag ptr in the Node field */ 539 540 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node); 541 if (!Tag) 542 { 543 return; 544 } 545 546 /* Match the name in the info table */ 547 548 Info = AcpiAhMatchPredefinedName (Tag); 549 if (Info) 550 { 551 AcpiOsPrintf (" // %4.4s: %s", Tag, 552 ACPI_CAST_PTR (char, Info->Description)); 553 } 554 555 /* AML buffer (String) was allocated in AcpiGetTagPathname */ 556 557 ACPI_FREE (IndexOp->Common.Value.String); 558 559 #endif 560 return; 561 } 562 563 564 /******************************************************************************* 565 * 566 * FUNCTION: AcpiDmMethodFlags 567 * 568 * PARAMETERS: Op - Method Object to be examined 569 * 570 * RETURN: None 571 * 572 * DESCRIPTION: Decode control method flags 573 * 574 ******************************************************************************/ 575 576 void 577 AcpiDmMethodFlags ( 578 ACPI_PARSE_OBJECT *Op) 579 { 580 UINT32 Flags; 581 UINT32 Args; 582 583 584 /* The next Op contains the flags */ 585 586 Op = AcpiPsGetDepthNext (NULL, Op); 587 Flags = (UINT8) Op->Common.Value.Integer; 588 Args = Flags & 0x07; 589 590 /* Mark the Op as completed */ 591 592 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 593 594 /* 1) Method argument count */ 595 596 AcpiOsPrintf (", %u, ", Args); 597 598 /* 2) Serialize rule */ 599 600 if (!(Flags & 0x08)) 601 { 602 AcpiOsPrintf ("Not"); 603 } 604 605 AcpiOsPrintf ("Serialized"); 606 607 /* 3) SyncLevel */ 608 609 if (Flags & 0xF0) 610 { 611 AcpiOsPrintf (", %u", Flags >> 4); 612 } 613 } 614 615 616 /******************************************************************************* 617 * 618 * FUNCTION: AcpiDmFieldFlags 619 * 620 * PARAMETERS: Op - Field Object to be examined 621 * 622 * RETURN: None 623 * 624 * DESCRIPTION: Decode Field definition flags 625 * 626 ******************************************************************************/ 627 628 void 629 AcpiDmFieldFlags ( 630 ACPI_PARSE_OBJECT *Op) 631 { 632 UINT32 Flags; 633 634 635 Op = Op->Common.Next; 636 Flags = (UINT8) Op->Common.Value.Integer; 637 638 /* Mark the Op as completed */ 639 640 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 641 642 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]); 643 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]); 644 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]); 645 } 646 647 648 /******************************************************************************* 649 * 650 * FUNCTION: AcpiDmAddressSpace 651 * 652 * PARAMETERS: SpaceId - ID to be translated 653 * 654 * RETURN: None 655 * 656 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword 657 * 658 ******************************************************************************/ 659 660 void 661 AcpiDmAddressSpace ( 662 UINT8 SpaceId) 663 { 664 665 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) 666 { 667 if (SpaceId == 0x7F) 668 { 669 AcpiOsPrintf ("FFixedHW, "); 670 } 671 else 672 { 673 AcpiOsPrintf ("0x%.2X, ", SpaceId); 674 } 675 } 676 else 677 { 678 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]); 679 } 680 } 681 682 683 /******************************************************************************* 684 * 685 * FUNCTION: AcpiDmRegionFlags 686 * 687 * PARAMETERS: Op - Object to be examined 688 * 689 * RETURN: None 690 * 691 * DESCRIPTION: Decode OperationRegion flags 692 * 693 ******************************************************************************/ 694 695 void 696 AcpiDmRegionFlags ( 697 ACPI_PARSE_OBJECT *Op) 698 { 699 700 /* The next Op contains the SpaceId */ 701 702 Op = AcpiPsGetDepthNext (NULL, Op); 703 704 /* Mark the Op as completed */ 705 706 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 707 708 AcpiOsPrintf (", "); 709 AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer); 710 } 711 712 713 /******************************************************************************* 714 * 715 * FUNCTION: AcpiDmMatchOp 716 * 717 * PARAMETERS: Op - Match Object to be examined 718 * 719 * RETURN: None 720 * 721 * DESCRIPTION: Decode Match opcode operands 722 * 723 ******************************************************************************/ 724 725 void 726 AcpiDmMatchOp ( 727 ACPI_PARSE_OBJECT *Op) 728 { 729 ACPI_PARSE_OBJECT *NextOp; 730 731 732 NextOp = AcpiPsGetDepthNext (NULL, Op); 733 NextOp = NextOp->Common.Next; 734 735 if (!NextOp) 736 { 737 /* Handle partial tree during single-step */ 738 739 return; 740 } 741 742 /* Mark the two nodes that contain the encoding for the match keywords */ 743 744 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP; 745 746 NextOp = NextOp->Common.Next; 747 NextOp = NextOp->Common.Next; 748 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP; 749 } 750 751 752 /******************************************************************************* 753 * 754 * FUNCTION: AcpiDmMatchKeyword 755 * 756 * PARAMETERS: Op - Match Object to be examined 757 * 758 * RETURN: None 759 * 760 * DESCRIPTION: Decode Match opcode operands 761 * 762 ******************************************************************************/ 763 764 static void 765 AcpiDmMatchKeyword ( 766 ACPI_PARSE_OBJECT *Op) 767 { 768 769 if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE) 770 { 771 AcpiOsPrintf ("/* Unknown Match Keyword encoding */"); 772 } 773 else 774 { 775 AcpiOsPrintf ("%s", 776 AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]); 777 } 778 } 779 780 781 /******************************************************************************* 782 * 783 * FUNCTION: AcpiDmDisassembleOneOp 784 * 785 * PARAMETERS: WalkState - Current walk info 786 * Info - Parse tree walk info 787 * Op - Op that is to be printed 788 * 789 * RETURN: None 790 * 791 * DESCRIPTION: Disassemble a single AML opcode 792 * 793 ******************************************************************************/ 794 795 void 796 AcpiDmDisassembleOneOp ( 797 ACPI_WALK_STATE *WalkState, 798 ACPI_OP_WALK_INFO *Info, 799 ACPI_PARSE_OBJECT *Op) 800 { 801 const ACPI_OPCODE_INFO *OpInfo = NULL; 802 UINT32 Offset; 803 UINT32 Length; 804 ACPI_PARSE_OBJECT *Child; 805 ACPI_STATUS Status; 806 UINT8 *Aml; 807 const AH_DEVICE_ID *IdInfo; 808 809 810 if (!Op) 811 { 812 AcpiOsPrintf ("<NULL OP PTR>"); 813 return; 814 } 815 816 if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF) 817 { 818 return; /* ElseIf macro was already emitted */ 819 } 820 821 switch (Op->Common.DisasmOpcode) 822 { 823 case ACPI_DASM_MATCHOP: 824 825 AcpiDmMatchKeyword (Op); 826 return; 827 828 case ACPI_DASM_LNOT_SUFFIX: 829 830 if (!AcpiGbl_CstyleDisassembly) 831 { 832 switch (Op->Common.AmlOpcode) 833 { 834 case AML_LOGICAL_EQUAL_OP: 835 AcpiOsPrintf ("LNotEqual"); 836 break; 837 838 case AML_LOGICAL_GREATER_OP: 839 AcpiOsPrintf ("LLessEqual"); 840 break; 841 842 case AML_LOGICAL_LESS_OP: 843 AcpiOsPrintf ("LGreaterEqual"); 844 break; 845 846 default: 847 break; 848 } 849 } 850 851 Op->Common.DisasmOpcode = 0; 852 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 853 return; 854 855 default: 856 break; 857 } 858 859 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 860 861 /* The op and arguments */ 862 863 switch (Op->Common.AmlOpcode) 864 { 865 case AML_LOGICAL_NOT_OP: 866 867 Child = Op->Common.Value.Arg; 868 if ((Child->Common.AmlOpcode == AML_LOGICAL_EQUAL_OP) || 869 (Child->Common.AmlOpcode == AML_LOGICAL_GREATER_OP) || 870 (Child->Common.AmlOpcode == AML_LOGICAL_LESS_OP)) 871 { 872 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX; 873 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; 874 } 875 else 876 { 877 AcpiOsPrintf ("%s", OpInfo->Name); 878 } 879 break; 880 881 case AML_BYTE_OP: 882 883 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer); 884 break; 885 886 case AML_WORD_OP: 887 888 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID) 889 { 890 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer); 891 } 892 else 893 { 894 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer); 895 } 896 break; 897 898 case AML_DWORD_OP: 899 900 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID) 901 { 902 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer); 903 } 904 else 905 { 906 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer); 907 } 908 break; 909 910 case AML_QWORD_OP: 911 912 AcpiOsPrintf ("0x%8.8X%8.8X", 913 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); 914 break; 915 916 case AML_STRING_OP: 917 918 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX); 919 920 /* For _HID/_CID strings, attempt to output a descriptive comment */ 921 922 if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING) 923 { 924 /* If we know about the ID, emit the description */ 925 926 IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String); 927 if (IdInfo) 928 { 929 AcpiOsPrintf (" /* %s */", IdInfo->Description); 930 } 931 } 932 break; 933 934 case AML_BUFFER_OP: 935 /* 936 * Determine the type of buffer. We can have one of the following: 937 * 938 * 1) ResourceTemplate containing Resource Descriptors. 939 * 2) Unicode String buffer 940 * 3) ASCII String buffer 941 * 4) Raw data buffer (if none of the above) 942 * 943 * Since there are no special AML opcodes to differentiate these 944 * types of buffers, we have to closely look at the data in the 945 * buffer to determine the type. 946 */ 947 if (!AcpiGbl_NoResourceDisassembly) 948 { 949 Status = AcpiDmIsResourceTemplate (WalkState, Op); 950 if (ACPI_SUCCESS (Status)) 951 { 952 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE; 953 AcpiOsPrintf ("ResourceTemplate"); 954 break; 955 } 956 else if (Status == AE_AML_NO_RESOURCE_END_TAG) 957 { 958 AcpiOsPrintf ( 959 "/**** Is ResourceTemplate, " 960 "but EndTag not at buffer end ****/ "); 961 } 962 } 963 964 if (AcpiDmIsUuidBuffer (Op)) 965 { 966 Op->Common.DisasmOpcode = ACPI_DASM_UUID; 967 AcpiOsPrintf ("ToUUID ("); 968 } 969 else if (AcpiDmIsUnicodeBuffer (Op)) 970 { 971 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE; 972 AcpiOsPrintf ("Unicode ("); 973 } 974 else if (AcpiDmIsStringBuffer (Op)) 975 { 976 Op->Common.DisasmOpcode = ACPI_DASM_STRING; 977 AcpiOsPrintf ("Buffer"); 978 } 979 else if (AcpiDmIsPldBuffer (Op)) 980 { 981 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD; 982 AcpiOsPrintf ("ToPLD ("); 983 } 984 else 985 { 986 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER; 987 AcpiOsPrintf ("Buffer"); 988 } 989 break; 990 991 case AML_INT_NAMEPATH_OP: 992 993 AcpiDmNamestring (Op->Common.Value.Name); 994 break; 995 996 case AML_INT_NAMEDFIELD_OP: 997 998 Length = AcpiDmDumpName (Op->Named.Name); 999 1000 AcpiOsPrintf (","); 1001 ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0); 1002 AcpiOsPrintf ("%*.s %u", (unsigned) (5 - Length), " ", 1003 (UINT32) Op->Common.Value.Integer); 1004 1005 AcpiDmCommaIfFieldMember (Op); 1006 1007 Info->BitOffset += (UINT32) Op->Common.Value.Integer; 1008 break; 1009 1010 case AML_INT_RESERVEDFIELD_OP: 1011 1012 /* Offset() -- Must account for previous offsets */ 1013 1014 Offset = (UINT32) Op->Common.Value.Integer; 1015 Info->BitOffset += Offset; 1016 1017 if (Info->BitOffset % 8 == 0) 1018 { 1019 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset)); 1020 } 1021 else 1022 { 1023 AcpiOsPrintf (" , %u", Offset); 1024 } 1025 1026 AcpiDmCommaIfFieldMember (Op); 1027 break; 1028 1029 case AML_INT_ACCESSFIELD_OP: 1030 case AML_INT_EXTACCESSFIELD_OP: 1031 1032 AcpiOsPrintf ("AccessAs (%s, ", 1033 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]); 1034 1035 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8)); 1036 1037 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP) 1038 { 1039 AcpiOsPrintf (" (0x%2.2X)", (unsigned) 1040 ((Op->Common.Value.Integer >> 16) & 0xFF)); 1041 } 1042 1043 AcpiOsPrintf (")"); 1044 AcpiDmCommaIfFieldMember (Op); 1045 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 1046 break; 1047 1048 case AML_INT_CONNECTION_OP: 1049 /* 1050 * Two types of Connection() - one with a buffer object, the 1051 * other with a namestring that points to a buffer object. 1052 */ 1053 AcpiOsPrintf ("Connection ("); 1054 Child = Op->Common.Value.Arg; 1055 1056 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP) 1057 { 1058 AcpiOsPrintf ("\n"); 1059 1060 Aml = Child->Named.Data; 1061 Length = (UINT32) Child->Common.Value.Integer; 1062 1063 Info->Level += 1; 1064 Info->MappingOp = Op; 1065 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE; 1066 1067 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length); 1068 1069 Info->Level -= 1; 1070 AcpiDmIndent (Info->Level); 1071 } 1072 else 1073 { 1074 AcpiDmNamestring (Child->Common.Value.Name); 1075 } 1076 1077 AcpiOsPrintf (")"); 1078 AcpiDmCommaIfFieldMember (Op); 1079 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 1080 ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, NULL, 0); 1081 AcpiOsPrintf ("\n"); 1082 1083 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */ 1084 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1085 break; 1086 1087 case AML_INT_BYTELIST_OP: 1088 1089 AcpiDmByteList (Info, Op); 1090 break; 1091 1092 case AML_INT_METHODCALL_OP: 1093 1094 Op = AcpiPsGetDepthNext (NULL, Op); 1095 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1096 1097 AcpiDmNamestring (Op->Common.Value.Name); 1098 break; 1099 1100 case AML_WHILE_OP: 1101 1102 if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH) 1103 { 1104 AcpiOsPrintf ("%s", "Switch"); 1105 break; 1106 } 1107 1108 AcpiOsPrintf ("%s", OpInfo->Name); 1109 break; 1110 1111 case AML_IF_OP: 1112 1113 if (Op->Common.DisasmOpcode == ACPI_DASM_CASE) 1114 { 1115 AcpiOsPrintf ("%s", "Case"); 1116 break; 1117 } 1118 1119 AcpiOsPrintf ("%s", OpInfo->Name); 1120 break; 1121 1122 case AML_ELSE_OP: 1123 1124 AcpiDmConvertToElseIf (Op); 1125 break; 1126 1127 case AML_EXTERNAL_OP: 1128 1129 if (AcpiGbl_DmEmitExternalOpcodes) 1130 { 1131 AcpiDmEmitExternal (AcpiPsGetArg(Op, 0), 1132 AcpiPsGetArg(Op, 1)); 1133 break; 1134 } 1135 1136 break; 1137 1138 default: 1139 1140 /* Just get the opcode name and print it */ 1141 1142 AcpiOsPrintf ("%s", OpInfo->Name); 1143 1144 1145 #ifdef ACPI_DEBUGGER 1146 1147 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) && 1148 (WalkState) && 1149 (WalkState->Results) && 1150 (WalkState->ResultCount)) 1151 { 1152 AcpiDbDecodeInternalObject ( 1153 WalkState->Results->Results.ObjDesc [ 1154 (WalkState->ResultCount - 1) % 1155 ACPI_RESULTS_FRAME_OBJ_NUM]); 1156 } 1157 #endif 1158 1159 break; 1160 } 1161 } 1162 1163 1164 /******************************************************************************* 1165 * 1166 * FUNCTION: AcpiDmConvertToElseIf 1167 * 1168 * PARAMETERS: OriginalElseOp - ELSE Object to be examined 1169 * 1170 * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator. 1171 * 1172 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf 1173 * 1174 * EXAMPLE: 1175 * 1176 * This If..Else..If nested sequence: 1177 * 1178 * If (Arg0 == 1) 1179 * { 1180 * Local0 = 4 1181 * } 1182 * Else 1183 * { 1184 * If (Arg0 == 2) 1185 * { 1186 * Local0 = 5 1187 * } 1188 * } 1189 * 1190 * Is converted to this simpler If..ElseIf sequence: 1191 * 1192 * If (Arg0 == 1) 1193 * { 1194 * Local0 = 4 1195 * } 1196 * ElseIf (Arg0 == 2) 1197 * { 1198 * Local0 = 5 1199 * } 1200 * 1201 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL 1202 * macro that emits an Else opcode followed by an If opcode. This function 1203 * reverses these AML sequences back to an ElseIf macro where possible. This 1204 * can make the disassembled ASL code simpler and more like the original code. 1205 * 1206 ******************************************************************************/ 1207 1208 static void 1209 AcpiDmConvertToElseIf ( 1210 ACPI_PARSE_OBJECT *OriginalElseOp) 1211 { 1212 ACPI_PARSE_OBJECT *IfOp; 1213 ACPI_PARSE_OBJECT *ElseOp; 1214 1215 1216 /* 1217 * To be able to perform the conversion, two conditions must be satisfied: 1218 * 1) The first child of the Else must be an If statement. 1219 * 2) The If block can only be followed by an Else block and these must 1220 * be the only blocks under the original Else. 1221 */ 1222 IfOp = OriginalElseOp->Common.Value.Arg; 1223 1224 if (!IfOp || 1225 (IfOp->Common.AmlOpcode != AML_IF_OP) || 1226 (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP))) 1227 { 1228 /* Not a proper Else..If sequence, cannot convert to ElseIf */ 1229 1230 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT) 1231 { 1232 AcpiOsPrintf ("%s", "Default"); 1233 return; 1234 } 1235 1236 AcpiOsPrintf ("%s", "Else"); 1237 return; 1238 } 1239 1240 /* Cannot have anything following the If...Else block */ 1241 1242 ElseOp = IfOp->Common.Next; 1243 if (ElseOp && ElseOp->Common.Next) 1244 { 1245 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT) 1246 { 1247 AcpiOsPrintf ("%s", "Default"); 1248 return; 1249 } 1250 1251 AcpiOsPrintf ("%s", "Else"); 1252 return; 1253 } 1254 1255 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT) 1256 { 1257 /* 1258 * There is an ElseIf but in this case the Else is actually 1259 * a Default block for a Switch/Case statement. No conversion. 1260 */ 1261 AcpiOsPrintf ("%s", "Default"); 1262 return; 1263 } 1264 1265 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE) 1266 { 1267 /* 1268 * This ElseIf is actually a Case block for a Switch/Case 1269 * statement. Print Case but do not return so that we can 1270 * promote the subtree and keep the indentation level. 1271 */ 1272 AcpiOsPrintf ("%s", "Case"); 1273 } 1274 else 1275 { 1276 /* Emit ElseIf, mark the IF as now an ELSEIF */ 1277 1278 AcpiOsPrintf ("%s", "ElseIf"); 1279 } 1280 1281 IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF; 1282 1283 /* The IF parent will now be the same as the original ELSE parent */ 1284 1285 IfOp->Common.Parent = OriginalElseOp->Common.Parent; 1286 1287 /* 1288 * Update the NEXT pointers to restructure the parse tree, essentially 1289 * promoting an If..Else block up to the same level as the original 1290 * Else. 1291 * 1292 * Check if the IF has a corresponding ELSE peer 1293 */ 1294 ElseOp = IfOp->Common.Next; 1295 if (ElseOp && 1296 (ElseOp->Common.AmlOpcode == AML_ELSE_OP)) 1297 { 1298 /* If an ELSE matches the IF, promote it also */ 1299 1300 ElseOp->Common.Parent = OriginalElseOp->Common.Parent; 1301 1302 /* Promote the entire block under the ElseIf (All Next OPs) */ 1303 1304 AcpiDmPromoteSubtree (OriginalElseOp); 1305 } 1306 else 1307 { 1308 /* Otherwise, set the IF NEXT to the original ELSE NEXT */ 1309 1310 IfOp->Common.Next = OriginalElseOp->Common.Next; 1311 } 1312 1313 /* Detach the child IF block from the original ELSE */ 1314 1315 OriginalElseOp->Common.Value.Arg = NULL; 1316 1317 /* Ignore the original ELSE from now on */ 1318 1319 OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1320 OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; 1321 1322 /* Insert IF (now ELSEIF) as next peer of the original ELSE */ 1323 1324 OriginalElseOp->Common.Next = IfOp; 1325 } 1326 1327 1328 /******************************************************************************* 1329 * 1330 * FUNCTION: AcpiDmPromoteSubtree 1331 * 1332 * PARAMETERS: StartOpOp - Original parent of the entire subtree 1333 * 1334 * RETURN: None 1335 * 1336 * DESCRIPTION: Promote an entire parse subtree up one level. 1337 * 1338 ******************************************************************************/ 1339 1340 static void 1341 AcpiDmPromoteSubtree ( 1342 ACPI_PARSE_OBJECT *StartOp) 1343 { 1344 ACPI_PARSE_OBJECT *Op; 1345 ACPI_PARSE_OBJECT *ParentOp; 1346 1347 1348 /* New parent for subtree elements */ 1349 1350 ParentOp = StartOp->Common.Parent; 1351 1352 /* First child starts the subtree */ 1353 1354 Op = StartOp->Common.Value.Arg; 1355 1356 /* Walk the top-level elements of the subtree */ 1357 1358 while (Op) 1359 { 1360 Op->Common.Parent = ParentOp; 1361 if (!Op->Common.Next) 1362 { 1363 /* Last Op in list, update its next field */ 1364 1365 Op->Common.Next = StartOp->Common.Next; 1366 break; 1367 } 1368 Op = Op->Common.Next; 1369 } 1370 } 1371 1372 /******************************************************************************* 1373 * 1374 * FUNCTION: AcpiDmIsTempName 1375 * 1376 * PARAMETERS: Op - Object to be examined 1377 * 1378 * RETURN: TRUE if object is a temporary (_T_x) name for a matching While 1379 * loop that can be converted to a Switch. 1380 * 1381 * DESCRIPTION: _T_X objects are only used for Switch statements. If a temporary 1382 * name exists, search the siblings for a matching While (One) loop 1383 * that can be converted to a Switch. Return TRUE if a match was 1384 * found, FALSE otherwise. 1385 * 1386 ******************************************************************************/ 1387 1388 BOOLEAN 1389 AcpiDmIsTempName ( 1390 ACPI_PARSE_OBJECT *Op) 1391 { 1392 ACPI_PARSE_OBJECT *CurrentOp; 1393 char *Temp; 1394 1395 if (Op->Common.AmlOpcode != AML_NAME_OP) 1396 { 1397 return (FALSE); 1398 } 1399 1400 Temp = (char *)(Op->Common.Aml); 1401 ++Temp; 1402 1403 if (strncmp(Temp, "_T_", 3)) 1404 { 1405 return (FALSE); 1406 } 1407 1408 CurrentOp = Op->Common.Next; 1409 while (CurrentOp) 1410 { 1411 if (CurrentOp->Common.AmlOpcode == AML_WHILE_OP && 1412 AcpiDmIsSwitchBlock(CurrentOp, Temp)) 1413 { 1414 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1415 CurrentOp->Common.DisasmOpcode = ACPI_DASM_SWITCH; 1416 1417 return (TRUE); 1418 } 1419 CurrentOp = CurrentOp->Common.Next; 1420 } 1421 1422 return (FALSE); 1423 } 1424 1425 /******************************************************************************* 1426 * 1427 * FUNCTION: AcpiDmIsSwitchBlock 1428 * 1429 * PARAMETERS: Op - While Object 1430 * 1431 * RETURN: TRUE if While block can be converted to a Switch/Case block 1432 * 1433 * DESCRIPTION: Determines if While block is a Switch/Case statement. Modifies 1434 * parse tree to allow for Switch/Case disassembly during walk. 1435 * 1436 * EXAMPLE: Example of parse tree to be converted 1437 * 1438 * While 1439 * One 1440 * Store 1441 * ByteConst 1442 * -NamePath- 1443 * If 1444 * LEqual 1445 * -NamePath- 1446 * Zero 1447 * Return 1448 * One 1449 * Else 1450 * Return 1451 * WordConst 1452 * Break 1453 * 1454 ******************************************************************************/ 1455 1456 static BOOLEAN 1457 AcpiDmIsSwitchBlock ( 1458 ACPI_PARSE_OBJECT *Op, 1459 char *Temp) 1460 { 1461 ACPI_PARSE_OBJECT *OneOp; 1462 ACPI_PARSE_OBJECT *StoreOp; 1463 ACPI_PARSE_OBJECT *NamePathOp; 1464 ACPI_PARSE_OBJECT *PredicateOp; 1465 ACPI_PARSE_OBJECT *CurrentOp; 1466 ACPI_PARSE_OBJECT *TempOp; 1467 1468 /* Check for One Op Predicate */ 1469 1470 OneOp = AcpiPsGetArg (Op, 0); 1471 if (!OneOp || (OneOp->Common.AmlOpcode != AML_ONE_OP)) 1472 { 1473 return (FALSE); 1474 } 1475 1476 /* Check for Store Op */ 1477 1478 StoreOp = OneOp->Common.Next; 1479 if (!StoreOp || (StoreOp->Common.AmlOpcode != AML_STORE_OP)) 1480 { 1481 return (FALSE); 1482 } 1483 1484 /* Check for Name Op with _T_ string */ 1485 1486 NamePathOp = AcpiPsGetArg (StoreOp, 1); 1487 if (!NamePathOp || (NamePathOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 1488 { 1489 return (FALSE); 1490 } 1491 1492 if (strncmp((char *)(NamePathOp->Common.Aml), Temp, 4)) 1493 { 1494 return (FALSE); 1495 } 1496 1497 /* This is a Switch/Case control block */ 1498 1499 /* Ignore the One Op Predicate */ 1500 1501 OneOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1502 1503 /* Ignore the Store Op, but not the children */ 1504 1505 StoreOp->Common.DisasmOpcode = ACPI_DASM_IGNORE_SINGLE; 1506 1507 /* 1508 * First arg of Store Op is the Switch condition. 1509 * Mark it as a Switch predicate and as a parameter list for paren 1510 * closing and correct indentation. 1511 */ 1512 PredicateOp = AcpiPsGetArg (StoreOp, 0); 1513 PredicateOp->Common.DisasmOpcode = ACPI_DASM_SWITCH_PREDICATE; 1514 PredicateOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST; 1515 1516 /* Ignore the Name Op */ 1517 1518 NamePathOp->Common.DisasmFlags = ACPI_PARSEOP_IGNORE; 1519 1520 /* Remaining opcodes are the Case statements (If/ElseIf's) */ 1521 1522 CurrentOp = StoreOp->Common.Next; 1523 while (AcpiDmIsCaseBlock (CurrentOp)) 1524 { 1525 /* Block is a Case structure */ 1526 1527 if (CurrentOp->Common.AmlOpcode == AML_ELSE_OP) 1528 { 1529 /* ElseIf */ 1530 1531 CurrentOp->Common.DisasmOpcode = ACPI_DASM_CASE; 1532 CurrentOp = AcpiPsGetArg (CurrentOp, 0); 1533 } 1534 1535 /* If */ 1536 1537 CurrentOp->Common.DisasmOpcode = ACPI_DASM_CASE; 1538 1539 /* 1540 * Mark the parse tree for Case disassembly. There are two 1541 * types of Case statements. The first type of statement begins with 1542 * an LEqual. The second starts with an LNot and uses a Match statement 1543 * on a Package of constants. 1544 */ 1545 TempOp = AcpiPsGetArg (CurrentOp, 0); 1546 switch (TempOp->Common.AmlOpcode) 1547 { 1548 case (AML_LOGICAL_EQUAL_OP): 1549 1550 /* Ignore just the LEqual Op */ 1551 1552 TempOp->Common.DisasmOpcode = ACPI_DASM_IGNORE_SINGLE; 1553 1554 /* Ignore the NamePath Op */ 1555 1556 TempOp = AcpiPsGetArg (TempOp, 0); 1557 TempOp->Common.DisasmFlags = ACPI_PARSEOP_IGNORE; 1558 1559 /* 1560 * Second arg of LEqual will be the Case predicate. 1561 * Mark it as a predicate and also as a parameter list for paren 1562 * closing and correct indentation. 1563 */ 1564 PredicateOp = TempOp->Common.Next; 1565 PredicateOp->Common.DisasmOpcode = ACPI_DASM_SWITCH_PREDICATE; 1566 PredicateOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST; 1567 1568 break; 1569 1570 case (AML_LOGICAL_NOT_OP): 1571 1572 /* 1573 * The Package will be the predicate of the Case statement. 1574 * It's under: 1575 * LNOT 1576 * LEQUAL 1577 * MATCH 1578 * PACKAGE 1579 */ 1580 1581 /* Get the LEqual Op from LNot */ 1582 1583 TempOp = AcpiPsGetArg (TempOp, 0); 1584 1585 /* Get the Match Op from LEqual */ 1586 1587 TempOp = AcpiPsGetArg (TempOp, 0); 1588 1589 /* Get the Package Op from Match */ 1590 1591 PredicateOp = AcpiPsGetArg (TempOp, 0); 1592 1593 /* Mark as parameter list for paren closing */ 1594 1595 PredicateOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST; 1596 1597 /* 1598 * The Package list would be too deeply indented if we 1599 * chose to simply ignore the all the parent opcodes, so 1600 * we rearrange the parse tree instead. 1601 */ 1602 1603 /* 1604 * Save the second arg of the If/Else Op which is the 1605 * block code of code for this Case statement. 1606 */ 1607 TempOp = AcpiPsGetArg (CurrentOp, 1); 1608 1609 /* 1610 * Move the Package Op to the child (predicate) of the 1611 * Case statement. 1612 */ 1613 CurrentOp->Common.Value.Arg = PredicateOp; 1614 PredicateOp->Common.Parent = CurrentOp; 1615 1616 /* Add the block code */ 1617 1618 PredicateOp->Common.Next = TempOp; 1619 1620 break; 1621 1622 default: 1623 1624 /* Should never get here */ 1625 1626 break; 1627 } 1628 1629 /* Advance to next Case block */ 1630 1631 CurrentOp = CurrentOp->Common.Next; 1632 } 1633 1634 /* If CurrentOp is now an Else, then this is a Default block */ 1635 1636 if (CurrentOp && CurrentOp->Common.AmlOpcode == AML_ELSE_OP) 1637 { 1638 CurrentOp->Common.DisasmOpcode = ACPI_DASM_DEFAULT; 1639 } 1640 1641 /* 1642 * From the first If advance to the Break op. It's possible to 1643 * have an Else (Default) op here when there is only one Case 1644 * statement, so check for it. 1645 */ 1646 CurrentOp = StoreOp->Common.Next->Common.Next; 1647 if (CurrentOp->Common.AmlOpcode == AML_ELSE_OP) 1648 { 1649 CurrentOp = CurrentOp->Common.Next; 1650 } 1651 1652 /* Ignore the Break Op */ 1653 1654 CurrentOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1655 1656 return (TRUE); 1657 } 1658 1659 /******************************************************************************* 1660 * 1661 * FUNCTION: AcpiDmIsCaseBlock 1662 * 1663 * PARAMETERS: Op - Object to test 1664 * 1665 * RETURN: TRUE if Object is beginning of a Case block. 1666 * 1667 * DESCRIPTION: Determines if an Object is the beginning of a Case block for a 1668 * Switch/Case statement. Parse tree must be one of the following 1669 * forms: 1670 * 1671 * Else (Optional) 1672 * If 1673 * LEqual 1674 * -NamePath- _T_x 1675 * 1676 * Else (Optional) 1677 * If 1678 * LNot 1679 * LEqual 1680 * Match 1681 * Package 1682 * ByteConst 1683 * -NamePath- _T_x 1684 * 1685 ******************************************************************************/ 1686 1687 static BOOLEAN 1688 AcpiDmIsCaseBlock ( 1689 ACPI_PARSE_OBJECT *Op) 1690 { 1691 ACPI_PARSE_OBJECT *CurrentOp; 1692 1693 if (!Op) 1694 { 1695 return (FALSE); 1696 } 1697 1698 /* Look for an If or ElseIf */ 1699 1700 CurrentOp = Op; 1701 if (CurrentOp->Common.AmlOpcode == AML_ELSE_OP) 1702 { 1703 CurrentOp = AcpiPsGetArg (CurrentOp, 0); 1704 if (!CurrentOp) 1705 { 1706 return (FALSE); 1707 } 1708 } 1709 1710 if (!CurrentOp || CurrentOp->Common.AmlOpcode != AML_IF_OP) 1711 { 1712 return (FALSE); 1713 } 1714 1715 /* Child must be LEqual or LNot */ 1716 1717 CurrentOp = AcpiPsGetArg (CurrentOp, 0); 1718 if (!CurrentOp) 1719 { 1720 return (FALSE); 1721 } 1722 1723 switch (CurrentOp->Common.AmlOpcode) 1724 { 1725 case (AML_LOGICAL_EQUAL_OP): 1726 1727 /* Next child must be NamePath with string _T_ */ 1728 1729 CurrentOp = AcpiPsGetArg (CurrentOp, 0); 1730 if (!CurrentOp || !CurrentOp->Common.Value.Name || 1731 strncmp(CurrentOp->Common.Value.Name, "_T_", 3)) 1732 { 1733 return (FALSE); 1734 } 1735 1736 break; 1737 1738 case (AML_LOGICAL_NOT_OP): 1739 1740 /* Child of LNot must be LEqual op */ 1741 1742 CurrentOp = AcpiPsGetArg (CurrentOp, 0); 1743 if (!CurrentOp || (CurrentOp->Common.AmlOpcode != AML_LOGICAL_EQUAL_OP)) 1744 { 1745 return (FALSE); 1746 } 1747 1748 /* Child of LNot must be Match op */ 1749 1750 CurrentOp = AcpiPsGetArg (CurrentOp, 0); 1751 if (!CurrentOp || (CurrentOp->Common.AmlOpcode != AML_MATCH_OP)) 1752 { 1753 return (FALSE); 1754 } 1755 1756 /* First child of Match must be Package op */ 1757 1758 CurrentOp = AcpiPsGetArg (CurrentOp, 0); 1759 if (!CurrentOp || (CurrentOp->Common.AmlOpcode != AML_PACKAGE_OP)) 1760 { 1761 return (FALSE); 1762 } 1763 1764 /* Third child of Match must be NamePath with string _T_ */ 1765 1766 CurrentOp = AcpiPsGetArg (CurrentOp->Common.Parent, 2); 1767 if (!CurrentOp || !CurrentOp->Common.Value.Name || 1768 strncmp(CurrentOp->Common.Value.Name, "_T_", 3)) 1769 { 1770 return (FALSE); 1771 } 1772 1773 break; 1774 1775 default: 1776 1777 return (FALSE); 1778 } 1779 1780 return (TRUE); 1781 } 1782 1783 #endif /* ACPI_DISASSEMBLER */ 1784