1 /****************************************************************************** 2 * 3 * Module Name: exdebug - Support for stores to the AML Debug Object 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 "acpi.h" 45 #include "accommon.h" 46 #include "acnamesp.h" 47 #include "acinterp.h" 48 #include "acparser.h" 49 50 51 #define _COMPONENT ACPI_EXECUTER 52 ACPI_MODULE_NAME ("exdebug") 53 54 55 static ACPI_OPERAND_OBJECT *AcpiGbl_TraceMethodObject = NULL; 56 57 /* Local prototypes */ 58 59 #ifdef ACPI_DEBUG_OUTPUT 60 static const char * 61 AcpiExGetTraceEventName ( 62 ACPI_TRACE_EVENT_TYPE Type); 63 #endif 64 65 66 #ifndef ACPI_NO_ERROR_MESSAGES 67 /******************************************************************************* 68 * 69 * FUNCTION: AcpiExDoDebugObject 70 * 71 * PARAMETERS: SourceDesc - Object to be output to "Debug Object" 72 * Level - Indentation level (used for packages) 73 * Index - Current package element, zero if not pkg 74 * 75 * RETURN: None 76 * 77 * DESCRIPTION: Handles stores to the AML Debug Object. For example: 78 * Store(INT1, Debug) 79 * 80 * This function is not compiled if ACPI_NO_ERROR_MESSAGES is set. 81 * 82 * This function is only enabled if AcpiGbl_EnableAmlDebugObject is set. 83 * Thus, in the normal operational case, stores to the debug object are 84 * ignored but can be easily enabled if necessary. 85 * 86 ******************************************************************************/ 87 88 void 89 AcpiExDoDebugObject ( 90 ACPI_OPERAND_OBJECT *SourceDesc, 91 UINT32 Level, 92 UINT32 Index) 93 { 94 UINT32 i; 95 UINT32 Timer; 96 ACPI_OPERAND_OBJECT *ObjectDesc; 97 UINT32 Value; 98 99 100 ACPI_FUNCTION_TRACE_PTR (ExDoDebugObject, SourceDesc); 101 102 103 /* Output must be enabled via the DebugObject global */ 104 105 if (!AcpiGbl_EnableAmlDebugObject) 106 { 107 return_VOID; 108 } 109 110 /* 111 * We will emit the current timer value (in microseconds) with each 112 * debug output. Only need the lower 26 bits. This allows for 67 113 * million microseconds or 67 seconds before rollover. 114 */ 115 Timer = ((UINT32) AcpiOsGetTimer () / 10); /* (100 nanoseconds to microseconds) */ 116 Timer &= 0x03FFFFFF; 117 118 /* 119 * Print line header as long as we are not in the middle of an 120 * object display 121 */ 122 if (!((Level > 0) && Index == 0)) 123 { 124 AcpiOsPrintf ("[ACPI Debug %.8u] %*s", Timer, Level, " "); 125 } 126 127 /* Display the index for package output only */ 128 129 if (Index > 0) 130 { 131 AcpiOsPrintf ("(%.2u) ", Index-1); 132 } 133 134 if (!SourceDesc) 135 { 136 AcpiOsPrintf ("[Null Object]\n"); 137 return_VOID; 138 } 139 140 if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_OPERAND) 141 { 142 AcpiOsPrintf ("%s ", AcpiUtGetObjectTypeName (SourceDesc)); 143 144 if (!AcpiUtValidInternalObject (SourceDesc)) 145 { 146 AcpiOsPrintf ("%p, Invalid Internal Object!\n", SourceDesc); 147 return_VOID; 148 } 149 } 150 else if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED) 151 { 152 AcpiOsPrintf ("%s: %p\n", 153 AcpiUtGetTypeName (((ACPI_NAMESPACE_NODE *) SourceDesc)->Type), 154 SourceDesc); 155 return_VOID; 156 } 157 else 158 { 159 return_VOID; 160 } 161 162 /* SourceDesc is of type ACPI_DESC_TYPE_OPERAND */ 163 164 switch (SourceDesc->Common.Type) 165 { 166 case ACPI_TYPE_INTEGER: 167 168 /* Output correct integer width */ 169 170 if (AcpiGbl_IntegerByteWidth == 4) 171 { 172 AcpiOsPrintf ("0x%8.8X\n", 173 (UINT32) SourceDesc->Integer.Value); 174 } 175 else 176 { 177 AcpiOsPrintf ("0x%8.8X%8.8X\n", 178 ACPI_FORMAT_UINT64 (SourceDesc->Integer.Value)); 179 } 180 break; 181 182 case ACPI_TYPE_BUFFER: 183 184 AcpiOsPrintf ("[0x%.2X]\n", (UINT32) SourceDesc->Buffer.Length); 185 AcpiUtDumpBuffer (SourceDesc->Buffer.Pointer, 186 (SourceDesc->Buffer.Length < 256) ? 187 SourceDesc->Buffer.Length : 256, DB_BYTE_DISPLAY, 0); 188 break; 189 190 case ACPI_TYPE_STRING: 191 192 AcpiOsPrintf ("[0x%.2X] \"%s\"\n", 193 SourceDesc->String.Length, SourceDesc->String.Pointer); 194 break; 195 196 case ACPI_TYPE_PACKAGE: 197 198 AcpiOsPrintf ("[Contains 0x%.2X Elements]\n", 199 SourceDesc->Package.Count); 200 201 /* Output the entire contents of the package */ 202 203 for (i = 0; i < SourceDesc->Package.Count; i++) 204 { 205 AcpiExDoDebugObject (SourceDesc->Package.Elements[i], 206 Level+4, i+1); 207 } 208 break; 209 210 case ACPI_TYPE_LOCAL_REFERENCE: 211 212 AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (SourceDesc)); 213 214 /* Decode the reference */ 215 216 switch (SourceDesc->Reference.Class) 217 { 218 case ACPI_REFCLASS_INDEX: 219 220 AcpiOsPrintf ("0x%X\n", SourceDesc->Reference.Value); 221 break; 222 223 case ACPI_REFCLASS_TABLE: 224 225 /* Case for DdbHandle */ 226 227 AcpiOsPrintf ("Table Index 0x%X\n", SourceDesc->Reference.Value); 228 return_VOID; 229 230 default: 231 232 break; 233 } 234 235 AcpiOsPrintf (" "); 236 237 /* Check for valid node first, then valid object */ 238 239 if (SourceDesc->Reference.Node) 240 { 241 if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc->Reference.Node) != 242 ACPI_DESC_TYPE_NAMED) 243 { 244 AcpiOsPrintf (" %p - Not a valid namespace node\n", 245 SourceDesc->Reference.Node); 246 } 247 else 248 { 249 AcpiOsPrintf ("Node %p [%4.4s] ", SourceDesc->Reference.Node, 250 (SourceDesc->Reference.Node)->Name.Ascii); 251 252 switch ((SourceDesc->Reference.Node)->Type) 253 { 254 /* These types have no attached object */ 255 256 case ACPI_TYPE_DEVICE: 257 AcpiOsPrintf ("Device\n"); 258 break; 259 260 case ACPI_TYPE_THERMAL: 261 AcpiOsPrintf ("Thermal Zone\n"); 262 break; 263 264 default: 265 266 AcpiExDoDebugObject ((SourceDesc->Reference.Node)->Object, 267 Level+4, 0); 268 break; 269 } 270 } 271 } 272 else if (SourceDesc->Reference.Object) 273 { 274 if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc->Reference.Object) == 275 ACPI_DESC_TYPE_NAMED) 276 { 277 AcpiExDoDebugObject (((ACPI_NAMESPACE_NODE *) 278 SourceDesc->Reference.Object)->Object, 279 Level+4, 0); 280 } 281 else 282 { 283 ObjectDesc = SourceDesc->Reference.Object; 284 Value = SourceDesc->Reference.Value; 285 286 switch (ObjectDesc->Common.Type) 287 { 288 case ACPI_TYPE_BUFFER: 289 290 AcpiOsPrintf ("Buffer[%u] = 0x%2.2X\n", 291 Value, *SourceDesc->Reference.IndexPointer); 292 break; 293 294 case ACPI_TYPE_STRING: 295 296 AcpiOsPrintf ("String[%u] = \"%c\" (0x%2.2X)\n", 297 Value, *SourceDesc->Reference.IndexPointer, 298 *SourceDesc->Reference.IndexPointer); 299 break; 300 301 case ACPI_TYPE_PACKAGE: 302 303 AcpiOsPrintf ("Package[%u] = ", Value); 304 AcpiExDoDebugObject (*SourceDesc->Reference.Where, 305 Level+4, 0); 306 break; 307 308 default: 309 310 AcpiOsPrintf ("Unknown Reference object type %X\n", 311 ObjectDesc->Common.Type); 312 break; 313 } 314 } 315 } 316 break; 317 318 default: 319 320 AcpiOsPrintf ("%p\n", SourceDesc); 321 break; 322 } 323 324 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n")); 325 return_VOID; 326 } 327 #endif 328 329 330 /******************************************************************************* 331 * 332 * FUNCTION: AcpiExInterpreterTraceEnabled 333 * 334 * PARAMETERS: Name - Whether method name should be matched, 335 * this should be checked before starting 336 * the tracer 337 * 338 * RETURN: TRUE if interpreter trace is enabled. 339 * 340 * DESCRIPTION: Check whether interpreter trace is enabled 341 * 342 ******************************************************************************/ 343 344 static BOOLEAN 345 AcpiExInterpreterTraceEnabled ( 346 char *Name) 347 { 348 349 /* Check if tracing is enabled */ 350 351 if (!(AcpiGbl_TraceFlags & ACPI_TRACE_ENABLED)) 352 { 353 return (FALSE); 354 } 355 356 /* 357 * Check if tracing is filtered: 358 * 359 * 1. If the tracer is started, AcpiGbl_TraceMethodObject should have 360 * been filled by the trace starter 361 * 2. If the tracer is not started, AcpiGbl_TraceMethodName should be 362 * matched if it is specified 363 * 3. If the tracer is oneshot style, AcpiGbl_TraceMethodName should 364 * not be cleared by the trace stopper during the first match 365 */ 366 if (AcpiGbl_TraceMethodObject) 367 { 368 return (TRUE); 369 } 370 if (Name && 371 (AcpiGbl_TraceMethodName && 372 strcmp (AcpiGbl_TraceMethodName, Name))) 373 { 374 return (FALSE); 375 } 376 if ((AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) && 377 !AcpiGbl_TraceMethodName) 378 { 379 return (FALSE); 380 } 381 382 return (TRUE); 383 } 384 385 386 /******************************************************************************* 387 * 388 * FUNCTION: AcpiExGetTraceEventName 389 * 390 * PARAMETERS: Type - Trace event type 391 * 392 * RETURN: Trace event name. 393 * 394 * DESCRIPTION: Used to obtain the full trace event name. 395 * 396 ******************************************************************************/ 397 398 #ifdef ACPI_DEBUG_OUTPUT 399 400 static const char * 401 AcpiExGetTraceEventName ( 402 ACPI_TRACE_EVENT_TYPE Type) 403 { 404 switch (Type) 405 { 406 case ACPI_TRACE_AML_METHOD: 407 408 return "Method"; 409 410 case ACPI_TRACE_AML_OPCODE: 411 412 return "Opcode"; 413 414 case ACPI_TRACE_AML_REGION: 415 416 return "Region"; 417 418 default: 419 420 return ""; 421 } 422 } 423 424 #endif 425 426 427 /******************************************************************************* 428 * 429 * FUNCTION: AcpiExTracePoint 430 * 431 * PARAMETERS: Type - Trace event type 432 * Begin - TRUE if before execution 433 * Aml - Executed AML address 434 * Pathname - Object path 435 * 436 * RETURN: None 437 * 438 * DESCRIPTION: Internal interpreter execution trace. 439 * 440 ******************************************************************************/ 441 442 void 443 AcpiExTracePoint ( 444 ACPI_TRACE_EVENT_TYPE Type, 445 BOOLEAN Begin, 446 UINT8 *Aml, 447 char *Pathname) 448 { 449 450 ACPI_FUNCTION_NAME (ExTracePoint); 451 452 453 if (Pathname) 454 { 455 ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, 456 "%s %s [0x%p:%s] execution.\n", 457 AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", 458 Aml, Pathname)); 459 } 460 else 461 { 462 ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, 463 "%s %s [0x%p] execution.\n", 464 AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", 465 Aml)); 466 } 467 } 468 469 470 /******************************************************************************* 471 * 472 * FUNCTION: AcpiExStartTraceMethod 473 * 474 * PARAMETERS: MethodNode - Node of the method 475 * ObjDesc - The method object 476 * WalkState - current state, NULL if not yet executing 477 * a method. 478 * 479 * RETURN: None 480 * 481 * DESCRIPTION: Start control method execution trace 482 * 483 ******************************************************************************/ 484 485 void 486 AcpiExStartTraceMethod ( 487 ACPI_NAMESPACE_NODE *MethodNode, 488 ACPI_OPERAND_OBJECT *ObjDesc, 489 ACPI_WALK_STATE *WalkState) 490 { 491 ACPI_STATUS Status; 492 char *Pathname = NULL; 493 BOOLEAN Enabled = FALSE; 494 495 496 ACPI_FUNCTION_NAME (ExStartTraceMethod); 497 498 499 if (MethodNode) 500 { 501 Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); 502 } 503 504 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 505 if (ACPI_FAILURE (Status)) 506 { 507 goto Exit; 508 } 509 510 Enabled = AcpiExInterpreterTraceEnabled (Pathname); 511 if (Enabled && !AcpiGbl_TraceMethodObject) 512 { 513 AcpiGbl_TraceMethodObject = ObjDesc; 514 AcpiGbl_OriginalDbgLevel = AcpiDbgLevel; 515 AcpiGbl_OriginalDbgLayer = AcpiDbgLayer; 516 AcpiDbgLevel = ACPI_TRACE_LEVEL_ALL; 517 AcpiDbgLayer = ACPI_TRACE_LAYER_ALL; 518 519 if (AcpiGbl_TraceDbgLevel) 520 { 521 AcpiDbgLevel = AcpiGbl_TraceDbgLevel; 522 } 523 if (AcpiGbl_TraceDbgLayer) 524 { 525 AcpiDbgLayer = AcpiGbl_TraceDbgLayer; 526 } 527 } 528 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 529 530 Exit: 531 if (Enabled) 532 { 533 ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, TRUE, 534 ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); 535 } 536 if (Pathname) 537 { 538 ACPI_FREE (Pathname); 539 } 540 } 541 542 543 /******************************************************************************* 544 * 545 * FUNCTION: AcpiExStopTraceMethod 546 * 547 * PARAMETERS: MethodNode - Node of the method 548 * ObjDesc - The method object 549 * WalkState - current state, NULL if not yet executing 550 * a method. 551 * 552 * RETURN: None 553 * 554 * DESCRIPTION: Stop control method execution trace 555 * 556 ******************************************************************************/ 557 558 void 559 AcpiExStopTraceMethod ( 560 ACPI_NAMESPACE_NODE *MethodNode, 561 ACPI_OPERAND_OBJECT *ObjDesc, 562 ACPI_WALK_STATE *WalkState) 563 { 564 ACPI_STATUS Status; 565 char *Pathname = NULL; 566 BOOLEAN Enabled; 567 568 569 ACPI_FUNCTION_NAME (ExStopTraceMethod); 570 571 572 if (MethodNode) 573 { 574 Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); 575 } 576 577 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 578 if (ACPI_FAILURE (Status)) 579 { 580 goto ExitPath; 581 } 582 583 Enabled = AcpiExInterpreterTraceEnabled (NULL); 584 585 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 586 587 if (Enabled) 588 { 589 ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE, 590 ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); 591 } 592 593 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 594 if (ACPI_FAILURE (Status)) 595 { 596 goto ExitPath; 597 } 598 599 /* Check whether the tracer should be stopped */ 600 601 if (AcpiGbl_TraceMethodObject == ObjDesc) 602 { 603 /* Disable further tracing if type is one-shot */ 604 605 if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) 606 { 607 AcpiGbl_TraceMethodName = NULL; 608 } 609 610 AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; 611 AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; 612 AcpiGbl_TraceMethodObject = NULL; 613 } 614 615 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 616 617 ExitPath: 618 if (Pathname) 619 { 620 ACPI_FREE (Pathname); 621 } 622 } 623 624 625 /******************************************************************************* 626 * 627 * FUNCTION: AcpiExStartTraceOpcode 628 * 629 * PARAMETERS: Op - The parser opcode object 630 * WalkState - current state, NULL if not yet executing 631 * a method. 632 * 633 * RETURN: None 634 * 635 * DESCRIPTION: Start opcode execution trace 636 * 637 ******************************************************************************/ 638 639 void 640 AcpiExStartTraceOpcode ( 641 ACPI_PARSE_OBJECT *Op, 642 ACPI_WALK_STATE *WalkState) 643 { 644 645 ACPI_FUNCTION_NAME (ExStartTraceOpcode); 646 647 648 if (AcpiExInterpreterTraceEnabled (NULL) && 649 (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) 650 { 651 ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, TRUE, 652 Op->Common.Aml, Op->Common.AmlOpName); 653 } 654 } 655 656 657 /******************************************************************************* 658 * 659 * FUNCTION: AcpiExStopTraceOpcode 660 * 661 * PARAMETERS: Op - The parser opcode object 662 * WalkState - current state, NULL if not yet executing 663 * a method. 664 * 665 * RETURN: None 666 * 667 * DESCRIPTION: Stop opcode execution trace 668 * 669 ******************************************************************************/ 670 671 void 672 AcpiExStopTraceOpcode ( 673 ACPI_PARSE_OBJECT *Op, 674 ACPI_WALK_STATE *WalkState) 675 { 676 677 ACPI_FUNCTION_NAME (ExStopTraceOpcode); 678 679 680 if (AcpiExInterpreterTraceEnabled (NULL) && 681 (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) 682 { 683 ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, FALSE, 684 Op->Common.Aml, Op->Common.AmlOpName); 685 } 686 } 687