1 /******************************************************************************* 2 * 3 * Module Name: dbmethod - Debug commands for control methods 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 #include <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acdispat.h> 47 #include <contrib/dev/acpica/include/acnamesp.h> 48 #include <contrib/dev/acpica/include/acdebug.h> 49 #include <contrib/dev/acpica/include/acdisasm.h> 50 #include <contrib/dev/acpica/include/acparser.h> 51 #include <contrib/dev/acpica/include/acpredef.h> 52 53 54 #ifdef ACPI_DEBUGGER 55 56 #define _COMPONENT ACPI_CA_DEBUGGER 57 ACPI_MODULE_NAME ("dbmethod") 58 59 60 /******************************************************************************* 61 * 62 * FUNCTION: AcpiDbSetMethodBreakpoint 63 * 64 * PARAMETERS: Location - AML offset of breakpoint 65 * WalkState - Current walk info 66 * Op - Current Op (from parse walk) 67 * 68 * RETURN: None 69 * 70 * DESCRIPTION: Set a breakpoint in a control method at the specified 71 * AML offset 72 * 73 ******************************************************************************/ 74 75 void 76 AcpiDbSetMethodBreakpoint ( 77 char *Location, 78 ACPI_WALK_STATE *WalkState, 79 ACPI_PARSE_OBJECT *Op) 80 { 81 UINT32 Address; 82 83 84 if (!Op) 85 { 86 AcpiOsPrintf ("There is no method currently executing\n"); 87 return; 88 } 89 90 /* Get and verify the breakpoint address */ 91 92 Address = strtoul (Location, NULL, 16); 93 if (Address <= Op->Common.AmlOffset) 94 { 95 AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n", 96 Address, Op->Common.AmlOffset); 97 } 98 99 /* Save breakpoint in current walk */ 100 101 WalkState->UserBreakpoint = Address; 102 AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address); 103 } 104 105 106 /******************************************************************************* 107 * 108 * FUNCTION: AcpiDbSetMethodCallBreakpoint 109 * 110 * PARAMETERS: Op - Current Op (from parse walk) 111 * 112 * RETURN: None 113 * 114 * DESCRIPTION: Set a breakpoint in a control method at the specified 115 * AML offset 116 * 117 ******************************************************************************/ 118 119 void 120 AcpiDbSetMethodCallBreakpoint ( 121 ACPI_PARSE_OBJECT *Op) 122 { 123 124 125 if (!Op) 126 { 127 AcpiOsPrintf ("There is no method currently executing\n"); 128 return; 129 } 130 131 AcpiGbl_StepToNextCall = TRUE; 132 } 133 134 135 /******************************************************************************* 136 * 137 * FUNCTION: AcpiDbSetMethodData 138 * 139 * PARAMETERS: TypeArg - L for local, A for argument 140 * IndexArg - which one 141 * ValueArg - Value to set. 142 * 143 * RETURN: None 144 * 145 * DESCRIPTION: Set a local or argument for the running control method. 146 * NOTE: only object supported is Number. 147 * 148 ******************************************************************************/ 149 150 void 151 AcpiDbSetMethodData ( 152 char *TypeArg, 153 char *IndexArg, 154 char *ValueArg) 155 { 156 char Type; 157 UINT32 Index; 158 UINT32 Value; 159 ACPI_WALK_STATE *WalkState; 160 ACPI_OPERAND_OBJECT *ObjDesc; 161 ACPI_STATUS Status; 162 ACPI_NAMESPACE_NODE *Node; 163 164 165 /* Validate TypeArg */ 166 167 AcpiUtStrupr (TypeArg); 168 Type = TypeArg[0]; 169 if ((Type != 'L') && 170 (Type != 'A') && 171 (Type != 'N')) 172 { 173 AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg); 174 return; 175 } 176 177 Value = strtoul (ValueArg, NULL, 16); 178 179 if (Type == 'N') 180 { 181 Node = AcpiDbConvertToNode (IndexArg); 182 if (!Node) 183 { 184 return; 185 } 186 187 if (Node->Type != ACPI_TYPE_INTEGER) 188 { 189 AcpiOsPrintf ("Can only set Integer nodes\n"); 190 return; 191 } 192 ObjDesc = Node->Object; 193 ObjDesc->Integer.Value = Value; 194 return; 195 } 196 197 /* Get the index and value */ 198 199 Index = strtoul (IndexArg, NULL, 16); 200 201 WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); 202 if (!WalkState) 203 { 204 AcpiOsPrintf ("There is no method currently executing\n"); 205 return; 206 } 207 208 /* Create and initialize the new object */ 209 210 ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value); 211 if (!ObjDesc) 212 { 213 AcpiOsPrintf ("Could not create an internal object\n"); 214 return; 215 } 216 217 /* Store the new object into the target */ 218 219 switch (Type) 220 { 221 case 'A': 222 223 /* Set a method argument */ 224 225 if (Index > ACPI_METHOD_MAX_ARG) 226 { 227 AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index); 228 goto Cleanup; 229 } 230 231 Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc, 232 WalkState); 233 if (ACPI_FAILURE (Status)) 234 { 235 goto Cleanup; 236 } 237 238 ObjDesc = WalkState->Arguments[Index].Object; 239 240 AcpiOsPrintf ("Arg%u: ", Index); 241 AcpiDmDisplayInternalObject (ObjDesc, WalkState); 242 break; 243 244 case 'L': 245 246 /* Set a method local */ 247 248 if (Index > ACPI_METHOD_MAX_LOCAL) 249 { 250 AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index); 251 goto Cleanup; 252 } 253 254 Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc, 255 WalkState); 256 if (ACPI_FAILURE (Status)) 257 { 258 goto Cleanup; 259 } 260 261 ObjDesc = WalkState->LocalVariables[Index].Object; 262 263 AcpiOsPrintf ("Local%u: ", Index); 264 AcpiDmDisplayInternalObject (ObjDesc, WalkState); 265 break; 266 267 default: 268 269 break; 270 } 271 272 Cleanup: 273 AcpiUtRemoveReference (ObjDesc); 274 } 275 276 277 /******************************************************************************* 278 * 279 * FUNCTION: AcpiDbDisassembleAml 280 * 281 * PARAMETERS: Statements - Number of statements to disassemble 282 * Op - Current Op (from parse walk) 283 * 284 * RETURN: None 285 * 286 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 287 * of statements specified. 288 * 289 ******************************************************************************/ 290 291 void 292 AcpiDbDisassembleAml ( 293 char *Statements, 294 ACPI_PARSE_OBJECT *Op) 295 { 296 UINT32 NumStatements = 8; 297 298 299 if (!Op) 300 { 301 AcpiOsPrintf ("There is no method currently executing\n"); 302 return; 303 } 304 305 if (Statements) 306 { 307 NumStatements = strtoul (Statements, NULL, 0); 308 } 309 310 #ifdef ACPI_DISASSEMBLER 311 AcpiDmDisassemble (NULL, Op, NumStatements); 312 #endif 313 } 314 315 316 /******************************************************************************* 317 * 318 * FUNCTION: AcpiDbDisassembleMethod 319 * 320 * PARAMETERS: Name - Name of control method 321 * 322 * RETURN: None 323 * 324 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 325 * of statements specified. 326 * 327 ******************************************************************************/ 328 329 ACPI_STATUS 330 AcpiDbDisassembleMethod ( 331 char *Name) 332 { 333 ACPI_STATUS Status; 334 ACPI_PARSE_OBJECT *Op; 335 ACPI_WALK_STATE *WalkState; 336 ACPI_OPERAND_OBJECT *ObjDesc; 337 ACPI_NAMESPACE_NODE *Method; 338 339 340 Method = AcpiDbConvertToNode (Name); 341 if (!Method) 342 { 343 return (AE_BAD_PARAMETER); 344 } 345 346 if (Method->Type != ACPI_TYPE_METHOD) 347 { 348 ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method", 349 Name, AcpiUtGetTypeName (Method->Type))); 350 return (AE_BAD_PARAMETER); 351 } 352 353 ObjDesc = Method->Object; 354 355 Op = AcpiPsCreateScopeOp (); 356 if (!Op) 357 { 358 return (AE_NO_MEMORY); 359 } 360 361 /* Create and initialize a new walk state */ 362 363 WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 364 if (!WalkState) 365 { 366 return (AE_NO_MEMORY); 367 } 368 369 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, 370 ObjDesc->Method.AmlStart, 371 ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 372 if (ACPI_FAILURE (Status)) 373 { 374 return (Status); 375 } 376 377 Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); 378 WalkState->OwnerId = ObjDesc->Method.OwnerId; 379 380 /* Push start scope on scope stack and make it current */ 381 382 Status = AcpiDsScopeStackPush (Method, 383 Method->Type, WalkState); 384 if (ACPI_FAILURE (Status)) 385 { 386 return (Status); 387 } 388 389 /* Parse the entire method AML including deferred operators */ 390 391 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 392 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 393 394 Status = AcpiPsParseAml (WalkState); 395 (void) AcpiDmParseDeferredOps (Op); 396 397 /* Now we can disassemble the method */ 398 399 AcpiGbl_DbOpt_Verbose = FALSE; 400 #ifdef ACPI_DISASSEMBLER 401 AcpiDmDisassemble (NULL, Op, 0); 402 #endif 403 AcpiGbl_DbOpt_Verbose = TRUE; 404 405 AcpiPsDeleteParseTree (Op); 406 407 /* Method cleanup */ 408 409 AcpiNsDeleteNamespaceSubtree (Method); 410 AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId); 411 AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId); 412 return (AE_OK); 413 } 414 415 #endif /* ACPI_DEBUGGER */ 416