1 /******************************************************************************* 2 * 3 * Module Name: dmopcode - AML disassembler, specific AML opcodes 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2026, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 #include "acinterp.h" 49 #include "acnamesp.h" 50 #include "acdebug.h" 51 #include "acconvert.h" 52 53 54 #define _COMPONENT ACPI_CA_DEBUGGER 55 ACPI_MODULE_NAME ("dmopcode") 56 57 58 /* Local prototypes */ 59 60 static void 61 AcpiDmMatchKeyword ( 62 ACPI_PARSE_OBJECT *Op); 63 64 static void 65 AcpiDmConvertToElseIf ( 66 ACPI_PARSE_OBJECT *Op); 67 68 static void 69 AcpiDmPromoteSubtree ( 70 ACPI_PARSE_OBJECT *StartOp); 71 72 /******************************************************************************* 73 * 74 * FUNCTION: AcpiDmDisplayTargetPathname 75 * 76 * PARAMETERS: Op - Parse object 77 * 78 * RETURN: None 79 * 80 * DESCRIPTION: For AML opcodes that have a target operand, display the full 81 * pathname for the target, in a comment field. Handles Return() 82 * statements also. 83 * 84 ******************************************************************************/ 85 86 void 87 AcpiDmDisplayTargetPathname ( 88 ACPI_PARSE_OBJECT *Op) 89 { 90 ACPI_PARSE_OBJECT *NextOp; 91 ACPI_PARSE_OBJECT *PrevOp = NULL; 92 char *Pathname; 93 const ACPI_OPCODE_INFO *OpInfo; 94 95 96 if (Op->Common.AmlOpcode == AML_RETURN_OP) 97 { 98 PrevOp = Op->Asl.Value.Arg; 99 } 100 else 101 { 102 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 103 if (!(OpInfo->Flags & AML_HAS_TARGET)) 104 { 105 return; 106 } 107 108 /* Target is the last Op in the arg list */ 109 110 NextOp = Op->Asl.Value.Arg; 111 while (NextOp) 112 { 113 PrevOp = NextOp; 114 NextOp = PrevOp->Asl.Next; 115 } 116 } 117 118 if (!PrevOp) 119 { 120 return; 121 } 122 123 /* We must have a namepath AML opcode */ 124 125 if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP) 126 { 127 return; 128 } 129 130 /* A null string is the "no target specified" case */ 131 132 if (!PrevOp->Asl.Value.String) 133 { 134 return; 135 } 136 137 /* No node means "unresolved external reference" */ 138 139 if (!PrevOp->Asl.Node) 140 { 141 AcpiOsPrintf (" /* External reference */"); 142 return; 143 } 144 145 /* Ignore if path is already from the root */ 146 147 if (*PrevOp->Asl.Value.String == '\\') 148 { 149 return; 150 } 151 152 /* Now: we can get the full pathname */ 153 154 Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node); 155 if (!Pathname) 156 { 157 return; 158 } 159 160 AcpiOsPrintf (" /* %s */", Pathname); 161 ACPI_FREE (Pathname); 162 } 163 164 165 /******************************************************************************* 166 * 167 * FUNCTION: AcpiDmNotifyDescription 168 * 169 * PARAMETERS: Op - Name() parse object 170 * 171 * RETURN: None 172 * 173 * DESCRIPTION: Emit a description comment for the value associated with a 174 * Notify() operator. 175 * 176 ******************************************************************************/ 177 178 void 179 AcpiDmNotifyDescription ( 180 ACPI_PARSE_OBJECT *Op) 181 { 182 ACPI_PARSE_OBJECT *NextOp; 183 ACPI_NAMESPACE_NODE *Node; 184 UINT8 NotifyValue; 185 UINT8 Type = ACPI_TYPE_ANY; 186 187 188 /* The notify value is the second argument */ 189 190 NextOp = Op->Asl.Value.Arg; 191 NextOp = NextOp->Asl.Next; 192 193 switch (NextOp->Common.AmlOpcode) 194 { 195 case AML_ZERO_OP: 196 case AML_ONE_OP: 197 198 NotifyValue = (UINT8) NextOp->Common.AmlOpcode; 199 break; 200 201 case AML_BYTE_OP: 202 203 NotifyValue = (UINT8) NextOp->Asl.Value.Integer; 204 break; 205 206 default: 207 return; 208 } 209 210 /* 211 * Attempt to get the namespace node so we can determine the object type. 212 * Some notify values are dependent on the object type (Device, Thermal, 213 * or Processor). 214 */ 215 Node = Op->Asl.Node; 216 if (Node) 217 { 218 Type = Node->Type; 219 } 220 221 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type)); 222 } 223 224 225 /******************************************************************************* 226 * 227 * FUNCTION: AcpiDmPredefinedDescription 228 * 229 * PARAMETERS: Op - Name() parse object 230 * 231 * RETURN: None 232 * 233 * DESCRIPTION: Emit a description comment for a predefined ACPI name. 234 * Used for iASL compiler only. 235 * 236 ******************************************************************************/ 237 238 void 239 AcpiDmPredefinedDescription ( 240 ACPI_PARSE_OBJECT *Op) 241 { 242 #ifdef ACPI_ASL_COMPILER 243 const AH_PREDEFINED_NAME *Info; 244 char *NameString; 245 int LastCharIsDigit; 246 int LastCharsAreHex; 247 248 249 if (!Op) 250 { 251 return; 252 } 253 254 /* Ensure that the comment field is emitted only once */ 255 256 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED) 257 { 258 return; 259 } 260 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED; 261 262 /* Predefined name must start with an underscore */ 263 264 NameString = ACPI_CAST_PTR (char, &Op->Named.Name); 265 if (NameString[0] != '_') 266 { 267 return; 268 } 269 270 /* 271 * Check for the special ACPI names: 272 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a 273 * (where d=decimal_digit, x=hex_digit, a=anything) 274 * 275 * Convert these to the generic name for table lookup. 276 * Note: NameString is guaranteed to be upper case here. 277 */ 278 LastCharIsDigit = 279 (isdigit ((int) NameString[3])); /* d */ 280 LastCharsAreHex = 281 (isxdigit ((int) NameString[2]) && /* xx */ 282 isxdigit ((int) NameString[3])); 283 284 switch (NameString[1]) 285 { 286 case 'A': 287 288 if ((NameString[2] == 'C') && (LastCharIsDigit)) 289 { 290 NameString = "_ACx"; 291 } 292 else if ((NameString[2] == 'L') && (LastCharIsDigit)) 293 { 294 NameString = "_ALx"; 295 } 296 break; 297 298 case 'E': 299 300 if ((NameString[2] == 'J') && (LastCharIsDigit)) 301 { 302 NameString = "_EJx"; 303 } 304 else if (LastCharsAreHex) 305 { 306 NameString = "_Exx"; 307 } 308 break; 309 310 case 'L': 311 312 if (LastCharsAreHex) 313 { 314 NameString = "_Lxx"; 315 } 316 break; 317 318 case 'Q': 319 320 if (LastCharsAreHex) 321 { 322 NameString = "_Qxx"; 323 } 324 break; 325 326 case 'T': 327 328 if (NameString[2] == '_') 329 { 330 NameString = "_T_x"; 331 } 332 break; 333 334 case 'W': 335 336 if (LastCharsAreHex) 337 { 338 NameString = "_Wxx"; 339 } 340 break; 341 342 default: 343 344 break; 345 } 346 347 /* Match the name in the info table */ 348 349 Info = AcpiAhMatchPredefinedName (NameString); 350 if (Info) 351 { 352 AcpiOsPrintf (" // %4.4s: %s", 353 NameString, ACPI_CAST_PTR (char, Info->Description)); 354 } 355 356 #endif 357 return; 358 } 359 360 361 /******************************************************************************* 362 * 363 * FUNCTION: AcpiDmFieldPredefinedDescription 364 * 365 * PARAMETERS: Op - Parse object 366 * 367 * RETURN: None 368 * 369 * DESCRIPTION: Emit a description comment for a resource descriptor tag 370 * (which is a predefined ACPI name.) Used for iASL compiler only. 371 * 372 ******************************************************************************/ 373 374 void 375 AcpiDmFieldPredefinedDescription ( 376 ACPI_PARSE_OBJECT *Op) 377 { 378 #ifdef ACPI_ASL_COMPILER 379 ACPI_PARSE_OBJECT *IndexOp; 380 char *Tag; 381 const ACPI_OPCODE_INFO *OpInfo; 382 const AH_PREDEFINED_NAME *Info; 383 384 385 if (!Op) 386 { 387 return; 388 } 389 390 /* Ensure that the comment field is emitted only once */ 391 392 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED) 393 { 394 return; 395 } 396 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED; 397 398 /* 399 * Op must be one of the Create* operators: CreateField, CreateBitField, 400 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField 401 */ 402 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 403 if (!(OpInfo->Flags & AML_CREATE)) 404 { 405 return; 406 } 407 408 /* Second argument is the Index argument */ 409 410 IndexOp = Op->Common.Value.Arg; 411 IndexOp = IndexOp->Common.Next; 412 413 /* Index argument must be a namepath */ 414 415 if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP) 416 { 417 return; 418 } 419 420 /* Major cheat: We previously put the Tag ptr in the Node field */ 421 422 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node); 423 if (!Tag || (*Tag == 0)) 424 { 425 return; 426 } 427 428 /* Is the tag a predefined name? */ 429 430 Info = AcpiAhMatchPredefinedName (Tag); 431 if (!Info) 432 { 433 /* Not a predefined name (does not start with underscore) */ 434 435 return; 436 } 437 438 AcpiOsPrintf (" // %4.4s: %s", Tag, 439 ACPI_CAST_PTR (char, Info->Description)); 440 441 /* String contains the prefix path, free it */ 442 443 ACPI_FREE (IndexOp->Common.Value.String); 444 IndexOp->Common.Value.String = NULL; 445 #endif 446 447 return; 448 } 449 450 451 /******************************************************************************* 452 * 453 * FUNCTION: AcpiDmMethodFlags 454 * 455 * PARAMETERS: Op - Method Object to be examined 456 * 457 * RETURN: None 458 * 459 * DESCRIPTION: Decode control method flags 460 * 461 ******************************************************************************/ 462 463 void 464 AcpiDmMethodFlags ( 465 ACPI_PARSE_OBJECT *Op) 466 { 467 UINT32 Flags; 468 UINT32 Args; 469 470 471 /* The next Op contains the flags */ 472 473 Op = AcpiPsGetDepthNext (NULL, Op); 474 Flags = (UINT8) Op->Common.Value.Integer; 475 Args = Flags & 0x07; 476 477 /* Mark the Op as completed */ 478 479 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 480 481 /* 1) Method argument count */ 482 483 AcpiOsPrintf (", %u, ", Args); 484 485 /* 2) Serialize rule */ 486 487 if (!(Flags & 0x08)) 488 { 489 AcpiOsPrintf ("Not"); 490 } 491 492 AcpiOsPrintf ("Serialized"); 493 494 /* 3) SyncLevel */ 495 496 if (Flags & 0xF0) 497 { 498 AcpiOsPrintf (", %u", Flags >> 4); 499 } 500 } 501 502 503 /******************************************************************************* 504 * 505 * FUNCTION: AcpiDmFieldFlags 506 * 507 * PARAMETERS: Op - Field Object to be examined 508 * 509 * RETURN: None 510 * 511 * DESCRIPTION: Decode Field definition flags 512 * 513 ******************************************************************************/ 514 515 void 516 AcpiDmFieldFlags ( 517 ACPI_PARSE_OBJECT *Op) 518 { 519 UINT32 Flags; 520 521 522 Op = Op->Common.Next; 523 Flags = (UINT8) Op->Common.Value.Integer; 524 525 /* Mark the Op as completed */ 526 527 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 528 529 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]); 530 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]); 531 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]); 532 } 533 534 535 /******************************************************************************* 536 * 537 * FUNCTION: AcpiDmAddressSpace 538 * 539 * PARAMETERS: SpaceId - ID to be translated 540 * 541 * RETURN: None 542 * 543 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword 544 * 545 ******************************************************************************/ 546 547 void 548 AcpiDmAddressSpace ( 549 UINT8 SpaceId) 550 { 551 552 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) 553 { 554 if (SpaceId == 0x7F) 555 { 556 AcpiOsPrintf ("FFixedHW, "); 557 } 558 else 559 { 560 AcpiOsPrintf ("0x%.2X, ", SpaceId); 561 } 562 } 563 else 564 { 565 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]); 566 } 567 } 568 569 570 /******************************************************************************* 571 * 572 * FUNCTION: AcpiDmRegionFlags 573 * 574 * PARAMETERS: Op - Object to be examined 575 * 576 * RETURN: None 577 * 578 * DESCRIPTION: Decode OperationRegion flags 579 * 580 ******************************************************************************/ 581 582 void 583 AcpiDmRegionFlags ( 584 ACPI_PARSE_OBJECT *Op) 585 { 586 587 /* The next Op contains the SpaceId */ 588 589 Op = AcpiPsGetDepthNext (NULL, Op); 590 591 /* Mark the Op as completed */ 592 593 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 594 595 AcpiOsPrintf (", "); 596 AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer); 597 } 598 599 600 /******************************************************************************* 601 * 602 * FUNCTION: AcpiDmMatchOp 603 * 604 * PARAMETERS: Op - Match Object to be examined 605 * 606 * RETURN: None 607 * 608 * DESCRIPTION: Decode Match opcode operands 609 * 610 ******************************************************************************/ 611 612 void 613 AcpiDmMatchOp ( 614 ACPI_PARSE_OBJECT *Op) 615 { 616 ACPI_PARSE_OBJECT *NextOp; 617 618 619 NextOp = AcpiPsGetDepthNext (NULL, Op); 620 NextOp = NextOp->Common.Next; 621 622 if (!NextOp) 623 { 624 /* Handle partial tree during single-step */ 625 626 return; 627 } 628 629 /* Mark the two nodes that contain the encoding for the match keywords */ 630 631 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP; 632 633 NextOp = NextOp->Common.Next; 634 NextOp = NextOp->Common.Next; 635 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP; 636 } 637 638 639 /******************************************************************************* 640 * 641 * FUNCTION: AcpiDmMatchKeyword 642 * 643 * PARAMETERS: Op - Match Object to be examined 644 * 645 * RETURN: None 646 * 647 * DESCRIPTION: Decode Match opcode operands 648 * 649 ******************************************************************************/ 650 651 static void 652 AcpiDmMatchKeyword ( 653 ACPI_PARSE_OBJECT *Op) 654 { 655 656 if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE) 657 { 658 AcpiOsPrintf ("/* Unknown Match Keyword encoding */"); 659 } 660 else 661 { 662 AcpiOsPrintf ("%s", 663 AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]); 664 } 665 } 666 667 668 /******************************************************************************* 669 * 670 * FUNCTION: AcpiDmDisassembleOneOp 671 * 672 * PARAMETERS: WalkState - Current walk info 673 * Info - Parse tree walk info 674 * Op - Op that is to be printed 675 * 676 * RETURN: None 677 * 678 * DESCRIPTION: Disassemble a single AML opcode 679 * 680 ******************************************************************************/ 681 682 void 683 AcpiDmDisassembleOneOp ( 684 ACPI_WALK_STATE *WalkState, 685 ACPI_OP_WALK_INFO *Info, 686 ACPI_PARSE_OBJECT *Op) 687 { 688 const ACPI_OPCODE_INFO *OpInfo = NULL; 689 UINT32 Offset; 690 UINT32 Length; 691 ACPI_PARSE_OBJECT *Child; 692 ACPI_PARSE_OBJECT *MethodCallOp; 693 ACPI_STATUS Status; 694 UINT8 *Aml; 695 const AH_DEVICE_ID *IdInfo; 696 697 698 if (!Op) 699 { 700 AcpiOsPrintf ("<NULL OP PTR>"); 701 return; 702 } 703 704 if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF) 705 { 706 return; /* ElseIf macro was already emitted */ 707 } 708 709 switch (Op->Common.DisasmOpcode) 710 { 711 case ACPI_DASM_MATCHOP: 712 713 AcpiDmMatchKeyword (Op); 714 return; 715 716 case ACPI_DASM_LNOT_SUFFIX: 717 718 if (!AcpiGbl_CstyleDisassembly) 719 { 720 switch (Op->Common.AmlOpcode) 721 { 722 case AML_LOGICAL_EQUAL_OP: 723 AcpiOsPrintf ("LNotEqual"); 724 break; 725 726 case AML_LOGICAL_GREATER_OP: 727 AcpiOsPrintf ("LLessEqual"); 728 break; 729 730 case AML_LOGICAL_LESS_OP: 731 AcpiOsPrintf ("LGreaterEqual"); 732 break; 733 734 default: 735 break; 736 } 737 } 738 739 Op->Common.DisasmOpcode = 0; 740 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 741 return; 742 743 default: 744 break; 745 } 746 747 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 748 749 /* The op and arguments */ 750 751 switch (Op->Common.AmlOpcode) 752 { 753 case AML_LOGICAL_NOT_OP: 754 755 Child = Op->Common.Value.Arg; 756 if ((Child->Common.AmlOpcode == AML_LOGICAL_EQUAL_OP) || 757 (Child->Common.AmlOpcode == AML_LOGICAL_GREATER_OP) || 758 (Child->Common.AmlOpcode == AML_LOGICAL_LESS_OP)) 759 { 760 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX; 761 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; 762 } 763 else 764 { 765 AcpiOsPrintf ("%s", OpInfo->Name); 766 } 767 break; 768 769 case AML_BYTE_OP: 770 771 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer); 772 break; 773 774 case AML_WORD_OP: 775 776 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID) 777 { 778 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer); 779 } 780 else 781 { 782 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer); 783 } 784 break; 785 786 case AML_DWORD_OP: 787 788 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID) 789 { 790 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer); 791 } 792 else 793 { 794 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer); 795 } 796 break; 797 798 case AML_QWORD_OP: 799 800 AcpiOsPrintf ("0x%8.8X%8.8X", 801 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); 802 break; 803 804 case AML_STRING_OP: 805 806 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX); 807 808 /* For _HID/_CID strings, attempt to output a descriptive comment */ 809 810 if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING) 811 { 812 /* If we know about the ID, emit the description */ 813 814 IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String); 815 if (IdInfo) 816 { 817 AcpiOsPrintf (" /* %s */", IdInfo->Description); 818 } 819 } 820 break; 821 822 case AML_BUFFER_OP: 823 /* 824 * Determine the type of buffer. We can have one of the following: 825 * 826 * 1) ResourceTemplate containing Resource Descriptors. 827 * 2) Unicode String buffer 828 * 3) ASCII String buffer 829 * 4) Raw data buffer (if none of the above) 830 * 831 * Since there are no special AML opcodes to differentiate these 832 * types of buffers, we have to closely look at the data in the 833 * buffer to determine the type. 834 */ 835 if (!AcpiGbl_NoResourceDisassembly) 836 { 837 Status = AcpiDmIsResourceTemplate (WalkState, Op); 838 if (ACPI_SUCCESS (Status)) 839 { 840 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE; 841 AcpiOsPrintf ("ResourceTemplate"); 842 break; 843 } 844 else if (Status == AE_AML_NO_RESOURCE_END_TAG) 845 { 846 AcpiOsPrintf ( 847 "/**** Is ResourceTemplate, " 848 "but EndTag not at buffer end ****/ "); 849 } 850 } 851 852 if (AcpiDmIsUuidBuffer (Op)) 853 { 854 Op->Common.DisasmOpcode = ACPI_DASM_UUID; 855 AcpiOsPrintf ("ToUUID ("); 856 } 857 else if (AcpiDmIsUnicodeBuffer (Op)) 858 { 859 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE; 860 AcpiOsPrintf ("Unicode ("); 861 } 862 else if (AcpiDmIsStringBuffer (Op)) 863 { 864 Op->Common.DisasmOpcode = ACPI_DASM_STRING; 865 AcpiOsPrintf ("Buffer"); 866 } 867 else if (AcpiDmIsPldBuffer (Op)) 868 { 869 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD; 870 AcpiOsPrintf ("ToPLD ("); 871 } 872 else 873 { 874 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER; 875 AcpiOsPrintf ("Buffer"); 876 } 877 break; 878 879 case AML_INT_NAMEPATH_OP: 880 881 AcpiDmNamestring (Op->Common.Value.Name); 882 /* If this namepath is a Package element, emit a separating comma */ 883 if ((Op->Common.Parent) && 884 ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 885 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))) 886 { 887 AcpiOsPrintf (", "); 888 } 889 break; 890 891 case AML_INT_NAMEDFIELD_OP: 892 893 Length = AcpiDmDumpName (Op->Named.Name); 894 895 AcpiOsPrintf (","); 896 ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0); 897 AcpiOsPrintf ("%*.s %u", (unsigned) (5 - Length), " ", 898 (UINT32) Op->Common.Value.Integer); 899 900 AcpiDmCommaIfFieldMember (Op); 901 902 Info->BitOffset += (UINT32) Op->Common.Value.Integer; 903 break; 904 905 case AML_INT_RESERVEDFIELD_OP: 906 907 /* Offset() -- Must account for previous offsets */ 908 909 Offset = (UINT32) Op->Common.Value.Integer; 910 Info->BitOffset += Offset; 911 912 if (Info->BitOffset % 8 == 0) 913 { 914 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset)); 915 } 916 else 917 { 918 AcpiOsPrintf (" , %u", Offset); 919 } 920 921 AcpiDmCommaIfFieldMember (Op); 922 break; 923 924 case AML_INT_ACCESSFIELD_OP: 925 case AML_INT_EXTACCESSFIELD_OP: 926 927 AcpiOsPrintf ("AccessAs (%s, ", 928 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]); 929 930 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8)); 931 932 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP) 933 { 934 AcpiOsPrintf (" (0x%2.2X)", (unsigned) 935 ((Op->Common.Value.Integer >> 16) & 0xFF)); 936 } 937 938 AcpiOsPrintf (")"); 939 AcpiDmCommaIfFieldMember (Op); 940 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 941 break; 942 943 case AML_INT_CONNECTION_OP: 944 /* 945 * Two types of Connection() - one with a buffer object, the 946 * other with a namestring that points to a buffer object. 947 */ 948 AcpiOsPrintf ("Connection ("); 949 Child = Op->Common.Value.Arg; 950 951 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP) 952 { 953 AcpiOsPrintf ("\n"); 954 955 Aml = Child->Named.Data; 956 Length = (UINT32) Child->Common.Value.Integer; 957 958 Info->Level += 1; 959 Info->MappingOp = Op; 960 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE; 961 962 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length); 963 964 Info->Level -= 1; 965 AcpiDmIndent (Info->Level); 966 } 967 else 968 { 969 AcpiDmNamestring (Child->Common.Value.Name); 970 } 971 972 AcpiOsPrintf (")"); 973 AcpiDmCommaIfFieldMember (Op); 974 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 975 ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, NULL, 0); 976 AcpiOsPrintf ("\n"); 977 978 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */ 979 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 980 break; 981 982 case AML_INT_BYTELIST_OP: 983 984 AcpiDmByteList (Info, Op); 985 break; 986 987 case AML_INT_METHODCALL_OP: 988 989 MethodCallOp = Op; 990 Op = AcpiPsGetDepthNext (NULL, Op); 991 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 992 993 AcpiDmNamestring (Op->Common.Value.Name); 994 995 /* If the method name is a Package element, emit a separating comma */ 996 if ((MethodCallOp->Common.Parent) && 997 ((MethodCallOp->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 998 (MethodCallOp->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))) 999 { 1000 AcpiOsPrintf (", "); 1001 } 1002 break; 1003 1004 case AML_WHILE_OP: 1005 1006 if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH) 1007 { 1008 AcpiOsPrintf ("%s", "Switch"); 1009 break; 1010 } 1011 1012 AcpiOsPrintf ("%s", OpInfo->Name); 1013 break; 1014 1015 case AML_IF_OP: 1016 1017 if (Op->Common.DisasmOpcode == ACPI_DASM_CASE) 1018 { 1019 AcpiOsPrintf ("%s", "Case"); 1020 break; 1021 } 1022 1023 AcpiOsPrintf ("%s", OpInfo->Name); 1024 break; 1025 1026 case AML_ELSE_OP: 1027 1028 AcpiDmConvertToElseIf (Op); 1029 break; 1030 1031 case AML_EXTERNAL_OP: 1032 1033 if (AcpiGbl_DmEmitExternalOpcodes) 1034 { 1035 AcpiDmEmitExternal (Op, AcpiPsGetArg(Op, 0)); 1036 } 1037 1038 break; 1039 1040 default: 1041 1042 /* Just get the opcode name and print it */ 1043 1044 AcpiOsPrintf ("%s", OpInfo->Name); 1045 1046 1047 #ifdef ACPI_DEBUGGER 1048 1049 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) && 1050 (WalkState) && 1051 (WalkState->Results) && 1052 (WalkState->ResultCount)) 1053 { 1054 AcpiDbDecodeInternalObject ( 1055 WalkState->Results->Results.ObjDesc [ 1056 (WalkState->ResultCount - 1) % 1057 ACPI_RESULTS_FRAME_OBJ_NUM]); 1058 } 1059 #endif 1060 1061 break; 1062 } 1063 } 1064 1065 1066 /******************************************************************************* 1067 * 1068 * FUNCTION: AcpiDmConvertToElseIf 1069 * 1070 * PARAMETERS: OriginalElseOp - ELSE Object to be examined 1071 * 1072 * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator. 1073 * 1074 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf 1075 * 1076 * EXAMPLE: 1077 * 1078 * This If..Else..If nested sequence: 1079 * 1080 * If (Arg0 == 1) 1081 * { 1082 * Local0 = 4 1083 * } 1084 * Else 1085 * { 1086 * If (Arg0 == 2) 1087 * { 1088 * Local0 = 5 1089 * } 1090 * } 1091 * 1092 * Is converted to this simpler If..ElseIf sequence: 1093 * 1094 * If (Arg0 == 1) 1095 * { 1096 * Local0 = 4 1097 * } 1098 * ElseIf (Arg0 == 2) 1099 * { 1100 * Local0 = 5 1101 * } 1102 * 1103 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL 1104 * macro that emits an Else opcode followed by an If opcode. This function 1105 * reverses these AML sequences back to an ElseIf macro where possible. This 1106 * can make the disassembled ASL code simpler and more like the original code. 1107 * 1108 ******************************************************************************/ 1109 1110 static void 1111 AcpiDmConvertToElseIf ( 1112 ACPI_PARSE_OBJECT *OriginalElseOp) 1113 { 1114 ACPI_PARSE_OBJECT *IfOp; 1115 ACPI_PARSE_OBJECT *ElseOp; 1116 1117 1118 /* 1119 * To be able to perform the conversion, two conditions must be satisfied: 1120 * 1) The first child of the Else must be an If statement. 1121 * 2) The If block can only be followed by an Else block and these must 1122 * be the only blocks under the original Else. 1123 */ 1124 IfOp = OriginalElseOp->Common.Value.Arg; 1125 1126 if (!IfOp || 1127 (IfOp->Common.AmlOpcode != AML_IF_OP) || 1128 (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP))) 1129 { 1130 /* Not a proper Else..If sequence, cannot convert to ElseIf */ 1131 1132 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT) 1133 { 1134 AcpiOsPrintf ("%s", "Default"); 1135 return; 1136 } 1137 1138 AcpiOsPrintf ("%s", "Else"); 1139 return; 1140 } 1141 1142 /* Cannot have anything following the If...Else block */ 1143 1144 ElseOp = IfOp->Common.Next; 1145 if (ElseOp && ElseOp->Common.Next) 1146 { 1147 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT) 1148 { 1149 AcpiOsPrintf ("%s", "Default"); 1150 return; 1151 } 1152 1153 AcpiOsPrintf ("%s", "Else"); 1154 return; 1155 } 1156 1157 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT) 1158 { 1159 /* 1160 * There is an ElseIf but in this case the Else is actually 1161 * a Default block for a Switch/Case statement. No conversion. 1162 */ 1163 AcpiOsPrintf ("%s", "Default"); 1164 return; 1165 } 1166 1167 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE) 1168 { 1169 /* 1170 * This ElseIf is actually a Case block for a Switch/Case 1171 * statement. Print Case but do not return so that we can 1172 * promote the subtree and keep the indentation level. 1173 */ 1174 AcpiOsPrintf ("%s", "Case"); 1175 } 1176 else 1177 { 1178 /* Emit ElseIf, mark the IF as now an ELSEIF */ 1179 1180 AcpiOsPrintf ("%s", "ElseIf"); 1181 } 1182 1183 IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF; 1184 1185 /* The IF parent will now be the same as the original ELSE parent */ 1186 1187 IfOp->Common.Parent = OriginalElseOp->Common.Parent; 1188 1189 /* 1190 * Update the NEXT pointers to restructure the parse tree, essentially 1191 * promoting an If..Else block up to the same level as the original 1192 * Else. 1193 * 1194 * Check if the IF has a corresponding ELSE peer 1195 */ 1196 ElseOp = IfOp->Common.Next; 1197 if (ElseOp && 1198 (ElseOp->Common.AmlOpcode == AML_ELSE_OP)) 1199 { 1200 /* If an ELSE matches the IF, promote it also */ 1201 1202 ElseOp->Common.Parent = OriginalElseOp->Common.Parent; 1203 1204 /* Promote the entire block under the ElseIf (All Next OPs) */ 1205 1206 AcpiDmPromoteSubtree (OriginalElseOp); 1207 } 1208 else 1209 { 1210 /* Otherwise, set the IF NEXT to the original ELSE NEXT */ 1211 1212 IfOp->Common.Next = OriginalElseOp->Common.Next; 1213 } 1214 1215 /* Detach the child IF block from the original ELSE */ 1216 1217 OriginalElseOp->Common.Value.Arg = NULL; 1218 1219 /* Ignore the original ELSE from now on */ 1220 1221 OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1222 OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; 1223 1224 /* Insert IF (now ELSEIF) as next peer of the original ELSE */ 1225 1226 OriginalElseOp->Common.Next = IfOp; 1227 } 1228 1229 1230 /******************************************************************************* 1231 * 1232 * FUNCTION: AcpiDmPromoteSubtree 1233 * 1234 * PARAMETERS: StartOpOp - Original parent of the entire subtree 1235 * 1236 * RETURN: None 1237 * 1238 * DESCRIPTION: Promote an entire parse subtree up one level. 1239 * 1240 ******************************************************************************/ 1241 1242 static void 1243 AcpiDmPromoteSubtree ( 1244 ACPI_PARSE_OBJECT *StartOp) 1245 { 1246 ACPI_PARSE_OBJECT *Op; 1247 ACPI_PARSE_OBJECT *ParentOp; 1248 1249 1250 /* New parent for subtree elements */ 1251 1252 ParentOp = StartOp->Common.Parent; 1253 1254 /* First child starts the subtree */ 1255 1256 Op = StartOp->Common.Value.Arg; 1257 1258 /* Walk the top-level elements of the subtree */ 1259 1260 while (Op) 1261 { 1262 Op->Common.Parent = ParentOp; 1263 if (!Op->Common.Next) 1264 { 1265 /* Last Op in list, update its next field */ 1266 1267 Op->Common.Next = StartOp->Common.Next; 1268 break; 1269 } 1270 Op = Op->Common.Next; 1271 } 1272 } 1273