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 "acpi.h" 46 #include "accommon.h" 47 #include "acdispat.h" 48 #include "acnamesp.h" 49 #include "acdebug.h" 50 #include "acdisasm.h" 51 #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 AcpiDmDisassemble (NULL, Op, NumStatements); 315 } 316 317 318 /******************************************************************************* 319 * 320 * FUNCTION: AcpiDbDisassembleMethod 321 * 322 * PARAMETERS: Name - Name of control method 323 * 324 * RETURN: None 325 * 326 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 327 * of statements specified. 328 * 329 ******************************************************************************/ 330 331 ACPI_STATUS 332 AcpiDbDisassembleMethod ( 333 char *Name) 334 { 335 ACPI_STATUS Status; 336 ACPI_PARSE_OBJECT *Op; 337 ACPI_WALK_STATE *WalkState; 338 ACPI_OPERAND_OBJECT *ObjDesc; 339 ACPI_NAMESPACE_NODE *Method; 340 341 342 Method = AcpiDbConvertToNode (Name); 343 if (!Method) 344 { 345 return (AE_BAD_PARAMETER); 346 } 347 348 ObjDesc = Method->Object; 349 350 Op = AcpiPsCreateScopeOp (); 351 if (!Op) 352 { 353 return (AE_NO_MEMORY); 354 } 355 356 /* Create and initialize a new walk state */ 357 358 WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 359 if (!WalkState) 360 { 361 return (AE_NO_MEMORY); 362 } 363 364 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, 365 ObjDesc->Method.AmlStart, 366 ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 367 if (ACPI_FAILURE (Status)) 368 { 369 return (Status); 370 } 371 372 /* Parse the AML */ 373 374 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 375 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 376 Status = AcpiPsParseAml (WalkState); 377 378 AcpiDmDisassemble (NULL, Op, 0); 379 AcpiPsDeleteParseTree (Op); 380 return (AE_OK); 381 } 382 383 384 /******************************************************************************* 385 * 386 * FUNCTION: AcpiDbWalkForExecute 387 * 388 * PARAMETERS: Callback from WalkNamespace 389 * 390 * RETURN: Status 391 * 392 * DESCRIPTION: Batch execution module. Currently only executes predefined 393 * ACPI names. 394 * 395 ******************************************************************************/ 396 397 static ACPI_STATUS 398 AcpiDbWalkForExecute ( 399 ACPI_HANDLE ObjHandle, 400 UINT32 NestingLevel, 401 void *Context, 402 void **ReturnValue) 403 { 404 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 405 ACPI_EXECUTE_WALK *Info = (ACPI_EXECUTE_WALK *) Context; 406 ACPI_BUFFER ReturnObj; 407 ACPI_STATUS Status; 408 char *Pathname; 409 UINT32 i; 410 ACPI_DEVICE_INFO *ObjInfo; 411 ACPI_OBJECT_LIST ParamObjects; 412 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 413 const ACPI_PREDEFINED_INFO *Predefined; 414 415 416 Predefined = AcpiNsCheckForPredefinedName (Node); 417 if (!Predefined) 418 { 419 return (AE_OK); 420 } 421 422 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) 423 { 424 return (AE_OK); 425 } 426 427 Pathname = AcpiNsGetExternalPathname (Node); 428 if (!Pathname) 429 { 430 return (AE_OK); 431 } 432 433 /* Get the object info for number of method parameters */ 434 435 Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo); 436 if (ACPI_FAILURE (Status)) 437 { 438 return (Status); 439 } 440 441 ParamObjects.Pointer = NULL; 442 ParamObjects.Count = 0; 443 444 if (ObjInfo->Type == ACPI_TYPE_METHOD) 445 { 446 /* Setup default parameters */ 447 448 for (i = 0; i < ObjInfo->ParamCount; i++) 449 { 450 Params[i].Type = ACPI_TYPE_INTEGER; 451 Params[i].Integer.Value = 1; 452 } 453 454 ParamObjects.Pointer = Params; 455 ParamObjects.Count = ObjInfo->ParamCount; 456 } 457 458 ACPI_FREE (ObjInfo); 459 ReturnObj.Pointer = NULL; 460 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 461 462 /* Do the actual method execution */ 463 464 AcpiGbl_MethodExecuting = TRUE; 465 466 Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj); 467 468 AcpiOsPrintf ("%-32s returned %s\n", Pathname, AcpiFormatException (Status)); 469 AcpiGbl_MethodExecuting = FALSE; 470 ACPI_FREE (Pathname); 471 472 /* Ignore status from method execution */ 473 474 Status = AE_OK; 475 476 /* Update count, check if we have executed enough methods */ 477 478 Info->Count++; 479 if (Info->Count >= Info->MaxCount) 480 { 481 Status = AE_CTRL_TERMINATE; 482 } 483 484 return (Status); 485 } 486 487 488 /******************************************************************************* 489 * 490 * FUNCTION: AcpiDbBatchExecute 491 * 492 * PARAMETERS: CountArg - Max number of methods to execute 493 * 494 * RETURN: None 495 * 496 * DESCRIPTION: Namespace batch execution. Execute predefined names in the 497 * namespace, up to the max count, if specified. 498 * 499 ******************************************************************************/ 500 501 void 502 AcpiDbBatchExecute ( 503 char *CountArg) 504 { 505 ACPI_EXECUTE_WALK Info; 506 507 508 Info.Count = 0; 509 Info.MaxCount = ACPI_UINT32_MAX; 510 511 if (CountArg) 512 { 513 Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0); 514 } 515 516 517 /* Search all nodes in namespace */ 518 519 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 520 AcpiDbWalkForExecute, NULL, (void *) &Info, NULL); 521 522 AcpiOsPrintf ("Executed %u predefined names in the namespace\n", Info.Count); 523 } 524 525 #endif /* ACPI_DEBUGGER */