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