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