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