dmwalk.c revision 237412
198944Sobrien/******************************************************************************* 298944Sobrien * 3130803Smarcel * Module Name: dmwalk - AML disassembly tree walk 4130803Smarcel * 598944Sobrien ******************************************************************************/ 698944Sobrien 798944Sobrien/* 898944Sobrien * Copyright (C) 2000 - 2012, Intel Corp. 998944Sobrien * All rights reserved. 1098944Sobrien * 1198944Sobrien * Redistribution and use in source and binary forms, with or without 1298944Sobrien * modification, are permitted provided that the following conditions 1398944Sobrien * are met: 1498944Sobrien * 1. Redistributions of source code must retain the above copyright 1598944Sobrien * notice, this list of conditions, and the following disclaimer, 1698944Sobrien * without modification. 1798944Sobrien * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1898944Sobrien * substantially similar to the "NO WARRANTY" disclaimer below 1998944Sobrien * ("Disclaimer") and any redistribution must be conditioned upon 2098944Sobrien * including a substantially similar Disclaimer requirement for further 2198944Sobrien * binary redistribution. 2298944Sobrien * 3. Neither the names of the above-listed copyright holders nor the names 23130803Smarcel * of any contributors may be used to endorse or promote products derived 24130803Smarcel * from this software without specific prior written permission. 2598944Sobrien * 2698944Sobrien * Alternatively, this software may be distributed under the terms of the 27130803Smarcel * GNU General Public License ("GPL") version 2 as published by the Free 2898944Sobrien * Software Foundation. 2998944Sobrien * 30130803Smarcel * NO WARRANTY 3198944Sobrien * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32130803Smarcel * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3398944Sobrien * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34130803Smarcel * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35130803Smarcel * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36130803Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37130803Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38130803Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39130803Smarcel * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40130803Smarcel * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4198944Sobrien * POSSIBILITY OF SUCH DAMAGES. 4298944Sobrien */ 4398944Sobrien 4498944Sobrien 4598944Sobrien#include <contrib/dev/acpica/include/acpi.h> 4698944Sobrien#include <contrib/dev/acpica/include/accommon.h> 4798944Sobrien#include <contrib/dev/acpica/include/acparser.h> 4898944Sobrien#include <contrib/dev/acpica/include/amlcode.h> 4998944Sobrien#include <contrib/dev/acpica/include/acdisasm.h> 5098944Sobrien#include <contrib/dev/acpica/include/acdebug.h> 5198944Sobrien 52130803Smarcel 5398944Sobrien#ifdef ACPI_DISASSEMBLER 5498944Sobrien 5598944Sobrien#define _COMPONENT ACPI_CA_DEBUGGER 5698944Sobrien ACPI_MODULE_NAME ("dmwalk") 5798944Sobrien 5898944Sobrien 5998944Sobrien#define DB_FULL_OP_INFO "[%4.4s] @%5.5X #%4.4X: " 6098944Sobrien 6198944Sobrien/* Stub for non-compiler code */ 6298944Sobrien 6398944Sobrien#ifndef ACPI_ASL_COMPILER 6498944Sobrienvoid 65130803SmarcelAcpiDmEmitExternals ( 6698944Sobrien void) 6798944Sobrien{ 68130803Smarcel return; 69130803Smarcel} 70130803Smarcel#endif 71130803Smarcel 7298944Sobrien/* Local prototypes */ 73130803Smarcel 7498944Sobrienstatic ACPI_STATUS 7598944SobrienAcpiDmDescendingOp ( 7698944Sobrien ACPI_PARSE_OBJECT *Op, 7798944Sobrien UINT32 Level, 7898944Sobrien void *Context); 79130803Smarcel 80130803Smarcelstatic ACPI_STATUS 8198944SobrienAcpiDmAscendingOp ( 82130803Smarcel ACPI_PARSE_OBJECT *Op, 8398944Sobrien UINT32 Level, 8498944Sobrien void *Context); 85130803Smarcel 86130803Smarcelstatic UINT32 87130803SmarcelAcpiDmBlockType ( 8898944Sobrien ACPI_PARSE_OBJECT *Op); 8998944Sobrien 9098944Sobrien 91130803Smarcel/******************************************************************************* 9298944Sobrien * 9398944Sobrien * FUNCTION: AcpiDmDisassemble 9498944Sobrien * 9598944Sobrien * PARAMETERS: WalkState - Current state 9698944Sobrien * Origin - Starting object 97130803Smarcel * NumOpcodes - Max number of opcodes to be displayed 9898944Sobrien * 9998944Sobrien * RETURN: None 10098944Sobrien * 101130803Smarcel * DESCRIPTION: Disassemble parser object and its children. This is the 10298944Sobrien * main entry point of the disassembler. 10398944Sobrien * 10498944Sobrien ******************************************************************************/ 105130803Smarcel 10698944Sobrienvoid 10798944SobrienAcpiDmDisassemble ( 108130803Smarcel ACPI_WALK_STATE *WalkState, 109130803Smarcel ACPI_PARSE_OBJECT *Origin, 11098944Sobrien UINT32 NumOpcodes) 111130803Smarcel{ 11298944Sobrien ACPI_PARSE_OBJECT *Op = Origin; 11398944Sobrien ACPI_OP_WALK_INFO Info; 11498944Sobrien 11598944Sobrien 11698944Sobrien if (!Op) 11798944Sobrien { 11898944Sobrien return; 119130803Smarcel } 12098944Sobrien 12198944Sobrien Info.Flags = 0; 12298944Sobrien Info.Level = 0; 123130803Smarcel Info.Count = 0; 12498944Sobrien Info.WalkState = WalkState; 12598944Sobrien AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info); 12698944Sobrien return; 12798944Sobrien} 12898944Sobrien 12998944Sobrien 13098944Sobrien/******************************************************************************* 13198944Sobrien * 13298944Sobrien * FUNCTION: AcpiDmWalkParseTree 13398944Sobrien * 13498944Sobrien * PARAMETERS: Op - Root Op object 13598944Sobrien * DescendingCallback - Called during tree descent 13698944Sobrien * AscendingCallback - Called during tree ascent 13798944Sobrien * Context - To be passed to the callbacks 13898944Sobrien * 13998944Sobrien * RETURN: Status from callback(s) 14098944Sobrien * 14198944Sobrien * DESCRIPTION: Walk the entire parse tree. 14298944Sobrien * 14398944Sobrien ******************************************************************************/ 14498944Sobrien 14598944Sobrienvoid 14698944SobrienAcpiDmWalkParseTree ( 14798944Sobrien ACPI_PARSE_OBJECT *Op, 14898944Sobrien ASL_WALK_CALLBACK DescendingCallback, 14998944Sobrien ASL_WALK_CALLBACK AscendingCallback, 15098944Sobrien void *Context) 15198944Sobrien{ 15298944Sobrien BOOLEAN NodePreviouslyVisited; 153130803Smarcel ACPI_PARSE_OBJECT *StartOp = Op; 15498944Sobrien ACPI_STATUS Status; 15598944Sobrien ACPI_PARSE_OBJECT *Next; 15698944Sobrien ACPI_OP_WALK_INFO *Info = Context; 15798944Sobrien 15898944Sobrien 15998944Sobrien Info->Level = 0; 160130803Smarcel NodePreviouslyVisited = FALSE; 161130803Smarcel 162130803Smarcel while (Op) 16398944Sobrien { 164130803Smarcel if (NodePreviouslyVisited) 165130803Smarcel { 16698944Sobrien if (AscendingCallback) 16798944Sobrien { 16898944Sobrien Status = AscendingCallback (Op, Info->Level, Context); 169130803Smarcel if (ACPI_FAILURE (Status)) 170130803Smarcel { 17198944Sobrien return; 172130803Smarcel } 17398944Sobrien } 174130803Smarcel } 17598944Sobrien else 176130803Smarcel { 177130803Smarcel /* Let the callback process the node */ 178130803Smarcel 179130803Smarcel Status = DescendingCallback (Op, Info->Level, Context); 18098944Sobrien if (ACPI_SUCCESS (Status)) 181130803Smarcel { 182130803Smarcel /* Visit children first, once */ 183130803Smarcel 18498944Sobrien Next = AcpiPsGetArg (Op, 0); 18598944Sobrien if (Next) 18698944Sobrien { 187130803Smarcel Info->Level++; 18898944Sobrien Op = Next; 18998944Sobrien continue; 19098944Sobrien } 191130803Smarcel } 192130803Smarcel else if (Status != AE_CTRL_DEPTH) 19398944Sobrien { 194130803Smarcel /* Exit immediately on any error */ 195130803Smarcel 19698944Sobrien return; 19798944Sobrien } 198130803Smarcel } 199130803Smarcel 20098944Sobrien /* Terminate walk at start op */ 20198944Sobrien 20298944Sobrien if (Op == StartOp) 20398944Sobrien { 20498944Sobrien break; 205130803Smarcel } 20698944Sobrien 20798944Sobrien /* No more children, re-visit this node */ 208130803Smarcel 209130803Smarcel if (!NodePreviouslyVisited) 210130803Smarcel { 211130803Smarcel NodePreviouslyVisited = TRUE; 21298944Sobrien continue; 213130803Smarcel } 21498944Sobrien 21598944Sobrien /* No more children, visit peers */ 21698944Sobrien 21798944Sobrien if (Op->Common.Next) 21898944Sobrien { 21998944Sobrien Op = Op->Common.Next; 22098944Sobrien NodePreviouslyVisited = FALSE; 22198944Sobrien } 222130803Smarcel else 223130803Smarcel { 22498944Sobrien /* No peers, re-visit parent */ 225130803Smarcel 226130803Smarcel if (Info->Level != 0 ) 22798944Sobrien { 228130803Smarcel Info->Level--; 22998944Sobrien } 230130803Smarcel 231130803Smarcel Op = Op->Common.Parent; 23298944Sobrien NodePreviouslyVisited = TRUE; 233130803Smarcel } 234130803Smarcel } 235130803Smarcel 236130803Smarcel /* If we get here, the walk completed with no errors */ 237130803Smarcel 238130803Smarcel return; 239130803Smarcel} 240130803Smarcel 24198944Sobrien 24298944Sobrien/******************************************************************************* 243130803Smarcel * 244130803Smarcel * FUNCTION: AcpiDmBlockType 24598944Sobrien * 24698944Sobrien * PARAMETERS: Op - Object to be examined 247218822Sdim * 24898944Sobrien * RETURN: BlockType - not a block, parens, braces, or even both. 24998944Sobrien * 25098944Sobrien * DESCRIPTION: Type of block for this op (parens or braces) 25198944Sobrien * 252130803Smarcel ******************************************************************************/ 25398944Sobrien 254130803Smarcelstatic UINT32 255130803SmarcelAcpiDmBlockType ( 256130803Smarcel ACPI_PARSE_OBJECT *Op) 257130803Smarcel{ 258130803Smarcel const ACPI_OPCODE_INFO *OpInfo; 259130803Smarcel 260130803Smarcel 261130803Smarcel if (!Op) 262130803Smarcel { 263130803Smarcel return (BLOCK_NONE); 264130803Smarcel } 265130803Smarcel 266130803Smarcel switch (Op->Common.AmlOpcode) 26798944Sobrien { 268130803Smarcel case AML_ELSE_OP: 269130803Smarcel 270130803Smarcel return (BLOCK_BRACE); 271130803Smarcel 272130803Smarcel case AML_METHOD_OP: 27398944Sobrien case AML_DEVICE_OP: 27498944Sobrien case AML_SCOPE_OP: 27598944Sobrien case AML_PROCESSOR_OP: 276130803Smarcel case AML_POWER_RES_OP: 27798944Sobrien case AML_THERMAL_ZONE_OP: 27898944Sobrien case AML_IF_OP: 27998944Sobrien case AML_WHILE_OP: 28098944Sobrien case AML_FIELD_OP: 281130803Smarcel case AML_INDEX_FIELD_OP: 28298944Sobrien case AML_BANK_FIELD_OP: 28398944Sobrien 284130803Smarcel return (BLOCK_PAREN | BLOCK_BRACE); 285130803Smarcel 28698944Sobrien case AML_BUFFER_OP: 28798944Sobrien 28898944Sobrien if (Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) 28998944Sobrien { 29098944Sobrien return (BLOCK_NONE); 29198944Sobrien } 29298944Sobrien 29398944Sobrien /*lint -fallthrough */ 29498944Sobrien 295130803Smarcel case AML_PACKAGE_OP: 29698944Sobrien case AML_VAR_PACKAGE_OP: 29798944Sobrien 29898944Sobrien return (BLOCK_PAREN | BLOCK_BRACE); 29998944Sobrien 30098944Sobrien case AML_EVENT_OP: 30198944Sobrien 30298944Sobrien return (BLOCK_PAREN); 30398944Sobrien 30498944Sobrien default: 30598944Sobrien 306130803Smarcel OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 30798944Sobrien if (OpInfo->Flags & AML_HAS_ARGS) 30898944Sobrien { 309130803Smarcel return (BLOCK_PAREN); 310130803Smarcel } 311130803Smarcel 31298944Sobrien return (BLOCK_NONE); 313130803Smarcel } 31498944Sobrien} 315130803Smarcel 31698944Sobrien 317130803Smarcel/******************************************************************************* 318130803Smarcel * 319130803Smarcel * FUNCTION: AcpiDmListType 320130803Smarcel * 32198944Sobrien * PARAMETERS: Op - Object to be examined 322130803Smarcel * 323130803Smarcel * RETURN: ListType - has commas or not. 324130803Smarcel * 325130803Smarcel * DESCRIPTION: Type of block for this op (parens or braces) 326130803Smarcel * 327130803Smarcel ******************************************************************************/ 328130803Smarcel 32998944SobrienUINT32 33098944SobrienAcpiDmListType ( 331130803Smarcel ACPI_PARSE_OBJECT *Op) 33298944Sobrien{ 333130803Smarcel const ACPI_OPCODE_INFO *OpInfo; 334130803Smarcel 335130803Smarcel 336130803Smarcel if (!Op) 33798944Sobrien { 338130803Smarcel return (BLOCK_NONE); 339130803Smarcel } 340130803Smarcel 341130803Smarcel switch (Op->Common.AmlOpcode) 342130803Smarcel { 343130803Smarcel 344130803Smarcel case AML_ELSE_OP: 345130803Smarcel case AML_METHOD_OP: 346130803Smarcel case AML_DEVICE_OP: 347130803Smarcel case AML_SCOPE_OP: 348130803Smarcel case AML_POWER_RES_OP: 349130803Smarcel case AML_PROCESSOR_OP: 35098944Sobrien case AML_THERMAL_ZONE_OP: 351130803Smarcel case AML_IF_OP: 352130803Smarcel case AML_WHILE_OP: 353130803Smarcel case AML_FIELD_OP: 354130803Smarcel case AML_INDEX_FIELD_OP: 355130803Smarcel case AML_BANK_FIELD_OP: 356130803Smarcel 357130803Smarcel return (BLOCK_NONE); 358130803Smarcel 359130803Smarcel case AML_BUFFER_OP: 360130803Smarcel case AML_PACKAGE_OP: 36198944Sobrien case AML_VAR_PACKAGE_OP: 362130803Smarcel 36398944Sobrien return (BLOCK_COMMA_LIST); 36498944Sobrien 365130803Smarcel default: 36698944Sobrien 367130803Smarcel OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 368130803Smarcel if (OpInfo->Flags & AML_HAS_ARGS) 369130803Smarcel { 370130803Smarcel return (BLOCK_COMMA_LIST); 371130803Smarcel } 372130803Smarcel 37398944Sobrien return (BLOCK_NONE); 374130803Smarcel } 375130803Smarcel} 376130803Smarcel 37798944Sobrien 378130803Smarcel/******************************************************************************* 379130803Smarcel * 38098944Sobrien * FUNCTION: AcpiDmDescendingOp 381130803Smarcel * 382130803Smarcel * PARAMETERS: ASL_WALK_CALLBACK 38398944Sobrien * 38498944Sobrien * RETURN: Status 385130803Smarcel * 386130803Smarcel * DESCRIPTION: First visitation of a parse object during tree descent. 387130803Smarcel * Decode opcode name and begin parameter list(s), if any. 388130803Smarcel * 389130803Smarcel ******************************************************************************/ 39098944Sobrien 39198944Sobrienstatic ACPI_STATUS 39298944SobrienAcpiDmDescendingOp ( 393130803Smarcel ACPI_PARSE_OBJECT *Op, 394130803Smarcel UINT32 Level, 39598944Sobrien void *Context) 39698944Sobrien{ 397130803Smarcel ACPI_OP_WALK_INFO *Info = Context; 39898944Sobrien const ACPI_OPCODE_INFO *OpInfo; 39998944Sobrien UINT32 Name; 40098944Sobrien ACPI_PARSE_OBJECT *NextOp; 40198944Sobrien 402130803Smarcel 40398944Sobrien if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) 40498944Sobrien { 40598944Sobrien /* Ignore this op -- it was handled elsewhere */ 40698944Sobrien 40798944Sobrien return (AE_CTRL_DEPTH); 40898944Sobrien } 40998944Sobrien 41098944Sobrien /* Level 0 is at the Definition Block level */ 41198944Sobrien 41298944Sobrien if (Level == 0) 41398944Sobrien { 41498944Sobrien /* In verbose mode, print the AML offset, opcode and depth count */ 415130803Smarcel 416130803Smarcel if (Info->WalkState) 417130803Smarcel { 418130803Smarcel VERBOSE_PRINT ((DB_FULL_OP_INFO, 419130803Smarcel (Info->WalkState->MethodNode ? 420130803Smarcel Info->WalkState->MethodNode->Name.Ascii : " "), 42198944Sobrien Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode)); 42298944Sobrien } 42398944Sobrien 42498944Sobrien if (Op->Common.AmlOpcode == AML_SCOPE_OP) 425130803Smarcel { 42698944Sobrien /* This is the beginning of the Definition Block */ 427130803Smarcel 428130803Smarcel AcpiOsPrintf ("{\n"); 429130803Smarcel 430130803Smarcel /* Emit all External() declarations here */ 43198944Sobrien 43298944Sobrien AcpiDmEmitExternals (); 43398944Sobrien return (AE_OK); 43498944Sobrien } 435130803Smarcel } 436130803Smarcel else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 437130803Smarcel (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 438130803Smarcel (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 43998944Sobrien { 440130803Smarcel /* 44198944Sobrien * This is a first-level element of a term list, 44298944Sobrien * indent a new line 44398944Sobrien */ 44498944Sobrien AcpiDmIndent (Level); 44598944Sobrien Info->LastLevel = Level; 44698944Sobrien Info->Count = 0; 44798944Sobrien } 44898944Sobrien 44998944Sobrien /* 45098944Sobrien * This is an inexpensive mechanism to try and keep lines from getting 451130803Smarcel * too long. When the limit is hit, start a new line at the previous 452130803Smarcel * indent plus one. A better but more expensive mechanism would be to 453130803Smarcel * keep track of the current column. 45498944Sobrien */ 455130803Smarcel Info->Count++; 456130803Smarcel if (Info->Count /* +Info->LastLevel */ > 10) 457130803Smarcel { 458130803Smarcel Info->Count = 0; 459130803Smarcel AcpiOsPrintf ("\n"); 460130803Smarcel AcpiDmIndent (Info->LastLevel + 1); 461130803Smarcel } 46298944Sobrien 46398944Sobrien /* Print the opcode name */ 46498944Sobrien 465130803Smarcel AcpiDmDisassembleOneOp (NULL, Info, Op); 46698944Sobrien 467130803Smarcel if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) || 468130803Smarcel (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP)) 46998944Sobrien { 470130803Smarcel return (AE_OK); 47198944Sobrien } 47298944Sobrien 473130803Smarcel if ((Op->Common.AmlOpcode == AML_NAME_OP) || 47498944Sobrien (Op->Common.AmlOpcode == AML_RETURN_OP)) 47598944Sobrien { 47698944Sobrien Info->Level--; 47798944Sobrien } 47898944Sobrien 47998944Sobrien /* Start the opcode argument list if necessary */ 480130803Smarcel 48198944Sobrien OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 482130803Smarcel 48398944Sobrien if ((OpInfo->Flags & AML_HAS_ARGS) || 48498944Sobrien (Op->Common.AmlOpcode == AML_EVENT_OP)) 485130803Smarcel { 48698944Sobrien /* This opcode has an argument list */ 48798944Sobrien 488130803Smarcel if (AcpiDmBlockType (Op) & BLOCK_PAREN) 48998944Sobrien { 49098944Sobrien AcpiOsPrintf (" ("); 49198944Sobrien } 49298944Sobrien 49398944Sobrien /* If this is a named opcode, print the associated name value */ 49498944Sobrien 495130803Smarcel if (OpInfo->Flags & AML_NAMED) 496130803Smarcel { 49798944Sobrien switch (Op->Common.AmlOpcode) 49898944Sobrien { 49998944Sobrien case AML_ALIAS_OP: 50098944Sobrien 50198944Sobrien NextOp = AcpiPsGetDepthNext (NULL, Op); 502 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 503 AcpiDmNamestring (NextOp->Common.Value.Name); 504 AcpiOsPrintf (", "); 505 506 /*lint -fallthrough */ 507 508 default: 509 510 Name = AcpiPsGetName (Op); 511 if (Op->Named.Path) 512 { 513 AcpiDmNamestring ((char *) Op->Named.Path); 514 } 515 else 516 { 517 AcpiDmDumpName (Name); 518 } 519 520 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP) 521 { 522 if (AcpiGbl_DbOpt_verbose) 523 { 524 (void) AcpiPsDisplayObjectPathname (NULL, Op); 525 } 526 } 527 break; 528 } 529 530 switch (Op->Common.AmlOpcode) 531 { 532 case AML_METHOD_OP: 533 534 AcpiDmMethodFlags (Op); 535 AcpiOsPrintf (")"); 536 537 /* Emit description comment for Method() with a predefined ACPI name */ 538 539 AcpiDmPredefinedDescription (Op); 540 break; 541 542 543 case AML_NAME_OP: 544 545 /* Check for _HID and related EISAID() */ 546 547 AcpiDmIsEisaId (Op); 548 AcpiOsPrintf (", "); 549 break; 550 551 552 case AML_REGION_OP: 553 554 AcpiDmRegionFlags (Op); 555 break; 556 557 558 case AML_POWER_RES_OP: 559 560 /* Mark the next two Ops as part of the parameter list */ 561 562 AcpiOsPrintf (", "); 563 NextOp = AcpiPsGetDepthNext (NULL, Op); 564 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 565 566 NextOp = NextOp->Common.Next; 567 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 568 return (AE_OK); 569 570 571 case AML_PROCESSOR_OP: 572 573 /* Mark the next three Ops as part of the parameter list */ 574 575 AcpiOsPrintf (", "); 576 NextOp = AcpiPsGetDepthNext (NULL, Op); 577 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 578 579 NextOp = NextOp->Common.Next; 580 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 581 582 NextOp = NextOp->Common.Next; 583 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 584 return (AE_OK); 585 586 587 case AML_MUTEX_OP: 588 case AML_DATA_REGION_OP: 589 590 AcpiOsPrintf (", "); 591 return (AE_OK); 592 593 594 case AML_EVENT_OP: 595 case AML_ALIAS_OP: 596 597 return (AE_OK); 598 599 600 case AML_SCOPE_OP: 601 case AML_DEVICE_OP: 602 case AML_THERMAL_ZONE_OP: 603 604 AcpiOsPrintf (")"); 605 break; 606 607 608 default: 609 610 AcpiOsPrintf ("*** Unhandled named opcode %X\n", 611 Op->Common.AmlOpcode); 612 break; 613 } 614 } 615 616 else switch (Op->Common.AmlOpcode) 617 { 618 case AML_FIELD_OP: 619 case AML_BANK_FIELD_OP: 620 case AML_INDEX_FIELD_OP: 621 622 Info->BitOffset = 0; 623 624 /* Name of the parent OperationRegion */ 625 626 NextOp = AcpiPsGetDepthNext (NULL, Op); 627 AcpiDmNamestring (NextOp->Common.Value.Name); 628 AcpiOsPrintf (", "); 629 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 630 631 switch (Op->Common.AmlOpcode) 632 { 633 case AML_BANK_FIELD_OP: 634 635 /* Namestring - Bank Name */ 636 637 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 638 AcpiDmNamestring (NextOp->Common.Value.Name); 639 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 640 AcpiOsPrintf (", "); 641 642 /* 643 * Bank Value. This is a TermArg in the middle of the parameter 644 * list, must handle it here. 645 * 646 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST 647 * eliminates newline in the output. 648 */ 649 NextOp = NextOp->Common.Next; 650 651 Info->Flags = ACPI_PARSEOP_PARAMLIST; 652 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp, 653 AcpiDmAscendingOp, Info); 654 Info->Flags = 0; 655 Info->Level = Level; 656 657 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 658 AcpiOsPrintf (", "); 659 break; 660 661 case AML_INDEX_FIELD_OP: 662 663 /* Namestring - Data Name */ 664 665 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 666 AcpiDmNamestring (NextOp->Common.Value.Name); 667 AcpiOsPrintf (", "); 668 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 669 break; 670 671 default: 672 673 break; 674 } 675 676 AcpiDmFieldFlags (NextOp); 677 break; 678 679 680 case AML_BUFFER_OP: 681 682 /* The next op is the size parameter */ 683 684 NextOp = AcpiPsGetDepthNext (NULL, Op); 685 if (!NextOp) 686 { 687 /* Single-step support */ 688 689 return (AE_OK); 690 } 691 692 if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE) 693 { 694 /* 695 * We have a resource list. Don't need to output 696 * the buffer size Op. Open up a new block 697 */ 698 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 699 NextOp = NextOp->Common.Next; 700 AcpiOsPrintf (")"); 701 702 /* Emit description comment for Name() with a predefined ACPI name */ 703 704 AcpiDmPredefinedDescription (Op->Asl.Parent); 705 706 AcpiOsPrintf ("\n"); 707 AcpiDmIndent (Info->Level); 708 AcpiOsPrintf ("{\n"); 709 return (AE_OK); 710 } 711 712 /* Normal Buffer, mark size as in the parameter list */ 713 714 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 715 return (AE_OK); 716 717 718 case AML_VAR_PACKAGE_OP: 719 case AML_IF_OP: 720 case AML_WHILE_OP: 721 722 /* The next op is the size or predicate parameter */ 723 724 NextOp = AcpiPsGetDepthNext (NULL, Op); 725 if (NextOp) 726 { 727 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 728 } 729 return (AE_OK); 730 731 732 case AML_PACKAGE_OP: 733 734 /* The next op is the size parameter */ 735 736 NextOp = AcpiPsGetDepthNext (NULL, Op); 737 if (NextOp) 738 { 739 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 740 } 741 return (AE_OK); 742 743 744 case AML_MATCH_OP: 745 746 AcpiDmMatchOp (Op); 747 break; 748 749 750 default: 751 752 break; 753 } 754 755 if (AcpiDmBlockType (Op) & BLOCK_BRACE) 756 { 757 AcpiOsPrintf ("\n"); 758 AcpiDmIndent (Level); 759 AcpiOsPrintf ("{\n"); 760 } 761 } 762 763 return (AE_OK); 764} 765 766 767/******************************************************************************* 768 * 769 * FUNCTION: AcpiDmAscendingOp 770 * 771 * PARAMETERS: ASL_WALK_CALLBACK 772 * 773 * RETURN: Status 774 * 775 * DESCRIPTION: Second visitation of a parse object, during ascent of parse 776 * tree. Close out any parameter lists and complete the opcode. 777 * 778 ******************************************************************************/ 779 780static ACPI_STATUS 781AcpiDmAscendingOp ( 782 ACPI_PARSE_OBJECT *Op, 783 UINT32 Level, 784 void *Context) 785{ 786 ACPI_OP_WALK_INFO *Info = Context; 787 ACPI_PARSE_OBJECT *ParentOp; 788 789 790 if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) 791 { 792 /* Ignore this op -- it was handled elsewhere */ 793 794 return (AE_OK); 795 } 796 797 if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP)) 798 { 799 /* Indicates the end of the current descriptor block (table) */ 800 801 AcpiOsPrintf ("}\n\n"); 802 return (AE_OK); 803 } 804 805 switch (AcpiDmBlockType (Op)) 806 { 807 case BLOCK_PAREN: 808 809 /* Completed an op that has arguments, add closing paren */ 810 811 AcpiOsPrintf (")"); 812 813 if (Op->Common.AmlOpcode == AML_NAME_OP) 814 { 815 /* Emit description comment for Name() with a predefined ACPI name */ 816 817 AcpiDmPredefinedDescription (Op); 818 } 819 else 820 { 821 /* For Create* operators, attempt to emit resource tag description */ 822 823 AcpiDmFieldPredefinedDescription (Op); 824 } 825 826 /* Could be a nested operator, check if comma required */ 827 828 if (!AcpiDmCommaIfListMember (Op)) 829 { 830 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 831 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 832 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 833 { 834 /* 835 * This is a first-level element of a term list 836 * start a new line 837 */ 838 if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST)) 839 { 840 AcpiOsPrintf ("\n"); 841 } 842 } 843 } 844 break; 845 846 847 case BLOCK_BRACE: 848 case (BLOCK_BRACE | BLOCK_PAREN): 849 850 /* Completed an op that has a term list, add closing brace */ 851 852 if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST) 853 { 854 AcpiOsPrintf ("}"); 855 } 856 else 857 { 858 AcpiDmIndent (Level); 859 AcpiOsPrintf ("}"); 860 } 861 862 AcpiDmCommaIfListMember (Op); 863 864 if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN) 865 { 866 AcpiOsPrintf ("\n"); 867 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)) 868 { 869 if ((Op->Common.AmlOpcode == AML_IF_OP) && 870 (Op->Common.Next) && 871 (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP)) 872 { 873 break; 874 } 875 876 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 877 (!Op->Common.Next)) 878 { 879 break; 880 } 881 AcpiOsPrintf ("\n"); 882 } 883 } 884 break; 885 886 887 case BLOCK_NONE: 888 default: 889 890 /* Could be a nested operator, check if comma required */ 891 892 if (!AcpiDmCommaIfListMember (Op)) 893 { 894 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 895 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 896 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 897 { 898 /* 899 * This is a first-level element of a term list 900 * start a new line 901 */ 902 AcpiOsPrintf ("\n"); 903 } 904 } 905 else if (Op->Common.Parent) 906 { 907 switch (Op->Common.Parent->Common.AmlOpcode) 908 { 909 case AML_PACKAGE_OP: 910 case AML_VAR_PACKAGE_OP: 911 912 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) 913 { 914 AcpiOsPrintf ("\n"); 915 } 916 break; 917 918 default: 919 920 break; 921 } 922 } 923 break; 924 } 925 926 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST) 927 { 928 if ((Op->Common.Next) && 929 (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) 930 { 931 return (AE_OK); 932 } 933 934 /* 935 * Just completed a parameter node for something like "Buffer (param)". 936 * Close the paren and open up the term list block with a brace 937 */ 938 if (Op->Common.Next) 939 { 940 AcpiOsPrintf (")"); 941 942 /* Emit description comment for Name() with a predefined ACPI name */ 943 944 ParentOp = Op->Common.Parent; 945 if (ParentOp) 946 { 947 ParentOp = ParentOp->Common.Parent; 948 if (ParentOp && ParentOp->Asl.AmlOpcode == AML_NAME_OP) 949 { 950 AcpiDmPredefinedDescription (ParentOp); 951 } 952 } 953 AcpiOsPrintf ("\n"); 954 AcpiDmIndent (Level - 1); 955 AcpiOsPrintf ("{\n"); 956 } 957 else 958 { 959 Op->Common.Parent->Common.DisasmFlags |= 960 ACPI_PARSEOP_EMPTY_TERMLIST; 961 AcpiOsPrintf (") {"); 962 } 963 } 964 965 if ((Op->Common.AmlOpcode == AML_NAME_OP) || 966 (Op->Common.AmlOpcode == AML_RETURN_OP)) 967 { 968 Info->Level++; 969 } 970 return (AE_OK); 971} 972 973 974#endif /* ACPI_DISASSEMBLER */ 975