1 /******************************************************************************* 2 * 3 * Module Name: dbcmds - Miscellaneous debug commands and output routines 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 "acevents.h" 47 #include "acdebug.h" 48 #include "acnamesp.h" 49 #include "acresrc.h" 50 #include "actables.h" 51 52 #ifdef ACPI_DEBUGGER 53 54 #define _COMPONENT ACPI_CA_DEBUGGER 55 ACPI_MODULE_NAME ("dbcmds") 56 57 58 /* Local prototypes */ 59 60 static void 61 AcpiDmCompareAmlResources ( 62 UINT8 *Aml1Buffer, 63 ACPI_RSDESC_SIZE Aml1BufferLength, 64 UINT8 *Aml2Buffer, 65 ACPI_RSDESC_SIZE Aml2BufferLength); 66 67 static ACPI_STATUS 68 AcpiDmTestResourceConversion ( 69 ACPI_NAMESPACE_NODE *Node, 70 char *Name); 71 72 static ACPI_STATUS 73 AcpiDbResourceCallback ( 74 ACPI_RESOURCE *Resource, 75 void *Context); 76 77 static ACPI_STATUS 78 AcpiDbDeviceResources ( 79 ACPI_HANDLE ObjHandle, 80 UINT32 NestingLevel, 81 void *Context, 82 void **ReturnValue); 83 84 static void 85 AcpiDbDoOneSleepState ( 86 UINT8 SleepState); 87 88 89 static char *AcpiDbTraceMethodName = NULL; 90 91 /******************************************************************************* 92 * 93 * FUNCTION: AcpiDbConvertToNode 94 * 95 * PARAMETERS: InString - String to convert 96 * 97 * RETURN: Pointer to a NS node 98 * 99 * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or 100 * alphanumeric strings. 101 * 102 ******************************************************************************/ 103 104 ACPI_NAMESPACE_NODE * 105 AcpiDbConvertToNode ( 106 char *InString) 107 { 108 ACPI_NAMESPACE_NODE *Node; 109 ACPI_SIZE Address; 110 111 112 if ((*InString >= 0x30) && (*InString <= 0x39)) 113 { 114 /* Numeric argument, convert */ 115 116 Address = strtoul (InString, NULL, 16); 117 Node = ACPI_TO_POINTER (Address); 118 if (!AcpiOsReadable (Node, sizeof (ACPI_NAMESPACE_NODE))) 119 { 120 AcpiOsPrintf ("Address %p is invalid", 121 Node); 122 return (NULL); 123 } 124 125 /* Make sure pointer is valid NS node */ 126 127 if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) 128 { 129 AcpiOsPrintf ("Address %p is not a valid namespace node [%s]\n", 130 Node, AcpiUtGetDescriptorName (Node)); 131 return (NULL); 132 } 133 } 134 else 135 { 136 /* 137 * Alpha argument: The parameter is a name string that must be 138 * resolved to a Namespace object. 139 */ 140 Node = AcpiDbLocalNsLookup (InString); 141 if (!Node) 142 { 143 AcpiOsPrintf ("Could not find [%s] in namespace, defaulting to root node\n", 144 InString); 145 Node = AcpiGbl_RootNode; 146 } 147 } 148 149 return (Node); 150 } 151 152 153 /******************************************************************************* 154 * 155 * FUNCTION: AcpiDbSleep 156 * 157 * PARAMETERS: ObjectArg - Desired sleep state (0-5). NULL means 158 * invoke all possible sleep states. 159 * 160 * RETURN: Status 161 * 162 * DESCRIPTION: Simulate sleep/wake sequences 163 * 164 ******************************************************************************/ 165 166 ACPI_STATUS 167 AcpiDbSleep ( 168 char *ObjectArg) 169 { 170 UINT8 SleepState; 171 UINT32 i; 172 173 174 ACPI_FUNCTION_TRACE (AcpiDbSleep); 175 176 177 /* Null input (no arguments) means to invoke all sleep states */ 178 179 if (!ObjectArg) 180 { 181 AcpiOsPrintf ("Invoking all possible sleep states, 0-%d\n", 182 ACPI_S_STATES_MAX); 183 184 for (i = 0; i <= ACPI_S_STATES_MAX; i++) 185 { 186 AcpiDbDoOneSleepState ((UINT8) i); 187 } 188 189 return_ACPI_STATUS (AE_OK); 190 } 191 192 /* Convert argument to binary and invoke the sleep state */ 193 194 SleepState = (UINT8) strtoul (ObjectArg, NULL, 0); 195 AcpiDbDoOneSleepState (SleepState); 196 return_ACPI_STATUS (AE_OK); 197 } 198 199 200 /******************************************************************************* 201 * 202 * FUNCTION: AcpiDbDoOneSleepState 203 * 204 * PARAMETERS: SleepState - Desired sleep state (0-5) 205 * 206 * RETURN: Status 207 * 208 * DESCRIPTION: Simulate a sleep/wake sequence 209 * 210 ******************************************************************************/ 211 212 static void 213 AcpiDbDoOneSleepState ( 214 UINT8 SleepState) 215 { 216 ACPI_STATUS Status; 217 UINT8 SleepTypeA; 218 UINT8 SleepTypeB; 219 220 221 /* Validate parameter */ 222 223 if (SleepState > ACPI_S_STATES_MAX) 224 { 225 AcpiOsPrintf ("Sleep state %d out of range (%d max)\n", 226 SleepState, ACPI_S_STATES_MAX); 227 return; 228 } 229 230 AcpiOsPrintf ("\n---- Invoking sleep state S%d (%s):\n", 231 SleepState, AcpiGbl_SleepStateNames[SleepState]); 232 233 /* Get the values for the sleep type registers (for display only) */ 234 235 Status = AcpiGetSleepTypeData (SleepState, &SleepTypeA, &SleepTypeB); 236 if (ACPI_FAILURE (Status)) 237 { 238 AcpiOsPrintf ("Could not evaluate [%s] method, %s\n", 239 AcpiGbl_SleepStateNames[SleepState], 240 AcpiFormatException (Status)); 241 return; 242 } 243 244 AcpiOsPrintf ( 245 "Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n", 246 SleepState, SleepTypeA, SleepTypeB); 247 248 /* Invoke the various sleep/wake interfaces */ 249 250 AcpiOsPrintf ("**** Sleep: Prepare to sleep (S%d) ****\n", 251 SleepState); 252 Status = AcpiEnterSleepStatePrep (SleepState); 253 if (ACPI_FAILURE (Status)) 254 { 255 goto ErrorExit; 256 } 257 258 AcpiOsPrintf ("**** Sleep: Going to sleep (S%d) ****\n", 259 SleepState); 260 Status = AcpiEnterSleepState (SleepState); 261 if (ACPI_FAILURE (Status)) 262 { 263 goto ErrorExit; 264 } 265 266 AcpiOsPrintf ("**** Wake: Prepare to return from sleep (S%d) ****\n", 267 SleepState); 268 Status = AcpiLeaveSleepStatePrep (SleepState); 269 if (ACPI_FAILURE (Status)) 270 { 271 goto ErrorExit; 272 } 273 274 AcpiOsPrintf ("**** Wake: Return from sleep (S%d) ****\n", 275 SleepState); 276 Status = AcpiLeaveSleepState (SleepState); 277 if (ACPI_FAILURE (Status)) 278 { 279 goto ErrorExit; 280 } 281 282 return; 283 284 285 ErrorExit: 286 ACPI_EXCEPTION ((AE_INFO, Status, "During invocation of sleep state S%d", 287 SleepState)); 288 } 289 290 291 /******************************************************************************* 292 * 293 * FUNCTION: AcpiDbDisplayLocks 294 * 295 * PARAMETERS: None 296 * 297 * RETURN: None 298 * 299 * DESCRIPTION: Display information about internal mutexes. 300 * 301 ******************************************************************************/ 302 303 void 304 AcpiDbDisplayLocks ( 305 void) 306 { 307 UINT32 i; 308 309 310 for (i = 0; i < ACPI_MAX_MUTEX; i++) 311 { 312 AcpiOsPrintf ("%26s : %s\n", AcpiUtGetMutexName (i), 313 AcpiGbl_MutexInfo[i].ThreadId == ACPI_MUTEX_NOT_ACQUIRED 314 ? "Locked" : "Unlocked"); 315 } 316 } 317 318 319 /******************************************************************************* 320 * 321 * FUNCTION: AcpiDbDisplayTableInfo 322 * 323 * PARAMETERS: TableArg - Name of table to be displayed 324 * 325 * RETURN: None 326 * 327 * DESCRIPTION: Display information about loaded tables. Current 328 * implementation displays all loaded tables. 329 * 330 ******************************************************************************/ 331 332 void 333 AcpiDbDisplayTableInfo ( 334 char *TableArg) 335 { 336 UINT32 i; 337 ACPI_TABLE_DESC *TableDesc; 338 ACPI_STATUS Status; 339 340 341 /* Header */ 342 343 AcpiOsPrintf ("Idx ID Status Type TableHeader (Sig, Address, Length)\n"); 344 345 /* Walk the entire root table list */ 346 347 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 348 { 349 TableDesc = &AcpiGbl_RootTableList.Tables[i]; 350 351 /* Index and Table ID */ 352 353 AcpiOsPrintf ("%3u %.2u ", i, TableDesc->OwnerId); 354 355 /* Decode the table flags */ 356 357 if (!(TableDesc->Flags & ACPI_TABLE_IS_LOADED)) 358 { 359 AcpiOsPrintf ("NotLoaded "); 360 } 361 else 362 { 363 AcpiOsPrintf (" Loaded "); 364 } 365 366 switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) 367 { 368 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: 369 370 AcpiOsPrintf ("External/virtual "); 371 break; 372 373 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: 374 375 AcpiOsPrintf ("Internal/physical "); 376 break; 377 378 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: 379 380 AcpiOsPrintf ("Internal/virtual "); 381 break; 382 383 default: 384 385 AcpiOsPrintf ("INVALID TYPE "); 386 break; 387 } 388 389 /* Make sure that the table is mapped */ 390 391 Status = AcpiTbValidateTable (TableDesc); 392 if (ACPI_FAILURE (Status)) 393 { 394 return; 395 } 396 397 /* Dump the table header */ 398 399 if (TableDesc->Pointer) 400 { 401 AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer); 402 } 403 else 404 { 405 /* If the pointer is null, the table has been unloaded */ 406 407 ACPI_INFO ((AE_INFO, "%4.4s - Table has been unloaded", 408 TableDesc->Signature.Ascii)); 409 } 410 } 411 } 412 413 414 /******************************************************************************* 415 * 416 * FUNCTION: AcpiDbUnloadAcpiTable 417 * 418 * PARAMETERS: ObjectName - Namespace pathname for an object that 419 * is owned by the table to be unloaded 420 * 421 * RETURN: None 422 * 423 * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned 424 * by the table. 425 * 426 ******************************************************************************/ 427 428 void 429 AcpiDbUnloadAcpiTable ( 430 char *ObjectName) 431 { 432 ACPI_NAMESPACE_NODE *Node; 433 ACPI_STATUS Status; 434 435 436 /* Translate name to an Named object */ 437 438 Node = AcpiDbConvertToNode (ObjectName); 439 if (!Node) 440 { 441 return; 442 } 443 444 Status = AcpiUnloadParentTable (ACPI_CAST_PTR (ACPI_HANDLE, Node)); 445 if (ACPI_SUCCESS (Status)) 446 { 447 AcpiOsPrintf ("Parent of [%s] (%p) unloaded and uninstalled\n", 448 ObjectName, Node); 449 } 450 else 451 { 452 AcpiOsPrintf ("%s, while unloading parent table of [%s]\n", 453 AcpiFormatException (Status), ObjectName); 454 } 455 } 456 457 458 /******************************************************************************* 459 * 460 * FUNCTION: AcpiDbSendNotify 461 * 462 * PARAMETERS: Name - Name of ACPI object where to send notify 463 * Value - Value of the notify to send. 464 * 465 * RETURN: None 466 * 467 * DESCRIPTION: Send an ACPI notification. The value specified is sent to the 468 * named object as an ACPI notify. 469 * 470 ******************************************************************************/ 471 472 void 473 AcpiDbSendNotify ( 474 char *Name, 475 UINT32 Value) 476 { 477 ACPI_NAMESPACE_NODE *Node; 478 ACPI_STATUS Status; 479 480 481 /* Translate name to an Named object */ 482 483 Node = AcpiDbConvertToNode (Name); 484 if (!Node) 485 { 486 return; 487 } 488 489 /* Dispatch the notify if legal */ 490 491 if (AcpiEvIsNotifyObject (Node)) 492 { 493 Status = AcpiEvQueueNotifyRequest (Node, Value); 494 if (ACPI_FAILURE (Status)) 495 { 496 AcpiOsPrintf ("Could not queue notify\n"); 497 } 498 } 499 else 500 { 501 AcpiOsPrintf ( 502 "Named object [%4.4s] Type %s, must be Device/Thermal/Processor type\n", 503 AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type)); 504 } 505 } 506 507 508 /******************************************************************************* 509 * 510 * FUNCTION: AcpiDbDisplayInterfaces 511 * 512 * PARAMETERS: ActionArg - Null, "install", or "remove" 513 * InterfaceNameArg - Name for install/remove options 514 * 515 * RETURN: None 516 * 517 * DESCRIPTION: Display or modify the global _OSI interface list 518 * 519 ******************************************************************************/ 520 521 void 522 AcpiDbDisplayInterfaces ( 523 char *ActionArg, 524 char *InterfaceNameArg) 525 { 526 ACPI_INTERFACE_INFO *NextInterface; 527 char *SubString; 528 ACPI_STATUS Status; 529 530 531 /* If no arguments, just display current interface list */ 532 533 if (!ActionArg) 534 { 535 (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, 536 ACPI_WAIT_FOREVER); 537 538 NextInterface = AcpiGbl_SupportedInterfaces; 539 while (NextInterface) 540 { 541 if (!(NextInterface->Flags & ACPI_OSI_INVALID)) 542 { 543 AcpiOsPrintf ("%s\n", NextInterface->Name); 544 } 545 NextInterface = NextInterface->Next; 546 } 547 548 AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 549 return; 550 } 551 552 /* If ActionArg exists, so must InterfaceNameArg */ 553 554 if (!InterfaceNameArg) 555 { 556 AcpiOsPrintf ("Missing Interface Name argument\n"); 557 return; 558 } 559 560 /* Uppercase the action for match below */ 561 562 AcpiUtStrupr (ActionArg); 563 564 /* Install - install an interface */ 565 566 SubString = strstr ("INSTALL", ActionArg); 567 if (SubString) 568 { 569 Status = AcpiInstallInterface (InterfaceNameArg); 570 if (ACPI_FAILURE (Status)) 571 { 572 AcpiOsPrintf ("%s, while installing \"%s\"\n", 573 AcpiFormatException (Status), InterfaceNameArg); 574 } 575 return; 576 } 577 578 /* Remove - remove an interface */ 579 580 SubString = strstr ("REMOVE", ActionArg); 581 if (SubString) 582 { 583 Status = AcpiRemoveInterface (InterfaceNameArg); 584 if (ACPI_FAILURE (Status)) 585 { 586 AcpiOsPrintf ("%s, while removing \"%s\"\n", 587 AcpiFormatException (Status), InterfaceNameArg); 588 } 589 return; 590 } 591 592 /* Invalid ActionArg */ 593 594 AcpiOsPrintf ("Invalid action argument: %s\n", ActionArg); 595 return; 596 } 597 598 599 /******************************************************************************* 600 * 601 * FUNCTION: AcpiDbDisplayTemplate 602 * 603 * PARAMETERS: BufferArg - Buffer name or address 604 * 605 * RETURN: None 606 * 607 * DESCRIPTION: Dump a buffer that contains a resource template 608 * 609 ******************************************************************************/ 610 611 void 612 AcpiDbDisplayTemplate ( 613 char *BufferArg) 614 { 615 ACPI_NAMESPACE_NODE *Node; 616 ACPI_STATUS Status; 617 ACPI_BUFFER ReturnBuffer; 618 619 620 /* Translate BufferArg to an Named object */ 621 622 Node = AcpiDbConvertToNode (BufferArg); 623 if (!Node || (Node == AcpiGbl_RootNode)) 624 { 625 AcpiOsPrintf ("Invalid argument: %s\n", BufferArg); 626 return; 627 } 628 629 /* We must have a buffer object */ 630 631 if (Node->Type != ACPI_TYPE_BUFFER) 632 { 633 AcpiOsPrintf ("Not a Buffer object, cannot be a template: %s\n", 634 BufferArg); 635 return; 636 } 637 638 ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE; 639 ReturnBuffer.Pointer = AcpiGbl_DbBuffer; 640 641 /* Attempt to convert the raw buffer to a resource list */ 642 643 Status = AcpiRsCreateResourceList (Node->Object, &ReturnBuffer); 644 645 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 646 AcpiDbgLevel |= ACPI_LV_RESOURCES; 647 648 if (ACPI_FAILURE (Status)) 649 { 650 AcpiOsPrintf ("Could not convert Buffer to a resource list: %s, %s\n", 651 BufferArg, AcpiFormatException (Status)); 652 goto DumpBuffer; 653 } 654 655 /* Now we can dump the resource list */ 656 657 AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, 658 ReturnBuffer.Pointer)); 659 660 DumpBuffer: 661 AcpiOsPrintf ("\nRaw data buffer:\n"); 662 AcpiUtDebugDumpBuffer ((UINT8 *) Node->Object->Buffer.Pointer, 663 Node->Object->Buffer.Length, 664 DB_BYTE_DISPLAY, ACPI_UINT32_MAX); 665 666 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 667 return; 668 } 669 670 671 /******************************************************************************* 672 * 673 * FUNCTION: AcpiDmCompareAmlResources 674 * 675 * PARAMETERS: Aml1Buffer - Contains first resource list 676 * Aml1BufferLength - Length of first resource list 677 * Aml2Buffer - Contains second resource list 678 * Aml2BufferLength - Length of second resource list 679 * 680 * RETURN: None 681 * 682 * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in 683 * order to isolate a miscompare to an individual resource) 684 * 685 ******************************************************************************/ 686 687 static void 688 AcpiDmCompareAmlResources ( 689 UINT8 *Aml1Buffer, 690 ACPI_RSDESC_SIZE Aml1BufferLength, 691 UINT8 *Aml2Buffer, 692 ACPI_RSDESC_SIZE Aml2BufferLength) 693 { 694 UINT8 *Aml1; 695 UINT8 *Aml2; 696 UINT8 *Aml1End; 697 UINT8 *Aml2End; 698 ACPI_RSDESC_SIZE Aml1Length; 699 ACPI_RSDESC_SIZE Aml2Length; 700 ACPI_RSDESC_SIZE Offset = 0; 701 UINT8 ResourceType; 702 UINT32 Count = 0; 703 UINT32 i; 704 705 706 /* Compare overall buffer sizes (may be different due to size rounding) */ 707 708 if (Aml1BufferLength != Aml2BufferLength) 709 { 710 AcpiOsPrintf ( 711 "**** Buffer length mismatch in converted AML: Original %X, New %X ****\n", 712 Aml1BufferLength, Aml2BufferLength); 713 } 714 715 Aml1 = Aml1Buffer; 716 Aml2 = Aml2Buffer; 717 Aml1End = Aml1Buffer + Aml1BufferLength; 718 Aml2End = Aml2Buffer + Aml2BufferLength; 719 720 /* Walk the descriptor lists, comparing each descriptor */ 721 722 while ((Aml1 < Aml1End) && (Aml2 < Aml2End)) 723 { 724 /* Get the lengths of each descriptor */ 725 726 Aml1Length = AcpiUtGetDescriptorLength (Aml1); 727 Aml2Length = AcpiUtGetDescriptorLength (Aml2); 728 ResourceType = AcpiUtGetResourceType (Aml1); 729 730 /* Check for descriptor length match */ 731 732 if (Aml1Length != Aml2Length) 733 { 734 AcpiOsPrintf ( 735 "**** Length mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X Len1 %X, Len2 %X ****\n", 736 Count, ResourceType, Offset, Aml1Length, Aml2Length); 737 } 738 739 /* Check for descriptor byte match */ 740 741 else if (memcmp (Aml1, Aml2, Aml1Length)) 742 { 743 AcpiOsPrintf ( 744 "**** Data mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X ****\n", 745 Count, ResourceType, Offset); 746 747 for (i = 0; i < Aml1Length; i++) 748 { 749 if (Aml1[i] != Aml2[i]) 750 { 751 AcpiOsPrintf ( 752 "Mismatch at byte offset %.2X: is %2.2X, should be %2.2X\n", 753 i, Aml2[i], Aml1[i]); 754 } 755 } 756 } 757 758 /* Exit on EndTag descriptor */ 759 760 if (ResourceType == ACPI_RESOURCE_NAME_END_TAG) 761 { 762 return; 763 } 764 765 /* Point to next descriptor in each buffer */ 766 767 Count++; 768 Offset += Aml1Length; 769 Aml1 += Aml1Length; 770 Aml2 += Aml2Length; 771 } 772 } 773 774 775 /******************************************************************************* 776 * 777 * FUNCTION: AcpiDmTestResourceConversion 778 * 779 * PARAMETERS: Node - Parent device node 780 * Name - resource method name (_CRS) 781 * 782 * RETURN: Status 783 * 784 * DESCRIPTION: Compare the original AML with a conversion of the AML to 785 * internal resource list, then back to AML. 786 * 787 ******************************************************************************/ 788 789 static ACPI_STATUS 790 AcpiDmTestResourceConversion ( 791 ACPI_NAMESPACE_NODE *Node, 792 char *Name) 793 { 794 ACPI_STATUS Status; 795 ACPI_BUFFER ReturnBuffer; 796 ACPI_BUFFER ResourceBuffer; 797 ACPI_BUFFER NewAml; 798 ACPI_OBJECT *OriginalAml; 799 800 801 AcpiOsPrintf ("Resource Conversion Comparison:\n"); 802 803 NewAml.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 804 ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 805 ResourceBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 806 807 /* Get the original _CRS AML resource template */ 808 809 Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnBuffer); 810 if (ACPI_FAILURE (Status)) 811 { 812 AcpiOsPrintf ("Could not obtain %s: %s\n", 813 Name, AcpiFormatException (Status)); 814 return (Status); 815 } 816 817 /* Get the AML resource template, converted to internal resource structs */ 818 819 Status = AcpiGetCurrentResources (Node, &ResourceBuffer); 820 if (ACPI_FAILURE (Status)) 821 { 822 AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n", 823 AcpiFormatException (Status)); 824 goto Exit1; 825 } 826 827 /* Convert internal resource list to external AML resource template */ 828 829 Status = AcpiRsCreateAmlResources (&ResourceBuffer, &NewAml); 830 if (ACPI_FAILURE (Status)) 831 { 832 AcpiOsPrintf ("AcpiRsCreateAmlResources failed: %s\n", 833 AcpiFormatException (Status)); 834 goto Exit2; 835 } 836 837 /* Compare original AML to the newly created AML resource list */ 838 839 OriginalAml = ReturnBuffer.Pointer; 840 841 AcpiDmCompareAmlResources (OriginalAml->Buffer.Pointer, 842 (ACPI_RSDESC_SIZE) OriginalAml->Buffer.Length, 843 NewAml.Pointer, (ACPI_RSDESC_SIZE) NewAml.Length); 844 845 /* Cleanup and exit */ 846 847 ACPI_FREE (NewAml.Pointer); 848 Exit2: 849 ACPI_FREE (ResourceBuffer.Pointer); 850 Exit1: 851 ACPI_FREE (ReturnBuffer.Pointer); 852 return (Status); 853 } 854 855 856 /******************************************************************************* 857 * 858 * FUNCTION: AcpiDbResourceCallback 859 * 860 * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK 861 * 862 * RETURN: Status 863 * 864 * DESCRIPTION: Simple callback to exercise AcpiWalkResources and 865 * AcpiWalkResourceBuffer. 866 * 867 ******************************************************************************/ 868 869 static ACPI_STATUS 870 AcpiDbResourceCallback ( 871 ACPI_RESOURCE *Resource, 872 void *Context) 873 { 874 875 return (AE_OK); 876 } 877 878 879 /******************************************************************************* 880 * 881 * FUNCTION: AcpiDbDeviceResources 882 * 883 * PARAMETERS: ACPI_WALK_CALLBACK 884 * 885 * RETURN: Status 886 * 887 * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object. 888 * 889 ******************************************************************************/ 890 891 static ACPI_STATUS 892 AcpiDbDeviceResources ( 893 ACPI_HANDLE ObjHandle, 894 UINT32 NestingLevel, 895 void *Context, 896 void **ReturnValue) 897 { 898 ACPI_NAMESPACE_NODE *Node; 899 ACPI_NAMESPACE_NODE *PrtNode = NULL; 900 ACPI_NAMESPACE_NODE *CrsNode = NULL; 901 ACPI_NAMESPACE_NODE *PrsNode = NULL; 902 ACPI_NAMESPACE_NODE *AeiNode = NULL; 903 char *ParentPath; 904 ACPI_BUFFER ReturnBuffer; 905 ACPI_STATUS Status; 906 907 908 Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); 909 ParentPath = AcpiNsGetExternalPathname (Node); 910 if (!ParentPath) 911 { 912 return (AE_NO_MEMORY); 913 } 914 915 /* Get handles to the resource methods for this device */ 916 917 (void) AcpiGetHandle (Node, METHOD_NAME__PRT, ACPI_CAST_PTR (ACPI_HANDLE, &PrtNode)); 918 (void) AcpiGetHandle (Node, METHOD_NAME__CRS, ACPI_CAST_PTR (ACPI_HANDLE, &CrsNode)); 919 (void) AcpiGetHandle (Node, METHOD_NAME__PRS, ACPI_CAST_PTR (ACPI_HANDLE, &PrsNode)); 920 (void) AcpiGetHandle (Node, METHOD_NAME__AEI, ACPI_CAST_PTR (ACPI_HANDLE, &AeiNode)); 921 if (!PrtNode && !CrsNode && !PrsNode && !AeiNode) 922 { 923 goto Cleanup; /* Nothing to do */ 924 } 925 926 AcpiOsPrintf ("\nDevice: %s\n", ParentPath); 927 928 /* Prepare for a return object of arbitrary size */ 929 930 ReturnBuffer.Pointer = AcpiGbl_DbBuffer; 931 ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE; 932 933 934 /* _PRT */ 935 936 if (PrtNode) 937 { 938 AcpiOsPrintf ("Evaluating _PRT\n"); 939 940 Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnBuffer); 941 if (ACPI_FAILURE (Status)) 942 { 943 AcpiOsPrintf ("Could not evaluate _PRT: %s\n", 944 AcpiFormatException (Status)); 945 goto GetCrs; 946 } 947 948 ReturnBuffer.Pointer = AcpiGbl_DbBuffer; 949 ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE; 950 951 Status = AcpiGetIrqRoutingTable (Node, &ReturnBuffer); 952 if (ACPI_FAILURE (Status)) 953 { 954 AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n", 955 AcpiFormatException (Status)); 956 goto GetCrs; 957 } 958 959 AcpiRsDumpIrqList (ACPI_CAST_PTR (UINT8, AcpiGbl_DbBuffer)); 960 } 961 962 963 /* _CRS */ 964 965 GetCrs: 966 if (CrsNode) 967 { 968 AcpiOsPrintf ("Evaluating _CRS\n"); 969 970 ReturnBuffer.Pointer = AcpiGbl_DbBuffer; 971 ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE; 972 973 Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnBuffer); 974 if (ACPI_FAILURE (Status)) 975 { 976 AcpiOsPrintf ("Could not evaluate _CRS: %s\n", 977 AcpiFormatException (Status)); 978 goto GetPrs; 979 } 980 981 /* This code exercises the AcpiWalkResources interface */ 982 983 Status = AcpiWalkResources (Node, METHOD_NAME__CRS, 984 AcpiDbResourceCallback, NULL); 985 if (ACPI_FAILURE (Status)) 986 { 987 AcpiOsPrintf ("AcpiWalkResources failed: %s\n", 988 AcpiFormatException (Status)); 989 goto GetPrs; 990 } 991 992 /* Get the _CRS resource list (test ALLOCATE buffer) */ 993 994 ReturnBuffer.Pointer = NULL; 995 ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 996 997 Status = AcpiGetCurrentResources (Node, &ReturnBuffer); 998 if (ACPI_FAILURE (Status)) 999 { 1000 AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n", 1001 AcpiFormatException (Status)); 1002 goto GetPrs; 1003 } 1004 1005 /* This code exercises the AcpiWalkResourceBuffer interface */ 1006 1007 Status = AcpiWalkResourceBuffer (&ReturnBuffer, 1008 AcpiDbResourceCallback, NULL); 1009 if (ACPI_FAILURE (Status)) 1010 { 1011 AcpiOsPrintf ("AcpiWalkResourceBuffer failed: %s\n", 1012 AcpiFormatException (Status)); 1013 goto EndCrs; 1014 } 1015 1016 /* Dump the _CRS resource list */ 1017 1018 AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, 1019 ReturnBuffer.Pointer)); 1020 1021 /* 1022 * Perform comparison of original AML to newly created AML. This 1023 * tests both the AML->Resource conversion and the Resource->AML 1024 * conversion. 1025 */ 1026 (void) AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS); 1027 1028 /* Execute _SRS with the resource list */ 1029 1030 AcpiOsPrintf ("Evaluating _SRS\n"); 1031 1032 Status = AcpiSetCurrentResources (Node, &ReturnBuffer); 1033 if (ACPI_FAILURE (Status)) 1034 { 1035 AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n", 1036 AcpiFormatException (Status)); 1037 goto EndCrs; 1038 } 1039 1040 EndCrs: 1041 ACPI_FREE (ReturnBuffer.Pointer); 1042 } 1043 1044 1045 /* _PRS */ 1046 1047 GetPrs: 1048 if (PrsNode) 1049 { 1050 AcpiOsPrintf ("Evaluating _PRS\n"); 1051 1052 ReturnBuffer.Pointer = AcpiGbl_DbBuffer; 1053 ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE; 1054 1055 Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnBuffer); 1056 if (ACPI_FAILURE (Status)) 1057 { 1058 AcpiOsPrintf ("Could not evaluate _PRS: %s\n", 1059 AcpiFormatException (Status)); 1060 goto GetAei; 1061 } 1062 1063 ReturnBuffer.Pointer = AcpiGbl_DbBuffer; 1064 ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE; 1065 1066 Status = AcpiGetPossibleResources (Node, &ReturnBuffer); 1067 if (ACPI_FAILURE (Status)) 1068 { 1069 AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n", 1070 AcpiFormatException (Status)); 1071 goto GetAei; 1072 } 1073 1074 AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer)); 1075 } 1076 1077 1078 /* _AEI */ 1079 1080 GetAei: 1081 if (AeiNode) 1082 { 1083 AcpiOsPrintf ("Evaluating _AEI\n"); 1084 1085 ReturnBuffer.Pointer = AcpiGbl_DbBuffer; 1086 ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE; 1087 1088 Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnBuffer); 1089 if (ACPI_FAILURE (Status)) 1090 { 1091 AcpiOsPrintf ("Could not evaluate _AEI: %s\n", 1092 AcpiFormatException (Status)); 1093 goto Cleanup; 1094 } 1095 1096 ReturnBuffer.Pointer = AcpiGbl_DbBuffer; 1097 ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE; 1098 1099 Status = AcpiGetEventResources (Node, &ReturnBuffer); 1100 if (ACPI_FAILURE (Status)) 1101 { 1102 AcpiOsPrintf ("AcpiGetEventResources failed: %s\n", 1103 AcpiFormatException (Status)); 1104 goto Cleanup; 1105 } 1106 1107 AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer)); 1108 } 1109 1110 1111 Cleanup: 1112 ACPI_FREE (ParentPath); 1113 return (AE_OK); 1114 } 1115 1116 1117 /******************************************************************************* 1118 * 1119 * FUNCTION: AcpiDbDisplayResources 1120 * 1121 * PARAMETERS: ObjectArg - String object name or object pointer. 1122 * NULL or "*" means "display resources for 1123 * all devices" 1124 * 1125 * RETURN: None 1126 * 1127 * DESCRIPTION: Display the resource objects associated with a device. 1128 * 1129 ******************************************************************************/ 1130 1131 void 1132 AcpiDbDisplayResources ( 1133 char *ObjectArg) 1134 { 1135 ACPI_NAMESPACE_NODE *Node; 1136 1137 1138 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 1139 AcpiDbgLevel |= ACPI_LV_RESOURCES; 1140 1141 /* Asterisk means "display resources for all devices" */ 1142 1143 if (!ObjectArg || (!strcmp (ObjectArg, "*"))) 1144 { 1145 (void) AcpiWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 1146 ACPI_UINT32_MAX, AcpiDbDeviceResources, NULL, NULL, NULL); 1147 } 1148 else 1149 { 1150 /* Convert string to object pointer */ 1151 1152 Node = AcpiDbConvertToNode (ObjectArg); 1153 if (Node) 1154 { 1155 if (Node->Type != ACPI_TYPE_DEVICE) 1156 { 1157 AcpiOsPrintf ("%4.4s: Name is not a device object (%s)\n", 1158 Node->Name.Ascii, AcpiUtGetTypeName (Node->Type)); 1159 } 1160 else 1161 { 1162 (void) AcpiDbDeviceResources (Node, 0, NULL, NULL); 1163 } 1164 } 1165 } 1166 1167 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 1168 } 1169 1170 1171 #if (!ACPI_REDUCED_HARDWARE) 1172 /******************************************************************************* 1173 * 1174 * FUNCTION: AcpiDbGenerateGpe 1175 * 1176 * PARAMETERS: GpeArg - Raw GPE number, ascii string 1177 * BlockArg - GPE block number, ascii string 1178 * 0 or 1 for FADT GPE blocks 1179 * 1180 * RETURN: None 1181 * 1182 * DESCRIPTION: Simulate firing of a GPE 1183 * 1184 ******************************************************************************/ 1185 1186 void 1187 AcpiDbGenerateGpe ( 1188 char *GpeArg, 1189 char *BlockArg) 1190 { 1191 UINT32 BlockNumber = 0; 1192 UINT32 GpeNumber; 1193 ACPI_GPE_EVENT_INFO *GpeEventInfo; 1194 1195 1196 GpeNumber = strtoul (GpeArg, NULL, 0); 1197 1198 /* 1199 * If no block arg, or block arg == 0 or 1, use the FADT-defined 1200 * GPE blocks. 1201 */ 1202 if (BlockArg) 1203 { 1204 BlockNumber = strtoul (BlockArg, NULL, 0); 1205 if (BlockNumber == 1) 1206 { 1207 BlockNumber = 0; 1208 } 1209 } 1210 1211 GpeEventInfo = AcpiEvGetGpeEventInfo (ACPI_TO_POINTER (BlockNumber), 1212 GpeNumber); 1213 if (!GpeEventInfo) 1214 { 1215 AcpiOsPrintf ("Invalid GPE\n"); 1216 return; 1217 } 1218 1219 (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber); 1220 } 1221 1222 void 1223 AcpiDbGenerateSci ( 1224 void) 1225 { 1226 AcpiEvSciDispatch (); 1227 } 1228 1229 #endif /* !ACPI_REDUCED_HARDWARE */ 1230 1231 1232 /******************************************************************************* 1233 * 1234 * FUNCTION: AcpiDbTrace 1235 * 1236 * PARAMETERS: EnableArg - ENABLE/AML to enable tracer 1237 * DISABLE to disable tracer 1238 * MethodArg - Method to trace 1239 * OnceArg - Whether trace once 1240 * 1241 * RETURN: None 1242 * 1243 * DESCRIPTION: Control method tracing facility 1244 * 1245 ******************************************************************************/ 1246 1247 void 1248 AcpiDbTrace ( 1249 char *EnableArg, 1250 char *MethodArg, 1251 char *OnceArg) 1252 { 1253 UINT32 DebugLevel = 0; 1254 UINT32 DebugLayer = 0; 1255 UINT32 Flags = 0; 1256 1257 1258 if (EnableArg) 1259 { 1260 AcpiUtStrupr (EnableArg); 1261 } 1262 if (OnceArg) 1263 { 1264 AcpiUtStrupr (OnceArg); 1265 } 1266 if (MethodArg) 1267 { 1268 if (AcpiDbTraceMethodName) 1269 { 1270 ACPI_FREE (AcpiDbTraceMethodName); 1271 AcpiDbTraceMethodName = NULL; 1272 } 1273 AcpiDbTraceMethodName = ACPI_ALLOCATE (strlen (MethodArg) + 1); 1274 if (!AcpiDbTraceMethodName) 1275 { 1276 AcpiOsPrintf ("Failed to allocate method name (%s)\n", MethodArg); 1277 return; 1278 } 1279 strcpy (AcpiDbTraceMethodName, MethodArg); 1280 } 1281 if (!strcmp (EnableArg, "ENABLE") || 1282 !strcmp (EnableArg, "METHOD") || 1283 !strcmp (EnableArg, "OPCODE")) 1284 { 1285 if (!strcmp (EnableArg, "ENABLE")) 1286 { 1287 /* Inherit current console settings */ 1288 1289 DebugLevel = AcpiGbl_DbConsoleDebugLevel; 1290 DebugLayer = AcpiDbgLayer; 1291 } 1292 else 1293 { 1294 /* Restrict console output to trace points only */ 1295 1296 DebugLevel = ACPI_LV_TRACE_POINT; 1297 DebugLayer = ACPI_EXECUTER; 1298 } 1299 1300 Flags = ACPI_TRACE_ENABLED; 1301 if (!strcmp (EnableArg, "OPCODE")) 1302 { 1303 Flags |= ACPI_TRACE_OPCODE; 1304 } 1305 if (OnceArg && !strcmp (OnceArg, "ONCE")) 1306 { 1307 Flags |= ACPI_TRACE_ONESHOT; 1308 } 1309 } 1310 1311 (void) AcpiDebugTrace (AcpiDbTraceMethodName, 1312 DebugLevel, DebugLayer, Flags); 1313 } 1314 1315 #endif /* ACPI_DEBUGGER */ 1316