dbmethod.c revision 281075
192108Sphk/******************************************************************************* 292108Sphk * 392108Sphk * Module Name: dbmethod - Debug commands for control methods 4248508Skib * 592108Sphk ******************************************************************************/ 692108Sphk 792108Sphk/* 892108Sphk * Copyright (C) 2000 - 2015, Intel Corp. 992108Sphk * All rights reserved. 1092108Sphk * 1192108Sphk * Redistribution and use in source and binary forms, with or without 12248508Skib * modification, are permitted provided that the following conditions 13248508Skib * are met: 14248508Skib * 1. Redistributions of source code must retain the above copyright 1592108Sphk * notice, this list of conditions, and the following disclaimer, 1692108Sphk * without modification. 1792108Sphk * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1892108Sphk * substantially similar to the "NO WARRANTY" disclaimer below 1992108Sphk * ("Disclaimer") and any redistribution must be conditioned upon 2092108Sphk * including a substantially similar Disclaimer requirement for further 2192108Sphk * binary redistribution. 2292108Sphk * 3. Neither the names of the above-listed copyright holders nor the names 2392108Sphk * of any contributors may be used to endorse or promote products derived 2492108Sphk * from this software without specific prior written permission. 2592108Sphk * 2692108Sphk * Alternatively, this software may be distributed under the terms of the 2792108Sphk * GNU General Public License ("GPL") version 2 as published by the Free 2892108Sphk * Software Foundation. 2992108Sphk * 3092108Sphk * NO WARRANTY 3192108Sphk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3292108Sphk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3392108Sphk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3492108Sphk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3592108Sphk * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3692108Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3792108Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3892108Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3992108Sphk * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40116196Sobrien * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41116196Sobrien * POSSIBILITY OF SUCH DAMAGES. 4292108Sphk */ 4392108Sphk 4492108Sphk#include <contrib/dev/acpica/include/acpi.h> 4592108Sphk#include <contrib/dev/acpica/include/accommon.h> 4692108Sphk#include <contrib/dev/acpica/include/acdispat.h> 4792108Sphk#include <contrib/dev/acpica/include/acnamesp.h> 48136755Srwatson#include <contrib/dev/acpica/include/acdebug.h> 49150177Sjhb#include <contrib/dev/acpica/include/acdisasm.h> 50149576Spjd#include <contrib/dev/acpica/include/acparser.h> 51248508Skib#include <contrib/dev/acpica/include/acpredef.h> 52252330Sjeff 5392108Sphk 5492108Sphk#ifdef ACPI_DEBUGGER 5592108Sphk 5693250Sphk#define _COMPONENT ACPI_CA_DEBUGGER 57112370Sphk ACPI_MODULE_NAME ("dbmethod") 5892108Sphk 59114526Sphk 60248508Skib/******************************************************************************* 61248508Skib * 62248508Skib * FUNCTION: AcpiDbSetMethodBreakpoint 63248508Skib * 64248508Skib * PARAMETERS: Location - AML offset of breakpoint 65248508Skib * WalkState - Current walk info 66248508Skib * Op - Current Op (from parse walk) 67114526Sphk * 68260385Sscottl * RETURN: None 69260385Sscottl * 7092108Sphk * DESCRIPTION: Set a breakpoint in a control method at the specified 7192108Sphk * AML offset 72125137Sphk * 7392108Sphk ******************************************************************************/ 74287569Simp 75287569Simpvoid 76287569SimpAcpiDbSetMethodBreakpoint ( 77287569Simp char *Location, 78287569Simp ACPI_WALK_STATE *WalkState, 79287569Simp ACPI_PARSE_OBJECT *Op) 80287569Simp{ 81287569Simp UINT32 Address; 82287569Simp 83287569Simp 84287569Simp if (!Op) 85114526Sphk { 86106338Sphk AcpiOsPrintf ("There is no method currently executing\n"); 87193981Sluigi return; 88193981Sluigi } 89193981Sluigi 90193981Sluigi /* Get and verify the breakpoint address */ 91193981Sluigi 92193981Sluigi Address = ACPI_STRTOUL (Location, NULL, 16); 93193981Sluigi if (Address <= Op->Common.AmlOffset) 94193981Sluigi { 95193981Sluigi AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n", 9692108Sphk Address, Op->Common.AmlOffset); 9792108Sphk } 9892108Sphk 9992108Sphk /* Save breakpoint in current walk */ 10092108Sphk 10192108Sphk WalkState->UserBreakpoint = Address; 10292108Sphk AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address); 10392108Sphk} 10492108Sphk 10592108Sphk 10692108Sphk/******************************************************************************* 10792108Sphk * 10892108Sphk * FUNCTION: AcpiDbSetMethodCallBreakpoint 10992108Sphk * 11092108Sphk * PARAMETERS: Op - Current Op (from parse walk) 11192108Sphk * 11292108Sphk * RETURN: None 11392108Sphk * 11492108Sphk * DESCRIPTION: Set a breakpoint in a control method at the specified 11592108Sphk * AML offset 11692108Sphk * 11792108Sphk ******************************************************************************/ 11892108Sphk 11992108Sphkvoid 12092108SphkAcpiDbSetMethodCallBreakpoint ( 12192108Sphk ACPI_PARSE_OBJECT *Op) 12292108Sphk{ 12392108Sphk 12492108Sphk 12592108Sphk if (!Op) 12693818Sjhb { 12792108Sphk AcpiOsPrintf ("There is no method currently executing\n"); 12892108Sphk return; 12992108Sphk } 13092108Sphk 13192108Sphk AcpiGbl_StepToNextCall = TRUE; 13292108Sphk} 13392108Sphk 13492108Sphk 13592108Sphk/******************************************************************************* 136134519Sphk * 137134519Sphk * FUNCTION: AcpiDbSetMethodData 138134519Sphk * 13992108Sphk * PARAMETERS: TypeArg - L for local, A for argument 14092108Sphk * IndexArg - which one 14192108Sphk * ValueArg - Value to set. 14292108Sphk * 14392108Sphk * RETURN: None 14492108Sphk * 14592108Sphk * DESCRIPTION: Set a local or argument for the running control method. 14692108Sphk * NOTE: only object supported is Number. 14792108Sphk * 14892108Sphk ******************************************************************************/ 14992108Sphk 150114526Sphkvoid 151149576SpjdAcpiDbSetMethodData ( 152173001Spjd char *TypeArg, 153149576Spjd char *IndexArg, 154149576Spjd char *ValueArg) 155149576Spjd{ 156149576Spjd char Type; 157149576Spjd UINT32 Index; 158149576Spjd UINT32 Value; 159149576Spjd ACPI_WALK_STATE *WalkState; 16092108Sphk ACPI_OPERAND_OBJECT *ObjDesc; 16192108Sphk ACPI_STATUS Status; 16292108Sphk ACPI_NAMESPACE_NODE *Node; 163134379Sphk 164134379Sphk 165134379Sphk /* Validate TypeArg */ 166134379Sphk 167134379Sphk AcpiUtStrupr (TypeArg); 168134379Sphk Type = TypeArg[0]; 169149576Spjd if ((Type != 'L') && 170173001Spjd (Type != 'A') && 171149576Spjd (Type != 'N')) 172149576Spjd { 173149576Spjd AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg); 174149576Spjd return; 175149576Spjd } 176149576Spjd 177149576Spjd Value = ACPI_STRTOUL (ValueArg, NULL, 16); 178134379Sphk 179134379Sphk if (Type == 'N') 180134379Sphk { 18192108Sphk Node = AcpiDbConvertToNode (IndexArg); 18292108Sphk if (!Node) 18392108Sphk { 184149576Spjd return; 185173001Spjd } 186149576Spjd 18792108Sphk if (Node->Type != ACPI_TYPE_INTEGER) 188149576Spjd { 189149576Spjd AcpiOsPrintf ("Can only set Integer nodes\n"); 190149576Spjd return; 191149576Spjd } 192149576Spjd ObjDesc = Node->Object; 193114526Sphk ObjDesc->Integer.Value = Value; 19492108Sphk return; 19592108Sphk } 19692108Sphk 19792108Sphk /* Get the index and value */ 19892108Sphk 19992108Sphk Index = ACPI_STRTOUL (IndexArg, NULL, 16); 20092108Sphk 201114526Sphk WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); 202104058Sphk if (!WalkState) 203110517Sphk { 204104058Sphk AcpiOsPrintf ("There is no method currently executing\n"); 205239132Sjimharris return; 206239132Sjimharris } 207239132Sjimharris 208292348Sken /* Create and initialize the new object */ 209292348Sken 210239132Sjimharris ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value); 211239132Sjimharris if (!ObjDesc) 212292348Sken { 213292348Sken AcpiOsPrintf ("Could not create an internal object\n"); 214104058Sphk return; 215104058Sphk } 216104058Sphk 217248508Skib /* Store the new object into the target */ 218248508Skib 219248508Skib switch (Type) 220104058Sphk { 221193981Sluigi case 'A': 222193981Sluigi 223193981Sluigi /* Set a method argument */ 224110523Sphk 225104058Sphk if (Index > ACPI_METHOD_MAX_ARG) 226149576Spjd { 227173001Spjd AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index); 228149576Spjd goto Cleanup; 229149576Spjd } 230156686Sru 231149576Spjd Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc, 232149576Spjd WalkState); 233149576Spjd if (ACPI_FAILURE (Status)) 234149576Spjd { 23592108Sphk goto Cleanup; 23692108Sphk } 23792108Sphk 238159304Spjd ObjDesc = WalkState->Arguments[Index].Object; 239159304Spjd 240159304Spjd AcpiOsPrintf ("Arg%u: ", Index); 241159304Spjd AcpiDmDisplayInternalObject (ObjDesc, WalkState); 242159304Spjd break; 243159304Spjd 244292348Sken case 'L': 245159304Spjd 246159304Spjd /* Set a method local */ 247159304Spjd 248159304Spjd if (Index > ACPI_METHOD_MAX_LOCAL) 249159304Spjd { 250248508Skib AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index); 251248508Skib goto Cleanup; 252248508Skib } 253159304Spjd 254159304Spjd Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc, 255159304Spjd WalkState); 256173001Spjd if (ACPI_FAILURE (Status)) 257159304Spjd { 258159304Spjd goto Cleanup; 259159304Spjd } 260159304Spjd 261159304Spjd ObjDesc = WalkState->LocalVariables[Index].Object; 262159304Spjd 263159304Spjd AcpiOsPrintf ("Local%u: ", Index); 264159304Spjd AcpiDmDisplayInternalObject (ObjDesc, WalkState); 265159304Spjd break; 266159304Spjd 26792108Sphk default: 26892108Sphk 26992108Sphk break; 27092108Sphk } 27192108Sphk 27292108SphkCleanup: 273125137Sphk AcpiUtRemoveReference (ObjDesc); 274114526Sphk} 275114526Sphk 276114526Sphk 277114526Sphk/******************************************************************************* 27892108Sphk * 27992108Sphk * FUNCTION: AcpiDbDisassembleAml 28092108Sphk * 28194283Sphk * PARAMETERS: Statements - Number of statements to disassemble 28292108Sphk * Op - Current Op (from parse walk) 28392108Sphk * 28492108Sphk * RETURN: None 28592108Sphk * 28692108Sphk * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 287134379Sphk * of statements specified. 288104665Sphk * 289104665Sphk ******************************************************************************/ 290104665Sphk 291104665Sphkvoid 292104665SphkAcpiDbDisassembleAml ( 293104665Sphk char *Statements, 294104665Sphk ACPI_PARSE_OBJECT *Op) 295104665Sphk{ 296104665Sphk UINT32 NumStatements = 8; 29792108Sphk 29892108Sphk 29992108Sphk if (!Op) 300163832Spjd { 301163832Spjd AcpiOsPrintf ("There is no method currently executing\n"); 302163832Spjd return; 303163832Spjd } 304163832Spjd 305163832Spjd if (Statements) 306163832Spjd { 307163832Spjd NumStatements = ACPI_STRTOUL (Statements, NULL, 0); 308163832Spjd } 309212160Sgibbs 310163832Spjd#ifdef ACPI_DISASSEMBLER 311163832Spjd AcpiDmDisassemble (NULL, Op, NumStatements); 312163832Spjd#endif 313163832Spjd} 314163832Spjd 315163832Spjd 316163832Spjd/******************************************************************************* 317163832Spjd * 318163832Spjd * FUNCTION: AcpiDbDisassembleMethod 319163832Spjd * 320163832Spjd * PARAMETERS: Name - Name of control method 321110471Sphk * 322110471Sphk * RETURN: None 32392108Sphk * 324110471Sphk * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 325110471Sphk * of statements specified. 326260385Sscottl * 327260385Sscottl ******************************************************************************/ 32892108Sphk 329110471SphkACPI_STATUS 330110471SphkAcpiDbDisassembleMethod ( 33192108Sphk char *Name) 332110471Sphk{ 33393778Sphk ACPI_STATUS Status; 33493778Sphk ACPI_PARSE_OBJECT *Op; 33593778Sphk ACPI_WALK_STATE *WalkState; 336110471Sphk ACPI_OPERAND_OBJECT *ObjDesc; 337110471Sphk ACPI_NAMESPACE_NODE *Method; 33893778Sphk 33993778Sphk 34093778Sphk Method = AcpiDbConvertToNode (Name); 341163832Spjd if (!Method) 342110471Sphk { 343110471Sphk return (AE_BAD_PARAMETER); 34493778Sphk } 34593778Sphk 346110471Sphk if (Method->Type != ACPI_TYPE_METHOD) 34793778Sphk { 34893778Sphk ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method", 349110471Sphk Name, AcpiUtGetTypeName (Method->Type))); 350110471Sphk return (AE_BAD_PARAMETER); 351238886Smav } 352238886Smav 353110471Sphk ObjDesc = Method->Object; 35493778Sphk 35593778Sphk Op = AcpiPsCreateScopeOp (); 35693778Sphk if (!Op) 35793778Sphk { 358206650Savg return (AE_NO_MEMORY); 359206650Savg } 360121323Sphk 361108051Sphk /* Create and initialize a new walk state */ 362110471Sphk 363110471Sphk WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 364108051Sphk if (!WalkState) 365110471Sphk { 366110471Sphk return (AE_NO_MEMORY); 367121253Sphk } 368121253Sphk 369121253Sphk Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, 370110471Sphk ObjDesc->Method.AmlStart, 371110471Sphk ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 372260385Sscottl if (ACPI_FAILURE (Status)) 373260385Sscottl { 374260385Sscottl return (Status); 375260385Sscottl } 376260385Sscottl 377260385Sscottl Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); 378260385Sscottl WalkState->OwnerId = ObjDesc->Method.OwnerId; 379260385Sscottl 380260385Sscottl /* Push start scope on scope stack and make it current */ 381260385Sscottl 382260385Sscottl Status = AcpiDsScopeStackPush (Method, 383260385Sscottl Method->Type, WalkState); 384260385Sscottl if (ACPI_FAILURE (Status)) 385260385Sscottl { 386260385Sscottl return (Status); 387260385Sscottl } 388260385Sscottl 389260385Sscottl /* Parse the entire method AML including deferred operators */ 390260385Sscottl 391260385Sscottl WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 392260385Sscottl WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 393260385Sscottl 394260385Sscottl Status = AcpiPsParseAml (WalkState); 395260385Sscottl (void) AcpiDmParseDeferredOps (Op); 396260385Sscottl 397260385Sscottl /* Now we can disassemble the method */ 398260385Sscottl 399260385Sscottl AcpiGbl_DbOpt_verbose = FALSE; 400260385Sscottl#ifdef ACPI_DISASSEMBLER 401260385Sscottl AcpiDmDisassemble (NULL, Op, 0); 402260385Sscottl#endif 403260385Sscottl AcpiGbl_DbOpt_verbose = TRUE; 404260385Sscottl 40593778Sphk AcpiPsDeleteParseTree (Op); 40693778Sphk 40793778Sphk /* Method cleanup */ 40892108Sphk 409260385Sscottl AcpiNsDeleteNamespaceSubtree (Method); 410110471Sphk AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId); 411110471Sphk AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId); 412193981Sluigi return (AE_OK); 413193981Sluigi} 414193981Sluigi 415193981Sluigi#endif /* ACPI_DEBUGGER */ 416193981Sluigi