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