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