dmopcode.c revision 298714
1189251Ssam/******************************************************************************* 2189251Ssam * 3189251Ssam * Module Name: dmopcode - AML disassembler, specific AML opcodes 4189251Ssam * 5252726Srpaulo ******************************************************************************/ 6252726Srpaulo 7189251Ssam/* 8189251Ssam * Copyright (C) 2000 - 2016, Intel Corp. 9189251Ssam * All rights reserved. 10189251Ssam * 11189251Ssam * Redistribution and use in source and binary forms, with or without 12214734Srpaulo * modification, are permitted provided that the following conditions 13189251Ssam * are met: 14189251Ssam * 1. Redistributions of source code must retain the above copyright 15189251Ssam * notice, this list of conditions, and the following disclaimer, 16189251Ssam * without modification. 17189251Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18189251Ssam * substantially similar to the "NO WARRANTY" disclaimer below 19189251Ssam * ("Disclaimer") and any redistribution must be conditioned upon 20189251Ssam * including a substantially similar Disclaimer requirement for further 21189251Ssam * binary redistribution. 22189251Ssam * 3. Neither the names of the above-listed copyright holders nor the names 23189251Ssam * of any contributors may be used to endorse or promote products derived 24189251Ssam * from this software without specific prior written permission. 25189251Ssam * 26189251Ssam * Alternatively, this software may be distributed under the terms of the 27189251Ssam * GNU General Public License ("GPL") version 2 as published by the Free 28189251Ssam * Software Foundation. 29189251Ssam * 30189251Ssam * NO WARRANTY 31189251Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32189251Ssam * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33189251Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34189251Ssam * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35189251Ssam * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36189251Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37189251Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38189251Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39189251Ssam * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40189251Ssam * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41189251Ssam * POSSIBILITY OF SUCH DAMAGES. 42189251Ssam */ 43189251Ssam 44189251Ssam#include <contrib/dev/acpica/include/acpi.h> 45189251Ssam#include <contrib/dev/acpica/include/accommon.h> 46189251Ssam#include <contrib/dev/acpica/include/acparser.h> 47189251Ssam#include <contrib/dev/acpica/include/amlcode.h> 48189251Ssam#include <contrib/dev/acpica/include/acinterp.h> 49189251Ssam#include <contrib/dev/acpica/include/acnamesp.h> 50189251Ssam#include <contrib/dev/acpica/include/acdebug.h> 51189251Ssam 52189251Ssam 53189251Ssam#define _COMPONENT ACPI_CA_DEBUGGER 54189251Ssam ACPI_MODULE_NAME ("dmopcode") 55189251Ssam 56189251Ssam 57189251Ssam/* Local prototypes */ 58189251Ssam 59189251Ssamstatic void 60189251SsamAcpiDmMatchKeyword ( 61189251Ssam ACPI_PARSE_OBJECT *Op); 62189251Ssam 63189251Ssamstatic void 64189251SsamAcpiDmConvertToElseIf ( 65189251Ssam ACPI_PARSE_OBJECT *Op); 66189251Ssam 67189251Ssam 68189251Ssam/******************************************************************************* 69189251Ssam * 70189251Ssam * FUNCTION: AcpiDmDisplayTargetPathname 71189251Ssam * 72189251Ssam * PARAMETERS: Op - Parse object 73189251Ssam * 74189251Ssam * RETURN: None 75189251Ssam * 76189251Ssam * DESCRIPTION: For AML opcodes that have a target operand, display the full 77189251Ssam * pathname for the target, in a comment field. Handles Return() 78189251Ssam * statements also. 79189251Ssam * 80189251Ssam ******************************************************************************/ 81189251Ssam 82189251Ssamvoid 83189251SsamAcpiDmDisplayTargetPathname ( 84189251Ssam ACPI_PARSE_OBJECT *Op) 85189251Ssam{ 86189251Ssam ACPI_PARSE_OBJECT *NextOp; 87189251Ssam ACPI_PARSE_OBJECT *PrevOp = NULL; 88189251Ssam char *Pathname; 89189251Ssam const ACPI_OPCODE_INFO *OpInfo; 90189251Ssam 91189251Ssam 92189251Ssam if (Op->Common.AmlOpcode == AML_RETURN_OP) 93189251Ssam { 94189251Ssam PrevOp = Op->Asl.Value.Arg; 95189251Ssam } 96189251Ssam else 97189251Ssam { 98189251Ssam OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 99189251Ssam if (!(OpInfo->Flags & AML_HAS_TARGET)) 100189251Ssam { 101189251Ssam return; 102189251Ssam } 103189251Ssam 104189251Ssam /* Target is the last Op in the arg list */ 105189251Ssam 106189251Ssam NextOp = Op->Asl.Value.Arg; 107189251Ssam while (NextOp) 108189251Ssam { 109189251Ssam PrevOp = NextOp; 110189251Ssam NextOp = PrevOp->Asl.Next; 111189251Ssam } 112189251Ssam } 113189251Ssam 114189251Ssam if (!PrevOp) 115189251Ssam { 116189251Ssam return; 117189251Ssam } 118189251Ssam 119189251Ssam /* We must have a namepath AML opcode */ 120189251Ssam 121189251Ssam if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP) 122189251Ssam { 123189251Ssam return; 124189251Ssam } 125189251Ssam 126189251Ssam /* A null string is the "no target specified" case */ 127189251Ssam 128189251Ssam if (!PrevOp->Asl.Value.String) 129189251Ssam { 130189251Ssam return; 131189251Ssam } 132189251Ssam 133189251Ssam /* No node means "unresolved external reference" */ 134189251Ssam 135189251Ssam if (!PrevOp->Asl.Node) 136189251Ssam { 137189251Ssam AcpiOsPrintf (" /* External reference */"); 138189251Ssam return; 139189251Ssam } 140189251Ssam 141189251Ssam /* Ignore if path is already from the root */ 142189251Ssam 143189251Ssam if (*PrevOp->Asl.Value.String == '\\') 144189251Ssam { 145189251Ssam return; 146189251Ssam } 147189251Ssam 148189251Ssam /* Now: we can get the full pathname */ 149189251Ssam 150189251Ssam Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node); 151189251Ssam if (!Pathname) 152189251Ssam { 153189251Ssam return; 154189251Ssam } 155189251Ssam 156189251Ssam AcpiOsPrintf (" /* %s */", Pathname); 157189251Ssam ACPI_FREE (Pathname); 158189251Ssam} 159189251Ssam 160189251Ssam 161189251Ssam/******************************************************************************* 162189251Ssam * 163189251Ssam * FUNCTION: AcpiDmNotifyDescription 164189251Ssam * 165189251Ssam * PARAMETERS: Op - Name() parse object 166189251Ssam * 167189251Ssam * RETURN: None 168189251Ssam * 169189251Ssam * DESCRIPTION: Emit a description comment for the value associated with a 170189251Ssam * Notify() operator. 171189251Ssam * 172189251Ssam ******************************************************************************/ 173189251Ssam 174214734Srpaulovoid 175214734SrpauloAcpiDmNotifyDescription ( 176214734Srpaulo ACPI_PARSE_OBJECT *Op) 177214734Srpaulo{ 178214734Srpaulo ACPI_PARSE_OBJECT *NextOp; 179214734Srpaulo ACPI_NAMESPACE_NODE *Node; 180214734Srpaulo UINT8 NotifyValue; 181189251Ssam UINT8 Type = ACPI_TYPE_ANY; 182189251Ssam 183189251Ssam 184189251Ssam /* The notify value is the second argument */ 185189251Ssam 186189251Ssam NextOp = Op->Asl.Value.Arg; 187189251Ssam NextOp = NextOp->Asl.Next; 188189251Ssam 189189251Ssam switch (NextOp->Common.AmlOpcode) 190189251Ssam { 191189251Ssam case AML_ZERO_OP: 192189251Ssam case AML_ONE_OP: 193189251Ssam 194189251Ssam NotifyValue = (UINT8) NextOp->Common.AmlOpcode; 195189251Ssam break; 196189251Ssam 197189251Ssam case AML_BYTE_OP: 198189251Ssam 199189251Ssam NotifyValue = (UINT8) NextOp->Asl.Value.Integer; 200189251Ssam break; 201189251Ssam 202189251Ssam default: 203189251Ssam return; 204189251Ssam } 205189251Ssam 206189251Ssam /* 207189251Ssam * Attempt to get the namespace node so we can determine the object type. 208189251Ssam * Some notify values are dependent on the object type (Device, Thermal, 209189251Ssam * or Processor). 210189251Ssam */ 211189251Ssam Node = Op->Asl.Node; 212189251Ssam if (Node) 213189251Ssam { 214189251Ssam Type = Node->Type; 215189251Ssam } 216189251Ssam 217189251Ssam AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type)); 218189251Ssam} 219189251Ssam 220189251Ssam 221189251Ssam/******************************************************************************* 222189251Ssam * 223189251Ssam * FUNCTION: AcpiDmPredefinedDescription 224189251Ssam * 225189251Ssam * PARAMETERS: Op - Name() parse object 226189251Ssam * 227189251Ssam * RETURN: None 228189251Ssam * 229189251Ssam * DESCRIPTION: Emit a description comment for a predefined ACPI name. 230189251Ssam * Used for iASL compiler only. 231189251Ssam * 232189251Ssam ******************************************************************************/ 233189251Ssam 234189251Ssamvoid 235189251SsamAcpiDmPredefinedDescription ( 236189251Ssam ACPI_PARSE_OBJECT *Op) 237189251Ssam{ 238189251Ssam#ifdef ACPI_ASL_COMPILER 239189251Ssam const AH_PREDEFINED_NAME *Info; 240189251Ssam char *NameString; 241189251Ssam int LastCharIsDigit; 242189251Ssam int LastCharsAreHex; 243189251Ssam 244189251Ssam 245189251Ssam if (!Op) 246189251Ssam { 247189251Ssam return; 248189251Ssam } 249189251Ssam 250189251Ssam /* Ensure that the comment field is emitted only once */ 251189251Ssam 252189251Ssam if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED) 253189251Ssam { 254189251Ssam return; 255189251Ssam } 256189251Ssam Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED; 257189251Ssam 258189251Ssam /* Predefined name must start with an underscore */ 259189251Ssam 260189251Ssam NameString = ACPI_CAST_PTR (char, &Op->Named.Name); 261252726Srpaulo if (NameString[0] != '_') 262252726Srpaulo { 263189251Ssam return; 264252726Srpaulo } 265252726Srpaulo 266252726Srpaulo /* 267252726Srpaulo * Check for the special ACPI names: 268252726Srpaulo * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a 269252726Srpaulo * (where d=decimal_digit, x=hex_digit, a=anything) 270252726Srpaulo * 271252726Srpaulo * Convert these to the generic name for table lookup. 272252726Srpaulo * Note: NameString is guaranteed to be upper case here. 273252726Srpaulo */ 274252726Srpaulo LastCharIsDigit = 275252726Srpaulo (isdigit ((int) NameString[3])); /* d */ 276189251Ssam LastCharsAreHex = 277189251Ssam (isxdigit ((int) NameString[2]) && /* xx */ 278189251Ssam isxdigit ((int) NameString[3])); 279252726Srpaulo 280252726Srpaulo switch (NameString[1]) 281252726Srpaulo { 282252726Srpaulo case 'A': 283252726Srpaulo 284252726Srpaulo if ((NameString[2] == 'C') && (LastCharIsDigit)) 285252726Srpaulo { 286189251Ssam NameString = "_ACx"; 287189251Ssam } 288189251Ssam else if ((NameString[2] == 'L') && (LastCharIsDigit)) 289189251Ssam { 290189251Ssam NameString = "_ALx"; 291189251Ssam } 292189251Ssam break; 293189251Ssam 294252726Srpaulo case 'E': 295189251Ssam 296252726Srpaulo if ((NameString[2] == 'J') && (LastCharIsDigit)) 297189251Ssam { 298189251Ssam NameString = "_EJx"; 299189251Ssam } 300189251Ssam else if (LastCharsAreHex) 301189251Ssam { 302189251Ssam NameString = "_Exx"; 303189251Ssam } 304189251Ssam break; 305189251Ssam 306189251Ssam case 'L': 307189251Ssam 308189251Ssam if (LastCharsAreHex) 309189251Ssam { 310189251Ssam NameString = "_Lxx"; 311189251Ssam } 312189251Ssam break; 313189251Ssam 314189251Ssam case 'Q': 315189251Ssam 316189251Ssam if (LastCharsAreHex) 317189251Ssam { 318189251Ssam NameString = "_Qxx"; 319252726Srpaulo } 320252726Srpaulo break; 321189251Ssam 322189251Ssam case 'T': 323252726Srpaulo 324189251Ssam if (NameString[2] == '_') 325189251Ssam { 326189251Ssam NameString = "_T_x"; 327189251Ssam } 328189251Ssam break; 329189251Ssam 330189251Ssam case 'W': 331189251Ssam 332189251Ssam if (LastCharsAreHex) 333189251Ssam { 334189251Ssam NameString = "_Wxx"; 335189251Ssam } 336189251Ssam break; 337189251Ssam 338189251Ssam default: 339189251Ssam 340189251Ssam break; 341189251Ssam } 342252726Srpaulo 343189251Ssam /* 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 370void 371AcpiDmFieldPredefinedDescription ( 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 450void 451AcpiDmMethodFlags ( 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 502void 503AcpiDmFieldFlags ( 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 534void 535AcpiDmAddressSpace ( 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 569void 570AcpiDmRegionFlags ( 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 599void 600AcpiDmMatchOp ( 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 638static void 639AcpiDmMatchKeyword ( 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 669void 670AcpiDmDisassembleOneOp ( 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 break; 975 976 default: 977 978 /* Just get the opcode name and print it */ 979 980 AcpiOsPrintf ("%s", OpInfo->Name); 981 982 983#ifdef ACPI_DEBUGGER 984 985 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) && 986 (WalkState) && 987 (WalkState->Results) && 988 (WalkState->ResultCount)) 989 { 990 AcpiDbDecodeInternalObject ( 991 WalkState->Results->Results.ObjDesc [ 992 (WalkState->ResultCount - 1) % 993 ACPI_RESULTS_FRAME_OBJ_NUM]); 994 } 995#endif 996 997 break; 998 } 999} 1000 1001 1002/******************************************************************************* 1003 * 1004 * FUNCTION: AcpiDmConvertToElseIf 1005 * 1006 * PARAMETERS: OriginalElseOp - ELSE Object to be examined 1007 * 1008 * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator. 1009 * 1010 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf 1011 * 1012 * EXAMPLE: 1013 * 1014 * This If..Else..If nested sequence: 1015 * 1016 * If (Arg0 == 1) 1017 * { 1018 * Local0 = 4 1019 * } 1020 * Else 1021 * { 1022 * If (Arg0 == 2) 1023 * { 1024 * Local0 = 5 1025 * } 1026 * } 1027 * 1028 * Is converted to this simpler If..ElseIf sequence: 1029 * 1030 * If (Arg0 == 1) 1031 * { 1032 * Local0 = 4 1033 * } 1034 * ElseIf (Arg0 == 2) 1035 * { 1036 * Local0 = 5 1037 * } 1038 * 1039 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL 1040 * macro that emits an Else opcode followed by an If opcode. This function 1041 * reverses these AML sequences back to an ElseIf macro where possible. This 1042 * can make the disassembled ASL code simpler and more like the original code. 1043 * 1044 ******************************************************************************/ 1045 1046static void 1047AcpiDmConvertToElseIf ( 1048 ACPI_PARSE_OBJECT *OriginalElseOp) 1049{ 1050 ACPI_PARSE_OBJECT *IfOp; 1051 ACPI_PARSE_OBJECT *ElseOp; 1052 1053 1054 /* 1055 * To be able to perform the conversion, two conditions must be satisfied: 1056 * 1) The first child of the Else must be an If statement. 1057 * 2) The If block can only be followed by an Else block and these must 1058 * be the only blocks under the original Else. 1059 */ 1060 IfOp = OriginalElseOp->Common.Value.Arg; 1061 if (!IfOp || 1062 (IfOp->Common.AmlOpcode != AML_IF_OP) || 1063 (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP))) 1064 { 1065 /* Not an Else..If sequence, cannot convert to ElseIf */ 1066 1067 AcpiOsPrintf ("%s", "Else"); 1068 return; 1069 } 1070 1071 /* Emit ElseIf, mark the IF as now an ELSEIF */ 1072 1073 AcpiOsPrintf ("%s", "ElseIf"); 1074 IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF; 1075 1076 /* The IF parent will now be the same as the original ELSE parent */ 1077 1078 IfOp->Common.Parent = OriginalElseOp->Common.Parent; 1079 1080 /* 1081 * Update the NEXT pointers to restructure the parse tree, essentially 1082 * promoting an If..Else block up to the same level as the original 1083 * Else. 1084 * 1085 * Check if the IF has a corresponding ELSE peer 1086 */ 1087 ElseOp = IfOp->Common.Next; 1088 if (ElseOp && 1089 (ElseOp->Common.AmlOpcode == AML_ELSE_OP)) 1090 { 1091 /* If an ELSE matches the IF, promote it also */ 1092 1093 ElseOp->Common.Parent = OriginalElseOp->Common.Parent; 1094 ElseOp->Common.Next = OriginalElseOp->Common.Next; 1095 } 1096 else 1097 { 1098 /* Otherwise, set the IF NEXT to the original ELSE NEXT */ 1099 1100 IfOp->Common.Next = OriginalElseOp->Common.Next; 1101 } 1102 1103 /* Detach the child IF block from the original ELSE */ 1104 1105 OriginalElseOp->Common.Value.Arg = NULL; 1106 1107 /* Ignore the original ELSE from now on */ 1108 1109 OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1110 OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; 1111 1112 /* Insert IF (now ELSEIF) as next peer of the original ELSE */ 1113 1114 OriginalElseOp->Common.Next = IfOp; 1115} 1116