1/******************************************************************************* 2 * 3 * Module Name: dbmethod - Debug commands for control methods 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2011, 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 45#include <contrib/dev/acpica/include/acpi.h> 46#include <contrib/dev/acpica/include/accommon.h> 47#include <contrib/dev/acpica/include/acdispat.h> 48#include <contrib/dev/acpica/include/acnamesp.h> 49#include <contrib/dev/acpica/include/acdebug.h> 50#include <contrib/dev/acpica/include/acdisasm.h> 51#include <contrib/dev/acpica/include/acparser.h> 52 53 54#ifdef ACPI_DEBUGGER 55 56#define _COMPONENT ACPI_CA_DEBUGGER 57 ACPI_MODULE_NAME ("dbmethod") 58 59 60/* Local prototypes */ 61 62static ACPI_STATUS 63AcpiDbWalkForExecute ( 64 ACPI_HANDLE ObjHandle, 65 UINT32 NestingLevel, 66 void *Context, 67 void **ReturnValue); 68 69 70/******************************************************************************* 71 * 72 * FUNCTION: AcpiDbSetMethodBreakpoint 73 * 74 * PARAMETERS: Location - AML offset of breakpoint 75 * WalkState - Current walk info 76 * Op - Current Op (from parse walk) 77 * 78 * RETURN: None 79 * 80 * DESCRIPTION: Set a breakpoint in a control method at the specified 81 * AML offset 82 * 83 ******************************************************************************/ 84 85void 86AcpiDbSetMethodBreakpoint ( 87 char *Location, 88 ACPI_WALK_STATE *WalkState, 89 ACPI_PARSE_OBJECT *Op) 90{ 91 UINT32 Address; 92 93 94 if (!Op) 95 { 96 AcpiOsPrintf ("There is no method currently executing\n"); 97 return; 98 } 99 100 /* Get and verify the breakpoint address */ 101 102 Address = ACPI_STRTOUL (Location, NULL, 16); 103 if (Address <= Op->Common.AmlOffset) 104 { 105 AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n", 106 Address, Op->Common.AmlOffset); 107 } 108 109 /* Save breakpoint in current walk */ 110 111 WalkState->UserBreakpoint = Address; 112 AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address); 113} 114 115 116/******************************************************************************* 117 * 118 * FUNCTION: AcpiDbSetMethodCallBreakpoint 119 * 120 * PARAMETERS: Op - Current Op (from parse walk) 121 * 122 * RETURN: None 123 * 124 * DESCRIPTION: Set a breakpoint in a control method at the specified 125 * AML offset 126 * 127 ******************************************************************************/ 128 129void 130AcpiDbSetMethodCallBreakpoint ( 131 ACPI_PARSE_OBJECT *Op) 132{ 133 134 135 if (!Op) 136 { 137 AcpiOsPrintf ("There is no method currently executing\n"); 138 return; 139 } 140 141 AcpiGbl_StepToNextCall = TRUE; 142} 143 144 145/******************************************************************************* 146 * 147 * FUNCTION: AcpiDbSetMethodData 148 * 149 * PARAMETERS: TypeArg - L for local, A for argument 150 * IndexArg - which one 151 * ValueArg - Value to set. 152 * 153 * RETURN: None 154 * 155 * DESCRIPTION: Set a local or argument for the running control method. 156 * NOTE: only object supported is Number. 157 * 158 ******************************************************************************/ 159 160void 161AcpiDbSetMethodData ( 162 char *TypeArg, 163 char *IndexArg, 164 char *ValueArg) 165{ 166 char Type; 167 UINT32 Index; 168 UINT32 Value; 169 ACPI_WALK_STATE *WalkState; 170 ACPI_OPERAND_OBJECT *ObjDesc; 171 ACPI_STATUS Status; 172 ACPI_NAMESPACE_NODE *Node; 173 174 175 /* Validate TypeArg */ 176 177 AcpiUtStrupr (TypeArg); 178 Type = TypeArg[0]; 179 if ((Type != 'L') && 180 (Type != 'A') && 181 (Type != 'N')) 182 { 183 AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg); 184 return; 185 } 186 187 Value = ACPI_STRTOUL (ValueArg, NULL, 16); 188 189 if (Type == 'N') 190 { 191 Node = AcpiDbConvertToNode (IndexArg); 192 if (Node->Type != ACPI_TYPE_INTEGER) 193 { 194 AcpiOsPrintf ("Can only set Integer nodes\n"); 195 return; 196 } 197 ObjDesc = Node->Object; 198 ObjDesc->Integer.Value = Value; 199 return; 200 } 201 202 /* Get the index and value */ 203 204 Index = ACPI_STRTOUL (IndexArg, NULL, 16); 205 206 WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); 207 if (!WalkState) 208 { 209 AcpiOsPrintf ("There is no method currently executing\n"); 210 return; 211 } 212 213 /* Create and initialize the new object */ 214 215 ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value); 216 if (!ObjDesc) 217 { 218 AcpiOsPrintf ("Could not create an internal object\n"); 219 return; 220 } 221 222 /* Store the new object into the target */ 223 224 switch (Type) 225 { 226 case 'A': 227 228 /* Set a method argument */ 229 230 if (Index > ACPI_METHOD_MAX_ARG) 231 { 232 AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index); 233 goto Cleanup; 234 } 235 236 Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc, 237 WalkState); 238 if (ACPI_FAILURE (Status)) 239 { 240 goto Cleanup; 241 } 242 243 ObjDesc = WalkState->Arguments[Index].Object; 244 245 AcpiOsPrintf ("Arg%u: ", Index); 246 AcpiDmDisplayInternalObject (ObjDesc, WalkState); 247 break; 248 249 case 'L': 250 251 /* Set a method local */ 252 253 if (Index > ACPI_METHOD_MAX_LOCAL) 254 { 255 AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index); 256 goto Cleanup; 257 } 258 259 Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc, 260 WalkState); 261 if (ACPI_FAILURE (Status)) 262 { 263 goto Cleanup; 264 } 265 266 ObjDesc = WalkState->LocalVariables[Index].Object; 267 268 AcpiOsPrintf ("Local%u: ", Index); 269 AcpiDmDisplayInternalObject (ObjDesc, WalkState); 270 break; 271 272 default: 273 break; 274 } 275 276Cleanup: 277 AcpiUtRemoveReference (ObjDesc); 278} 279 280 281/******************************************************************************* 282 * 283 * FUNCTION: AcpiDbDisassembleAml 284 * 285 * PARAMETERS: Statements - Number of statements to disassemble 286 * Op - Current Op (from parse walk) 287 * 288 * RETURN: None 289 * 290 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 291 * of statements specified. 292 * 293 ******************************************************************************/ 294 295void 296AcpiDbDisassembleAml ( 297 char *Statements, 298 ACPI_PARSE_OBJECT *Op) 299{ 300 UINT32 NumStatements = 8; 301 302 303 if (!Op) 304 { 305 AcpiOsPrintf ("There is no method currently executing\n"); 306 return; 307 } 308 309 if (Statements) 310 { 311 NumStatements = ACPI_STRTOUL (Statements, NULL, 0); 312 } 313 314#ifdef ACPI_DISASSEMBLER 315 AcpiDmDisassemble (NULL, Op, NumStatements); 316#endif 317} 318 319 320/******************************************************************************* 321 * 322 * FUNCTION: AcpiDbDisassembleMethod 323 * 324 * PARAMETERS: Name - Name of control method 325 * 326 * RETURN: None 327 * 328 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 329 * of statements specified. 330 * 331 ******************************************************************************/ 332 333ACPI_STATUS 334AcpiDbDisassembleMethod ( 335 char *Name) 336{ 337 ACPI_STATUS Status; 338 ACPI_PARSE_OBJECT *Op; 339 ACPI_WALK_STATE *WalkState; 340 ACPI_OPERAND_OBJECT *ObjDesc; 341 ACPI_NAMESPACE_NODE *Method; 342 343 344 Method = AcpiDbConvertToNode (Name); 345 if (!Method) 346 { 347 return (AE_BAD_PARAMETER); 348 } 349 350 ObjDesc = Method->Object; 351 352 Op = AcpiPsCreateScopeOp (); 353 if (!Op) 354 { 355 return (AE_NO_MEMORY); 356 } 357 358 /* Create and initialize a new walk state */ 359 360 WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 361 if (!WalkState) 362 { 363 return (AE_NO_MEMORY); 364 } 365 366 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, 367 ObjDesc->Method.AmlStart, 368 ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 369 if (ACPI_FAILURE (Status)) 370 { 371 return (Status); 372 } 373 374 /* Parse the AML */ 375 376 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 377 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 378 Status = AcpiPsParseAml (WalkState); 379 380#ifdef ACPI_DISASSEMBLER 381 AcpiDmDisassemble (NULL, Op, 0); 382#endif 383 AcpiPsDeleteParseTree (Op); 384 return (AE_OK); 385} 386 387 388/******************************************************************************* 389 * 390 * FUNCTION: AcpiDbWalkForExecute 391 * 392 * PARAMETERS: Callback from WalkNamespace 393 * 394 * RETURN: Status 395 * 396 * DESCRIPTION: Batch execution module. Currently only executes predefined 397 * ACPI names. 398 * 399 ******************************************************************************/ 400 401static ACPI_STATUS 402AcpiDbWalkForExecute ( 403 ACPI_HANDLE ObjHandle, 404 UINT32 NestingLevel, 405 void *Context, 406 void **ReturnValue) 407{ 408 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 409 ACPI_EXECUTE_WALK *Info = (ACPI_EXECUTE_WALK *) Context; 410 ACPI_BUFFER ReturnObj; 411 ACPI_STATUS Status; 412 char *Pathname; 413 UINT32 i; 414 ACPI_DEVICE_INFO *ObjInfo; 415 ACPI_OBJECT_LIST ParamObjects; 416 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 417 const ACPI_PREDEFINED_INFO *Predefined; 418 419 420 Predefined = AcpiNsCheckForPredefinedName (Node); 421 if (!Predefined) 422 { 423 return (AE_OK); 424 } 425 426 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) 427 { 428 return (AE_OK); 429 } 430 431 Pathname = AcpiNsGetExternalPathname (Node); 432 if (!Pathname) 433 { 434 return (AE_OK); 435 } 436 437 /* Get the object info for number of method parameters */ 438 439 Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo); 440 if (ACPI_FAILURE (Status)) 441 { 442 return (Status); 443 } 444 445 ParamObjects.Pointer = NULL; 446 ParamObjects.Count = 0; 447 448 if (ObjInfo->Type == ACPI_TYPE_METHOD) 449 { 450 /* Setup default parameters */ 451 452 for (i = 0; i < ObjInfo->ParamCount; i++) 453 { 454 Params[i].Type = ACPI_TYPE_INTEGER; 455 Params[i].Integer.Value = 1; 456 } 457 458 ParamObjects.Pointer = Params; 459 ParamObjects.Count = ObjInfo->ParamCount; 460 } 461 462 ACPI_FREE (ObjInfo); 463 ReturnObj.Pointer = NULL; 464 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 465 466 /* Do the actual method execution */ 467 468 AcpiGbl_MethodExecuting = TRUE; 469 470 Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj); 471 472 AcpiOsPrintf ("%-32s returned %s\n", Pathname, AcpiFormatException (Status)); 473 AcpiGbl_MethodExecuting = FALSE; 474 ACPI_FREE (Pathname); 475 476 /* Ignore status from method execution */ 477 478 Status = AE_OK; 479 480 /* Update count, check if we have executed enough methods */ 481 482 Info->Count++; 483 if (Info->Count >= Info->MaxCount) 484 { 485 Status = AE_CTRL_TERMINATE; 486 } 487 488 return (Status); 489} 490 491 492/******************************************************************************* 493 * 494 * FUNCTION: AcpiDbBatchExecute 495 * 496 * PARAMETERS: CountArg - Max number of methods to execute 497 * 498 * RETURN: None 499 * 500 * DESCRIPTION: Namespace batch execution. Execute predefined names in the 501 * namespace, up to the max count, if specified. 502 * 503 ******************************************************************************/ 504 505void 506AcpiDbBatchExecute ( 507 char *CountArg) 508{ 509 ACPI_EXECUTE_WALK Info; 510 511 512 Info.Count = 0; 513 Info.MaxCount = ACPI_UINT32_MAX; 514 515 if (CountArg) 516 { 517 Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0); 518 } 519 520 521 /* Search all nodes in namespace */ 522 523 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 524 AcpiDbWalkForExecute, NULL, (void *) &Info, NULL); 525 526 AcpiOsPrintf ("Executed %u predefined names in the namespace\n", Info.Count); 527} 528 529#endif /* ACPI_DEBUGGER */ 530