1 /****************************************************************************** 2 * 3 * Module Name: dmextern - Support for External() ASL statements 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #include <contrib/dev/acpica/include/acpi.h> 153 #include <contrib/dev/acpica/include/accommon.h> 154 #include <contrib/dev/acpica/include/amlcode.h> 155 #include <contrib/dev/acpica/include/acnamesp.h> 156 #include <contrib/dev/acpica/include/acdisasm.h> 157 #include <contrib/dev/acpica/compiler/aslcompiler.h> 158 #include <stdio.h> 159 #include <errno.h> 160 161 162 /* 163 * This module is used for application-level code (iASL disassembler) only. 164 * 165 * It contains the code to create and emit any necessary External() ASL 166 * statements for the module being disassembled. 167 */ 168 #define _COMPONENT ACPI_CA_DISASSEMBLER 169 ACPI_MODULE_NAME ("dmextern") 170 171 172 /* 173 * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL 174 * ObjectTypeKeyword. Used to generate typed external declarations 175 */ 176 static const char *AcpiGbl_DmTypeNames[] = 177 { 178 /* 00 */ ", UnknownObj", /* Type ANY */ 179 /* 01 */ ", IntObj", 180 /* 02 */ ", StrObj", 181 /* 03 */ ", BuffObj", 182 /* 04 */ ", PkgObj", 183 /* 05 */ ", FieldUnitObj", 184 /* 06 */ ", DeviceObj", 185 /* 07 */ ", EventObj", 186 /* 08 */ ", MethodObj", 187 /* 09 */ ", MutexObj", 188 /* 10 */ ", OpRegionObj", 189 /* 11 */ ", PowerResObj", 190 /* 12 */ ", ProcessorObj", 191 /* 13 */ ", ThermalZoneObj", 192 /* 14 */ ", BuffFieldObj", 193 /* 15 */ ", DDBHandleObj", 194 /* 16 */ "", /* Debug object */ 195 /* 17 */ ", FieldUnitObj", 196 /* 18 */ ", FieldUnitObj", 197 /* 19 */ ", FieldUnitObj" 198 }; 199 200 #define METHOD_SEPARATORS " \t,()\n" 201 202 203 /* Local prototypes */ 204 205 static const char * 206 AcpiDmGetObjectTypeName ( 207 ACPI_OBJECT_TYPE Type); 208 209 static char * 210 AcpiDmNormalizeParentPrefix ( 211 ACPI_PARSE_OBJECT *Op, 212 char *Path); 213 214 static void 215 AcpiDmAddPathToExternalList ( 216 char *Path, 217 UINT8 Type, 218 UINT32 Value, 219 UINT16 Flags); 220 221 static ACPI_STATUS 222 AcpiDmCreateNewExternal ( 223 char *ExternalPath, 224 char *InternalPath, 225 UINT8 Type, 226 UINT32 Value, 227 UINT16 Flags); 228 229 230 /******************************************************************************* 231 * 232 * FUNCTION: AcpiDmGetObjectTypeName 233 * 234 * PARAMETERS: Type - An ACPI_OBJECT_TYPE 235 * 236 * RETURN: Pointer to a string 237 * 238 * DESCRIPTION: Map an object type to the ASL object type string. 239 * 240 ******************************************************************************/ 241 242 static const char * 243 AcpiDmGetObjectTypeName ( 244 ACPI_OBJECT_TYPE Type) 245 { 246 247 if (Type == ACPI_TYPE_LOCAL_SCOPE) 248 { 249 Type = ACPI_TYPE_DEVICE; 250 } 251 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD) 252 { 253 return (""); 254 } 255 256 return (AcpiGbl_DmTypeNames[Type]); 257 } 258 259 260 /******************************************************************************* 261 * 262 * FUNCTION: AcpiDmNormalizeParentPrefix 263 * 264 * PARAMETERS: Op - Parse op 265 * Path - Path with parent prefix 266 * 267 * RETURN: The full pathname to the object (from the namespace root) 268 * 269 * DESCRIPTION: Returns the full pathname of a path with parent prefix 270 * The caller must free the fullpath returned. 271 * 272 ******************************************************************************/ 273 274 static char * 275 AcpiDmNormalizeParentPrefix ( 276 ACPI_PARSE_OBJECT *Op, 277 char *Path) 278 { 279 ACPI_NAMESPACE_NODE *Node; 280 char *Fullpath; 281 char *ParentPath; 282 ACPI_SIZE Length; 283 UINT32 Index = 0; 284 285 286 if (!Op) 287 { 288 return (NULL); 289 } 290 291 /* Search upwards in the parse tree until we reach the next namespace node */ 292 293 Op = Op->Common.Parent; 294 while (Op) 295 { 296 if (Op->Common.Node) 297 { 298 break; 299 } 300 301 Op = Op->Common.Parent; 302 } 303 304 if (!Op) 305 { 306 return (NULL); 307 } 308 309 /* 310 * Find the actual parent node for the reference: 311 * Remove all carat prefixes from the input path. 312 * There may be multiple parent prefixes (For example, ^^^M000) 313 */ 314 Node = Op->Common.Node; 315 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX)) 316 { 317 Node = Node->Parent; 318 Path++; 319 } 320 321 if (!Node) 322 { 323 return (NULL); 324 } 325 326 /* Get the full pathname for the parent node */ 327 328 ParentPath = AcpiNsGetExternalPathname (Node); 329 if (!ParentPath) 330 { 331 return (NULL); 332 } 333 334 Length = (strlen (ParentPath) + strlen (Path) + 1); 335 if (ParentPath[1]) 336 { 337 /* 338 * If ParentPath is not just a simple '\', increment the length 339 * for the required dot separator (ParentPath.Path) 340 */ 341 Length++; 342 343 /* For External() statements, we do not want a leading '\' */ 344 345 if (*ParentPath == AML_ROOT_PREFIX) 346 { 347 Index = 1; 348 } 349 } 350 351 Fullpath = ACPI_ALLOCATE_ZEROED (Length); 352 if (!Fullpath) 353 { 354 goto Cleanup; 355 } 356 357 /* 358 * Concatenate parent fullpath and path. For example, 359 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT" 360 * 361 * Copy the parent path 362 */ 363 strcpy (Fullpath, &ParentPath[Index]); 364 365 /* 366 * Add dot separator 367 * (don't need dot if parent fullpath is a single backslash) 368 */ 369 if (ParentPath[1]) 370 { 371 strcat (Fullpath, "."); 372 } 373 374 /* Copy child path (carat parent prefix(es) were skipped above) */ 375 376 strcat (Fullpath, Path); 377 378 Cleanup: 379 ACPI_FREE (ParentPath); 380 return (Fullpath); 381 } 382 383 384 /******************************************************************************* 385 * 386 * FUNCTION: AcpiDmAddToExternalFileList 387 * 388 * PARAMETERS: PathList - Single path or list separated by comma 389 * 390 * RETURN: None 391 * 392 * DESCRIPTION: Add external files to global list 393 * 394 ******************************************************************************/ 395 396 ACPI_STATUS 397 AcpiDmAddToExternalFileList ( 398 char *Pathname) 399 { 400 ACPI_EXTERNAL_FILE *ExternalFile; 401 char *LocalPathname; 402 403 404 if (!Pathname) 405 { 406 return (AE_OK); 407 } 408 409 LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1); 410 if (!LocalPathname) 411 { 412 return (AE_NO_MEMORY); 413 } 414 415 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE)); 416 if (!ExternalFile) 417 { 418 ACPI_FREE (LocalPathname); 419 return (AE_NO_MEMORY); 420 } 421 422 /* Take a copy of the file pathname */ 423 424 strcpy (LocalPathname, Pathname); 425 ExternalFile->Path = LocalPathname; 426 427 if (AcpiGbl_ExternalFileList) 428 { 429 ExternalFile->Next = AcpiGbl_ExternalFileList; 430 } 431 432 AcpiGbl_ExternalFileList = ExternalFile; 433 return (AE_OK); 434 } 435 436 437 /******************************************************************************* 438 * 439 * FUNCTION: AcpiDmClearExternalFileList 440 * 441 * PARAMETERS: None 442 * 443 * RETURN: None 444 * 445 * DESCRIPTION: Clear the external file list 446 * 447 ******************************************************************************/ 448 449 void 450 AcpiDmClearExternalFileList ( 451 void) 452 { 453 ACPI_EXTERNAL_FILE *NextExternal; 454 455 456 while (AcpiGbl_ExternalFileList) 457 { 458 NextExternal = AcpiGbl_ExternalFileList->Next; 459 ACPI_FREE (AcpiGbl_ExternalFileList->Path); 460 ACPI_FREE (AcpiGbl_ExternalFileList); 461 AcpiGbl_ExternalFileList = NextExternal; 462 } 463 } 464 465 466 /******************************************************************************* 467 * 468 * FUNCTION: AcpiDmGetExternalsFromFile 469 * 470 * PARAMETERS: None 471 * 472 * RETURN: None 473 * 474 * DESCRIPTION: Process the optional external reference file. 475 * 476 * Each line in the file should be of the form: 477 * External (<Method namepath>, MethodObj, <ArgCount>) 478 * 479 * Example: 480 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4) 481 * 482 ******************************************************************************/ 483 484 void 485 AcpiDmGetExternalsFromFile ( 486 void) 487 { 488 FILE *ExternalRefFile; 489 char *Token; 490 char *MethodName; 491 UINT32 ArgCount; 492 UINT32 ImportCount = 0; 493 494 495 if (!Gbl_ExternalRefFilename) 496 { 497 return; 498 } 499 500 /* Open the file */ 501 502 ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r"); 503 if (!ExternalRefFile) 504 { 505 fprintf (stderr, "Could not open external reference file \"%s\"\n", 506 Gbl_ExternalRefFilename); 507 AslAbort (); 508 return; 509 } 510 511 /* Each line defines a method */ 512 513 while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile)) 514 { 515 Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */ 516 if (!Token) 517 { 518 continue; 519 } 520 521 if (strcmp (Token, "External")) 522 { 523 continue; 524 } 525 526 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */ 527 if (!MethodName) 528 { 529 continue; 530 } 531 532 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */ 533 if (!Token) 534 { 535 continue; 536 } 537 538 if (strcmp (Token, "MethodObj")) 539 { 540 continue; 541 } 542 543 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */ 544 if (!Token) 545 { 546 continue; 547 } 548 549 /* Convert arg count string to an integer */ 550 551 errno = 0; 552 ArgCount = strtoul (Token, NULL, 0); 553 if (errno) 554 { 555 fprintf (stderr, "Invalid argument count (%s)\n", Token); 556 continue; 557 } 558 559 if (ArgCount > 7) 560 { 561 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount); 562 continue; 563 } 564 565 /* Add this external to the global list */ 566 567 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n", 568 Gbl_ExternalRefFilename, ArgCount, MethodName); 569 570 AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD, 571 ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE)); 572 ImportCount++; 573 } 574 575 if (!ImportCount) 576 { 577 fprintf (stderr, 578 "Did not find any external methods in reference file \"%s\"\n", 579 Gbl_ExternalRefFilename); 580 } 581 else 582 { 583 /* Add the external(s) to the namespace */ 584 585 AcpiDmAddExternalsToNamespace (); 586 587 AcpiOsPrintf ("%s: Imported %u external method definitions\n", 588 Gbl_ExternalRefFilename, ImportCount); 589 } 590 591 fclose (ExternalRefFile); 592 } 593 594 595 /******************************************************************************* 596 * 597 * FUNCTION: AcpiDmAddOpToExternalList 598 * 599 * PARAMETERS: Op - Current parser Op 600 * Path - Internal (AML) path to the object 601 * Type - ACPI object type to be added 602 * Value - Arg count if adding a Method object 603 * Flags - To be passed to the external object 604 * 605 * RETURN: None 606 * 607 * DESCRIPTION: Insert a new name into the global list of Externals which 608 * will in turn be later emitted as an External() declaration 609 * in the disassembled output. 610 * 611 * This function handles the most common case where the referenced 612 * name is simply not found in the constructed namespace. 613 * 614 ******************************************************************************/ 615 616 void 617 AcpiDmAddOpToExternalList ( 618 ACPI_PARSE_OBJECT *Op, 619 char *Path, 620 UINT8 Type, 621 UINT32 Value, 622 UINT16 Flags) 623 { 624 char *ExternalPath; 625 char *InternalPath = Path; 626 char *Temp; 627 ACPI_STATUS Status; 628 629 630 ACPI_FUNCTION_TRACE (DmAddOpToExternalList); 631 632 633 if (!Path) 634 { 635 return_VOID; 636 } 637 638 /* Remove a root backslash if present */ 639 640 if ((*Path == AML_ROOT_PREFIX) && (Path[1])) 641 { 642 Path++; 643 } 644 645 /* Externalize the pathname */ 646 647 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, 648 NULL, &ExternalPath); 649 if (ACPI_FAILURE (Status)) 650 { 651 return_VOID; 652 } 653 654 /* 655 * Get the full pathname from the root if "Path" has one or more 656 * parent prefixes (^). Note: path will not contain a leading '\'. 657 */ 658 if (*Path == (UINT8) AML_PARENT_PREFIX) 659 { 660 Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath); 661 662 /* Set new external path */ 663 664 ACPI_FREE (ExternalPath); 665 ExternalPath = Temp; 666 if (!Temp) 667 { 668 return_VOID; 669 } 670 671 /* Create the new internal pathname */ 672 673 Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED; 674 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath); 675 if (ACPI_FAILURE (Status)) 676 { 677 ACPI_FREE (ExternalPath); 678 return_VOID; 679 } 680 } 681 682 /* Create the new External() declaration node */ 683 684 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, 685 Type, Value, Flags); 686 if (ACPI_FAILURE (Status)) 687 { 688 ACPI_FREE (ExternalPath); 689 if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED) 690 { 691 ACPI_FREE (InternalPath); 692 } 693 } 694 695 return_VOID; 696 } 697 698 699 /******************************************************************************* 700 * 701 * FUNCTION: AcpiDmAddNodeToExternalList 702 * 703 * PARAMETERS: Node - Namespace node for object to be added 704 * Type - ACPI object type to be added 705 * Value - Arg count if adding a Method object 706 * Flags - To be passed to the external object 707 * 708 * RETURN: None 709 * 710 * DESCRIPTION: Insert a new name into the global list of Externals which 711 * will in turn be later emitted as an External() declaration 712 * in the disassembled output. 713 * 714 * This function handles the case where the referenced name has 715 * been found in the namespace, but the name originated in a 716 * table other than the one that is being disassembled (such 717 * as a table that is added via the iASL -e option). 718 * 719 ******************************************************************************/ 720 721 void 722 AcpiDmAddNodeToExternalList ( 723 ACPI_NAMESPACE_NODE *Node, 724 UINT8 Type, 725 UINT32 Value, 726 UINT16 Flags) 727 { 728 char *ExternalPath; 729 char *InternalPath; 730 char *Temp; 731 ACPI_STATUS Status; 732 733 734 ACPI_FUNCTION_TRACE (DmAddNodeToExternalList); 735 736 737 if (!Node) 738 { 739 return_VOID; 740 } 741 742 /* Get the full external and internal pathnames to the node */ 743 744 ExternalPath = AcpiNsGetExternalPathname (Node); 745 if (!ExternalPath) 746 { 747 return_VOID; 748 } 749 750 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath); 751 if (ACPI_FAILURE (Status)) 752 { 753 ACPI_FREE (ExternalPath); 754 return_VOID; 755 } 756 757 /* Remove the root backslash */ 758 759 if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1])) 760 { 761 Temp = ACPI_ALLOCATE_ZEROED (strlen (ExternalPath) + 1); 762 if (!Temp) 763 { 764 return_VOID; 765 } 766 767 strcpy (Temp, &ExternalPath[1]); 768 ACPI_FREE (ExternalPath); 769 ExternalPath = Temp; 770 } 771 772 /* Create the new External() declaration node */ 773 774 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type, 775 Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED)); 776 if (ACPI_FAILURE (Status)) 777 { 778 ACPI_FREE (ExternalPath); 779 ACPI_FREE (InternalPath); 780 } 781 782 return_VOID; 783 } 784 785 786 /******************************************************************************* 787 * 788 * FUNCTION: AcpiDmAddPathToExternalList 789 * 790 * PARAMETERS: Path - External name of the object to be added 791 * Type - ACPI object type to be added 792 * Value - Arg count if adding a Method object 793 * Flags - To be passed to the external object 794 * 795 * RETURN: None 796 * 797 * DESCRIPTION: Insert a new name into the global list of Externals which 798 * will in turn be later emitted as an External() declaration 799 * in the disassembled output. 800 * 801 * This function currently is used to add externals via a 802 * reference file (via the -fe iASL option). 803 * 804 ******************************************************************************/ 805 806 static void 807 AcpiDmAddPathToExternalList ( 808 char *Path, 809 UINT8 Type, 810 UINT32 Value, 811 UINT16 Flags) 812 { 813 char *InternalPath; 814 char *ExternalPath; 815 ACPI_STATUS Status; 816 817 818 ACPI_FUNCTION_TRACE (DmAddPathToExternalList); 819 820 821 if (!Path) 822 { 823 return_VOID; 824 } 825 826 /* Remove a root backslash if present */ 827 828 if ((*Path == AML_ROOT_PREFIX) && (Path[1])) 829 { 830 Path++; 831 } 832 833 /* Create the internal and external pathnames */ 834 835 Status = AcpiNsInternalizeName (Path, &InternalPath); 836 if (ACPI_FAILURE (Status)) 837 { 838 return_VOID; 839 } 840 841 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, 842 NULL, &ExternalPath); 843 if (ACPI_FAILURE (Status)) 844 { 845 ACPI_FREE (InternalPath); 846 return_VOID; 847 } 848 849 /* Create the new External() declaration node */ 850 851 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, 852 Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED)); 853 if (ACPI_FAILURE (Status)) 854 { 855 ACPI_FREE (ExternalPath); 856 ACPI_FREE (InternalPath); 857 } 858 859 return_VOID; 860 } 861 862 863 /******************************************************************************* 864 * 865 * FUNCTION: AcpiDmCreateNewExternal 866 * 867 * PARAMETERS: ExternalPath - External path to the object 868 * InternalPath - Internal (AML) path to the object 869 * Type - ACPI object type to be added 870 * Value - Arg count if adding a Method object 871 * Flags - To be passed to the external object 872 * 873 * RETURN: Status 874 * 875 * DESCRIPTION: Common low-level function to insert a new name into the global 876 * list of Externals which will in turn be later emitted as 877 * External() declarations in the disassembled output. 878 * 879 * Note: The external name should not include a root prefix 880 * (backslash). We do not want External() statements to contain 881 * a leading '\', as this prevents duplicate external statements 882 * of the form: 883 * 884 * External (\ABCD) 885 * External (ABCD) 886 * 887 * This would cause a compile time error when the disassembled 888 * output file is recompiled. 889 * 890 * There are two cases that are handled here. For both, we emit 891 * an External() statement: 892 * 1) The name was simply not found in the namespace. 893 * 2) The name was found, but it originated in a table other than 894 * the table that is being disassembled. 895 * 896 ******************************************************************************/ 897 898 static ACPI_STATUS 899 AcpiDmCreateNewExternal ( 900 char *ExternalPath, 901 char *InternalPath, 902 UINT8 Type, 903 UINT32 Value, 904 UINT16 Flags) 905 { 906 ACPI_EXTERNAL_LIST *NewExternal; 907 ACPI_EXTERNAL_LIST *NextExternal; 908 ACPI_EXTERNAL_LIST *PrevExternal = NULL; 909 910 911 ACPI_FUNCTION_TRACE (DmCreateNewExternal); 912 913 914 /* Check all existing externals to ensure no duplicates */ 915 916 NextExternal = AcpiGbl_ExternalList; 917 while (NextExternal) 918 { 919 /* Check for duplicates */ 920 921 if (!strcmp (ExternalPath, NextExternal->Path)) 922 { 923 /* 924 * If this external came from an External() opcode, we are 925 * finished with this one. (No need to check any further). 926 */ 927 if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE) 928 { 929 return_ACPI_STATUS (AE_ALREADY_EXISTS); 930 } 931 932 /* Allow upgrade of type from ANY */ 933 934 else if ((NextExternal->Type == ACPI_TYPE_ANY) && 935 (Type != ACPI_TYPE_ANY)) 936 { 937 NextExternal->Type = Type; 938 } 939 940 /* Update the argument count as necessary */ 941 942 if (Value < NextExternal->Value) 943 { 944 NextExternal->Value = Value; 945 } 946 947 /* Update flags. */ 948 949 NextExternal->Flags |= Flags; 950 NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED; 951 952 return_ACPI_STATUS (AE_ALREADY_EXISTS); 953 } 954 955 NextExternal = NextExternal->Next; 956 } 957 958 /* Allocate and init a new External() descriptor */ 959 960 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); 961 if (!NewExternal) 962 { 963 return_ACPI_STATUS (AE_NO_MEMORY); 964 } 965 966 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 967 "Adding external reference node (%s) type [%s]\n", 968 ExternalPath, AcpiUtGetTypeName (Type))); 969 970 NewExternal->Flags = Flags; 971 NewExternal->Value = Value; 972 NewExternal->Path = ExternalPath; 973 NewExternal->Type = Type; 974 NewExternal->Length = (UINT16) strlen (ExternalPath); 975 NewExternal->InternalPath = InternalPath; 976 977 /* Link the new descriptor into the global list, alphabetically ordered */ 978 979 NextExternal = AcpiGbl_ExternalList; 980 while (NextExternal) 981 { 982 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0) 983 { 984 if (PrevExternal) 985 { 986 PrevExternal->Next = NewExternal; 987 } 988 else 989 { 990 AcpiGbl_ExternalList = NewExternal; 991 } 992 993 NewExternal->Next = NextExternal; 994 return_ACPI_STATUS (AE_OK); 995 } 996 997 PrevExternal = NextExternal; 998 NextExternal = NextExternal->Next; 999 } 1000 1001 if (PrevExternal) 1002 { 1003 PrevExternal->Next = NewExternal; 1004 } 1005 else 1006 { 1007 AcpiGbl_ExternalList = NewExternal; 1008 } 1009 1010 return_ACPI_STATUS (AE_OK); 1011 } 1012 1013 1014 /******************************************************************************* 1015 * 1016 * FUNCTION: AcpiDmAddExternalsToNamespace 1017 * 1018 * PARAMETERS: None 1019 * 1020 * RETURN: None 1021 * 1022 * DESCRIPTION: Add all externals to the namespace. Allows externals to be 1023 * "resolved". 1024 * 1025 ******************************************************************************/ 1026 1027 void 1028 AcpiDmAddExternalsToNamespace ( 1029 void) 1030 { 1031 ACPI_STATUS Status; 1032 ACPI_NAMESPACE_NODE *Node; 1033 ACPI_OPERAND_OBJECT *ObjDesc; 1034 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 1035 1036 1037 while (External) 1038 { 1039 /* Add the external name (object) into the namespace */ 1040 1041 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type, 1042 ACPI_IMODE_LOAD_PASS1, 1043 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, 1044 NULL, &Node); 1045 1046 if (ACPI_FAILURE (Status)) 1047 { 1048 ACPI_EXCEPTION ((AE_INFO, Status, 1049 "while adding external to namespace [%s]", 1050 External->Path)); 1051 } 1052 1053 else switch (External->Type) 1054 { 1055 case ACPI_TYPE_METHOD: 1056 1057 /* For methods, we need to save the argument count */ 1058 1059 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 1060 ObjDesc->Method.ParamCount = (UINT8) External->Value; 1061 Node->Object = ObjDesc; 1062 break; 1063 1064 case ACPI_TYPE_REGION: 1065 1066 /* Regions require a region sub-object */ 1067 1068 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION); 1069 ObjDesc->Region.Node = Node; 1070 Node->Object = ObjDesc; 1071 break; 1072 1073 default: 1074 1075 break; 1076 } 1077 1078 External = External->Next; 1079 } 1080 } 1081 1082 1083 /******************************************************************************* 1084 * 1085 * FUNCTION: AcpiDmGetExternalMethodCount 1086 * 1087 * PARAMETERS: None 1088 * 1089 * RETURN: The number of control method externals in the external list 1090 * 1091 * DESCRIPTION: Return the number of method externals that have been generated. 1092 * If any control method externals have been found, we must 1093 * re-parse the entire definition block with the new information 1094 * (number of arguments for the methods.) This is limitation of 1095 * AML, we don't know the number of arguments from the control 1096 * method invocation itself. 1097 * 1098 ******************************************************************************/ 1099 1100 UINT32 1101 AcpiDmGetExternalMethodCount ( 1102 void) 1103 { 1104 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 1105 UINT32 Count = 0; 1106 1107 1108 while (External) 1109 { 1110 if (External->Type == ACPI_TYPE_METHOD) 1111 { 1112 Count++; 1113 } 1114 1115 External = External->Next; 1116 } 1117 1118 return (Count); 1119 } 1120 1121 1122 /******************************************************************************* 1123 * 1124 * FUNCTION: AcpiDmClearExternalList 1125 * 1126 * PARAMETERS: None 1127 * 1128 * RETURN: None 1129 * 1130 * DESCRIPTION: Free the entire External info list 1131 * 1132 ******************************************************************************/ 1133 1134 void 1135 AcpiDmClearExternalList ( 1136 void) 1137 { 1138 ACPI_EXTERNAL_LIST *NextExternal; 1139 1140 1141 while (AcpiGbl_ExternalList) 1142 { 1143 NextExternal = AcpiGbl_ExternalList->Next; 1144 ACPI_FREE (AcpiGbl_ExternalList->Path); 1145 ACPI_FREE (AcpiGbl_ExternalList); 1146 AcpiGbl_ExternalList = NextExternal; 1147 } 1148 } 1149 1150 1151 /******************************************************************************* 1152 * 1153 * FUNCTION: AcpiDmEmitExternals 1154 * 1155 * PARAMETERS: None 1156 * 1157 * RETURN: None 1158 * 1159 * DESCRIPTION: Emit an External() ASL statement for each of the externals in 1160 * the global external info list. 1161 * 1162 ******************************************************************************/ 1163 1164 void 1165 AcpiDmEmitExternals ( 1166 void) 1167 { 1168 ACPI_EXTERNAL_LIST *NextExternal; 1169 1170 1171 if (!AcpiGbl_ExternalList) 1172 { 1173 return; 1174 } 1175 1176 /* 1177 * Determine the number of control methods in the external list, and 1178 * also how many of those externals were resolved via the namespace. 1179 */ 1180 NextExternal = AcpiGbl_ExternalList; 1181 while (NextExternal) 1182 { 1183 if (NextExternal->Type == ACPI_TYPE_METHOD) 1184 { 1185 AcpiGbl_NumExternalMethods++; 1186 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE) 1187 { 1188 AcpiGbl_ResolvedExternalMethods++; 1189 } 1190 } 1191 1192 NextExternal = NextExternal->Next; 1193 } 1194 1195 /* Check if any control methods were unresolved */ 1196 1197 AcpiDmUnresolvedWarning (1); 1198 1199 if (Gbl_ExternalRefFilename) 1200 { 1201 AcpiOsPrintf ( 1202 " /*\n * External declarations were imported from\n" 1203 " * a reference file -- %s\n */\n\n", 1204 Gbl_ExternalRefFilename); 1205 } 1206 1207 /* 1208 * Walk and emit the list of externals found during the AML parsing 1209 */ 1210 while (AcpiGbl_ExternalList) 1211 { 1212 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED)) 1213 { 1214 AcpiOsPrintf (" External (%s%s)", 1215 AcpiGbl_ExternalList->Path, 1216 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type)); 1217 1218 /* Check for "unresolved" method reference */ 1219 1220 if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) && 1221 (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE))) 1222 { 1223 AcpiOsPrintf (" // Warning: Unknown method, " 1224 "guessing %u arguments", 1225 AcpiGbl_ExternalList->Value); 1226 } 1227 1228 /* Check for external from a external references file */ 1229 1230 else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE) 1231 { 1232 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 1233 { 1234 AcpiOsPrintf (" // %u Arguments", 1235 AcpiGbl_ExternalList->Value); 1236 } 1237 1238 AcpiOsPrintf (" // From external reference file"); 1239 } 1240 1241 /* This is the normal external case */ 1242 1243 else 1244 { 1245 /* For methods, add a comment with the number of arguments */ 1246 1247 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 1248 { 1249 AcpiOsPrintf (" // %u Arguments", 1250 AcpiGbl_ExternalList->Value); 1251 } 1252 } 1253 1254 AcpiOsPrintf ("\n"); 1255 } 1256 1257 /* Free this external info block and move on to next external */ 1258 1259 NextExternal = AcpiGbl_ExternalList->Next; 1260 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED) 1261 { 1262 ACPI_FREE (AcpiGbl_ExternalList->InternalPath); 1263 } 1264 1265 ACPI_FREE (AcpiGbl_ExternalList->Path); 1266 ACPI_FREE (AcpiGbl_ExternalList); 1267 AcpiGbl_ExternalList = NextExternal; 1268 } 1269 1270 AcpiOsPrintf ("\n"); 1271 } 1272 1273 1274 /******************************************************************************* 1275 * 1276 * FUNCTION: AcpiDmEmitExternal 1277 * 1278 * PARAMETERS: Op External Parse Object 1279 * 1280 * RETURN: None 1281 * 1282 * DESCRIPTION: Emit an External() ASL statement for the current External 1283 * parse object 1284 * 1285 ******************************************************************************/ 1286 1287 void 1288 AcpiDmEmitExternal ( 1289 ACPI_PARSE_OBJECT *NameOp, 1290 ACPI_PARSE_OBJECT *TypeOp) 1291 { 1292 AcpiOsPrintf ("External ("); 1293 AcpiDmNamestring (NameOp->Common.Value.Name); 1294 AcpiOsPrintf ("%s)\n", 1295 AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer)); 1296 } 1297 1298 1299 /******************************************************************************* 1300 * 1301 * FUNCTION: AcpiDmUnresolvedWarning 1302 * 1303 * PARAMETERS: Type - Where to output the warning. 1304 * 0 means write to stderr 1305 * 1 means write to AcpiOsPrintf 1306 * 1307 * RETURN: None 1308 * 1309 * DESCRIPTION: Issue warning message if there are unresolved external control 1310 * methods within the disassembly. 1311 * 1312 ******************************************************************************/ 1313 1314 #if 0 1315 Summary of the external control method problem: 1316 1317 When the -e option is used with disassembly, the various SSDTs are simply 1318 loaded into a global namespace for the disassembler to use in order to 1319 resolve control method references (invocations). 1320 1321 The disassembler tracks any such references, and will emit an External() 1322 statement for these types of methods, with the proper number of arguments . 1323 1324 Without the SSDTs, the AML does not contain enough information to properly 1325 disassemble the control method invocation -- because the disassembler does 1326 not know how many arguments to parse. 1327 1328 An example: Assume we have two control methods. ABCD has one argument, and 1329 EFGH has zero arguments. Further, we have two additional control methods 1330 that invoke ABCD and EFGH, named T1 and T2: 1331 1332 Method (ABCD, 1) 1333 { 1334 } 1335 Method (EFGH, 0) 1336 { 1337 } 1338 Method (T1) 1339 { 1340 ABCD (Add (2, 7, Local0)) 1341 } 1342 Method (T2) 1343 { 1344 EFGH () 1345 Add (2, 7, Local0) 1346 } 1347 1348 Here is the AML code that is generated for T1 and T2: 1349 1350 185: Method (T1) 1351 1352 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__." 1353 1354 186: { 1355 187: ABCD (Add (2, 7, Local0)) 1356 1357 00000353: 41 42 43 44 ............ "ABCD" 1358 00000357: 72 0A 02 0A 07 60 ...... "r....`" 1359 1360 188: } 1361 1362 190: Method (T2) 1363 1364 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__." 1365 1366 191: { 1367 192: EFGH () 1368 1369 00000364: 45 46 47 48 ............ "EFGH" 1370 1371 193: Add (2, 7, Local0) 1372 1373 00000368: 72 0A 02 0A 07 60 ...... "r....`" 1374 194: } 1375 1376 Note that the AML code for T1 and T2 is essentially identical. When 1377 disassembling this code, the methods ABCD and EFGH must be known to the 1378 disassembler, otherwise it does not know how to handle the method invocations. 1379 1380 In other words, if ABCD and EFGH are actually external control methods 1381 appearing in an SSDT, the disassembler does not know what to do unless 1382 the owning SSDT has been loaded via the -e option. 1383 #endif 1384 1385 static char ExternalWarningPart1[600]; 1386 static char ExternalWarningPart2[400]; 1387 static char ExternalWarningPart3[400]; 1388 static char ExternalWarningPart4[200]; 1389 1390 void 1391 AcpiDmUnresolvedWarning ( 1392 UINT8 Type) 1393 { 1394 char *Format; 1395 char Pad[] = " *"; 1396 char NoPad[] = ""; 1397 1398 1399 if (!AcpiGbl_NumExternalMethods) 1400 { 1401 return; 1402 } 1403 1404 if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods) 1405 { 1406 return; 1407 } 1408 1409 Format = Type ? Pad : NoPad; 1410 1411 sprintf (ExternalWarningPart1, 1412 "%s iASL Warning: There %s %u external control method%s found during\n" 1413 "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n" 1414 "%s ACPI tables may be required to properly disassemble the code. This\n" 1415 "%s resulting disassembler output file may not compile because the\n" 1416 "%s disassembler did not know how many arguments to assign to the\n" 1417 "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n" 1418 "%s runtime and may or may not be available via the host OS.\n", 1419 Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"), 1420 AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""), 1421 Format, AcpiGbl_ResolvedExternalMethods, 1422 (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"), 1423 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods), 1424 Format, Format, Format, Format, Format); 1425 1426 sprintf (ExternalWarningPart2, 1427 "%s To specify the tables needed to resolve external control method\n" 1428 "%s references, the -e option can be used to specify the filenames.\n" 1429 "%s Example iASL invocations:\n" 1430 "%s iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n" 1431 "%s iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n" 1432 "%s iasl -e ssdt*.aml -d dsdt.aml\n", 1433 Format, Format, Format, Format, Format, Format); 1434 1435 sprintf (ExternalWarningPart3, 1436 "%s In addition, the -fe option can be used to specify a file containing\n" 1437 "%s control method external declarations with the associated method\n" 1438 "%s argument counts. Each line of the file must be of the form:\n" 1439 "%s External (<method pathname>, MethodObj, <argument count>)\n" 1440 "%s Invocation:\n" 1441 "%s iasl -fe refs.txt -d dsdt.aml\n", 1442 Format, Format, Format, Format, Format, Format); 1443 1444 sprintf (ExternalWarningPart4, 1445 "%s The following methods were unresolved and many not compile properly\n" 1446 "%s because the disassembler had to guess at the number of arguments\n" 1447 "%s required for each:\n", 1448 Format, Format, Format); 1449 1450 if (Type) 1451 { 1452 if (!AcpiGbl_ExternalFileList) 1453 { 1454 /* The -e option was not specified */ 1455 1456 AcpiOsPrintf (" /*\n%s *\n%s *\n%s *\n%s */\n", 1457 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3, 1458 ExternalWarningPart4); 1459 } 1460 else 1461 { 1462 /* The -e option was specified, but there are still some unresolved externals */ 1463 1464 AcpiOsPrintf (" /*\n%s *\n%s *\n%s */\n", 1465 ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4); 1466 } 1467 } 1468 else 1469 { 1470 if (!AcpiGbl_ExternalFileList) 1471 { 1472 /* The -e option was not specified */ 1473 1474 fprintf (stderr, "\n%s\n%s\n%s\n", 1475 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3); 1476 } 1477 else 1478 { 1479 /* The -e option was specified, but there are still some unresolved externals */ 1480 1481 fprintf (stderr, "\n%s\n%s\n", 1482 ExternalWarningPart1, ExternalWarningPart3); 1483 } 1484 } 1485 } 1486