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 - 2020, 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 static const char *ExternalConflictMessage = 203 " // Conflicts with a later declaration"; 204 205 206 /* Local prototypes */ 207 208 static const char * 209 AcpiDmGetObjectTypeName ( 210 ACPI_OBJECT_TYPE Type); 211 212 static char * 213 AcpiDmNormalizeParentPrefix ( 214 ACPI_PARSE_OBJECT *Op, 215 char *Path); 216 217 static ACPI_STATUS 218 AcpiDmGetExternalAndInternalPath ( 219 ACPI_NAMESPACE_NODE *Node, 220 char **ExternalPath, 221 char **InternalPath); 222 223 static ACPI_STATUS 224 AcpiDmRemoveRootPrefix ( 225 char **Path); 226 227 static void 228 AcpiDmAddPathToExternalList ( 229 char *Path, 230 UINT8 Type, 231 UINT32 Value, 232 UINT16 Flags); 233 234 static ACPI_STATUS 235 AcpiDmCreateNewExternal ( 236 char *ExternalPath, 237 char *InternalPath, 238 UINT8 Type, 239 UINT32 Value, 240 UINT16 Flags); 241 242 static void 243 AcpiDmCheckForExternalConflict ( 244 char *Path); 245 246 static ACPI_STATUS 247 AcpiDmResolveExternal ( 248 char *Path, 249 UINT8 Type, 250 ACPI_NAMESPACE_NODE **Node); 251 252 253 static void 254 AcpiDmConflictingDeclaration ( 255 char *Path); 256 257 258 /******************************************************************************* 259 * 260 * FUNCTION: AcpiDmGetObjectTypeName 261 * 262 * PARAMETERS: Type - An ACPI_OBJECT_TYPE 263 * 264 * RETURN: Pointer to a string 265 * 266 * DESCRIPTION: Map an object type to the ASL object type string. 267 * 268 ******************************************************************************/ 269 270 static const char * 271 AcpiDmGetObjectTypeName ( 272 ACPI_OBJECT_TYPE Type) 273 { 274 275 if (Type == ACPI_TYPE_LOCAL_SCOPE) 276 { 277 Type = ACPI_TYPE_DEVICE; 278 } 279 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD) 280 { 281 return (""); 282 } 283 284 return (AcpiGbl_DmTypeNames[Type]); 285 } 286 287 288 /******************************************************************************* 289 * 290 * FUNCTION: AcpiDmNormalizeParentPrefix 291 * 292 * PARAMETERS: Op - Parse op 293 * Path - Path with parent prefix 294 * 295 * RETURN: The full pathname to the object (from the namespace root) 296 * 297 * DESCRIPTION: Returns the full pathname of a path with parent prefix 298 * The caller must free the fullpath returned. 299 * 300 ******************************************************************************/ 301 302 static char * 303 AcpiDmNormalizeParentPrefix ( 304 ACPI_PARSE_OBJECT *Op, 305 char *Path) 306 { 307 ACPI_NAMESPACE_NODE *Node; 308 char *Fullpath; 309 char *ParentPath; 310 ACPI_SIZE Length; 311 UINT32 Index = 0; 312 313 314 if (!Op) 315 { 316 return (NULL); 317 } 318 319 /* Search upwards in the parse tree until we reach the next namespace node */ 320 321 Op = Op->Common.Parent; 322 while (Op) 323 { 324 if (Op->Common.Node) 325 { 326 break; 327 } 328 329 Op = Op->Common.Parent; 330 } 331 332 if (!Op) 333 { 334 return (NULL); 335 } 336 337 /* 338 * Find the actual parent node for the reference: 339 * Remove all carat prefixes from the input path. 340 * There may be multiple parent prefixes (For example, ^^^M000) 341 */ 342 Node = Op->Common.Node; 343 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX)) 344 { 345 Node = Node->Parent; 346 Path++; 347 } 348 349 if (!Node) 350 { 351 return (NULL); 352 } 353 354 /* Get the full pathname for the parent node */ 355 356 ParentPath = AcpiNsGetExternalPathname (Node); 357 if (!ParentPath) 358 { 359 return (NULL); 360 } 361 362 Length = (strlen (ParentPath) + strlen (Path) + 1); 363 if (ParentPath[1]) 364 { 365 /* 366 * If ParentPath is not just a simple '\', increment the length 367 * for the required dot separator (ParentPath.Path) 368 */ 369 Length++; 370 371 /* For External() statements, we do not want a leading '\' */ 372 373 if (*ParentPath == AML_ROOT_PREFIX) 374 { 375 Index = 1; 376 } 377 } 378 379 Fullpath = ACPI_ALLOCATE_ZEROED (Length); 380 if (!Fullpath) 381 { 382 goto Cleanup; 383 } 384 385 /* 386 * Concatenate parent fullpath and path. For example, 387 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT" 388 * 389 * Copy the parent path 390 */ 391 strcpy (Fullpath, &ParentPath[Index]); 392 393 /* 394 * Add dot separator 395 * (don't need dot if parent fullpath is a single backslash) 396 */ 397 if (ParentPath[1]) 398 { 399 strcat (Fullpath, "."); 400 } 401 402 /* Copy child path (carat parent prefix(es) were skipped above) */ 403 404 strcat (Fullpath, Path); 405 406 Cleanup: 407 ACPI_FREE (ParentPath); 408 return (Fullpath); 409 } 410 411 412 /******************************************************************************* 413 * 414 * FUNCTION: AcpiDmAddToExternalFileList 415 * 416 * PARAMETERS: PathList - Single path or list separated by comma 417 * 418 * RETURN: None 419 * 420 * DESCRIPTION: Add external files to global list 421 * 422 ******************************************************************************/ 423 424 ACPI_STATUS 425 AcpiDmAddToExternalFileList ( 426 char *Pathname) 427 { 428 ACPI_EXTERNAL_FILE *ExternalFile; 429 char *LocalPathname; 430 431 432 if (!Pathname) 433 { 434 return (AE_OK); 435 } 436 437 LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1); 438 if (!LocalPathname) 439 { 440 return (AE_NO_MEMORY); 441 } 442 443 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE)); 444 if (!ExternalFile) 445 { 446 ACPI_FREE (LocalPathname); 447 return (AE_NO_MEMORY); 448 } 449 450 /* Take a copy of the file pathname */ 451 452 strcpy (LocalPathname, Pathname); 453 ExternalFile->Path = LocalPathname; 454 455 if (AcpiGbl_ExternalFileList) 456 { 457 ExternalFile->Next = AcpiGbl_ExternalFileList; 458 } 459 460 AcpiGbl_ExternalFileList = ExternalFile; 461 return (AE_OK); 462 } 463 464 465 /******************************************************************************* 466 * 467 * FUNCTION: AcpiDmClearExternalFileList 468 * 469 * PARAMETERS: None 470 * 471 * RETURN: None 472 * 473 * DESCRIPTION: Clear the external file list 474 * 475 ******************************************************************************/ 476 477 void 478 AcpiDmClearExternalFileList ( 479 void) 480 { 481 ACPI_EXTERNAL_FILE *NextExternal; 482 483 484 while (AcpiGbl_ExternalFileList) 485 { 486 NextExternal = AcpiGbl_ExternalFileList->Next; 487 ACPI_FREE (AcpiGbl_ExternalFileList->Path); 488 ACPI_FREE (AcpiGbl_ExternalFileList); 489 AcpiGbl_ExternalFileList = NextExternal; 490 } 491 } 492 493 494 /******************************************************************************* 495 * 496 * FUNCTION: AcpiDmGetExternalsFromFile 497 * 498 * PARAMETERS: None 499 * 500 * RETURN: None 501 * 502 * DESCRIPTION: Process the optional external reference file. 503 * 504 * Each line in the file should be of the form: 505 * External (<Method namepath>, MethodObj, <ArgCount>) 506 * 507 * Example: 508 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4) 509 * 510 ******************************************************************************/ 511 512 void 513 AcpiDmGetExternalsFromFile ( 514 void) 515 { 516 FILE *ExternalRefFile; 517 char *Token; 518 char *MethodName; 519 UINT32 ArgCount; 520 UINT32 ImportCount = 0; 521 522 523 if (!AslGbl_ExternalRefFilename) 524 { 525 return; 526 } 527 528 /* Open the file */ 529 530 ExternalRefFile = fopen (AslGbl_ExternalRefFilename, "r"); 531 if (!ExternalRefFile) 532 { 533 fprintf (stderr, "Could not open external reference file \"%s\"\n", 534 AslGbl_ExternalRefFilename); 535 AslAbort (); 536 return; 537 } 538 539 /* Each line defines a method */ 540 541 while (fgets (AslGbl_StringBuffer, ASL_STRING_BUFFER_SIZE, ExternalRefFile)) 542 { 543 Token = strtok (AslGbl_StringBuffer, METHOD_SEPARATORS); /* "External" */ 544 if (!Token) 545 { 546 continue; 547 } 548 549 if (strcmp (Token, "External")) 550 { 551 continue; 552 } 553 554 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */ 555 if (!MethodName) 556 { 557 continue; 558 } 559 560 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */ 561 if (!Token) 562 { 563 continue; 564 } 565 566 if (strcmp (Token, "MethodObj")) 567 { 568 continue; 569 } 570 571 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */ 572 if (!Token) 573 { 574 continue; 575 } 576 577 /* Convert arg count string to an integer */ 578 579 errno = 0; 580 ArgCount = strtoul (Token, NULL, 0); 581 if (errno) 582 { 583 fprintf (stderr, "Invalid argument count (%s)\n", Token); 584 continue; 585 } 586 587 if (ArgCount > 7) 588 { 589 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount); 590 continue; 591 } 592 593 /* Add this external to the global list */ 594 595 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n", 596 AslGbl_ExternalRefFilename, ArgCount, MethodName); 597 598 AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD, 599 ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE)); 600 ImportCount++; 601 } 602 603 if (!ImportCount) 604 { 605 fprintf (stderr, 606 "Did not find any external methods in reference file \"%s\"\n", 607 AslGbl_ExternalRefFilename); 608 } 609 else 610 { 611 /* Add the external(s) to the namespace */ 612 613 AcpiDmAddExternalListToNamespace (); 614 615 AcpiOsPrintf ("%s: Imported %u external method definitions\n", 616 AslGbl_ExternalRefFilename, ImportCount); 617 } 618 619 fclose (ExternalRefFile); 620 } 621 622 623 /******************************************************************************* 624 * 625 * FUNCTION: AcpiDmAddOpToExternalList 626 * 627 * PARAMETERS: Op - Current parser Op 628 * Path - Internal (AML) path to the object 629 * Type - ACPI object type to be added 630 * Value - Arg count if adding a Method object 631 * Flags - To be passed to the external object 632 * 633 * RETURN: None 634 * 635 * DESCRIPTION: Insert a new name into the global list of Externals which 636 * will in turn be later emitted as an External() declaration 637 * in the disassembled output. 638 * 639 * This function handles the most common case where the referenced 640 * name is simply not found in the constructed namespace. 641 * 642 ******************************************************************************/ 643 644 void 645 AcpiDmAddOpToExternalList ( 646 ACPI_PARSE_OBJECT *Op, 647 char *Path, 648 UINT8 Type, 649 UINT32 Value, 650 UINT16 Flags) 651 { 652 char *ExternalPath; 653 char *InternalPath = Path; 654 char *Temp; 655 ACPI_STATUS Status; 656 657 658 ACPI_FUNCTION_TRACE (DmAddOpToExternalList); 659 660 661 if (!Path) 662 { 663 return_VOID; 664 } 665 666 /* Remove a root backslash if present */ 667 668 if ((*Path == AML_ROOT_PREFIX) && (Path[1])) 669 { 670 Path++; 671 } 672 673 /* Externalize the pathname */ 674 675 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, 676 NULL, &ExternalPath); 677 if (ACPI_FAILURE (Status)) 678 { 679 return_VOID; 680 } 681 682 /* 683 * Get the full pathname from the root if "Path" has one or more 684 * parent prefixes (^). Note: path will not contain a leading '\'. 685 */ 686 if (*Path == (UINT8) AML_PARENT_PREFIX) 687 { 688 Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath); 689 690 /* Set new external path */ 691 692 ACPI_FREE (ExternalPath); 693 ExternalPath = Temp; 694 if (!Temp) 695 { 696 return_VOID; 697 } 698 699 /* Create the new internal pathname */ 700 701 Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED; 702 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath); 703 if (ACPI_FAILURE (Status)) 704 { 705 ACPI_FREE (ExternalPath); 706 return_VOID; 707 } 708 } 709 710 /* Create the new External() declaration node */ 711 712 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, 713 Type, Value, Flags); 714 if (ACPI_FAILURE (Status)) 715 { 716 ACPI_FREE (ExternalPath); 717 if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED) 718 { 719 ACPI_FREE (InternalPath); 720 } 721 } 722 723 return_VOID; 724 } 725 726 727 /******************************************************************************* 728 * 729 * FUNCTION: AcpiDmGetExternalAndInternalPath 730 * 731 * PARAMETERS: Node - Namespace node for object to be added 732 * ExternalPath - Will contain the external path of the node 733 * InternalPath - Will contain the internal path of the node 734 * 735 * RETURN: None 736 * 737 * DESCRIPTION: Get the External and Internal path from the given node. 738 * 739 ******************************************************************************/ 740 741 static ACPI_STATUS 742 AcpiDmGetExternalAndInternalPath ( 743 ACPI_NAMESPACE_NODE *Node, 744 char **ExternalPath, 745 char **InternalPath) 746 { 747 ACPI_STATUS Status; 748 749 750 if (!Node) 751 { 752 return (AE_BAD_PARAMETER); 753 } 754 755 /* Get the full external and internal pathnames to the node */ 756 757 *ExternalPath = AcpiNsGetExternalPathname (Node); 758 if (!*ExternalPath) 759 { 760 return (AE_BAD_PATHNAME); 761 } 762 763 Status = AcpiNsInternalizeName (*ExternalPath, InternalPath); 764 if (ACPI_FAILURE (Status)) 765 { 766 ACPI_FREE (*ExternalPath); 767 return (Status); 768 } 769 770 return (AE_OK); 771 } 772 773 774 /******************************************************************************* 775 * 776 * FUNCTION: AcpiDmRemoveRootPrefix 777 * 778 * PARAMETERS: Path - Remove Root prefix from this Path 779 * 780 * RETURN: None 781 * 782 * DESCRIPTION: Remove the root prefix character '\' from Path. 783 * 784 ******************************************************************************/ 785 786 static ACPI_STATUS 787 AcpiDmRemoveRootPrefix ( 788 char **Path) 789 { 790 char *InputPath = *Path; 791 792 793 if ((*InputPath == AML_ROOT_PREFIX) && (InputPath[1])) 794 { 795 if (!memmove(InputPath, InputPath+1, strlen(InputPath))) 796 { 797 return (AE_ERROR); 798 } 799 800 *Path = InputPath; 801 } 802 803 return (AE_OK); 804 } 805 806 807 /******************************************************************************* 808 * 809 * FUNCTION: AcpiDmAddNodeToExternalList 810 * 811 * PARAMETERS: Node - Namespace node for object to be added 812 * Type - ACPI object type to be added 813 * Value - Arg count if adding a Method object 814 * Flags - To be passed to the external object 815 * 816 * RETURN: None 817 * 818 * DESCRIPTION: Insert a new name into the global list of Externals which 819 * will in turn be later emitted as an External() declaration 820 * in the disassembled output. 821 * 822 * This function handles the case where the referenced name has 823 * been found in the namespace, but the name originated in a 824 * table other than the one that is being disassembled (such 825 * as a table that is added via the iASL -e option). 826 * 827 ******************************************************************************/ 828 829 void 830 AcpiDmAddNodeToExternalList ( 831 ACPI_NAMESPACE_NODE *Node, 832 UINT8 Type, 833 UINT32 Value, 834 UINT16 Flags) 835 { 836 char *ExternalPath; 837 char *InternalPath; 838 ACPI_STATUS Status; 839 840 841 ACPI_FUNCTION_TRACE (DmAddNodeToExternalList); 842 843 /* Get the full external and internal pathnames to the node */ 844 845 Status = AcpiDmGetExternalAndInternalPath (Node, &ExternalPath, &InternalPath); 846 if (ACPI_FAILURE (Status)) 847 { 848 return_VOID; 849 } 850 851 /* Remove the root backslash */ 852 853 Status = AcpiDmRemoveRootPrefix (&ExternalPath); 854 if (ACPI_FAILURE (Status)) 855 { 856 ACPI_FREE (ExternalPath); 857 ACPI_FREE (InternalPath); 858 return_VOID; 859 } 860 861 /* Create the new External() declaration node */ 862 863 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type, 864 Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED)); 865 if (ACPI_FAILURE (Status)) 866 { 867 ACPI_FREE (ExternalPath); 868 ACPI_FREE (InternalPath); 869 } 870 871 return_VOID; 872 } 873 874 875 /******************************************************************************* 876 * 877 * FUNCTION: AcpiDmAddPathToExternalList 878 * 879 * PARAMETERS: Path - External name of the object to be added 880 * Type - ACPI object type to be added 881 * Value - Arg count if adding a Method object 882 * Flags - To be passed to the external object 883 * 884 * RETURN: None 885 * 886 * DESCRIPTION: Insert a new name into the global list of Externals which 887 * will in turn be later emitted as an External() declaration 888 * in the disassembled output. 889 * 890 * This function currently is used to add externals via a 891 * reference file (via the -fe iASL option). 892 * 893 ******************************************************************************/ 894 895 static void 896 AcpiDmAddPathToExternalList ( 897 char *Path, 898 UINT8 Type, 899 UINT32 Value, 900 UINT16 Flags) 901 { 902 char *InternalPath; 903 char *ExternalPath; 904 ACPI_STATUS Status; 905 906 907 ACPI_FUNCTION_TRACE (DmAddPathToExternalList); 908 909 910 if (!Path) 911 { 912 return_VOID; 913 } 914 915 /* Remove a root backslash if present */ 916 917 if ((*Path == AML_ROOT_PREFIX) && (Path[1])) 918 { 919 Path++; 920 } 921 922 /* Create the internal and external pathnames */ 923 924 Status = AcpiNsInternalizeName (Path, &InternalPath); 925 if (ACPI_FAILURE (Status)) 926 { 927 return_VOID; 928 } 929 930 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, 931 NULL, &ExternalPath); 932 if (ACPI_FAILURE (Status)) 933 { 934 ACPI_FREE (InternalPath); 935 return_VOID; 936 } 937 938 /* Create the new External() declaration node */ 939 940 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, 941 Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED)); 942 if (ACPI_FAILURE (Status)) 943 { 944 ACPI_FREE (ExternalPath); 945 ACPI_FREE (InternalPath); 946 } 947 948 return_VOID; 949 } 950 951 952 /******************************************************************************* 953 * 954 * FUNCTION: AcpiDmCreateNewExternal 955 * 956 * PARAMETERS: ExternalPath - External path to the object 957 * InternalPath - Internal (AML) path to the object 958 * Type - ACPI object type to be added 959 * Value - Arg count if adding a Method object 960 * Flags - To be passed to the external object 961 * 962 * RETURN: Status 963 * 964 * DESCRIPTION: Common low-level function to insert a new name into the global 965 * list of Externals which will in turn be later emitted as 966 * External() declarations in the disassembled output. 967 * 968 * Note: The external name should not include a root prefix 969 * (backslash). We do not want External() statements to contain 970 * a leading '\', as this prevents duplicate external statements 971 * of the form: 972 * 973 * External (\ABCD) 974 * External (ABCD) 975 * 976 * This would cause a compile time error when the disassembled 977 * output file is recompiled. 978 * 979 * There are two cases that are handled here. For both, we emit 980 * an External() statement: 981 * 1) The name was simply not found in the namespace. 982 * 2) The name was found, but it originated in a table other than 983 * the table that is being disassembled. 984 * 985 ******************************************************************************/ 986 987 static ACPI_STATUS 988 AcpiDmCreateNewExternal ( 989 char *ExternalPath, 990 char *InternalPath, 991 UINT8 Type, 992 UINT32 Value, 993 UINT16 Flags) 994 { 995 ACPI_EXTERNAL_LIST *NewExternal; 996 ACPI_EXTERNAL_LIST *NextExternal; 997 ACPI_EXTERNAL_LIST *PrevExternal = NULL; 998 999 1000 ACPI_FUNCTION_TRACE (DmCreateNewExternal); 1001 1002 1003 /* Check all existing externals to ensure no duplicates */ 1004 1005 NextExternal = AcpiGbl_ExternalList; 1006 while (NextExternal) 1007 { 1008 /* Check for duplicates */ 1009 1010 if (!strcmp (ExternalPath, NextExternal->Path)) 1011 { 1012 /* 1013 * If this external came from an External() opcode, we are 1014 * finished with this one. (No need to check any further). 1015 */ 1016 if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE) 1017 { 1018 return_ACPI_STATUS (AE_ALREADY_EXISTS); 1019 } 1020 1021 /* Allow upgrade of type from ANY */ 1022 1023 else if ((NextExternal->Type == ACPI_TYPE_ANY) && 1024 (Type != ACPI_TYPE_ANY)) 1025 { 1026 NextExternal->Type = Type; 1027 } 1028 1029 /* Update the argument count as necessary */ 1030 1031 if (Value < NextExternal->Value) 1032 { 1033 NextExternal->Value = Value; 1034 } 1035 1036 /* Update flags. */ 1037 1038 NextExternal->Flags |= Flags; 1039 NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED; 1040 1041 return_ACPI_STATUS (AE_ALREADY_EXISTS); 1042 } 1043 1044 NextExternal = NextExternal->Next; 1045 } 1046 1047 /* Allocate and init a new External() descriptor */ 1048 1049 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); 1050 if (!NewExternal) 1051 { 1052 return_ACPI_STATUS (AE_NO_MEMORY); 1053 } 1054 1055 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 1056 "Adding external reference node (%s) type [%s]\n", 1057 ExternalPath, AcpiUtGetTypeName (Type))); 1058 1059 NewExternal->Flags = Flags; 1060 NewExternal->Value = Value; 1061 NewExternal->Path = ExternalPath; 1062 NewExternal->Type = Type; 1063 NewExternal->Length = (UINT16) strlen (ExternalPath); 1064 NewExternal->InternalPath = InternalPath; 1065 1066 /* Link the new descriptor into the global list, alphabetically ordered */ 1067 1068 NextExternal = AcpiGbl_ExternalList; 1069 while (NextExternal) 1070 { 1071 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0) 1072 { 1073 if (PrevExternal) 1074 { 1075 PrevExternal->Next = NewExternal; 1076 } 1077 else 1078 { 1079 AcpiGbl_ExternalList = NewExternal; 1080 } 1081 1082 NewExternal->Next = NextExternal; 1083 return_ACPI_STATUS (AE_OK); 1084 } 1085 1086 PrevExternal = NextExternal; 1087 NextExternal = NextExternal->Next; 1088 } 1089 1090 if (PrevExternal) 1091 { 1092 PrevExternal->Next = NewExternal; 1093 } 1094 else 1095 { 1096 AcpiGbl_ExternalList = NewExternal; 1097 } 1098 1099 return_ACPI_STATUS (AE_OK); 1100 } 1101 1102 1103 /******************************************************************************* 1104 * 1105 * FUNCTION: AcpiDmResolveExternal 1106 * 1107 * PARAMETERS: Path - Path of the external 1108 * Type - Type of the external 1109 * Node - Input node for AcpiNsLookup 1110 * 1111 * RETURN: Status 1112 * 1113 * DESCRIPTION: Resolve the external within the namespace by AcpiNsLookup. 1114 * If the returned node is an external and has the same type 1115 * we assume that it was either an existing external or a 1116 * 1117 ******************************************************************************/ 1118 1119 static ACPI_STATUS 1120 AcpiDmResolveExternal ( 1121 char *Path, 1122 UINT8 Type, 1123 ACPI_NAMESPACE_NODE **Node) 1124 { 1125 ACPI_STATUS Status; 1126 1127 1128 Status = AcpiNsLookup (NULL, Path, Type, 1129 ACPI_IMODE_LOAD_PASS1, 1130 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, 1131 NULL, Node); 1132 1133 if (!Node) 1134 { 1135 ACPI_EXCEPTION ((AE_INFO, Status, 1136 "while adding external to namespace [%s]", Path)); 1137 } 1138 1139 /* Note the asl code "external(a) external(a)" is acceptable ASL */ 1140 1141 else if ((*Node)->Type == Type && 1142 (*Node)->Flags & ANOBJ_IS_EXTERNAL) 1143 { 1144 return (AE_OK); 1145 } 1146 else 1147 { 1148 ACPI_EXCEPTION ((AE_INFO, AE_ERROR, 1149 "[%s] has conflicting declarations", Path)); 1150 } 1151 1152 return (AE_ERROR); 1153 } 1154 1155 1156 /******************************************************************************* 1157 * 1158 * FUNCTION: AcpiDmCreateSubobjectForExternal 1159 * 1160 * PARAMETERS: Type - Type of the external 1161 * Node - Namespace node from AcpiNsLookup 1162 * ParamCount - Value to be used for Method 1163 * 1164 * RETURN: None 1165 * 1166 * DESCRIPTION: Add one external to the namespace. Allows external to be 1167 * "resolved". 1168 * 1169 ******************************************************************************/ 1170 1171 void 1172 AcpiDmCreateSubobjectForExternal ( 1173 UINT8 Type, 1174 ACPI_NAMESPACE_NODE **Node, 1175 UINT32 ParamCount) 1176 { 1177 ACPI_OPERAND_OBJECT *ObjDesc; 1178 1179 1180 switch (Type) 1181 { 1182 case ACPI_TYPE_METHOD: 1183 1184 /* For methods, we need to save the argument count */ 1185 1186 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 1187 ObjDesc->Method.ParamCount = (UINT8) ParamCount; 1188 (*Node)->Object = ObjDesc; 1189 break; 1190 1191 case ACPI_TYPE_REGION: 1192 1193 /* Regions require a region sub-object */ 1194 1195 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION); 1196 ObjDesc->Region.Node = *Node; 1197 (*Node)->Object = ObjDesc; 1198 break; 1199 1200 default: 1201 1202 break; 1203 } 1204 } 1205 1206 1207 /******************************************************************************* 1208 * 1209 * FUNCTION: AcpiDmAddOneExternalToNamespace 1210 * 1211 * PARAMETERS: Path - External parse object 1212 * Type - Type of parse object 1213 * ParamCount - External method parameter count 1214 * 1215 * RETURN: None 1216 * 1217 * DESCRIPTION: Add one external to the namespace by resolvign the external 1218 * (by performing a namespace lookup) and annotating the resulting 1219 * namespace node with the appropriate information if the type 1220 * is ACPI_TYPE_REGION or ACPI_TYPE_METHOD. 1221 * 1222 ******************************************************************************/ 1223 1224 void 1225 AcpiDmAddOneExternalToNamespace ( 1226 char *Path, 1227 UINT8 Type, 1228 UINT32 ParamCount) 1229 { 1230 ACPI_STATUS Status; 1231 ACPI_NAMESPACE_NODE *Node; 1232 1233 1234 Status = AcpiDmResolveExternal (Path, Type, &Node); 1235 1236 if (ACPI_FAILURE (Status)) 1237 { 1238 return; 1239 } 1240 1241 AcpiDmCreateSubobjectForExternal (Type, &Node, ParamCount); 1242 1243 } 1244 1245 1246 /******************************************************************************* 1247 * 1248 * FUNCTION: AcpiDmAddExternalListToNamespace 1249 * 1250 * PARAMETERS: None 1251 * 1252 * RETURN: None 1253 * 1254 * DESCRIPTION: Add all externals within AcpiGbl_ExternalList to the namespace. 1255 * Allows externals to be "resolved". 1256 * 1257 ******************************************************************************/ 1258 1259 void 1260 AcpiDmAddExternalListToNamespace ( 1261 void) 1262 { 1263 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 1264 1265 1266 while (External) 1267 { 1268 AcpiDmAddOneExternalToNamespace (External->InternalPath, 1269 External->Type, External->Value); 1270 External = External->Next; 1271 } 1272 } 1273 1274 1275 /******************************************************************************* 1276 * 1277 * FUNCTION: AcpiDmGetUnresolvedExternalMethodCount 1278 * 1279 * PARAMETERS: None 1280 * 1281 * RETURN: The number of unresolved control method externals in the 1282 * external list 1283 * 1284 * DESCRIPTION: Return the number of unresolved external methods that have been 1285 * generated. If any unresolved control method externals have been 1286 * found, we must re-parse the entire definition block with the new 1287 * information (number of arguments for the methods.) 1288 * This is limitation of AML, we don't know the number of arguments 1289 * from the control method invocation itself. 1290 * 1291 * Note: resolved external control methods are external control 1292 * methods encoded with the AML_EXTERNAL_OP bytecode within the 1293 * AML being disassembled. 1294 * 1295 ******************************************************************************/ 1296 1297 UINT32 1298 AcpiDmGetUnresolvedExternalMethodCount ( 1299 void) 1300 { 1301 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 1302 UINT32 Count = 0; 1303 1304 1305 while (External) 1306 { 1307 if (External->Type == ACPI_TYPE_METHOD && 1308 !(External->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)) 1309 { 1310 Count++; 1311 } 1312 1313 External = External->Next; 1314 } 1315 1316 return (Count); 1317 } 1318 1319 1320 /******************************************************************************* 1321 * 1322 * FUNCTION: AcpiDmClearExternalList 1323 * 1324 * PARAMETERS: None 1325 * 1326 * RETURN: None 1327 * 1328 * DESCRIPTION: Free the entire External info list 1329 * 1330 ******************************************************************************/ 1331 1332 void 1333 AcpiDmClearExternalList ( 1334 void) 1335 { 1336 ACPI_EXTERNAL_LIST *NextExternal; 1337 1338 1339 while (AcpiGbl_ExternalList) 1340 { 1341 NextExternal = AcpiGbl_ExternalList->Next; 1342 ACPI_FREE (AcpiGbl_ExternalList->Path); 1343 ACPI_FREE (AcpiGbl_ExternalList); 1344 AcpiGbl_ExternalList = NextExternal; 1345 } 1346 } 1347 1348 1349 /******************************************************************************* 1350 * 1351 * FUNCTION: AcpiDmEmitExternals 1352 * 1353 * PARAMETERS: None 1354 * 1355 * RETURN: None 1356 * 1357 * DESCRIPTION: Emit an External() ASL statement for each of the externals in 1358 * the global external info list. 1359 * 1360 ******************************************************************************/ 1361 1362 void 1363 AcpiDmEmitExternals ( 1364 void) 1365 { 1366 ACPI_EXTERNAL_LIST *NextExternal; 1367 1368 1369 if (!AcpiGbl_ExternalList) 1370 { 1371 return; 1372 } 1373 1374 /* 1375 * Determine the number of control methods in the external list, and 1376 * also how many of those externals were resolved via the namespace. 1377 */ 1378 NextExternal = AcpiGbl_ExternalList; 1379 while (NextExternal) 1380 { 1381 if (NextExternal->Type == ACPI_TYPE_METHOD) 1382 { 1383 AcpiGbl_NumExternalMethods++; 1384 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE) 1385 { 1386 AcpiGbl_ResolvedExternalMethods++; 1387 } 1388 } 1389 1390 NextExternal = NextExternal->Next; 1391 } 1392 1393 /* Check if any control methods were unresolved */ 1394 1395 AcpiDmUnresolvedWarning (1); 1396 1397 if (AslGbl_ExternalRefFilename) 1398 { 1399 AcpiOsPrintf ( 1400 " /*\n * External declarations were imported from\n" 1401 " * a reference file -- %s\n */\n\n", 1402 AslGbl_ExternalRefFilename); 1403 } 1404 1405 /* 1406 * Walk and emit the list of externals found during the AML parsing 1407 */ 1408 while (AcpiGbl_ExternalList) 1409 { 1410 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED)) 1411 { 1412 AcpiOsPrintf (" External (%s%s)", 1413 AcpiGbl_ExternalList->Path, 1414 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type)); 1415 1416 /* Check for "unresolved" method reference */ 1417 1418 if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) && 1419 (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE))) 1420 { 1421 AcpiOsPrintf (" // Warning: Unknown method, " 1422 "guessing %u arguments", 1423 AcpiGbl_ExternalList->Value); 1424 } 1425 1426 /* Check for external from a external references file */ 1427 1428 else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE) 1429 { 1430 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 1431 { 1432 AcpiOsPrintf (" // %u Arguments", 1433 AcpiGbl_ExternalList->Value); 1434 } 1435 1436 AcpiOsPrintf (" // From external reference file"); 1437 } 1438 1439 /* This is the normal external case */ 1440 1441 else 1442 { 1443 /* For methods, add a comment with the number of arguments */ 1444 1445 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 1446 { 1447 AcpiOsPrintf (" // %u Arguments", 1448 AcpiGbl_ExternalList->Value); 1449 } 1450 } 1451 1452 if (AcpiGbl_ExternalList->Flags &= ACPI_EXT_CONFLICTING_DECLARATION) 1453 { 1454 AcpiOsPrintf ("%s", ExternalConflictMessage); 1455 AcpiDmConflictingDeclaration (AcpiGbl_ExternalList->Path); 1456 } 1457 AcpiOsPrintf ("\n"); 1458 } 1459 1460 /* Free this external info block and move on to next external */ 1461 1462 NextExternal = AcpiGbl_ExternalList->Next; 1463 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED) 1464 { 1465 ACPI_FREE (AcpiGbl_ExternalList->InternalPath); 1466 } 1467 1468 ACPI_FREE (AcpiGbl_ExternalList->Path); 1469 ACPI_FREE (AcpiGbl_ExternalList); 1470 AcpiGbl_ExternalList = NextExternal; 1471 } 1472 1473 AcpiOsPrintf ("\n"); 1474 } 1475 1476 1477 /******************************************************************************* 1478 * 1479 * FUNCTION: AcpiDmMarkExternalConflict 1480 * 1481 * PARAMETERS: Path - Namepath to search 1482 * 1483 * RETURN: ExternalList 1484 * 1485 * DESCRIPTION: Search the AcpiGbl_ExternalList for a matching path 1486 * 1487 ******************************************************************************/ 1488 1489 void 1490 AcpiDmMarkExternalConflict ( 1491 ACPI_NAMESPACE_NODE *Node) 1492 { 1493 ACPI_EXTERNAL_LIST *ExternalList = AcpiGbl_ExternalList; 1494 char *ExternalPath; 1495 char *InternalPath; 1496 char *Temp; 1497 ACPI_STATUS Status; 1498 1499 1500 ACPI_FUNCTION_TRACE (DmMarkExternalConflict); 1501 1502 1503 if (Node->Flags & ANOBJ_IS_EXTERNAL) 1504 { 1505 return_VOID; 1506 } 1507 1508 /* Get the full external and internal pathnames to the node */ 1509 1510 Status = AcpiDmGetExternalAndInternalPath (Node, 1511 &ExternalPath, &InternalPath); 1512 if (ACPI_FAILURE (Status)) 1513 { 1514 return_VOID; 1515 } 1516 1517 /* Remove the root backslash */ 1518 1519 Status = AcpiDmRemoveRootPrefix (&InternalPath); 1520 if (ACPI_FAILURE (Status)) 1521 { 1522 ACPI_FREE (InternalPath); 1523 ACPI_FREE (ExternalPath); 1524 return_VOID; 1525 } 1526 1527 while (ExternalList) 1528 { 1529 Temp = ExternalList->InternalPath; 1530 if ((*ExternalList->InternalPath == AML_ROOT_PREFIX) && 1531 (ExternalList->InternalPath[1])) 1532 { 1533 Temp++; 1534 } 1535 1536 if (!strcmp (ExternalList->InternalPath, InternalPath)) 1537 { 1538 ExternalList->Flags |= ACPI_EXT_CONFLICTING_DECLARATION; 1539 } 1540 ExternalList = ExternalList->Next; 1541 } 1542 1543 ACPI_FREE (InternalPath); 1544 ACPI_FREE (ExternalPath); 1545 1546 return_VOID; 1547 } 1548 1549 1550 /******************************************************************************* 1551 * 1552 * FUNCTION: AcpiDmConflictingDeclaration 1553 * 1554 * PARAMETERS: Path - Path with conflicting declaration 1555 * 1556 * RETURN: None 1557 * 1558 * DESCRIPTION: Emit a warning when printing conflicting ASL external 1559 * declarations. 1560 * 1561 ******************************************************************************/ 1562 1563 static void 1564 AcpiDmConflictingDeclaration ( 1565 char *Path) 1566 { 1567 fprintf (stderr, 1568 " Warning - Emitting ASL code \"External (%s)\"\n" 1569 " This is a conflicting declaration with some " 1570 "other declaration within the ASL code.\n" 1571 " This external declaration may need to be " 1572 "deleted in order to recompile the dsl file.\n\n", 1573 Path); 1574 } 1575 1576 1577 /******************************************************************************* 1578 * 1579 * FUNCTION: AcpiDmEmitExternal 1580 * 1581 * PARAMETERS: Op External Parse Object 1582 * 1583 * RETURN: None 1584 * 1585 * DESCRIPTION: Emit an External() ASL statement for the current External 1586 * parse object. Note: External Ops are named types so the 1587 * namepath is contained within NameOp->Name.Path. 1588 * 1589 ******************************************************************************/ 1590 1591 void 1592 AcpiDmEmitExternal ( 1593 ACPI_PARSE_OBJECT *NameOp, 1594 ACPI_PARSE_OBJECT *TypeOp) 1595 { 1596 AcpiOsPrintf ("External ("); 1597 AcpiDmNamestring (NameOp->Named.Path); 1598 AcpiOsPrintf ("%s)", 1599 AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer)); 1600 AcpiDmCheckForExternalConflict (NameOp->Named.Path); 1601 AcpiOsPrintf ("\n"); 1602 } 1603 1604 1605 /******************************************************************************* 1606 * 1607 * FUNCTION: AcpiDmCheckForExternalConflict 1608 * 1609 * PARAMETERS: Path - Path to check 1610 * 1611 * RETURN: None 1612 * 1613 * DESCRIPTION: Search the External List to see if the input Path has a 1614 * conflicting declaration. 1615 * 1616 ******************************************************************************/ 1617 1618 static void 1619 AcpiDmCheckForExternalConflict ( 1620 char *Path) 1621 { 1622 ACPI_EXTERNAL_LIST *ExternalList = AcpiGbl_ExternalList; 1623 char *ListItemPath; 1624 char *InputPath; 1625 1626 1627 if (!Path) 1628 { 1629 return; 1630 } 1631 1632 /* Move past the root prefix '\' */ 1633 1634 InputPath = Path; 1635 if ((*InputPath == AML_ROOT_PREFIX) && InputPath[1]) 1636 { 1637 InputPath++; 1638 } 1639 1640 while (ExternalList) 1641 { 1642 ListItemPath = ExternalList->Path; 1643 if (ListItemPath) 1644 { 1645 /* Move past the root prefix '\' */ 1646 1647 if ((*ListItemPath == AML_ROOT_PREFIX) && 1648 ListItemPath[1]) 1649 { 1650 ListItemPath++; 1651 } 1652 1653 if (!strcmp (ListItemPath, InputPath) && 1654 (ExternalList->Flags & ACPI_EXT_CONFLICTING_DECLARATION)) 1655 { 1656 AcpiOsPrintf ("%s", ExternalConflictMessage); 1657 AcpiDmConflictingDeclaration (Path); 1658 1659 return; 1660 } 1661 } 1662 ExternalList = ExternalList->Next; 1663 } 1664 } 1665 /******************************************************************************* 1666 * 1667 * FUNCTION: AcpiDmUnresolvedWarning 1668 * 1669 * PARAMETERS: Type - Where to output the warning. 1670 * 0 means write to stderr 1671 * 1 means write to AcpiOsPrintf 1672 * 1673 * RETURN: None 1674 * 1675 * DESCRIPTION: Issue warning message if there are unresolved external control 1676 * methods within the disassembly. 1677 * 1678 ******************************************************************************/ 1679 1680 /* 1681 Summary of the external control method problem: 1682 1683 When the -e option is used with disassembly, the various SSDTs are simply 1684 loaded into a global namespace for the disassembler to use in order to 1685 resolve control method references (invocations). 1686 1687 The disassembler tracks any such references, and will emit an External() 1688 statement for these types of methods, with the proper number of arguments . 1689 1690 Without the SSDTs, the AML does not contain enough information to properly 1691 disassemble the control method invocation -- because the disassembler does 1692 not know how many arguments to parse. 1693 1694 An example: Assume we have two control methods. ABCD has one argument, and 1695 EFGH has zero arguments. Further, we have two additional control methods 1696 that invoke ABCD and EFGH, named T1 and T2: 1697 1698 Method (ABCD, 1) 1699 { 1700 } 1701 Method (EFGH, 0) 1702 { 1703 } 1704 Method (T1) 1705 { 1706 ABCD (Add (2, 7, Local0)) 1707 } 1708 Method (T2) 1709 { 1710 EFGH () 1711 Add (2, 7, Local0) 1712 } 1713 1714 Here is the AML code that is generated for T1 and T2: 1715 1716 185: Method (T1) 1717 1718 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__." 1719 1720 186: { 1721 187: ABCD (Add (2, 7, Local0)) 1722 1723 00000353: 41 42 43 44 ............ "ABCD" 1724 00000357: 72 0A 02 0A 07 60 ...... "r....`" 1725 1726 188: } 1727 1728 190: Method (T2) 1729 1730 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__." 1731 1732 191: { 1733 192: EFGH () 1734 1735 00000364: 45 46 47 48 ............ "EFGH" 1736 1737 193: Add (2, 7, Local0) 1738 1739 00000368: 72 0A 02 0A 07 60 ...... "r....`" 1740 194: } 1741 1742 Note that the AML code for T1 and T2 is essentially identical. When 1743 disassembling this code, the methods ABCD and EFGH must be known to the 1744 disassembler, otherwise it does not know how to handle the method invocations. 1745 1746 In other words, if ABCD and EFGH are actually external control methods 1747 appearing in an SSDT, the disassembler does not know what to do unless 1748 the owning SSDT has been loaded via the -e option. 1749 */ 1750 1751 static char ExternalWarningPart1[600]; 1752 static char ExternalWarningPart2[400]; 1753 static char ExternalWarningPart3[400]; 1754 static char ExternalWarningPart4[200]; 1755 1756 void 1757 AcpiDmUnresolvedWarning ( 1758 UINT8 Type) 1759 { 1760 char *Format; 1761 char Pad[] = " *"; 1762 char NoPad[] = ""; 1763 1764 1765 if (!AcpiGbl_NumExternalMethods) 1766 { 1767 return; 1768 } 1769 1770 if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods) 1771 { 1772 return; 1773 } 1774 1775 Format = Type ? Pad : NoPad; 1776 1777 sprintf (ExternalWarningPart1, 1778 "%s iASL Warning: There %s %u external control method%s found during\n" 1779 "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n" 1780 "%s ACPI tables may be required to properly disassemble the code. This\n" 1781 "%s resulting disassembler output file may not compile because the\n" 1782 "%s disassembler did not know how many arguments to assign to the\n" 1783 "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n" 1784 "%s runtime and may or may not be available via the host OS.\n", 1785 Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"), 1786 AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""), 1787 Format, AcpiGbl_ResolvedExternalMethods, 1788 (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"), 1789 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods), 1790 Format, Format, Format, Format, Format); 1791 1792 sprintf (ExternalWarningPart2, 1793 "%s To specify the tables needed to resolve external control method\n" 1794 "%s references, the -e option can be used to specify the filenames.\n" 1795 "%s Example iASL invocations:\n" 1796 "%s iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n" 1797 "%s iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n" 1798 "%s iasl -e ssdt*.aml -d dsdt.aml\n", 1799 Format, Format, Format, Format, Format, Format); 1800 1801 sprintf (ExternalWarningPart3, 1802 "%s In addition, the -fe option can be used to specify a file containing\n" 1803 "%s control method external declarations with the associated method\n" 1804 "%s argument counts. Each line of the file must be of the form:\n" 1805 "%s External (<method pathname>, MethodObj, <argument count>)\n" 1806 "%s Invocation:\n" 1807 "%s iasl -fe refs.txt -d dsdt.aml\n", 1808 Format, Format, Format, Format, Format, Format); 1809 1810 sprintf (ExternalWarningPart4, 1811 "%s The following methods were unresolved and many not compile properly\n" 1812 "%s because the disassembler had to guess at the number of arguments\n" 1813 "%s required for each:\n", 1814 Format, Format, Format); 1815 1816 if (Type) 1817 { 1818 if (!AcpiGbl_ExternalFileList) 1819 { 1820 /* The -e option was not specified */ 1821 1822 AcpiOsPrintf (" /*\n%s *\n%s *\n%s *\n%s */\n", 1823 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3, 1824 ExternalWarningPart4); 1825 } 1826 else 1827 { 1828 /* The -e option was specified, but there are still some unresolved externals */ 1829 1830 AcpiOsPrintf (" /*\n%s *\n%s *\n%s */\n", 1831 ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4); 1832 } 1833 } 1834 else 1835 { 1836 if (!AcpiGbl_ExternalFileList) 1837 { 1838 /* The -e option was not specified */ 1839 1840 fprintf (stderr, "\n%s\n%s\n%s\n", 1841 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3); 1842 } 1843 else 1844 { 1845 /* The -e option was specified, but there are still some unresolved externals */ 1846 1847 fprintf (stderr, "\n%s\n%s\n", 1848 ExternalWarningPart1, ExternalWarningPart3); 1849 } 1850 } 1851 } 1852