dbcmds.c revision 217365
1/******************************************************************************* 2 * 3 * Module Name: dbcmds - debug commands and output routines 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2011, 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 45#include <contrib/dev/acpica/include/acpi.h> 46#include <contrib/dev/acpica/include/accommon.h> 47#include <contrib/dev/acpica/include/acdispat.h> 48#include <contrib/dev/acpica/include/acnamesp.h> 49#include <contrib/dev/acpica/include/acevents.h> 50#include <contrib/dev/acpica/include/acdebug.h> 51#include <contrib/dev/acpica/include/acresrc.h> 52#include <contrib/dev/acpica/include/acdisasm.h> 53#include <contrib/dev/acpica/include/actables.h> 54#include <contrib/dev/acpica/include/acparser.h> 55 56#ifdef ACPI_DEBUGGER 57 58#define _COMPONENT ACPI_CA_DEBUGGER 59 ACPI_MODULE_NAME ("dbcmds") 60 61 62/* Local prototypes */ 63 64static ACPI_STATUS 65AcpiDbIntegrityWalk ( 66 ACPI_HANDLE ObjHandle, 67 UINT32 NestingLevel, 68 void *Context, 69 void **ReturnValue); 70 71static ACPI_STATUS 72AcpiDbWalkAndMatchName ( 73 ACPI_HANDLE ObjHandle, 74 UINT32 NestingLevel, 75 void *Context, 76 void **ReturnValue); 77 78static ACPI_STATUS 79AcpiDbWalkForReferences ( 80 ACPI_HANDLE ObjHandle, 81 UINT32 NestingLevel, 82 void *Context, 83 void **ReturnValue); 84 85static ACPI_STATUS 86AcpiDbWalkForSpecificObjects ( 87 ACPI_HANDLE ObjHandle, 88 UINT32 NestingLevel, 89 void *Context, 90 void **ReturnValue); 91 92static ACPI_NAMESPACE_NODE * 93AcpiDbConvertToNode ( 94 char *InString); 95 96static void 97AcpiDmCompareAmlResources ( 98 UINT8 *Aml1Buffer, 99 ACPI_RSDESC_SIZE Aml1BufferLength, 100 UINT8 *Aml2Buffer, 101 ACPI_RSDESC_SIZE Aml2BufferLength); 102 103static ACPI_STATUS 104AcpiDmTestResourceConversion ( 105 ACPI_NAMESPACE_NODE *Node, 106 char *Name); 107 108 109/* 110 * Arguments for the Objects command 111 * These object types map directly to the ACPI_TYPES 112 */ 113static ARGUMENT_INFO AcpiDbObjectTypes [] = 114{ 115 {"ANY"}, 116 {"INTEGERS"}, 117 {"STRINGS"}, 118 {"BUFFERS"}, 119 {"PACKAGES"}, 120 {"FIELDS"}, 121 {"DEVICES"}, 122 {"EVENTS"}, 123 {"METHODS"}, 124 {"MUTEXES"}, 125 {"REGIONS"}, 126 {"POWERRESOURCES"}, 127 {"PROCESSORS"}, 128 {"THERMALZONES"}, 129 {"BUFFERFIELDS"}, 130 {"DDBHANDLES"}, 131 {"DEBUG"}, 132 {"REGIONFIELDS"}, 133 {"BANKFIELDS"}, 134 {"INDEXFIELDS"}, 135 {"REFERENCES"}, 136 {"ALIAS"}, 137 {NULL} /* Must be null terminated */ 138}; 139 140 141/******************************************************************************* 142 * 143 * FUNCTION: AcpiDbConvertToNode 144 * 145 * PARAMETERS: InString - String to convert 146 * 147 * RETURN: Pointer to a NS node 148 * 149 * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or 150 * alpha strings. 151 * 152 ******************************************************************************/ 153 154static ACPI_NAMESPACE_NODE * 155AcpiDbConvertToNode ( 156 char *InString) 157{ 158 ACPI_NAMESPACE_NODE *Node; 159 160 161 if ((*InString >= 0x30) && (*InString <= 0x39)) 162 { 163 /* Numeric argument, convert */ 164 165 Node = ACPI_TO_POINTER (ACPI_STRTOUL (InString, NULL, 16)); 166 if (!AcpiOsReadable (Node, sizeof (ACPI_NAMESPACE_NODE))) 167 { 168 AcpiOsPrintf ("Address %p is invalid in this address space\n", 169 Node); 170 return (NULL); 171 } 172 173 /* Make sure pointer is valid NS node */ 174 175 if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) 176 { 177 AcpiOsPrintf ("Address %p is not a valid NS node [%s]\n", 178 Node, AcpiUtGetDescriptorName (Node)); 179 return (NULL); 180 } 181 } 182 else 183 { 184 /* Alpha argument */ 185 /* The parameter is a name string that must be resolved to a 186 * Named obj 187 */ 188 Node = AcpiDbLocalNsLookup (InString); 189 if (!Node) 190 { 191 Node = AcpiGbl_RootNode; 192 } 193 } 194 195 return (Node); 196} 197 198 199/******************************************************************************* 200 * 201 * FUNCTION: AcpiDbSleep 202 * 203 * PARAMETERS: ObjectArg - Desired sleep state (0-5) 204 * 205 * RETURN: Status 206 * 207 * DESCRIPTION: Simulate a sleep/wake sequence 208 * 209 ******************************************************************************/ 210 211ACPI_STATUS 212AcpiDbSleep ( 213 char *ObjectArg) 214{ 215 ACPI_STATUS Status; 216 UINT8 SleepState; 217 218 219 SleepState = (UINT8) ACPI_STRTOUL (ObjectArg, NULL, 0); 220 221 AcpiOsPrintf ("**** Prepare to sleep ****\n"); 222 Status = AcpiEnterSleepStatePrep (SleepState); 223 if (ACPI_FAILURE (Status)) 224 { 225 return (Status); 226 } 227 228 AcpiOsPrintf ("**** Going to sleep ****\n"); 229 Status = AcpiEnterSleepState (SleepState); 230 if (ACPI_FAILURE (Status)) 231 { 232 return (Status); 233 } 234 235 AcpiOsPrintf ("**** returning from sleep ****\n"); 236 Status = AcpiLeaveSleepState (SleepState); 237 238 return (Status); 239} 240 241 242/******************************************************************************* 243 * 244 * FUNCTION: AcpiDbWalkForReferences 245 * 246 * PARAMETERS: Callback from WalkNamespace 247 * 248 * RETURN: Status 249 * 250 * DESCRIPTION: Check if this namespace object refers to the target object 251 * that is passed in as the context value. 252 * 253 * Note: Currently doesn't check subobjects within the Node's object 254 * 255 ******************************************************************************/ 256 257static ACPI_STATUS 258AcpiDbWalkForReferences ( 259 ACPI_HANDLE ObjHandle, 260 UINT32 NestingLevel, 261 void *Context, 262 void **ReturnValue) 263{ 264 ACPI_OPERAND_OBJECT *ObjDesc = (ACPI_OPERAND_OBJECT *) Context; 265 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 266 267 268 /* Check for match against the namespace node itself */ 269 270 if (Node == (void *) ObjDesc) 271 { 272 AcpiOsPrintf ("Object is a Node [%4.4s]\n", 273 AcpiUtGetNodeName (Node)); 274 } 275 276 /* Check for match against the object attached to the node */ 277 278 if (AcpiNsGetAttachedObject (Node) == ObjDesc) 279 { 280 AcpiOsPrintf ("Reference at Node->Object %p [%4.4s]\n", 281 Node, AcpiUtGetNodeName (Node)); 282 } 283 284 return (AE_OK); 285} 286 287 288/******************************************************************************* 289 * 290 * FUNCTION: AcpiDbFindReferences 291 * 292 * PARAMETERS: ObjectArg - String with hex value of the object 293 * 294 * RETURN: None 295 * 296 * DESCRIPTION: Search namespace for all references to the input object 297 * 298 ******************************************************************************/ 299 300void 301AcpiDbFindReferences ( 302 char *ObjectArg) 303{ 304 ACPI_OPERAND_OBJECT *ObjDesc; 305 306 307 /* Convert string to object pointer */ 308 309 ObjDesc = ACPI_TO_POINTER (ACPI_STRTOUL (ObjectArg, NULL, 16)); 310 311 /* Search all nodes in namespace */ 312 313 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 314 AcpiDbWalkForReferences, NULL, (void *) ObjDesc, NULL); 315} 316 317 318/******************************************************************************* 319 * 320 * FUNCTION: AcpiDbWalkForPredefinedNames 321 * 322 * PARAMETERS: Callback from WalkNamespace 323 * 324 * RETURN: Status 325 * 326 * DESCRIPTION: Detect and display predefined ACPI names (names that start with 327 * an underscore) 328 * 329 ******************************************************************************/ 330 331static ACPI_STATUS 332AcpiDbWalkForPredefinedNames ( 333 ACPI_HANDLE ObjHandle, 334 UINT32 NestingLevel, 335 void *Context, 336 void **ReturnValue) 337{ 338 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 339 UINT32 *Count = (UINT32 *) Context; 340 const ACPI_PREDEFINED_INFO *Predefined; 341 const ACPI_PREDEFINED_INFO *Package = NULL; 342 char *Pathname; 343 344 345 Predefined = AcpiNsCheckForPredefinedName (Node); 346 if (!Predefined) 347 { 348 return (AE_OK); 349 } 350 351 Pathname = AcpiNsGetExternalPathname (Node); 352 if (!Pathname) 353 { 354 return (AE_OK); 355 } 356 357 /* If method returns a package, the info is in the next table entry */ 358 359 if (Predefined->Info.ExpectedBtypes & ACPI_BTYPE_PACKAGE) 360 { 361 Package = Predefined + 1; 362 } 363 364 AcpiOsPrintf ("%-32s arg %X ret %2.2X", Pathname, 365 Predefined->Info.ParamCount, Predefined->Info.ExpectedBtypes); 366 367 if (Package) 368 { 369 AcpiOsPrintf (" PkgType %2.2X ObjType %2.2X Count %2.2X", 370 Package->RetInfo.Type, Package->RetInfo.ObjectType1, 371 Package->RetInfo.Count1); 372 } 373 374 AcpiOsPrintf("\n"); 375 376 AcpiNsCheckParameterCount (Pathname, Node, ACPI_UINT32_MAX, Predefined); 377 ACPI_FREE (Pathname); 378 (*Count)++; 379 380 return (AE_OK); 381} 382 383 384/******************************************************************************* 385 * 386 * FUNCTION: AcpiDbCheckPredefinedNames 387 * 388 * PARAMETERS: None 389 * 390 * RETURN: None 391 * 392 * DESCRIPTION: Validate all predefined names in the namespace 393 * 394 ******************************************************************************/ 395 396void 397AcpiDbCheckPredefinedNames ( 398 void) 399{ 400 UINT32 Count = 0; 401 402 403 /* Search all nodes in namespace */ 404 405 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 406 AcpiDbWalkForPredefinedNames, NULL, (void *) &Count, NULL); 407 408 AcpiOsPrintf ("Found %u predefined names in the namespace\n", Count); 409} 410 411 412/******************************************************************************* 413 * 414 * FUNCTION: AcpiDbWalkForExecute 415 * 416 * PARAMETERS: Callback from WalkNamespace 417 * 418 * RETURN: Status 419 * 420 * DESCRIPTION: Batch execution module. Currently only executes predefined 421 * ACPI names. 422 * 423 ******************************************************************************/ 424 425static ACPI_STATUS 426AcpiDbWalkForExecute ( 427 ACPI_HANDLE ObjHandle, 428 UINT32 NestingLevel, 429 void *Context, 430 void **ReturnValue) 431{ 432 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 433 ACPI_EXECUTE_WALK *Info = (ACPI_EXECUTE_WALK *) Context; 434 ACPI_BUFFER ReturnObj; 435 ACPI_STATUS Status; 436 char *Pathname; 437 UINT32 i; 438 ACPI_DEVICE_INFO *ObjInfo; 439 ACPI_OBJECT_LIST ParamObjects; 440 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 441 const ACPI_PREDEFINED_INFO *Predefined; 442 443 444 Predefined = AcpiNsCheckForPredefinedName (Node); 445 if (!Predefined) 446 { 447 return (AE_OK); 448 } 449 450 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) 451 { 452 return (AE_OK); 453 } 454 455 Pathname = AcpiNsGetExternalPathname (Node); 456 if (!Pathname) 457 { 458 return (AE_OK); 459 } 460 461 /* Get the object info for number of method parameters */ 462 463 Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo); 464 if (ACPI_FAILURE (Status)) 465 { 466 return (Status); 467 } 468 469 ParamObjects.Pointer = NULL; 470 ParamObjects.Count = 0; 471 472 if (ObjInfo->Type == ACPI_TYPE_METHOD) 473 { 474 /* Setup default parameters */ 475 476 for (i = 0; i < ObjInfo->ParamCount; i++) 477 { 478 Params[i].Type = ACPI_TYPE_INTEGER; 479 Params[i].Integer.Value = 1; 480 } 481 482 ParamObjects.Pointer = Params; 483 ParamObjects.Count = ObjInfo->ParamCount; 484 } 485 486 ACPI_FREE (ObjInfo); 487 ReturnObj.Pointer = NULL; 488 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 489 490 /* Do the actual method execution */ 491 492 AcpiGbl_MethodExecuting = TRUE; 493 494 Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj); 495 496 AcpiOsPrintf ("%-32s returned %s\n", Pathname, AcpiFormatException (Status)); 497 AcpiGbl_MethodExecuting = FALSE; 498 ACPI_FREE (Pathname); 499 500 /* Ignore status from method execution */ 501 502 Status = AE_OK; 503 504 /* Update count, check if we have executed enough methods */ 505 506 Info->Count++; 507 if (Info->Count >= Info->MaxCount) 508 { 509 Status = AE_CTRL_TERMINATE; 510 } 511 512 return (Status); 513} 514 515 516/******************************************************************************* 517 * 518 * FUNCTION: AcpiDbBatchExecute 519 * 520 * PARAMETERS: CountArg - Max number of methods to execute 521 * 522 * RETURN: None 523 * 524 * DESCRIPTION: Namespace batch execution. Execute predefined names in the 525 * namespace, up to the max count, if specified. 526 * 527 ******************************************************************************/ 528 529void 530AcpiDbBatchExecute ( 531 char *CountArg) 532{ 533 ACPI_EXECUTE_WALK Info; 534 535 536 Info.Count = 0; 537 Info.MaxCount = ACPI_UINT32_MAX; 538 539 if (CountArg) 540 { 541 Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0); 542 } 543 544 545 /* Search all nodes in namespace */ 546 547 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 548 AcpiDbWalkForExecute, NULL, (void *) &Info, NULL); 549 550 AcpiOsPrintf ("Executed %u predefined names in the namespace\n", Info.Count); 551} 552 553 554/******************************************************************************* 555 * 556 * FUNCTION: AcpiDbDisplayLocks 557 * 558 * PARAMETERS: None 559 * 560 * RETURN: None 561 * 562 * DESCRIPTION: Display information about internal mutexes. 563 * 564 ******************************************************************************/ 565 566void 567AcpiDbDisplayLocks ( 568 void) 569{ 570 UINT32 i; 571 572 573 for (i = 0; i < ACPI_MAX_MUTEX; i++) 574 { 575 AcpiOsPrintf ("%26s : %s\n", AcpiUtGetMutexName (i), 576 AcpiGbl_MutexInfo[i].ThreadId == ACPI_MUTEX_NOT_ACQUIRED 577 ? "Locked" : "Unlocked"); 578 } 579} 580 581 582/******************************************************************************* 583 * 584 * FUNCTION: AcpiDbDisplayTableInfo 585 * 586 * PARAMETERS: TableArg - String with name of table to be displayed 587 * 588 * RETURN: None 589 * 590 * DESCRIPTION: Display information about loaded tables. Current 591 * implementation displays all loaded tables. 592 * 593 ******************************************************************************/ 594 595void 596AcpiDbDisplayTableInfo ( 597 char *TableArg) 598{ 599 UINT32 i; 600 ACPI_TABLE_DESC *TableDesc; 601 ACPI_STATUS Status; 602 603 604 /* Walk the entire root table list */ 605 606 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 607 { 608 TableDesc = &AcpiGbl_RootTableList.Tables[i]; 609 AcpiOsPrintf ("%u ", i); 610 611 /* Make sure that the table is mapped */ 612 613 Status = AcpiTbVerifyTable (TableDesc); 614 if (ACPI_FAILURE (Status)) 615 { 616 return; 617 } 618 619 /* Dump the table header */ 620 621 if (TableDesc->Pointer) 622 { 623 AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer); 624 } 625 else 626 { 627 /* If the pointer is null, the table has been unloaded */ 628 629 ACPI_INFO ((AE_INFO, "%4.4s - Table has been unloaded", 630 TableDesc->Signature.Ascii)); 631 } 632 } 633} 634 635 636/******************************************************************************* 637 * 638 * FUNCTION: AcpiDbUnloadAcpiTable 639 * 640 * PARAMETERS: TableArg - Name of the table to be unloaded 641 * InstanceArg - Which instance of the table to unload (if 642 * there are multiple tables of the same type) 643 * 644 * RETURN: Nonde 645 * 646 * DESCRIPTION: Unload an ACPI table. 647 * Instance is not implemented 648 * 649 ******************************************************************************/ 650 651void 652AcpiDbUnloadAcpiTable ( 653 char *TableArg, 654 char *InstanceArg) 655{ 656/* TBD: Need to reimplement for new data structures */ 657 658#if 0 659 UINT32 i; 660 ACPI_STATUS Status; 661 662 663 /* Search all tables for the target type */ 664 665 for (i = 0; i < (ACPI_TABLE_ID_MAX+1); i++) 666 { 667 if (!ACPI_STRNCMP (TableArg, AcpiGbl_TableData[i].Signature, 668 AcpiGbl_TableData[i].SigLength)) 669 { 670 /* Found the table, unload it */ 671 672 Status = AcpiUnloadTable (i); 673 if (ACPI_SUCCESS (Status)) 674 { 675 AcpiOsPrintf ("[%s] unloaded and uninstalled\n", TableArg); 676 } 677 else 678 { 679 AcpiOsPrintf ("%s, while unloading [%s]\n", 680 AcpiFormatException (Status), TableArg); 681 } 682 683 return; 684 } 685 } 686 687 AcpiOsPrintf ("Unknown table type [%s]\n", TableArg); 688#endif 689} 690 691 692/******************************************************************************* 693 * 694 * FUNCTION: AcpiDbSetMethodBreakpoint 695 * 696 * PARAMETERS: Location - AML offset of breakpoint 697 * WalkState - Current walk info 698 * Op - Current Op (from parse walk) 699 * 700 * RETURN: None 701 * 702 * DESCRIPTION: Set a breakpoint in a control method at the specified 703 * AML offset 704 * 705 ******************************************************************************/ 706 707void 708AcpiDbSetMethodBreakpoint ( 709 char *Location, 710 ACPI_WALK_STATE *WalkState, 711 ACPI_PARSE_OBJECT *Op) 712{ 713 UINT32 Address; 714 715 716 if (!Op) 717 { 718 AcpiOsPrintf ("There is no method currently executing\n"); 719 return; 720 } 721 722 /* Get and verify the breakpoint address */ 723 724 Address = ACPI_STRTOUL (Location, NULL, 16); 725 if (Address <= Op->Common.AmlOffset) 726 { 727 AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n", 728 Address, Op->Common.AmlOffset); 729 } 730 731 /* Save breakpoint in current walk */ 732 733 WalkState->UserBreakpoint = Address; 734 AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address); 735} 736 737 738/******************************************************************************* 739 * 740 * FUNCTION: AcpiDbSetMethodCallBreakpoint 741 * 742 * PARAMETERS: Op - Current Op (from parse walk) 743 * 744 * RETURN: None 745 * 746 * DESCRIPTION: Set a breakpoint in a control method at the specified 747 * AML offset 748 * 749 ******************************************************************************/ 750 751void 752AcpiDbSetMethodCallBreakpoint ( 753 ACPI_PARSE_OBJECT *Op) 754{ 755 756 757 if (!Op) 758 { 759 AcpiOsPrintf ("There is no method currently executing\n"); 760 return; 761 } 762 763 AcpiGbl_StepToNextCall = TRUE; 764} 765 766 767/******************************************************************************* 768 * 769 * FUNCTION: AcpiDbDisassembleAml 770 * 771 * PARAMETERS: Statements - Number of statements to disassemble 772 * Op - Current Op (from parse walk) 773 * 774 * RETURN: None 775 * 776 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 777 * of statements specified. 778 * 779 ******************************************************************************/ 780 781void 782AcpiDbDisassembleAml ( 783 char *Statements, 784 ACPI_PARSE_OBJECT *Op) 785{ 786 UINT32 NumStatements = 8; 787 788 789 if (!Op) 790 { 791 AcpiOsPrintf ("There is no method currently executing\n"); 792 return; 793 } 794 795 if (Statements) 796 { 797 NumStatements = ACPI_STRTOUL (Statements, NULL, 0); 798 } 799 800#ifdef ACPI_DISASSEMBLER 801 AcpiDmDisassemble (NULL, Op, NumStatements); 802#endif 803} 804 805 806/******************************************************************************* 807 * 808 * FUNCTION: AcpiDbDisassembleMethod 809 * 810 * PARAMETERS: Name - Name of control method 811 * 812 * RETURN: None 813 * 814 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number 815 * of statements specified. 816 * 817 ******************************************************************************/ 818 819ACPI_STATUS 820AcpiDbDisassembleMethod ( 821 char *Name) 822{ 823 ACPI_STATUS Status; 824 ACPI_PARSE_OBJECT *Op; 825 ACPI_WALK_STATE *WalkState; 826 ACPI_OPERAND_OBJECT *ObjDesc; 827 ACPI_NAMESPACE_NODE *Method; 828 829 830 Method = AcpiDbConvertToNode (Name); 831 if (!Method) 832 { 833 return (AE_BAD_PARAMETER); 834 } 835 836 ObjDesc = Method->Object; 837 838 Op = AcpiPsCreateScopeOp (); 839 if (!Op) 840 { 841 return (AE_NO_MEMORY); 842 } 843 844 /* Create and initialize a new walk state */ 845 846 WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 847 if (!WalkState) 848 { 849 return (AE_NO_MEMORY); 850 } 851 852 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, 853 ObjDesc->Method.AmlStart, 854 ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 855 if (ACPI_FAILURE (Status)) 856 { 857 return (Status); 858 } 859 860 /* Parse the AML */ 861 862 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 863 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 864 Status = AcpiPsParseAml (WalkState); 865 866#ifdef ACPI_DISASSEMBLER 867 AcpiDmDisassemble (NULL, Op, 0); 868#endif 869 AcpiPsDeleteParseTree (Op); 870 return (AE_OK); 871} 872 873 874/******************************************************************************* 875 * 876 * FUNCTION: AcpiDbDumpNamespace 877 * 878 * PARAMETERS: StartArg - Node to begin namespace dump 879 * DepthArg - Maximum tree depth to be dumped 880 * 881 * RETURN: None 882 * 883 * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed 884 * with type and other information. 885 * 886 ******************************************************************************/ 887 888void 889AcpiDbDumpNamespace ( 890 char *StartArg, 891 char *DepthArg) 892{ 893 ACPI_HANDLE SubtreeEntry = AcpiGbl_RootNode; 894 UINT32 MaxDepth = ACPI_UINT32_MAX; 895 896 897 /* No argument given, just start at the root and dump entire namespace */ 898 899 if (StartArg) 900 { 901 SubtreeEntry = AcpiDbConvertToNode (StartArg); 902 if (!SubtreeEntry) 903 { 904 return; 905 } 906 907 /* Now we can check for the depth argument */ 908 909 if (DepthArg) 910 { 911 MaxDepth = ACPI_STRTOUL (DepthArg, NULL, 0); 912 } 913 } 914 915 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 916 AcpiOsPrintf ("ACPI Namespace (from %4.4s (%p) subtree):\n", 917 ((ACPI_NAMESPACE_NODE *) SubtreeEntry)->Name.Ascii, SubtreeEntry); 918 919 /* Display the subtree */ 920 921 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 922 AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, MaxDepth, 923 ACPI_OWNER_ID_MAX, SubtreeEntry); 924 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 925} 926 927 928/******************************************************************************* 929 * 930 * FUNCTION: AcpiDbDumpNamespaceByOwner 931 * 932 * PARAMETERS: OwnerArg - Owner ID whose nodes will be displayed 933 * DepthArg - Maximum tree depth to be dumped 934 * 935 * RETURN: None 936 * 937 * DESCRIPTION: Dump elements of the namespace that are owned by the OwnerId. 938 * 939 ******************************************************************************/ 940 941void 942AcpiDbDumpNamespaceByOwner ( 943 char *OwnerArg, 944 char *DepthArg) 945{ 946 ACPI_HANDLE SubtreeEntry = AcpiGbl_RootNode; 947 UINT32 MaxDepth = ACPI_UINT32_MAX; 948 ACPI_OWNER_ID OwnerId; 949 950 951 OwnerId = (ACPI_OWNER_ID) ACPI_STRTOUL (OwnerArg, NULL, 0); 952 953 /* Now we can check for the depth argument */ 954 955 if (DepthArg) 956 { 957 MaxDepth = ACPI_STRTOUL (DepthArg, NULL, 0); 958 } 959 960 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 961 AcpiOsPrintf ("ACPI Namespace by owner %X:\n", OwnerId); 962 963 /* Display the subtree */ 964 965 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 966 AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, MaxDepth, OwnerId, 967 SubtreeEntry); 968 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 969} 970 971 972/******************************************************************************* 973 * 974 * FUNCTION: AcpiDbSendNotify 975 * 976 * PARAMETERS: Name - Name of ACPI object to send the notify to 977 * Value - Value of the notify to send. 978 * 979 * RETURN: None 980 * 981 * DESCRIPTION: Send an ACPI notification. The value specified is sent to the 982 * named object as an ACPI notify. 983 * 984 ******************************************************************************/ 985 986void 987AcpiDbSendNotify ( 988 char *Name, 989 UINT32 Value) 990{ 991 ACPI_NAMESPACE_NODE *Node; 992 ACPI_STATUS Status; 993 994 995 /* Translate name to an Named object */ 996 997 Node = AcpiDbConvertToNode (Name); 998 if (!Node) 999 { 1000 return; 1001 } 1002 1003 /* Decode Named object type */ 1004 1005 switch (Node->Type) 1006 { 1007 case ACPI_TYPE_DEVICE: 1008 case ACPI_TYPE_THERMAL: 1009 1010 /* Send the notify */ 1011 1012 Status = AcpiEvQueueNotifyRequest (Node, Value); 1013 if (ACPI_FAILURE (Status)) 1014 { 1015 AcpiOsPrintf ("Could not queue notify\n"); 1016 } 1017 break; 1018 1019 default: 1020 AcpiOsPrintf ("Named object is not a device or a thermal object\n"); 1021 break; 1022 } 1023} 1024 1025 1026/******************************************************************************* 1027 * 1028 * FUNCTION: AcpiDbSetMethodData 1029 * 1030 * PARAMETERS: TypeArg - L for local, A for argument 1031 * IndexArg - which one 1032 * ValueArg - Value to set. 1033 * 1034 * RETURN: None 1035 * 1036 * DESCRIPTION: Set a local or argument for the running control method. 1037 * NOTE: only object supported is Number. 1038 * 1039 ******************************************************************************/ 1040 1041void 1042AcpiDbSetMethodData ( 1043 char *TypeArg, 1044 char *IndexArg, 1045 char *ValueArg) 1046{ 1047 char Type; 1048 UINT32 Index; 1049 UINT32 Value; 1050 ACPI_WALK_STATE *WalkState; 1051 ACPI_OPERAND_OBJECT *ObjDesc; 1052 ACPI_STATUS Status; 1053 ACPI_NAMESPACE_NODE *Node; 1054 1055 1056 /* Validate TypeArg */ 1057 1058 AcpiUtStrupr (TypeArg); 1059 Type = TypeArg[0]; 1060 if ((Type != 'L') && 1061 (Type != 'A') && 1062 (Type != 'N')) 1063 { 1064 AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg); 1065 return; 1066 } 1067 1068 Value = ACPI_STRTOUL (ValueArg, NULL, 16); 1069 1070 if (Type == 'N') 1071 { 1072 Node = AcpiDbConvertToNode (IndexArg); 1073 if (Node->Type != ACPI_TYPE_INTEGER) 1074 { 1075 AcpiOsPrintf ("Can only set Integer nodes\n"); 1076 return; 1077 } 1078 ObjDesc = Node->Object; 1079 ObjDesc->Integer.Value = Value; 1080 return; 1081 } 1082 1083 /* Get the index and value */ 1084 1085 Index = ACPI_STRTOUL (IndexArg, NULL, 16); 1086 1087 WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); 1088 if (!WalkState) 1089 { 1090 AcpiOsPrintf ("There is no method currently executing\n"); 1091 return; 1092 } 1093 1094 /* Create and initialize the new object */ 1095 1096 ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value); 1097 if (!ObjDesc) 1098 { 1099 AcpiOsPrintf ("Could not create an internal object\n"); 1100 return; 1101 } 1102 1103 /* Store the new object into the target */ 1104 1105 switch (Type) 1106 { 1107 case 'A': 1108 1109 /* Set a method argument */ 1110 1111 if (Index > ACPI_METHOD_MAX_ARG) 1112 { 1113 AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index); 1114 goto Cleanup; 1115 } 1116 1117 Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc, 1118 WalkState); 1119 if (ACPI_FAILURE (Status)) 1120 { 1121 goto Cleanup; 1122 } 1123 1124 ObjDesc = WalkState->Arguments[Index].Object; 1125 1126 AcpiOsPrintf ("Arg%u: ", Index); 1127 AcpiDmDisplayInternalObject (ObjDesc, WalkState); 1128 break; 1129 1130 case 'L': 1131 1132 /* Set a method local */ 1133 1134 if (Index > ACPI_METHOD_MAX_LOCAL) 1135 { 1136 AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index); 1137 goto Cleanup; 1138 } 1139 1140 Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc, 1141 WalkState); 1142 if (ACPI_FAILURE (Status)) 1143 { 1144 goto Cleanup; 1145 } 1146 1147 ObjDesc = WalkState->LocalVariables[Index].Object; 1148 1149 AcpiOsPrintf ("Local%u: ", Index); 1150 AcpiDmDisplayInternalObject (ObjDesc, WalkState); 1151 break; 1152 1153 default: 1154 break; 1155 } 1156 1157Cleanup: 1158 AcpiUtRemoveReference (ObjDesc); 1159} 1160 1161 1162/******************************************************************************* 1163 * 1164 * FUNCTION: AcpiDbWalkForSpecificObjects 1165 * 1166 * PARAMETERS: Callback from WalkNamespace 1167 * 1168 * RETURN: Status 1169 * 1170 * DESCRIPTION: Display short info about objects in the namespace 1171 * 1172 ******************************************************************************/ 1173 1174static ACPI_STATUS 1175AcpiDbWalkForSpecificObjects ( 1176 ACPI_HANDLE ObjHandle, 1177 UINT32 NestingLevel, 1178 void *Context, 1179 void **ReturnValue) 1180{ 1181 ACPI_WALK_INFO *Info = (ACPI_WALK_INFO *) Context; 1182 ACPI_BUFFER Buffer; 1183 ACPI_STATUS Status; 1184 1185 1186 Info->Count++; 1187 1188 /* Get and display the full pathname to this object */ 1189 1190 Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 1191 Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); 1192 if (ACPI_FAILURE (Status)) 1193 { 1194 AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); 1195 return (AE_OK); 1196 } 1197 1198 AcpiOsPrintf ("%32s", (char *) Buffer.Pointer); 1199 ACPI_FREE (Buffer.Pointer); 1200 1201 /* Dump short info about the object */ 1202 1203 (void) AcpiNsDumpOneObject (ObjHandle, NestingLevel, Info, NULL); 1204 return (AE_OK); 1205} 1206 1207 1208/******************************************************************************* 1209 * 1210 * FUNCTION: AcpiDbDisplayObjects 1211 * 1212 * PARAMETERS: ObjTypeArg - Type of object to display 1213 * DisplayCountArg - Max depth to display 1214 * 1215 * RETURN: None 1216 * 1217 * DESCRIPTION: Display objects in the namespace of the requested type 1218 * 1219 ******************************************************************************/ 1220 1221ACPI_STATUS 1222AcpiDbDisplayObjects ( 1223 char *ObjTypeArg, 1224 char *DisplayCountArg) 1225{ 1226 ACPI_WALK_INFO Info; 1227 ACPI_OBJECT_TYPE Type; 1228 1229 1230 /* Get the object type */ 1231 1232 Type = AcpiDbMatchArgument (ObjTypeArg, AcpiDbObjectTypes); 1233 if (Type == ACPI_TYPE_NOT_FOUND) 1234 { 1235 AcpiOsPrintf ("Invalid or unsupported argument\n"); 1236 return (AE_OK); 1237 } 1238 1239 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 1240 AcpiOsPrintf ( 1241 "Objects of type [%s] defined in the current ACPI Namespace:\n", 1242 AcpiUtGetTypeName (Type)); 1243 1244 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 1245 1246 Info.Count = 0; 1247 Info.OwnerId = ACPI_OWNER_ID_MAX; 1248 Info.DebugLevel = ACPI_UINT32_MAX; 1249 Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; 1250 1251 /* Walk the namespace from the root */ 1252 1253 (void) AcpiWalkNamespace (Type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 1254 AcpiDbWalkForSpecificObjects, NULL, (void *) &Info, NULL); 1255 1256 AcpiOsPrintf ( 1257 "\nFound %u objects of type [%s] in the current ACPI Namespace\n", 1258 Info.Count, AcpiUtGetTypeName (Type)); 1259 1260 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 1261 return (AE_OK); 1262} 1263 1264 1265/******************************************************************************* 1266 * 1267 * FUNCTION: AcpiDbDisplayInterfaces 1268 * 1269 * PARAMETERS: ActionArg - Null, "install", or "remove" 1270 * InterfaceNameArg - Name for install/remove options 1271 * 1272 * RETURN: None 1273 * 1274 * DESCRIPTION: Display or modify the global _OSI interface list 1275 * 1276 ******************************************************************************/ 1277 1278void 1279AcpiDbDisplayInterfaces ( 1280 char *ActionArg, 1281 char *InterfaceNameArg) 1282{ 1283 ACPI_INTERFACE_INFO *NextInterface; 1284 char *SubString; 1285 ACPI_STATUS Status; 1286 1287 1288 /* If no arguments, just display current interface list */ 1289 1290 if (!ActionArg) 1291 { 1292 (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, 1293 ACPI_WAIT_FOREVER); 1294 1295 NextInterface = AcpiGbl_SupportedInterfaces; 1296 1297 while (NextInterface) 1298 { 1299 if (!(NextInterface->Flags & ACPI_OSI_INVALID)) 1300 { 1301 AcpiOsPrintf ("%s\n", NextInterface->Name); 1302 } 1303 NextInterface = NextInterface->Next; 1304 } 1305 1306 AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 1307 return; 1308 } 1309 1310 /* If ActionArg exists, so must InterfaceNameArg */ 1311 1312 if (!InterfaceNameArg) 1313 { 1314 AcpiOsPrintf ("Missing Interface Name argument\n"); 1315 return; 1316 } 1317 1318 /* Uppercase the action for match below */ 1319 1320 AcpiUtStrupr (ActionArg); 1321 1322 /* Install - install an interface */ 1323 1324 SubString = ACPI_STRSTR ("INSTALL", ActionArg); 1325 if (SubString) 1326 { 1327 Status = AcpiInstallInterface (InterfaceNameArg); 1328 if (ACPI_FAILURE (Status)) 1329 { 1330 AcpiOsPrintf ("%s, while installing \"%s\"\n", 1331 AcpiFormatException (Status), InterfaceNameArg); 1332 } 1333 return; 1334 } 1335 1336 /* Remove - remove an interface */ 1337 1338 SubString = ACPI_STRSTR ("REMOVE", ActionArg); 1339 if (SubString) 1340 { 1341 Status = AcpiRemoveInterface (InterfaceNameArg); 1342 if (ACPI_FAILURE (Status)) 1343 { 1344 AcpiOsPrintf ("%s, while removing \"%s\"\n", 1345 AcpiFormatException (Status), InterfaceNameArg); 1346 } 1347 return; 1348 } 1349 1350 /* Invalid ActionArg */ 1351 1352 AcpiOsPrintf ("Invalid action argument: %s\n", ActionArg); 1353 return; 1354} 1355 1356 1357/******************************************************************************* 1358 * 1359 * FUNCTION: AcpiDbWalkAndMatchName 1360 * 1361 * PARAMETERS: Callback from WalkNamespace 1362 * 1363 * RETURN: Status 1364 * 1365 * DESCRIPTION: Find a particular name/names within the namespace. Wildcards 1366 * are supported -- '?' matches any character. 1367 * 1368 ******************************************************************************/ 1369 1370static ACPI_STATUS 1371AcpiDbWalkAndMatchName ( 1372 ACPI_HANDLE ObjHandle, 1373 UINT32 NestingLevel, 1374 void *Context, 1375 void **ReturnValue) 1376{ 1377 ACPI_STATUS Status; 1378 char *RequestedName = (char *) Context; 1379 UINT32 i; 1380 ACPI_BUFFER Buffer; 1381 ACPI_WALK_INFO Info; 1382 1383 1384 /* Check for a name match */ 1385 1386 for (i = 0; i < 4; i++) 1387 { 1388 /* Wildcard support */ 1389 1390 if ((RequestedName[i] != '?') && 1391 (RequestedName[i] != ((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Ascii[i])) 1392 { 1393 /* No match, just exit */ 1394 1395 return (AE_OK); 1396 } 1397 } 1398 1399 /* Get the full pathname to this object */ 1400 1401 Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 1402 Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); 1403 if (ACPI_FAILURE (Status)) 1404 { 1405 AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); 1406 } 1407 else 1408 { 1409 Info.OwnerId = ACPI_OWNER_ID_MAX; 1410 Info.DebugLevel = ACPI_UINT32_MAX; 1411 Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; 1412 1413 AcpiOsPrintf ("%32s", (char *) Buffer.Pointer); 1414 (void) AcpiNsDumpOneObject (ObjHandle, NestingLevel, &Info, NULL); 1415 ACPI_FREE (Buffer.Pointer); 1416 } 1417 1418 return (AE_OK); 1419} 1420 1421 1422/******************************************************************************* 1423 * 1424 * FUNCTION: AcpiDbFindNameInNamespace 1425 * 1426 * PARAMETERS: NameArg - The 4-character ACPI name to find. 1427 * wildcards are supported. 1428 * 1429 * RETURN: None 1430 * 1431 * DESCRIPTION: Search the namespace for a given name (with wildcards) 1432 * 1433 ******************************************************************************/ 1434 1435ACPI_STATUS 1436AcpiDbFindNameInNamespace ( 1437 char *NameArg) 1438{ 1439 char AcpiName[5] = "____"; 1440 char *AcpiNamePtr = AcpiName; 1441 1442 1443 if (ACPI_STRLEN (NameArg) > 4) 1444 { 1445 AcpiOsPrintf ("Name must be no longer than 4 characters\n"); 1446 return (AE_OK); 1447 } 1448 1449 /* Pad out name with underscores as necessary to create a 4-char name */ 1450 1451 AcpiUtStrupr (NameArg); 1452 while (*NameArg) 1453 { 1454 *AcpiNamePtr = *NameArg; 1455 AcpiNamePtr++; 1456 NameArg++; 1457 } 1458 1459 /* Walk the namespace from the root */ 1460 1461 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 1462 AcpiDbWalkAndMatchName, NULL, AcpiName, NULL); 1463 1464 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 1465 return (AE_OK); 1466} 1467 1468 1469/******************************************************************************* 1470 * 1471 * FUNCTION: AcpiDbSetScope 1472 * 1473 * PARAMETERS: Name - New scope path 1474 * 1475 * RETURN: Status 1476 * 1477 * DESCRIPTION: Set the "current scope" as maintained by this utility. 1478 * The scope is used as a prefix to ACPI paths. 1479 * 1480 ******************************************************************************/ 1481 1482void 1483AcpiDbSetScope ( 1484 char *Name) 1485{ 1486 ACPI_STATUS Status; 1487 ACPI_NAMESPACE_NODE *Node; 1488 1489 1490 if (!Name || Name[0] == 0) 1491 { 1492 AcpiOsPrintf ("Current scope: %s\n", AcpiGbl_DbScopeBuf); 1493 return; 1494 } 1495 1496 AcpiDbPrepNamestring (Name); 1497 1498 if (Name[0] == '\\') 1499 { 1500 /* Validate new scope from the root */ 1501 1502 Status = AcpiNsGetNode (AcpiGbl_RootNode, Name, ACPI_NS_NO_UPSEARCH, 1503 &Node); 1504 if (ACPI_FAILURE (Status)) 1505 { 1506 goto ErrorExit; 1507 } 1508 1509 ACPI_STRCPY (AcpiGbl_DbScopeBuf, Name); 1510 ACPI_STRCAT (AcpiGbl_DbScopeBuf, "\\"); 1511 } 1512 else 1513 { 1514 /* Validate new scope relative to old scope */ 1515 1516 Status = AcpiNsGetNode (AcpiGbl_DbScopeNode, Name, ACPI_NS_NO_UPSEARCH, 1517 &Node); 1518 if (ACPI_FAILURE (Status)) 1519 { 1520 goto ErrorExit; 1521 } 1522 1523 ACPI_STRCAT (AcpiGbl_DbScopeBuf, Name); 1524 ACPI_STRCAT (AcpiGbl_DbScopeBuf, "\\"); 1525 } 1526 1527 AcpiGbl_DbScopeNode = Node; 1528 AcpiOsPrintf ("New scope: %s\n", AcpiGbl_DbScopeBuf); 1529 return; 1530 1531ErrorExit: 1532 1533 AcpiOsPrintf ("Could not attach scope: %s, %s\n", 1534 Name, AcpiFormatException (Status)); 1535} 1536 1537 1538/******************************************************************************* 1539 * 1540 * FUNCTION: AcpiDmCompareAmlResources 1541 * 1542 * PARAMETERS: Aml1Buffer - Contains first resource list 1543 * Aml1BufferLength - Length of first resource list 1544 * Aml2Buffer - Contains second resource list 1545 * Aml2BufferLength - Length of second resource list 1546 * 1547 * RETURN: None 1548 * 1549 * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in 1550 * order to isolate a miscompare to an individual resource) 1551 * 1552 ******************************************************************************/ 1553 1554static void 1555AcpiDmCompareAmlResources ( 1556 UINT8 *Aml1Buffer, 1557 ACPI_RSDESC_SIZE Aml1BufferLength, 1558 UINT8 *Aml2Buffer, 1559 ACPI_RSDESC_SIZE Aml2BufferLength) 1560{ 1561 UINT8 *Aml1; 1562 UINT8 *Aml2; 1563 ACPI_RSDESC_SIZE Aml1Length; 1564 ACPI_RSDESC_SIZE Aml2Length; 1565 ACPI_RSDESC_SIZE Offset = 0; 1566 UINT8 ResourceType; 1567 UINT32 Count = 0; 1568 1569 1570 /* Compare overall buffer sizes (may be different due to size rounding) */ 1571 1572 if (Aml1BufferLength != Aml2BufferLength) 1573 { 1574 AcpiOsPrintf ( 1575 "**** Buffer length mismatch in converted AML: original %X new %X ****\n", 1576 Aml1BufferLength, Aml2BufferLength); 1577 } 1578 1579 Aml1 = Aml1Buffer; 1580 Aml2 = Aml2Buffer; 1581 1582 /* Walk the descriptor lists, comparing each descriptor */ 1583 1584 while (Aml1 < (Aml1Buffer + Aml1BufferLength)) 1585 { 1586 /* Get the lengths of each descriptor */ 1587 1588 Aml1Length = AcpiUtGetDescriptorLength (Aml1); 1589 Aml2Length = AcpiUtGetDescriptorLength (Aml2); 1590 ResourceType = AcpiUtGetResourceType (Aml1); 1591 1592 /* Check for descriptor length match */ 1593 1594 if (Aml1Length != Aml2Length) 1595 { 1596 AcpiOsPrintf ( 1597 "**** Length mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X L1 %X L2 %X ****\n", 1598 Count, ResourceType, Offset, Aml1Length, Aml2Length); 1599 } 1600 1601 /* Check for descriptor byte match */ 1602 1603 else if (ACPI_MEMCMP (Aml1, Aml2, Aml1Length)) 1604 { 1605 AcpiOsPrintf ( 1606 "**** Data mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X ****\n", 1607 Count, ResourceType, Offset); 1608 } 1609 1610 /* Exit on EndTag descriptor */ 1611 1612 if (ResourceType == ACPI_RESOURCE_NAME_END_TAG) 1613 { 1614 return; 1615 } 1616 1617 /* Point to next descriptor in each buffer */ 1618 1619 Count++; 1620 Offset += Aml1Length; 1621 Aml1 += Aml1Length; 1622 Aml2 += Aml2Length; 1623 } 1624} 1625 1626 1627/******************************************************************************* 1628 * 1629 * FUNCTION: AcpiDmTestResourceConversion 1630 * 1631 * PARAMETERS: Node - Parent device node 1632 * Name - resource method name (_CRS) 1633 * 1634 * RETURN: Status 1635 * 1636 * DESCRIPTION: Compare the original AML with a conversion of the AML to 1637 * internal resource list, then back to AML. 1638 * 1639 ******************************************************************************/ 1640 1641static ACPI_STATUS 1642AcpiDmTestResourceConversion ( 1643 ACPI_NAMESPACE_NODE *Node, 1644 char *Name) 1645{ 1646 ACPI_STATUS Status; 1647 ACPI_BUFFER ReturnObj; 1648 ACPI_BUFFER ResourceObj; 1649 ACPI_BUFFER NewAml; 1650 ACPI_OBJECT *OriginalAml; 1651 1652 1653 AcpiOsPrintf ("Resource Conversion Comparison:\n"); 1654 1655 NewAml.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 1656 ReturnObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 1657 ResourceObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 1658 1659 /* Get the original _CRS AML resource template */ 1660 1661 Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnObj); 1662 if (ACPI_FAILURE (Status)) 1663 { 1664 AcpiOsPrintf ("Could not obtain %s: %s\n", 1665 Name, AcpiFormatException (Status)); 1666 return (Status); 1667 } 1668 1669 /* Get the AML resource template, converted to internal resource structs */ 1670 1671 Status = AcpiGetCurrentResources (Node, &ResourceObj); 1672 if (ACPI_FAILURE (Status)) 1673 { 1674 AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n", 1675 AcpiFormatException (Status)); 1676 goto Exit1; 1677 } 1678 1679 /* Convert internal resource list to external AML resource template */ 1680 1681 Status = AcpiRsCreateAmlResources (ResourceObj.Pointer, &NewAml); 1682 if (ACPI_FAILURE (Status)) 1683 { 1684 AcpiOsPrintf ("AcpiRsCreateAmlResources failed: %s\n", 1685 AcpiFormatException (Status)); 1686 goto Exit2; 1687 } 1688 1689 /* Compare original AML to the newly created AML resource list */ 1690 1691 OriginalAml = ReturnObj.Pointer; 1692 1693 AcpiDmCompareAmlResources ( 1694 OriginalAml->Buffer.Pointer, (ACPI_RSDESC_SIZE) OriginalAml->Buffer.Length, 1695 NewAml.Pointer, (ACPI_RSDESC_SIZE) NewAml.Length); 1696 1697 /* Cleanup and exit */ 1698 1699 ACPI_FREE (NewAml.Pointer); 1700Exit2: 1701 ACPI_FREE (ResourceObj.Pointer); 1702Exit1: 1703 ACPI_FREE (ReturnObj.Pointer); 1704 return (Status); 1705} 1706 1707 1708/******************************************************************************* 1709 * 1710 * FUNCTION: AcpiDbDisplayResources 1711 * 1712 * PARAMETERS: ObjectArg - String with hex value of the object 1713 * 1714 * RETURN: None 1715 * 1716 * DESCRIPTION: Display the resource objects associated with a device. 1717 * 1718 ******************************************************************************/ 1719 1720void 1721AcpiDbDisplayResources ( 1722 char *ObjectArg) 1723{ 1724 ACPI_NAMESPACE_NODE *Node; 1725 ACPI_STATUS Status; 1726 ACPI_BUFFER ReturnObj; 1727 1728 1729 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 1730 AcpiDbgLevel |= ACPI_LV_RESOURCES; 1731 1732 /* Convert string to object pointer */ 1733 1734 Node = AcpiDbConvertToNode (ObjectArg); 1735 if (!Node) 1736 { 1737 return; 1738 } 1739 1740 /* Prepare for a return object of arbitrary size */ 1741 1742 ReturnObj.Pointer = AcpiGbl_DbBuffer; 1743 ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; 1744 1745 /* _PRT */ 1746 1747 AcpiOsPrintf ("Evaluating _PRT\n"); 1748 1749 /* Check if _PRT exists */ 1750 1751 Status = AcpiEvaluateObject (Node, METHOD_NAME__PRT, NULL, &ReturnObj); 1752 if (ACPI_FAILURE (Status)) 1753 { 1754 AcpiOsPrintf ("Could not obtain _PRT: %s\n", 1755 AcpiFormatException (Status)); 1756 goto GetCrs; 1757 } 1758 1759 ReturnObj.Pointer = AcpiGbl_DbBuffer; 1760 ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; 1761 1762 Status = AcpiGetIrqRoutingTable (Node, &ReturnObj); 1763 if (ACPI_FAILURE (Status)) 1764 { 1765 AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n", 1766 AcpiFormatException (Status)); 1767 goto GetCrs; 1768 } 1769 1770 AcpiRsDumpIrqList (ACPI_CAST_PTR (UINT8, AcpiGbl_DbBuffer)); 1771 1772 1773 /* _CRS */ 1774 1775GetCrs: 1776 AcpiOsPrintf ("Evaluating _CRS\n"); 1777 1778 ReturnObj.Pointer = AcpiGbl_DbBuffer; 1779 ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; 1780 1781 /* Check if _CRS exists */ 1782 1783 Status = AcpiEvaluateObject (Node, METHOD_NAME__CRS, NULL, &ReturnObj); 1784 if (ACPI_FAILURE (Status)) 1785 { 1786 AcpiOsPrintf ("Could not obtain _CRS: %s\n", 1787 AcpiFormatException (Status)); 1788 goto GetPrs; 1789 } 1790 1791 /* Get the _CRS resource list */ 1792 1793 ReturnObj.Pointer = AcpiGbl_DbBuffer; 1794 ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; 1795 1796 Status = AcpiGetCurrentResources (Node, &ReturnObj); 1797 if (ACPI_FAILURE (Status)) 1798 { 1799 AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n", 1800 AcpiFormatException (Status)); 1801 goto GetPrs; 1802 } 1803 1804 /* Dump the _CRS resource list */ 1805 1806 AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, 1807 ReturnObj.Pointer)); 1808 1809 /* 1810 * Perform comparison of original AML to newly created AML. This tests both 1811 * the AML->Resource conversion and the Resource->Aml conversion. 1812 */ 1813 Status = AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS); 1814 1815 /* Execute _SRS with the resource list */ 1816 1817 Status = AcpiSetCurrentResources (Node, &ReturnObj); 1818 if (ACPI_FAILURE (Status)) 1819 { 1820 AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n", 1821 AcpiFormatException (Status)); 1822 goto GetPrs; 1823 } 1824 1825 1826 /* _PRS */ 1827 1828GetPrs: 1829 AcpiOsPrintf ("Evaluating _PRS\n"); 1830 1831 ReturnObj.Pointer = AcpiGbl_DbBuffer; 1832 ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; 1833 1834 /* Check if _PRS exists */ 1835 1836 Status = AcpiEvaluateObject (Node, METHOD_NAME__PRS, NULL, &ReturnObj); 1837 if (ACPI_FAILURE (Status)) 1838 { 1839 AcpiOsPrintf ("Could not obtain _PRS: %s\n", 1840 AcpiFormatException (Status)); 1841 goto Cleanup; 1842 } 1843 1844 ReturnObj.Pointer = AcpiGbl_DbBuffer; 1845 ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; 1846 1847 Status = AcpiGetPossibleResources (Node, &ReturnObj); 1848 if (ACPI_FAILURE (Status)) 1849 { 1850 AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n", 1851 AcpiFormatException (Status)); 1852 goto Cleanup; 1853 } 1854 1855 AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer)); 1856 1857Cleanup: 1858 1859 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 1860 return; 1861} 1862 1863 1864/******************************************************************************* 1865 * 1866 * FUNCTION: AcpiDbIntegrityWalk 1867 * 1868 * PARAMETERS: Callback from WalkNamespace 1869 * 1870 * RETURN: Status 1871 * 1872 * DESCRIPTION: Examine one NS node for valid values. 1873 * 1874 ******************************************************************************/ 1875 1876static ACPI_STATUS 1877AcpiDbIntegrityWalk ( 1878 ACPI_HANDLE ObjHandle, 1879 UINT32 NestingLevel, 1880 void *Context, 1881 void **ReturnValue) 1882{ 1883 ACPI_INTEGRITY_INFO *Info = (ACPI_INTEGRITY_INFO *) Context; 1884 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 1885 ACPI_OPERAND_OBJECT *Object; 1886 BOOLEAN Alias = TRUE; 1887 1888 1889 Info->Nodes++; 1890 1891 /* Verify the NS node, and dereference aliases */ 1892 1893 while (Alias) 1894 { 1895 if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) 1896 { 1897 AcpiOsPrintf ("Invalid Descriptor Type for Node %p [%s] - is %2.2X should be %2.2X\n", 1898 Node, AcpiUtGetDescriptorName (Node), ACPI_GET_DESCRIPTOR_TYPE (Node), 1899 ACPI_DESC_TYPE_NAMED); 1900 return (AE_OK); 1901 } 1902 1903 if ((Node->Type == ACPI_TYPE_LOCAL_ALIAS) || 1904 (Node->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) 1905 { 1906 Node = (ACPI_NAMESPACE_NODE *) Node->Object; 1907 } 1908 else 1909 { 1910 Alias = FALSE; 1911 } 1912 } 1913 1914 if (Node->Type > ACPI_TYPE_LOCAL_MAX) 1915 { 1916 AcpiOsPrintf ("Invalid Object Type for Node %p, Type = %X\n", 1917 Node, Node->Type); 1918 return (AE_OK); 1919 } 1920 1921 if (!AcpiUtValidAcpiName (Node->Name.Integer)) 1922 { 1923 AcpiOsPrintf ("Invalid AcpiName for Node %p\n", Node); 1924 return (AE_OK); 1925 } 1926 1927 Object = AcpiNsGetAttachedObject (Node); 1928 if (Object) 1929 { 1930 Info->Objects++; 1931 if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) 1932 { 1933 AcpiOsPrintf ("Invalid Descriptor Type for Object %p [%s]\n", 1934 Object, AcpiUtGetDescriptorName (Object)); 1935 } 1936 } 1937 1938 return (AE_OK); 1939} 1940 1941 1942/******************************************************************************* 1943 * 1944 * FUNCTION: AcpiDbCheckIntegrity 1945 * 1946 * PARAMETERS: None 1947 * 1948 * RETURN: None 1949 * 1950 * DESCRIPTION: Check entire namespace for data structure integrity 1951 * 1952 ******************************************************************************/ 1953 1954void 1955AcpiDbCheckIntegrity ( 1956 void) 1957{ 1958 ACPI_INTEGRITY_INFO Info = {0,0}; 1959 1960 /* Search all nodes in namespace */ 1961 1962 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 1963 AcpiDbIntegrityWalk, NULL, (void *) &Info, NULL); 1964 1965 AcpiOsPrintf ("Verified %u namespace nodes with %u Objects\n", 1966 Info.Nodes, Info.Objects); 1967} 1968 1969 1970/******************************************************************************* 1971 * 1972 * FUNCTION: AcpiDbGenerateGpe 1973 * 1974 * PARAMETERS: GpeArg - Raw GPE number, ascii string 1975 * BlockArg - GPE block number, ascii string 1976 * 0 or 1 for FADT GPE blocks 1977 * 1978 * RETURN: None 1979 * 1980 * DESCRIPTION: Generate a GPE 1981 * 1982 ******************************************************************************/ 1983 1984void 1985AcpiDbGenerateGpe ( 1986 char *GpeArg, 1987 char *BlockArg) 1988{ 1989 UINT32 BlockNumber; 1990 UINT32 GpeNumber; 1991 ACPI_GPE_EVENT_INFO *GpeEventInfo; 1992 1993 1994 GpeNumber = ACPI_STRTOUL (GpeArg, NULL, 0); 1995 BlockNumber = ACPI_STRTOUL (BlockArg, NULL, 0); 1996 1997 1998 GpeEventInfo = AcpiEvGetGpeEventInfo (ACPI_TO_POINTER (BlockNumber), 1999 GpeNumber); 2000 if (!GpeEventInfo) 2001 { 2002 AcpiOsPrintf ("Invalid GPE\n"); 2003 return; 2004 } 2005 2006 (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber); 2007} 2008 2009 2010/******************************************************************************* 2011 * 2012 * FUNCTION: AcpiDbBusWalk 2013 * 2014 * PARAMETERS: Callback from WalkNamespace 2015 * 2016 * RETURN: Status 2017 * 2018 * DESCRIPTION: Display info about device objects that have a corresponding 2019 * _PRT method. 2020 * 2021 ******************************************************************************/ 2022 2023static ACPI_STATUS 2024AcpiDbBusWalk ( 2025 ACPI_HANDLE ObjHandle, 2026 UINT32 NestingLevel, 2027 void *Context, 2028 void **ReturnValue) 2029{ 2030 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 2031 ACPI_STATUS Status; 2032 ACPI_BUFFER Buffer; 2033 ACPI_NAMESPACE_NODE *TempNode; 2034 ACPI_DEVICE_INFO *Info; 2035 UINT32 i; 2036 2037 2038 if ((Node->Type != ACPI_TYPE_DEVICE) && 2039 (Node->Type != ACPI_TYPE_PROCESSOR)) 2040 { 2041 return (AE_OK); 2042 } 2043 2044 /* Exit if there is no _PRT under this device */ 2045 2046 Status = AcpiGetHandle (Node, METHOD_NAME__PRT, 2047 ACPI_CAST_PTR (ACPI_HANDLE, &TempNode)); 2048 if (ACPI_FAILURE (Status)) 2049 { 2050 return (AE_OK); 2051 } 2052 2053 /* Get the full path to this device object */ 2054 2055 Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 2056 Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); 2057 if (ACPI_FAILURE (Status)) 2058 { 2059 AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle); 2060 return (AE_OK); 2061 } 2062 2063 Status = AcpiGetObjectInfo (ObjHandle, &Info); 2064 if (ACPI_FAILURE (Status)) 2065 { 2066 return (AE_OK); 2067 } 2068 2069 /* Display the full path */ 2070 2071 AcpiOsPrintf ("%-32s Type %X", (char *) Buffer.Pointer, Node->Type); 2072 ACPI_FREE (Buffer.Pointer); 2073 2074 if (Info->Flags & ACPI_PCI_ROOT_BRIDGE) 2075 { 2076 AcpiOsPrintf (" - Is PCI Root Bridge"); 2077 } 2078 AcpiOsPrintf ("\n"); 2079 2080 /* _PRT info */ 2081 2082 AcpiOsPrintf ("_PRT: %p\n", TempNode); 2083 2084 /* Dump _ADR, _HID, _UID, _CID */ 2085 2086 if (Info->Valid & ACPI_VALID_ADR) 2087 { 2088 AcpiOsPrintf ("_ADR: %8.8X%8.8X\n", ACPI_FORMAT_UINT64 (Info->Address)); 2089 } 2090 else 2091 { 2092 AcpiOsPrintf ("_ADR: <Not Present>\n"); 2093 } 2094 2095 if (Info->Valid & ACPI_VALID_HID) 2096 { 2097 AcpiOsPrintf ("_HID: %s\n", Info->HardwareId.String); 2098 } 2099 else 2100 { 2101 AcpiOsPrintf ("_HID: <Not Present>\n"); 2102 } 2103 2104 if (Info->Valid & ACPI_VALID_UID) 2105 { 2106 AcpiOsPrintf ("_UID: %s\n", Info->UniqueId.String); 2107 } 2108 else 2109 { 2110 AcpiOsPrintf ("_UID: <Not Present>\n"); 2111 } 2112 2113 if (Info->Valid & ACPI_VALID_CID) 2114 { 2115 for (i = 0; i < Info->CompatibleIdList.Count; i++) 2116 { 2117 AcpiOsPrintf ("_CID: %s\n", 2118 Info->CompatibleIdList.Ids[i].String); 2119 } 2120 } 2121 else 2122 { 2123 AcpiOsPrintf ("_CID: <Not Present>\n"); 2124 } 2125 2126 ACPI_FREE (Info); 2127 return (AE_OK); 2128} 2129 2130 2131/******************************************************************************* 2132 * 2133 * FUNCTION: AcpiDbGetBusInfo 2134 * 2135 * PARAMETERS: None 2136 * 2137 * RETURN: None 2138 * 2139 * DESCRIPTION: Display info about system busses. 2140 * 2141 ******************************************************************************/ 2142 2143void 2144AcpiDbGetBusInfo ( 2145 void) 2146{ 2147 /* Search all nodes in namespace */ 2148 2149 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 2150 AcpiDbBusWalk, NULL, NULL, NULL); 2151} 2152 2153#endif /* ACPI_DEBUGGER */ 2154