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