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