1 /******************************************************************************* 2 * 3 * Module Name: dbcmds - Miscellaneous debug commands and output routines 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 #ifndef _KERNEL 52 #include "limits.h" 53 #endif 54 55 #define _COMPONENT ACPI_CA_DEBUGGER 56 ACPI_MODULE_NAME ("dbcmds") 57 58 59 /* Local prototypes */ 60 61 static void 62 AcpiDmCompareAmlResources ( 63 UINT8 *Aml1Buffer, 64 ACPI_RSDESC_SIZE Aml1BufferLength, 65 UINT8 *Aml2Buffer, 66 ACPI_RSDESC_SIZE Aml2BufferLength); 67 68 static ACPI_STATUS 69 AcpiDmTestResourceConversion ( 70 ACPI_NAMESPACE_NODE *Node, 71 char *Name); 72 73 static ACPI_STATUS 74 AcpiDbResourceCallback ( 75 ACPI_RESOURCE *Resource, 76 void *Context); 77 78 static ACPI_STATUS 79 AcpiDbDeviceResources ( 80 ACPI_HANDLE ObjHandle, 81 UINT32 NestingLevel, 82 void *Context, 83 void **ReturnValue); 84 85 static void 86 AcpiDbDoOneSleepState ( 87 UINT8 SleepState); 88 89 90 static char *AcpiDbTraceMethodName = NULL; 91 92 93 /******************************************************************************* 94 * 95 * FUNCTION: AcpiDbConvertToNode 96 * 97 * PARAMETERS: InString - String to convert 98 * 99 * RETURN: Pointer to a NS node 100 * 101 * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or 102 * alphanumeric strings. 103 * 104 ******************************************************************************/ 105 106 ACPI_NAMESPACE_NODE * 107 AcpiDbConvertToNode ( 108 char *InString) 109 { 110 ACPI_NAMESPACE_NODE *Node; 111 ACPI_SIZE Address; 112 113 114 if ((*InString >= 0x30) && (*InString <= 0x39)) 115 { 116 /* Numeric argument, convert */ 117 118 Address = strtoul (InString, NULL, 16); 119 Node = ACPI_TO_POINTER (Address); 120 if (!AcpiOsReadable (Node, sizeof (ACPI_NAMESPACE_NODE))) 121 { 122 AcpiOsPrintf ("Address %p is invalid", 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 (("%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 = AcpiNsGetNormalizedPathname (Node, TRUE); 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, __UNCONST(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 /******************************************************************************* 1189 * 1190 * FUNCTION: AcpiDbGenerateGed 1191 * 1192 * PARAMETERS: GedArg - Raw GED number, ascii string 1193 * 1194 * RETURN: None 1195 * 1196 * DESCRIPTION: Simulate firing of a GED 1197 * 1198 ******************************************************************************/ 1199 1200 void 1201 AcpiDbGenerateInterrupt ( 1202 char *GsivArg) 1203 { 1204 UINT32 GsivNumber; 1205 ACPI_GED_HANDLER_INFO *GedInfo = AcpiGbl_GedHandlerList; 1206 1207 if (!GedInfo) { 1208 AcpiOsPrintf ("No GED handling present\n"); 1209 } 1210 1211 GsivNumber = strtoul (GsivArg, NULL, 0); 1212 1213 while (GedInfo) { 1214 1215 if (GedInfo->IntId == GsivNumber) { 1216 ACPI_OBJECT_LIST ArgList; 1217 ACPI_OBJECT Arg0; 1218 ACPI_HANDLE EvtHandle = GedInfo->EvtMethod; 1219 ACPI_STATUS Status; 1220 1221 AcpiOsPrintf ("Evaluate GED _EVT (GSIV=%d)\n", GsivNumber); 1222 1223 if (!EvtHandle) { 1224 AcpiOsPrintf ("Undefined _EVT method\n"); 1225 return; 1226 } 1227 1228 Arg0.Integer.Type = ACPI_TYPE_INTEGER; 1229 Arg0.Integer.Value = GsivNumber; 1230 1231 ArgList.Count = 1; 1232 ArgList.Pointer = &Arg0; 1233 1234 Status = AcpiEvaluateObject (EvtHandle, NULL, &ArgList, NULL); 1235 if (ACPI_FAILURE (Status)) 1236 { 1237 AcpiOsPrintf ("Could not evaluate _EVT\n"); 1238 return; 1239 } 1240 1241 } 1242 GedInfo = GedInfo->Next; 1243 } 1244 } 1245 1246 #if (!ACPI_REDUCED_HARDWARE) 1247 /******************************************************************************* 1248 * 1249 * FUNCTION: AcpiDbGenerateGpe 1250 * 1251 * PARAMETERS: GpeArg - Raw GPE number, ascii string 1252 * BlockArg - GPE block number, ascii string 1253 * 0 or 1 for FADT GPE blocks 1254 * 1255 * RETURN: None 1256 * 1257 * DESCRIPTION: Simulate firing of a GPE 1258 * 1259 ******************************************************************************/ 1260 1261 void 1262 AcpiDbGenerateGpe ( 1263 char *GpeArg, 1264 char *BlockArg) 1265 { 1266 UINT32 BlockNumber = 0; 1267 UINT32 GpeNumber; 1268 ACPI_GPE_EVENT_INFO *GpeEventInfo; 1269 1270 1271 GpeNumber = strtoul (GpeArg, NULL, 0); 1272 1273 /* 1274 * If no block arg, or block arg == 0 or 1, use the FADT-defined 1275 * GPE blocks. 1276 */ 1277 if (BlockArg) 1278 { 1279 BlockNumber = strtoul (BlockArg, NULL, 0); 1280 if (BlockNumber == 1) 1281 { 1282 BlockNumber = 0; 1283 } 1284 } 1285 1286 GpeEventInfo = AcpiEvGetGpeEventInfo ( 1287 ACPI_TO_POINTER (BlockNumber), GpeNumber); 1288 if (!GpeEventInfo) 1289 { 1290 AcpiOsPrintf ("Invalid GPE\n"); 1291 return; 1292 } 1293 1294 (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber); 1295 } 1296 1297 1298 /******************************************************************************* 1299 * 1300 * FUNCTION: AcpiDbGenerateSci 1301 * 1302 * PARAMETERS: None 1303 * 1304 * RETURN: None 1305 * 1306 * DESCRIPTION: Simulate an SCI -- just call the SCI dispatch. 1307 * 1308 ******************************************************************************/ 1309 1310 void 1311 AcpiDbGenerateSci ( 1312 void) 1313 { 1314 AcpiEvSciDispatch (); 1315 } 1316 1317 #endif /* !ACPI_REDUCED_HARDWARE */ 1318 1319 1320 /******************************************************************************* 1321 * 1322 * FUNCTION: AcpiDbTrace 1323 * 1324 * PARAMETERS: EnableArg - ENABLE/AML to enable tracer 1325 * DISABLE to disable tracer 1326 * MethodArg - Method to trace 1327 * OnceArg - Whether trace once 1328 * 1329 * RETURN: None 1330 * 1331 * DESCRIPTION: Control method tracing facility 1332 * 1333 ******************************************************************************/ 1334 1335 void 1336 AcpiDbTrace ( 1337 char *EnableArg, 1338 char *MethodArg, 1339 char *OnceArg) 1340 { 1341 UINT32 DebugLevel = 0; 1342 UINT32 DebugLayer = 0; 1343 UINT32 Flags = 0; 1344 1345 1346 AcpiUtStrupr (EnableArg); 1347 AcpiUtStrupr (OnceArg); 1348 1349 if (MethodArg) 1350 { 1351 if (AcpiDbTraceMethodName) 1352 { 1353 ACPI_FREE (AcpiDbTraceMethodName); 1354 AcpiDbTraceMethodName = NULL; 1355 } 1356 1357 AcpiDbTraceMethodName = ACPI_ALLOCATE (strlen (MethodArg) + 1); 1358 if (!AcpiDbTraceMethodName) 1359 { 1360 AcpiOsPrintf ("Failed to allocate method name (%s)\n", 1361 MethodArg); 1362 return; 1363 } 1364 1365 strcpy (AcpiDbTraceMethodName, MethodArg); 1366 } 1367 1368 if (!strcmp (EnableArg, "ENABLE") || 1369 !strcmp (EnableArg, "METHOD") || 1370 !strcmp (EnableArg, "OPCODE")) 1371 { 1372 if (!strcmp (EnableArg, "ENABLE")) 1373 { 1374 /* Inherit current console settings */ 1375 1376 DebugLevel = AcpiGbl_DbConsoleDebugLevel; 1377 DebugLayer = AcpiDbgLayer; 1378 } 1379 else 1380 { 1381 /* Restrict console output to trace points only */ 1382 1383 DebugLevel = ACPI_LV_TRACE_POINT; 1384 DebugLayer = ACPI_EXECUTER; 1385 } 1386 1387 Flags = ACPI_TRACE_ENABLED; 1388 1389 if (!strcmp (EnableArg, "OPCODE")) 1390 { 1391 Flags |= ACPI_TRACE_OPCODE; 1392 } 1393 1394 if (OnceArg && !strcmp (OnceArg, "ONCE")) 1395 { 1396 Flags |= ACPI_TRACE_ONESHOT; 1397 } 1398 } 1399 1400 (void) AcpiDebugTrace (AcpiDbTraceMethodName, 1401 DebugLevel, DebugLayer, Flags); 1402 } 1403