1 /******************************************************************************* 2 * 3 * Module Name: dbmethod - Debug commands for control methods 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 62 static ACPI_STATUS 63 AcpiDbWalkForExecute ( 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 85 void 86 AcpiDbSetMethodBreakpoint ( 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 129 void 130 AcpiDbSetMethodCallBreakpoint ( 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 160 void 161 AcpiDbSetMethodData ( 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 276 Cleanup: 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 295 void 296 AcpiDbDisassembleAml ( 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 333 ACPI_STATUS 334 AcpiDbDisassembleMethod ( 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 if (Method->Type != ACPI_TYPE_METHOD) 351 { 352 ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method", 353 Name, AcpiUtGetTypeName (Method->Type))); 354 return (AE_BAD_PARAMETER); 355 } 356 357 ObjDesc = Method->Object; 358 359 Op = AcpiPsCreateScopeOp (); 360 if (!Op) 361 { 362 return (AE_NO_MEMORY); 363 } 364 365 /* Create and initialize a new walk state */ 366 367 WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 368 if (!WalkState) 369 { 370 return (AE_NO_MEMORY); 371 } 372 373 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, 374 ObjDesc->Method.AmlStart, 375 ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 376 if (ACPI_FAILURE (Status)) 377 { 378 return (Status); 379 } 380 381 Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); 382 WalkState->OwnerId = ObjDesc->Method.OwnerId; 383 384 /* Push start scope on scope stack and make it current */ 385 386 Status = AcpiDsScopeStackPush (Method, 387 Method->Type, WalkState); 388 if (ACPI_FAILURE (Status)) 389 { 390 return (Status); 391 } 392 393 /* Parse the entire method AML including deferred operators */ 394 395 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 396 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 397 398 Status = AcpiPsParseAml (WalkState); 399 (void) AcpiDmParseDeferredOps (Op); 400 401 /* Now we can disassemble the method */ 402 403 AcpiGbl_DbOpt_verbose = FALSE; 404 #ifdef ACPI_DISASSEMBLER 405 AcpiDmDisassemble (NULL, Op, 0); 406 #endif 407 AcpiGbl_DbOpt_verbose = TRUE; 408 409 AcpiPsDeleteParseTree (Op); 410 411 /* Method cleanup */ 412 413 AcpiNsDeleteNamespaceSubtree (Method); 414 AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId); 415 AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId); 416 return (AE_OK); 417 } 418 419 420 /******************************************************************************* 421 * 422 * FUNCTION: AcpiDbWalkForExecute 423 * 424 * PARAMETERS: Callback from WalkNamespace 425 * 426 * RETURN: Status 427 * 428 * DESCRIPTION: Batch execution module. Currently only executes predefined 429 * ACPI names. 430 * 431 ******************************************************************************/ 432 433 static ACPI_STATUS 434 AcpiDbWalkForExecute ( 435 ACPI_HANDLE ObjHandle, 436 UINT32 NestingLevel, 437 void *Context, 438 void **ReturnValue) 439 { 440 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 441 ACPI_DB_EXECUTE_WALK *Info = (ACPI_DB_EXECUTE_WALK *) Context; 442 ACPI_BUFFER ReturnObj; 443 ACPI_STATUS Status; 444 char *Pathname; 445 UINT32 i; 446 ACPI_DEVICE_INFO *ObjInfo; 447 ACPI_OBJECT_LIST ParamObjects; 448 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 449 const ACPI_PREDEFINED_INFO *Predefined; 450 451 452 Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii); 453 if (!Predefined) 454 { 455 return (AE_OK); 456 } 457 458 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) 459 { 460 return (AE_OK); 461 } 462 463 Pathname = AcpiNsGetExternalPathname (Node); 464 if (!Pathname) 465 { 466 return (AE_OK); 467 } 468 469 /* Get the object info for number of method parameters */ 470 471 Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo); 472 if (ACPI_FAILURE (Status)) 473 { 474 return (Status); 475 } 476 477 ParamObjects.Pointer = NULL; 478 ParamObjects.Count = 0; 479 480 if (ObjInfo->Type == ACPI_TYPE_METHOD) 481 { 482 /* Setup default parameters */ 483 484 for (i = 0; i < ObjInfo->ParamCount; i++) 485 { 486 Params[i].Type = ACPI_TYPE_INTEGER; 487 Params[i].Integer.Value = 1; 488 } 489 490 ParamObjects.Pointer = Params; 491 ParamObjects.Count = ObjInfo->ParamCount; 492 } 493 494 ACPI_FREE (ObjInfo); 495 ReturnObj.Pointer = NULL; 496 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 497 498 /* Do the actual method execution */ 499 500 AcpiGbl_MethodExecuting = TRUE; 501 502 Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj); 503 504 AcpiOsPrintf ("%-32s returned %s\n", Pathname, AcpiFormatException (Status)); 505 AcpiGbl_MethodExecuting = FALSE; 506 ACPI_FREE (Pathname); 507 508 /* Ignore status from method execution */ 509 510 Status = AE_OK; 511 512 /* Update count, check if we have executed enough methods */ 513 514 Info->Count++; 515 if (Info->Count >= Info->MaxCount) 516 { 517 Status = AE_CTRL_TERMINATE; 518 } 519 520 return (Status); 521 } 522 523 524 /******************************************************************************* 525 * 526 * FUNCTION: AcpiDbBatchExecute 527 * 528 * PARAMETERS: CountArg - Max number of methods to execute 529 * 530 * RETURN: None 531 * 532 * DESCRIPTION: Namespace batch execution. Execute predefined names in the 533 * namespace, up to the max count, if specified. 534 * 535 ******************************************************************************/ 536 537 void 538 AcpiDbBatchExecute ( 539 char *CountArg) 540 { 541 ACPI_DB_EXECUTE_WALK Info; 542 543 544 Info.Count = 0; 545 Info.MaxCount = ACPI_UINT32_MAX; 546 547 if (CountArg) 548 { 549 Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0); 550 } 551 552 553 /* Search all nodes in namespace */ 554 555 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 556 AcpiDbWalkForExecute, NULL, (void *) &Info, NULL); 557 558 AcpiOsPrintf ("Evaluated %u predefined names in the namespace\n", Info.Count); 559 } 560 561 #endif /* ACPI_DEBUGGER */ 562