1218585Sjkim/******************************************************************************* 2218585Sjkim * 3218585Sjkim * Module Name: dbmethod - Debug commands for control methods 4218585Sjkim * 5218585Sjkim ******************************************************************************/ 6218585Sjkim 7218585Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9218585Sjkim * All rights reserved. 10218585Sjkim * 11218585Sjkim * Redistribution and use in source and binary forms, with or without 12218585Sjkim * modification, are permitted provided that the following conditions 13218585Sjkim * are met: 14218585Sjkim * 1. Redistributions of source code must retain the above copyright 15218585Sjkim * notice, this list of conditions, and the following disclaimer, 16218585Sjkim * without modification. 17218585Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18218585Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19218585Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20218585Sjkim * including a substantially similar Disclaimer requirement for further 21218585Sjkim * binary redistribution. 22218585Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23218585Sjkim * of any contributors may be used to endorse or promote products derived 24218585Sjkim * from this software without specific prior written permission. 25218585Sjkim * 26218585Sjkim * Alternatively, this software may be distributed under the terms of the 27218585Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28218585Sjkim * Software Foundation. 29218585Sjkim * 30218585Sjkim * NO WARRANTY 31218585Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32218585Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33218585Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34218585Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35218585Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36218585Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37218585Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38218585Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39218585Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40218585Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41218585Sjkim * POSSIBILITY OF SUCH DAMAGES. 42218585Sjkim */ 43218585Sjkim 44218590Sjkim#include <contrib/dev/acpica/include/acpi.h> 45218590Sjkim#include <contrib/dev/acpica/include/accommon.h> 46218590Sjkim#include <contrib/dev/acpica/include/acdispat.h> 47218590Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 48218590Sjkim#include <contrib/dev/acpica/include/acdebug.h> 49218590Sjkim#include <contrib/dev/acpica/include/acparser.h> 50249663Sjkim#include <contrib/dev/acpica/include/acpredef.h> 51218585Sjkim 52218585Sjkim 53218585Sjkim#define _COMPONENT ACPI_CA_DEBUGGER 54218585Sjkim ACPI_MODULE_NAME ("dbmethod") 55218585Sjkim 56218585Sjkim 57218585Sjkim/******************************************************************************* 58218585Sjkim * 59218585Sjkim * FUNCTION: AcpiDbSetMethodBreakpoint 60218585Sjkim * 61218585Sjkim * PARAMETERS: Location - AML offset of breakpoint 62218585Sjkim * WalkState - Current walk info 63218585Sjkim * Op - Current Op (from parse walk) 64218585Sjkim * 65218585Sjkim * RETURN: None 66218585Sjkim * 67218585Sjkim * DESCRIPTION: Set a breakpoint in a control method at the specified 68218585Sjkim * AML offset 69218585Sjkim * 70218585Sjkim ******************************************************************************/ 71218585Sjkim 72218585Sjkimvoid 73218585SjkimAcpiDbSetMethodBreakpoint ( 74218585Sjkim char *Location, 75218585Sjkim ACPI_WALK_STATE *WalkState, 76218585Sjkim ACPI_PARSE_OBJECT *Op) 77218585Sjkim{ 78218585Sjkim UINT32 Address; 79306536Sjkim UINT32 AmlOffset; 80218585Sjkim 81218585Sjkim 82218585Sjkim if (!Op) 83218585Sjkim { 84218585Sjkim AcpiOsPrintf ("There is no method currently executing\n"); 85218585Sjkim return; 86218585Sjkim } 87218585Sjkim 88218585Sjkim /* Get and verify the breakpoint address */ 89218585Sjkim 90306536Sjkim Address = strtoul (Location, NULL, 16); 91306536Sjkim AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml, 92306536Sjkim WalkState->ParserState.AmlStart); 93306536Sjkim if (Address <= AmlOffset) 94218585Sjkim { 95218585Sjkim AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n", 96306536Sjkim Address, AmlOffset); 97218585Sjkim } 98218585Sjkim 99218585Sjkim /* Save breakpoint in current walk */ 100218585Sjkim 101218585Sjkim WalkState->UserBreakpoint = Address; 102218585Sjkim AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address); 103218585Sjkim} 104218585Sjkim 105218585Sjkim 106218585Sjkim/******************************************************************************* 107218585Sjkim * 108218585Sjkim * FUNCTION: AcpiDbSetMethodCallBreakpoint 109218585Sjkim * 110218585Sjkim * PARAMETERS: Op - Current Op (from parse walk) 111218585Sjkim * 112218585Sjkim * RETURN: None 113218585Sjkim * 114218585Sjkim * DESCRIPTION: Set a breakpoint in a control method at the specified 115218585Sjkim * AML offset 116218585Sjkim * 117218585Sjkim ******************************************************************************/ 118218585Sjkim 119218585Sjkimvoid 120218585SjkimAcpiDbSetMethodCallBreakpoint ( 121218585Sjkim ACPI_PARSE_OBJECT *Op) 122218585Sjkim{ 123218585Sjkim 124218585Sjkim 125218585Sjkim if (!Op) 126218585Sjkim { 127218585Sjkim AcpiOsPrintf ("There is no method currently executing\n"); 128218585Sjkim return; 129218585Sjkim } 130218585Sjkim 131218585Sjkim AcpiGbl_StepToNextCall = TRUE; 132218585Sjkim} 133218585Sjkim 134218585Sjkim 135218585Sjkim/******************************************************************************* 136218585Sjkim * 137218585Sjkim * FUNCTION: AcpiDbSetMethodData 138218585Sjkim * 139218585Sjkim * PARAMETERS: TypeArg - L for local, A for argument 140218585Sjkim * IndexArg - which one 141218585Sjkim * ValueArg - Value to set. 142218585Sjkim * 143218585Sjkim * RETURN: None 144218585Sjkim * 145218585Sjkim * DESCRIPTION: Set a local or argument for the running control method. 146218585Sjkim * NOTE: only object supported is Number. 147218585Sjkim * 148218585Sjkim ******************************************************************************/ 149218585Sjkim 150218585Sjkimvoid 151218585SjkimAcpiDbSetMethodData ( 152218585Sjkim char *TypeArg, 153218585Sjkim char *IndexArg, 154218585Sjkim char *ValueArg) 155218585Sjkim{ 156218585Sjkim char Type; 157218585Sjkim UINT32 Index; 158218585Sjkim UINT32 Value; 159218585Sjkim ACPI_WALK_STATE *WalkState; 160218585Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 161218585Sjkim ACPI_STATUS Status; 162218585Sjkim ACPI_NAMESPACE_NODE *Node; 163218585Sjkim 164218585Sjkim 165218585Sjkim /* Validate TypeArg */ 166218585Sjkim 167218585Sjkim AcpiUtStrupr (TypeArg); 168218585Sjkim Type = TypeArg[0]; 169218585Sjkim if ((Type != 'L') && 170218585Sjkim (Type != 'A') && 171218585Sjkim (Type != 'N')) 172218585Sjkim { 173218585Sjkim AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg); 174218585Sjkim return; 175218585Sjkim } 176218585Sjkim 177306536Sjkim Value = strtoul (ValueArg, NULL, 16); 178218585Sjkim 179218585Sjkim if (Type == 'N') 180218585Sjkim { 181218585Sjkim Node = AcpiDbConvertToNode (IndexArg); 182281075Sdim if (!Node) 183281075Sdim { 184281075Sdim return; 185281075Sdim } 186281075Sdim 187218585Sjkim if (Node->Type != ACPI_TYPE_INTEGER) 188218585Sjkim { 189218585Sjkim AcpiOsPrintf ("Can only set Integer nodes\n"); 190218585Sjkim return; 191218585Sjkim } 192218585Sjkim ObjDesc = Node->Object; 193218585Sjkim ObjDesc->Integer.Value = Value; 194218585Sjkim return; 195218585Sjkim } 196218585Sjkim 197218585Sjkim /* Get the index and value */ 198218585Sjkim 199306536Sjkim Index = strtoul (IndexArg, NULL, 16); 200218585Sjkim 201218585Sjkim WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); 202218585Sjkim if (!WalkState) 203218585Sjkim { 204218585Sjkim AcpiOsPrintf ("There is no method currently executing\n"); 205218585Sjkim return; 206218585Sjkim } 207218585Sjkim 208218585Sjkim /* Create and initialize the new object */ 209218585Sjkim 210218585Sjkim ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value); 211218585Sjkim if (!ObjDesc) 212218585Sjkim { 213218585Sjkim AcpiOsPrintf ("Could not create an internal object\n"); 214218585Sjkim return; 215218585Sjkim } 216218585Sjkim 217218585Sjkim /* Store the new object into the target */ 218218585Sjkim 219218585Sjkim switch (Type) 220218585Sjkim { 221218585Sjkim case 'A': 222218585Sjkim 223218585Sjkim /* Set a method argument */ 224218585Sjkim 225218585Sjkim if (Index > ACPI_METHOD_MAX_ARG) 226218585Sjkim { 227306536Sjkim AcpiOsPrintf ("Arg%u - Invalid argument name\n", 228306536Sjkim Index); 229218585Sjkim goto Cleanup; 230218585Sjkim } 231218585Sjkim 232306536Sjkim Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, 233306536Sjkim Index, ObjDesc, WalkState); 234218585Sjkim if (ACPI_FAILURE (Status)) 235218585Sjkim { 236218585Sjkim goto Cleanup; 237218585Sjkim } 238218585Sjkim 239218585Sjkim ObjDesc = WalkState->Arguments[Index].Object; 240218585Sjkim 241218585Sjkim AcpiOsPrintf ("Arg%u: ", Index); 242306536Sjkim AcpiDbDisplayInternalObject (ObjDesc, WalkState); 243218585Sjkim break; 244218585Sjkim 245218585Sjkim case 'L': 246218585Sjkim 247218585Sjkim /* Set a method local */ 248218585Sjkim 249218585Sjkim if (Index > ACPI_METHOD_MAX_LOCAL) 250218585Sjkim { 251306536Sjkim AcpiOsPrintf ("Local%u - Invalid local variable name\n", 252306536Sjkim Index); 253218585Sjkim goto Cleanup; 254218585Sjkim } 255218585Sjkim 256306536Sjkim Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, 257306536Sjkim Index, ObjDesc, WalkState); 258218585Sjkim if (ACPI_FAILURE (Status)) 259218585Sjkim { 260218585Sjkim goto Cleanup; 261218585Sjkim } 262218585Sjkim 263218585Sjkim ObjDesc = WalkState->LocalVariables[Index].Object; 264218585Sjkim 265218585Sjkim AcpiOsPrintf ("Local%u: ", Index); 266306536Sjkim AcpiDbDisplayInternalObject (ObjDesc, WalkState); 267218585Sjkim break; 268218585Sjkim 269218585Sjkim default: 270250838Sjkim 271218585Sjkim break; 272218585Sjkim } 273218585Sjkim 274218585SjkimCleanup: 275218585Sjkim AcpiUtRemoveReference (ObjDesc); 276218585Sjkim} 277218585Sjkim 278218585Sjkim 279218585Sjkim/******************************************************************************* 280218585Sjkim * 281218585Sjkim * FUNCTION: AcpiDbDisassembleAml 282218585Sjkim * 283218585Sjkim * PARAMETERS: Statements - Number of statements to disassemble 284218585Sjkim * Op - Current Op (from parse walk) 285218585Sjkim * 286218585Sjkim * RETURN: None 287218585Sjkim * 288218585Sjkim * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 289218585Sjkim * of statements specified. 290218585Sjkim * 291218585Sjkim ******************************************************************************/ 292218585Sjkim 293218585Sjkimvoid 294218585SjkimAcpiDbDisassembleAml ( 295218585Sjkim char *Statements, 296218585Sjkim ACPI_PARSE_OBJECT *Op) 297218585Sjkim{ 298218585Sjkim UINT32 NumStatements = 8; 299218585Sjkim 300218585Sjkim 301218585Sjkim if (!Op) 302218585Sjkim { 303218585Sjkim AcpiOsPrintf ("There is no method currently executing\n"); 304218585Sjkim return; 305218585Sjkim } 306218585Sjkim 307218585Sjkim if (Statements) 308218585Sjkim { 309306536Sjkim NumStatements = strtoul (Statements, NULL, 0); 310218585Sjkim } 311218585Sjkim 312218590Sjkim#ifdef ACPI_DISASSEMBLER 313218585Sjkim AcpiDmDisassemble (NULL, Op, NumStatements); 314218590Sjkim#endif 315218585Sjkim} 316218585Sjkim 317218585Sjkim 318218585Sjkim/******************************************************************************* 319218585Sjkim * 320218585Sjkim * FUNCTION: AcpiDbDisassembleMethod 321218585Sjkim * 322218585Sjkim * PARAMETERS: Name - Name of control method 323218585Sjkim * 324218585Sjkim * RETURN: None 325218585Sjkim * 326218585Sjkim * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 327218585Sjkim * of statements specified. 328218585Sjkim * 329218585Sjkim ******************************************************************************/ 330218585Sjkim 331218585SjkimACPI_STATUS 332218585SjkimAcpiDbDisassembleMethod ( 333218585Sjkim char *Name) 334218585Sjkim{ 335218585Sjkim ACPI_STATUS Status; 336218585Sjkim ACPI_PARSE_OBJECT *Op; 337218585Sjkim ACPI_WALK_STATE *WalkState; 338218585Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 339218585Sjkim ACPI_NAMESPACE_NODE *Method; 340218585Sjkim 341218585Sjkim 342218585Sjkim Method = AcpiDbConvertToNode (Name); 343218585Sjkim if (!Method) 344218585Sjkim { 345218585Sjkim return (AE_BAD_PARAMETER); 346218585Sjkim } 347218585Sjkim 348243347Sjkim if (Method->Type != ACPI_TYPE_METHOD) 349243347Sjkim { 350243347Sjkim ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method", 351243347Sjkim Name, AcpiUtGetTypeName (Method->Type))); 352243347Sjkim return (AE_BAD_PARAMETER); 353243347Sjkim } 354243347Sjkim 355218585Sjkim ObjDesc = Method->Object; 356218585Sjkim 357306536Sjkim Op = AcpiPsCreateScopeOp (ObjDesc->Method.AmlStart); 358218585Sjkim if (!Op) 359218585Sjkim { 360218585Sjkim return (AE_NO_MEMORY); 361218585Sjkim } 362218585Sjkim 363218585Sjkim /* Create and initialize a new walk state */ 364218585Sjkim 365218585Sjkim WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 366218585Sjkim if (!WalkState) 367218585Sjkim { 368218585Sjkim return (AE_NO_MEMORY); 369218585Sjkim } 370218585Sjkim 371218585Sjkim Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, 372243347Sjkim ObjDesc->Method.AmlStart, 373243347Sjkim ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 374218585Sjkim if (ACPI_FAILURE (Status)) 375218585Sjkim { 376218585Sjkim return (Status); 377218585Sjkim } 378218585Sjkim 379243347Sjkim Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); 380243347Sjkim WalkState->OwnerId = ObjDesc->Method.OwnerId; 381218585Sjkim 382243347Sjkim /* Push start scope on scope stack and make it current */ 383243347Sjkim 384243347Sjkim Status = AcpiDsScopeStackPush (Method, 385243347Sjkim Method->Type, WalkState); 386243347Sjkim if (ACPI_FAILURE (Status)) 387243347Sjkim { 388243347Sjkim return (Status); 389243347Sjkim } 390243347Sjkim 391243347Sjkim /* Parse the entire method AML including deferred operators */ 392243347Sjkim 393218585Sjkim WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 394218585Sjkim WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 395243347Sjkim 396218585Sjkim Status = AcpiPsParseAml (WalkState); 397306536Sjkim 398306536Sjkim#ifdef ACPI_DISASSEMBLER 399245582Sjkim (void) AcpiDmParseDeferredOps (Op); 400218585Sjkim 401243347Sjkim /* Now we can disassemble the method */ 402243347Sjkim 403306536Sjkim AcpiGbl_DmOpt_Verbose = FALSE; 404218585Sjkim AcpiDmDisassemble (NULL, Op, 0); 405306536Sjkim AcpiGbl_DmOpt_Verbose = TRUE; 406218590Sjkim#endif 407243347Sjkim 408218585Sjkim AcpiPsDeleteParseTree (Op); 409243347Sjkim 410243347Sjkim /* Method cleanup */ 411243347Sjkim 412243347Sjkim AcpiNsDeleteNamespaceSubtree (Method); 413243347Sjkim AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId); 414243347Sjkim AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId); 415218585Sjkim return (AE_OK); 416218585Sjkim} 417