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 - 2016, 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#include "acpi.h" 117#include "accommon.h" 118#include "amlcode.h" 119#include "acnamesp.h" 120#include "acdisasm.h" 121#include "aslcompiler.h" 122#include <stdio.h> 123#include <errno.h> 124 125 126/* 127 * This module is used for application-level code (iASL disassembler) only. 128 * 129 * It contains the code to create and emit any necessary External() ASL 130 * statements for the module being disassembled. 131 */ 132#define _COMPONENT ACPI_CA_DISASSEMBLER 133 ACPI_MODULE_NAME ("dmextern") 134 135 136/* 137 * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL 138 * ObjectTypeKeyword. Used to generate typed external declarations 139 */ 140static const char *AcpiGbl_DmTypeNames[] = 141{ 142 /* 00 */ ", UnknownObj", /* Type ANY */ 143 /* 01 */ ", IntObj", 144 /* 02 */ ", StrObj", 145 /* 03 */ ", BuffObj", 146 /* 04 */ ", PkgObj", 147 /* 05 */ ", FieldUnitObj", 148 /* 06 */ ", DeviceObj", 149 /* 07 */ ", EventObj", 150 /* 08 */ ", MethodObj", 151 /* 09 */ ", MutexObj", 152 /* 10 */ ", OpRegionObj", 153 /* 11 */ ", PowerResObj", 154 /* 12 */ ", ProcessorObj", 155 /* 13 */ ", ThermalZoneObj", 156 /* 14 */ ", BuffFieldObj", 157 /* 15 */ ", DDBHandleObj", 158 /* 16 */ "", /* Debug object */ 159 /* 17 */ ", FieldUnitObj", 160 /* 18 */ ", FieldUnitObj", 161 /* 19 */ ", FieldUnitObj" 162}; 163 164#define METHOD_SEPARATORS " \t,()\n" 165 166 167/* Local prototypes */ 168 169static const char * 170AcpiDmGetObjectTypeName ( 171 ACPI_OBJECT_TYPE Type); 172 173static char * 174AcpiDmNormalizeParentPrefix ( 175 ACPI_PARSE_OBJECT *Op, 176 char *Path); 177 178static void 179AcpiDmAddPathToExternalList ( 180 char *Path, 181 UINT8 Type, 182 UINT32 Value, 183 UINT16 Flags); 184 185static ACPI_STATUS 186AcpiDmCreateNewExternal ( 187 char *ExternalPath, 188 char *InternalPath, 189 UINT8 Type, 190 UINT32 Value, 191 UINT16 Flags); 192 193 194/******************************************************************************* 195 * 196 * FUNCTION: AcpiDmGetObjectTypeName 197 * 198 * PARAMETERS: Type - An ACPI_OBJECT_TYPE 199 * 200 * RETURN: Pointer to a string 201 * 202 * DESCRIPTION: Map an object type to the ASL object type string. 203 * 204 ******************************************************************************/ 205 206static const char * 207AcpiDmGetObjectTypeName ( 208 ACPI_OBJECT_TYPE Type) 209{ 210 211 if (Type == ACPI_TYPE_LOCAL_SCOPE) 212 { 213 Type = ACPI_TYPE_DEVICE; 214 } 215 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD) 216 { 217 return (""); 218 } 219 220 return (AcpiGbl_DmTypeNames[Type]); 221} 222 223 224/******************************************************************************* 225 * 226 * FUNCTION: AcpiDmNormalizeParentPrefix 227 * 228 * PARAMETERS: Op - Parse op 229 * Path - Path with parent prefix 230 * 231 * RETURN: The full pathname to the object (from the namespace root) 232 * 233 * DESCRIPTION: Returns the full pathname of a path with parent prefix 234 * The caller must free the fullpath returned. 235 * 236 ******************************************************************************/ 237 238static char * 239AcpiDmNormalizeParentPrefix ( 240 ACPI_PARSE_OBJECT *Op, 241 char *Path) 242{ 243 ACPI_NAMESPACE_NODE *Node; 244 char *Fullpath; 245 char *ParentPath; 246 ACPI_SIZE Length; 247 UINT32 Index = 0; 248 249 250 if (!Op) 251 { 252 return (NULL); 253 } 254 255 /* Search upwards in the parse tree until we reach the next namespace node */ 256 257 Op = Op->Common.Parent; 258 while (Op) 259 { 260 if (Op->Common.Node) 261 { 262 break; 263 } 264 265 Op = Op->Common.Parent; 266 } 267 268 if (!Op) 269 { 270 return (NULL); 271 } 272 273 /* 274 * Find the actual parent node for the reference: 275 * Remove all carat prefixes from the input path. 276 * There may be multiple parent prefixes (For example, ^^^M000) 277 */ 278 Node = Op->Common.Node; 279 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX)) 280 { 281 Node = Node->Parent; 282 Path++; 283 } 284 285 if (!Node) 286 { 287 return (NULL); 288 } 289 290 /* Get the full pathname for the parent node */ 291 292 ParentPath = AcpiNsGetExternalPathname (Node); 293 if (!ParentPath) 294 { 295 return (NULL); 296 } 297 298 Length = (strlen (ParentPath) + strlen (Path) + 1); 299 if (ParentPath[1]) 300 { 301 /* 302 * If ParentPath is not just a simple '\', increment the length 303 * for the required dot separator (ParentPath.Path) 304 */ 305 Length++; 306 307 /* For External() statements, we do not want a leading '\' */ 308 309 if (*ParentPath == AML_ROOT_PREFIX) 310 { 311 Index = 1; 312 } 313 } 314 315 Fullpath = ACPI_ALLOCATE_ZEROED (Length); 316 if (!Fullpath) 317 { 318 goto Cleanup; 319 } 320 321 /* 322 * Concatenate parent fullpath and path. For example, 323 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT" 324 * 325 * Copy the parent path 326 */ 327 strcpy (Fullpath, &ParentPath[Index]); 328 329 /* 330 * Add dot separator 331 * (don't need dot if parent fullpath is a single backslash) 332 */ 333 if (ParentPath[1]) 334 { 335 strcat (Fullpath, "."); 336 } 337 338 /* Copy child path (carat parent prefix(es) were skipped above) */ 339 340 strcat (Fullpath, Path); 341 342Cleanup: 343 ACPI_FREE (ParentPath); 344 return (Fullpath); 345} 346 347 348/******************************************************************************* 349 * 350 * FUNCTION: AcpiDmAddToExternalFileList 351 * 352 * PARAMETERS: PathList - Single path or list separated by comma 353 * 354 * RETURN: None 355 * 356 * DESCRIPTION: Add external files to global list 357 * 358 ******************************************************************************/ 359 360ACPI_STATUS 361AcpiDmAddToExternalFileList ( 362 char *Pathname) 363{ 364 ACPI_EXTERNAL_FILE *ExternalFile; 365 char *LocalPathname; 366 367 368 if (!Pathname) 369 { 370 return (AE_OK); 371 } 372 373 LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1); 374 if (!LocalPathname) 375 { 376 return (AE_NO_MEMORY); 377 } 378 379 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE)); 380 if (!ExternalFile) 381 { 382 ACPI_FREE (LocalPathname); 383 return (AE_NO_MEMORY); 384 } 385 386 /* Take a copy of the file pathname */ 387 388 strcpy (LocalPathname, Pathname); 389 ExternalFile->Path = LocalPathname; 390 391 if (AcpiGbl_ExternalFileList) 392 { 393 ExternalFile->Next = AcpiGbl_ExternalFileList; 394 } 395 396 AcpiGbl_ExternalFileList = ExternalFile; 397 return (AE_OK); 398} 399 400 401/******************************************************************************* 402 * 403 * FUNCTION: AcpiDmClearExternalFileList 404 * 405 * PARAMETERS: None 406 * 407 * RETURN: None 408 * 409 * DESCRIPTION: Clear the external file list 410 * 411 ******************************************************************************/ 412 413void 414AcpiDmClearExternalFileList ( 415 void) 416{ 417 ACPI_EXTERNAL_FILE *NextExternal; 418 419 420 while (AcpiGbl_ExternalFileList) 421 { 422 NextExternal = AcpiGbl_ExternalFileList->Next; 423 ACPI_FREE (AcpiGbl_ExternalFileList->Path); 424 ACPI_FREE (AcpiGbl_ExternalFileList); 425 AcpiGbl_ExternalFileList = NextExternal; 426 } 427} 428 429 430/******************************************************************************* 431 * 432 * FUNCTION: AcpiDmGetExternalsFromFile 433 * 434 * PARAMETERS: None 435 * 436 * RETURN: None 437 * 438 * DESCRIPTION: Process the optional external reference file. 439 * 440 * Each line in the file should be of the form: 441 * External (<Method namepath>, MethodObj, <ArgCount>) 442 * 443 * Example: 444 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4) 445 * 446 ******************************************************************************/ 447 448void 449AcpiDmGetExternalsFromFile ( 450 void) 451{ 452 FILE *ExternalRefFile; 453 char *Token; 454 char *MethodName; 455 UINT32 ArgCount; 456 UINT32 ImportCount = 0; 457 458 459 if (!Gbl_ExternalRefFilename) 460 { 461 return; 462 } 463 464 /* Open the file */ 465 466 ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r"); 467 if (!ExternalRefFile) 468 { 469 fprintf (stderr, "Could not open external reference file \"%s\"\n", 470 Gbl_ExternalRefFilename); 471 AslAbort (); 472 return; 473 } 474 475 /* Each line defines a method */ 476 477 while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile)) 478 { 479 Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */ 480 if (!Token) 481 { 482 continue; 483 } 484 485 if (strcmp (Token, "External")) 486 { 487 continue; 488 } 489 490 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */ 491 if (!MethodName) 492 { 493 continue; 494 } 495 496 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */ 497 if (!Token) 498 { 499 continue; 500 } 501 502 if (strcmp (Token, "MethodObj")) 503 { 504 continue; 505 } 506 507 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */ 508 if (!Token) 509 { 510 continue; 511 } 512 513 /* Convert arg count string to an integer */ 514 515 errno = 0; 516 ArgCount = strtoul (Token, NULL, 0); 517 if (errno) 518 { 519 fprintf (stderr, "Invalid argument count (%s)\n", Token); 520 continue; 521 } 522 523 if (ArgCount > 7) 524 { 525 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount); 526 continue; 527 } 528 529 /* Add this external to the global list */ 530 531 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n", 532 Gbl_ExternalRefFilename, ArgCount, MethodName); 533 534 AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD, 535 ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE)); 536 ImportCount++; 537 } 538 539 if (!ImportCount) 540 { 541 fprintf (stderr, 542 "Did not find any external methods in reference file \"%s\"\n", 543 Gbl_ExternalRefFilename); 544 } 545 else 546 { 547 /* Add the external(s) to the namespace */ 548 549 AcpiDmAddExternalsToNamespace (); 550 551 AcpiOsPrintf ("%s: Imported %u external method definitions\n", 552 Gbl_ExternalRefFilename, ImportCount); 553 } 554 555 fclose (ExternalRefFile); 556} 557 558 559/******************************************************************************* 560 * 561 * FUNCTION: AcpiDmAddOpToExternalList 562 * 563 * PARAMETERS: Op - Current parser Op 564 * Path - Internal (AML) path to the object 565 * Type - ACPI object type to be added 566 * Value - Arg count if adding a Method object 567 * Flags - To be passed to the external object 568 * 569 * RETURN: None 570 * 571 * DESCRIPTION: Insert a new name into the global list of Externals which 572 * will in turn be later emitted as an External() declaration 573 * in the disassembled output. 574 * 575 * This function handles the most common case where the referenced 576 * name is simply not found in the constructed namespace. 577 * 578 ******************************************************************************/ 579 580void 581AcpiDmAddOpToExternalList ( 582 ACPI_PARSE_OBJECT *Op, 583 char *Path, 584 UINT8 Type, 585 UINT32 Value, 586 UINT16 Flags) 587{ 588 char *ExternalPath; 589 char *InternalPath = Path; 590 char *Temp; 591 ACPI_STATUS Status; 592 593 594 ACPI_FUNCTION_TRACE (DmAddOpToExternalList); 595 596 597 if (!Path) 598 { 599 return_VOID; 600 } 601 602 /* Remove a root backslash if present */ 603 604 if ((*Path == AML_ROOT_PREFIX) && (Path[1])) 605 { 606 Path++; 607 } 608 609 /* Externalize the pathname */ 610 611 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, 612 NULL, &ExternalPath); 613 if (ACPI_FAILURE (Status)) 614 { 615 return_VOID; 616 } 617 618 /* 619 * Get the full pathname from the root if "Path" has one or more 620 * parent prefixes (^). Note: path will not contain a leading '\'. 621 */ 622 if (*Path == (UINT8) AML_PARENT_PREFIX) 623 { 624 Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath); 625 626 /* Set new external path */ 627 628 ACPI_FREE (ExternalPath); 629 ExternalPath = Temp; 630 if (!Temp) 631 { 632 return_VOID; 633 } 634 635 /* Create the new internal pathname */ 636 637 Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED; 638 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath); 639 if (ACPI_FAILURE (Status)) 640 { 641 ACPI_FREE (ExternalPath); 642 return_VOID; 643 } 644 } 645 646 /* Create the new External() declaration node */ 647 648 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, 649 Type, Value, Flags); 650 if (ACPI_FAILURE (Status)) 651 { 652 ACPI_FREE (ExternalPath); 653 if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED) 654 { 655 ACPI_FREE (InternalPath); 656 } 657 } 658 659 return_VOID; 660} 661 662 663/******************************************************************************* 664 * 665 * FUNCTION: AcpiDmAddNodeToExternalList 666 * 667 * PARAMETERS: Node - Namespace node for object to be added 668 * Type - ACPI object type to be added 669 * Value - Arg count if adding a Method object 670 * Flags - To be passed to the external object 671 * 672 * RETURN: None 673 * 674 * DESCRIPTION: Insert a new name into the global list of Externals which 675 * will in turn be later emitted as an External() declaration 676 * in the disassembled output. 677 * 678 * This function handles the case where the referenced name has 679 * been found in the namespace, but the name originated in a 680 * table other than the one that is being disassembled (such 681 * as a table that is added via the iASL -e option). 682 * 683 ******************************************************************************/ 684 685void 686AcpiDmAddNodeToExternalList ( 687 ACPI_NAMESPACE_NODE *Node, 688 UINT8 Type, 689 UINT32 Value, 690 UINT16 Flags) 691{ 692 char *ExternalPath; 693 char *InternalPath; 694 char *Temp; 695 ACPI_STATUS Status; 696 697 698 ACPI_FUNCTION_TRACE (DmAddNodeToExternalList); 699 700 701 if (!Node) 702 { 703 return_VOID; 704 } 705 706 /* Get the full external and internal pathnames to the node */ 707 708 ExternalPath = AcpiNsGetExternalPathname (Node); 709 if (!ExternalPath) 710 { 711 return_VOID; 712 } 713 714 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath); 715 if (ACPI_FAILURE (Status)) 716 { 717 ACPI_FREE (ExternalPath); 718 return_VOID; 719 } 720 721 /* Remove the root backslash */ 722 723 if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1])) 724 { 725 Temp = ACPI_ALLOCATE_ZEROED (strlen (ExternalPath) + 1); 726 if (!Temp) 727 { 728 return_VOID; 729 } 730 731 strcpy (Temp, &ExternalPath[1]); 732 ACPI_FREE (ExternalPath); 733 ExternalPath = Temp; 734 } 735 736 /* Create the new External() declaration node */ 737 738 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type, 739 Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED)); 740 if (ACPI_FAILURE (Status)) 741 { 742 ACPI_FREE (ExternalPath); 743 ACPI_FREE (InternalPath); 744 } 745 746 return_VOID; 747} 748 749 750/******************************************************************************* 751 * 752 * FUNCTION: AcpiDmAddPathToExternalList 753 * 754 * PARAMETERS: Path - External name of the object to be added 755 * Type - ACPI object type to be added 756 * Value - Arg count if adding a Method object 757 * Flags - To be passed to the external object 758 * 759 * RETURN: None 760 * 761 * DESCRIPTION: Insert a new name into the global list of Externals which 762 * will in turn be later emitted as an External() declaration 763 * in the disassembled output. 764 * 765 * This function currently is used to add externals via a 766 * reference file (via the -fe iASL option). 767 * 768 ******************************************************************************/ 769 770static void 771AcpiDmAddPathToExternalList ( 772 char *Path, 773 UINT8 Type, 774 UINT32 Value, 775 UINT16 Flags) 776{ 777 char *InternalPath; 778 char *ExternalPath; 779 ACPI_STATUS Status; 780 781 782 ACPI_FUNCTION_TRACE (DmAddPathToExternalList); 783 784 785 if (!Path) 786 { 787 return_VOID; 788 } 789 790 /* Remove a root backslash if present */ 791 792 if ((*Path == AML_ROOT_PREFIX) && (Path[1])) 793 { 794 Path++; 795 } 796 797 /* Create the internal and external pathnames */ 798 799 Status = AcpiNsInternalizeName (Path, &InternalPath); 800 if (ACPI_FAILURE (Status)) 801 { 802 return_VOID; 803 } 804 805 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, 806 NULL, &ExternalPath); 807 if (ACPI_FAILURE (Status)) 808 { 809 ACPI_FREE (InternalPath); 810 return_VOID; 811 } 812 813 /* Create the new External() declaration node */ 814 815 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, 816 Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED)); 817 if (ACPI_FAILURE (Status)) 818 { 819 ACPI_FREE (ExternalPath); 820 ACPI_FREE (InternalPath); 821 } 822 823 return_VOID; 824} 825 826 827/******************************************************************************* 828 * 829 * FUNCTION: AcpiDmCreateNewExternal 830 * 831 * PARAMETERS: ExternalPath - External path to the object 832 * InternalPath - Internal (AML) path to the object 833 * Type - ACPI object type to be added 834 * Value - Arg count if adding a Method object 835 * Flags - To be passed to the external object 836 * 837 * RETURN: Status 838 * 839 * DESCRIPTION: Common low-level function to insert a new name into the global 840 * list of Externals which will in turn be later emitted as 841 * External() declarations in the disassembled output. 842 * 843 * Note: The external name should not include a root prefix 844 * (backslash). We do not want External() statements to contain 845 * a leading '\', as this prevents duplicate external statements 846 * of the form: 847 * 848 * External (\ABCD) 849 * External (ABCD) 850 * 851 * This would cause a compile time error when the disassembled 852 * output file is recompiled. 853 * 854 * There are two cases that are handled here. For both, we emit 855 * an External() statement: 856 * 1) The name was simply not found in the namespace. 857 * 2) The name was found, but it originated in a table other than 858 * the table that is being disassembled. 859 * 860 ******************************************************************************/ 861 862static ACPI_STATUS 863AcpiDmCreateNewExternal ( 864 char *ExternalPath, 865 char *InternalPath, 866 UINT8 Type, 867 UINT32 Value, 868 UINT16 Flags) 869{ 870 ACPI_EXTERNAL_LIST *NewExternal; 871 ACPI_EXTERNAL_LIST *NextExternal; 872 ACPI_EXTERNAL_LIST *PrevExternal = NULL; 873 874 875 ACPI_FUNCTION_TRACE (DmCreateNewExternal); 876 877 878 /* Check all existing externals to ensure no duplicates */ 879 880 NextExternal = AcpiGbl_ExternalList; 881 while (NextExternal) 882 { 883 /* Check for duplicates */ 884 885 if (!strcmp (ExternalPath, NextExternal->Path)) 886 { 887 /* 888 * If this external came from an External() opcode, we are 889 * finished with this one. (No need to check any further). 890 */ 891 if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE) 892 { 893 return_ACPI_STATUS (AE_ALREADY_EXISTS); 894 } 895 896 /* Allow upgrade of type from ANY */ 897 898 else if ((NextExternal->Type == ACPI_TYPE_ANY) && 899 (Type != ACPI_TYPE_ANY)) 900 { 901 NextExternal->Type = Type; 902 } 903 904 /* Update the argument count as necessary */ 905 906 if (Value < NextExternal->Value) 907 { 908 NextExternal->Value = Value; 909 } 910 911 /* Update flags. */ 912 913 NextExternal->Flags |= Flags; 914 NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED; 915 916 return_ACPI_STATUS (AE_ALREADY_EXISTS); 917 } 918 919 NextExternal = NextExternal->Next; 920 } 921 922 /* Allocate and init a new External() descriptor */ 923 924 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); 925 if (!NewExternal) 926 { 927 return_ACPI_STATUS (AE_NO_MEMORY); 928 } 929 930 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 931 "Adding external reference node (%s) type [%s]\n", 932 ExternalPath, AcpiUtGetTypeName (Type))); 933 934 NewExternal->Flags = Flags; 935 NewExternal->Value = Value; 936 NewExternal->Path = ExternalPath; 937 NewExternal->Type = Type; 938 NewExternal->Length = (UINT16) strlen (ExternalPath); 939 NewExternal->InternalPath = InternalPath; 940 941 /* Link the new descriptor into the global list, alphabetically ordered */ 942 943 NextExternal = AcpiGbl_ExternalList; 944 while (NextExternal) 945 { 946 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0) 947 { 948 if (PrevExternal) 949 { 950 PrevExternal->Next = NewExternal; 951 } 952 else 953 { 954 AcpiGbl_ExternalList = NewExternal; 955 } 956 957 NewExternal->Next = NextExternal; 958 return_ACPI_STATUS (AE_OK); 959 } 960 961 PrevExternal = NextExternal; 962 NextExternal = NextExternal->Next; 963 } 964 965 if (PrevExternal) 966 { 967 PrevExternal->Next = NewExternal; 968 } 969 else 970 { 971 AcpiGbl_ExternalList = NewExternal; 972 } 973 974 return_ACPI_STATUS (AE_OK); 975} 976 977 978/******************************************************************************* 979 * 980 * FUNCTION: AcpiDmAddExternalsToNamespace 981 * 982 * PARAMETERS: None 983 * 984 * RETURN: None 985 * 986 * DESCRIPTION: Add all externals to the namespace. Allows externals to be 987 * "resolved". 988 * 989 ******************************************************************************/ 990 991void 992AcpiDmAddExternalsToNamespace ( 993 void) 994{ 995 ACPI_STATUS Status; 996 ACPI_NAMESPACE_NODE *Node; 997 ACPI_OPERAND_OBJECT *ObjDesc; 998 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 999 1000 1001 while (External) 1002 { 1003 /* Add the external name (object) into the namespace */ 1004 1005 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type, 1006 ACPI_IMODE_LOAD_PASS1, 1007 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, 1008 NULL, &Node); 1009 1010 if (ACPI_FAILURE (Status)) 1011 { 1012 ACPI_EXCEPTION ((AE_INFO, Status, 1013 "while adding external to namespace [%s]", 1014 External->Path)); 1015 } 1016 1017 else switch (External->Type) 1018 { 1019 case ACPI_TYPE_METHOD: 1020 1021 /* For methods, we need to save the argument count */ 1022 1023 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 1024 ObjDesc->Method.ParamCount = (UINT8) External->Value; 1025 Node->Object = ObjDesc; 1026 break; 1027 1028 case ACPI_TYPE_REGION: 1029 1030 /* Regions require a region sub-object */ 1031 1032 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION); 1033 ObjDesc->Region.Node = Node; 1034 Node->Object = ObjDesc; 1035 break; 1036 1037 default: 1038 1039 break; 1040 } 1041 1042 External = External->Next; 1043 } 1044} 1045 1046 1047/******************************************************************************* 1048 * 1049 * FUNCTION: AcpiDmGetExternalMethodCount 1050 * 1051 * PARAMETERS: None 1052 * 1053 * RETURN: The number of control method externals in the external list 1054 * 1055 * DESCRIPTION: Return the number of method externals that have been generated. 1056 * If any control method externals have been found, we must 1057 * re-parse the entire definition block with the new information 1058 * (number of arguments for the methods.) This is limitation of 1059 * AML, we don't know the number of arguments from the control 1060 * method invocation itself. 1061 * 1062 ******************************************************************************/ 1063 1064UINT32 1065AcpiDmGetExternalMethodCount ( 1066 void) 1067{ 1068 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 1069 UINT32 Count = 0; 1070 1071 1072 while (External) 1073 { 1074 if (External->Type == ACPI_TYPE_METHOD) 1075 { 1076 Count++; 1077 } 1078 1079 External = External->Next; 1080 } 1081 1082 return (Count); 1083} 1084 1085 1086/******************************************************************************* 1087 * 1088 * FUNCTION: AcpiDmClearExternalList 1089 * 1090 * PARAMETERS: None 1091 * 1092 * RETURN: None 1093 * 1094 * DESCRIPTION: Free the entire External info list 1095 * 1096 ******************************************************************************/ 1097 1098void 1099AcpiDmClearExternalList ( 1100 void) 1101{ 1102 ACPI_EXTERNAL_LIST *NextExternal; 1103 1104 1105 while (AcpiGbl_ExternalList) 1106 { 1107 NextExternal = AcpiGbl_ExternalList->Next; 1108 ACPI_FREE (AcpiGbl_ExternalList->Path); 1109 ACPI_FREE (AcpiGbl_ExternalList); 1110 AcpiGbl_ExternalList = NextExternal; 1111 } 1112} 1113 1114 1115/******************************************************************************* 1116 * 1117 * FUNCTION: AcpiDmEmitExternals 1118 * 1119 * PARAMETERS: None 1120 * 1121 * RETURN: None 1122 * 1123 * DESCRIPTION: Emit an External() ASL statement for each of the externals in 1124 * the global external info list. 1125 * 1126 ******************************************************************************/ 1127 1128void 1129AcpiDmEmitExternals ( 1130 void) 1131{ 1132 ACPI_EXTERNAL_LIST *NextExternal; 1133 1134 1135 if (!AcpiGbl_ExternalList) 1136 { 1137 return; 1138 } 1139 1140 /* 1141 * Determine the number of control methods in the external list, and 1142 * also how many of those externals were resolved via the namespace. 1143 */ 1144 NextExternal = AcpiGbl_ExternalList; 1145 while (NextExternal) 1146 { 1147 if (NextExternal->Type == ACPI_TYPE_METHOD) 1148 { 1149 AcpiGbl_NumExternalMethods++; 1150 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE) 1151 { 1152 AcpiGbl_ResolvedExternalMethods++; 1153 } 1154 } 1155 1156 NextExternal = NextExternal->Next; 1157 } 1158 1159 /* Check if any control methods were unresolved */ 1160 1161 AcpiDmUnresolvedWarning (1); 1162 1163 if (Gbl_ExternalRefFilename) 1164 { 1165 AcpiOsPrintf ( 1166 " /*\n * External declarations were imported from\n" 1167 " * a reference file -- %s\n */\n\n", 1168 Gbl_ExternalRefFilename); 1169 } 1170 1171 /* 1172 * Walk and emit the list of externals found during the AML parsing 1173 */ 1174 while (AcpiGbl_ExternalList) 1175 { 1176 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED)) 1177 { 1178 AcpiOsPrintf (" External (%s%s)", 1179 AcpiGbl_ExternalList->Path, 1180 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type)); 1181 1182 /* Check for "unresolved" method reference */ 1183 1184 if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) && 1185 (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE))) 1186 { 1187 AcpiOsPrintf (" // Warning: Unknown method, " 1188 "guessing %u arguments", 1189 AcpiGbl_ExternalList->Value); 1190 } 1191 1192 /* Check for external from a external references file */ 1193 1194 else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE) 1195 { 1196 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 1197 { 1198 AcpiOsPrintf (" // %u Arguments", 1199 AcpiGbl_ExternalList->Value); 1200 } 1201 1202 AcpiOsPrintf (" // From external reference file"); 1203 } 1204 1205 /* This is the normal external case */ 1206 1207 else 1208 { 1209 /* For methods, add a comment with the number of arguments */ 1210 1211 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 1212 { 1213 AcpiOsPrintf (" // %u Arguments", 1214 AcpiGbl_ExternalList->Value); 1215 } 1216 } 1217 1218 AcpiOsPrintf ("\n"); 1219 } 1220 1221 /* Free this external info block and move on to next external */ 1222 1223 NextExternal = AcpiGbl_ExternalList->Next; 1224 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED) 1225 { 1226 ACPI_FREE (AcpiGbl_ExternalList->InternalPath); 1227 } 1228 1229 ACPI_FREE (AcpiGbl_ExternalList->Path); 1230 ACPI_FREE (AcpiGbl_ExternalList); 1231 AcpiGbl_ExternalList = NextExternal; 1232 } 1233 1234 AcpiOsPrintf ("\n"); 1235} 1236 1237 1238/******************************************************************************* 1239 * 1240 * FUNCTION: AcpiDmUnresolvedWarning 1241 * 1242 * PARAMETERS: Type - Where to output the warning. 1243 * 0 means write to stderr 1244 * 1 means write to AcpiOsPrintf 1245 * 1246 * RETURN: None 1247 * 1248 * DESCRIPTION: Issue warning message if there are unresolved external control 1249 * methods within the disassembly. 1250 * 1251 ******************************************************************************/ 1252 1253#if 0 1254Summary of the external control method problem: 1255 1256When the -e option is used with disassembly, the various SSDTs are simply 1257loaded into a global namespace for the disassembler to use in order to 1258resolve control method references (invocations). 1259 1260The disassembler tracks any such references, and will emit an External() 1261statement for these types of methods, with the proper number of arguments . 1262 1263Without the SSDTs, the AML does not contain enough information to properly 1264disassemble the control method invocation -- because the disassembler does 1265not know how many arguments to parse. 1266 1267An example: Assume we have two control methods. ABCD has one argument, and 1268EFGH has zero arguments. Further, we have two additional control methods 1269that invoke ABCD and EFGH, named T1 and T2: 1270 1271 Method (ABCD, 1) 1272 { 1273 } 1274 Method (EFGH, 0) 1275 { 1276 } 1277 Method (T1) 1278 { 1279 ABCD (Add (2, 7, Local0)) 1280 } 1281 Method (T2) 1282 { 1283 EFGH () 1284 Add (2, 7, Local0) 1285 } 1286 1287Here is the AML code that is generated for T1 and T2: 1288 1289 185: Method (T1) 1290 12910000034C: 14 10 54 31 5F 5F 00 ... "..T1__." 1292 1293 186: { 1294 187: ABCD (Add (2, 7, Local0)) 1295 129600000353: 41 42 43 44 ............ "ABCD" 129700000357: 72 0A 02 0A 07 60 ...... "r....`" 1298 1299 188: } 1300 1301 190: Method (T2) 1302 13030000035D: 14 10 54 32 5F 5F 00 ... "..T2__." 1304 1305 191: { 1306 192: EFGH () 1307 130800000364: 45 46 47 48 ............ "EFGH" 1309 1310 193: Add (2, 7, Local0) 1311 131200000368: 72 0A 02 0A 07 60 ...... "r....`" 1313 194: } 1314 1315Note that the AML code for T1 and T2 is essentially identical. When 1316disassembling this code, the methods ABCD and EFGH must be known to the 1317disassembler, otherwise it does not know how to handle the method invocations. 1318 1319In other words, if ABCD and EFGH are actually external control methods 1320appearing in an SSDT, the disassembler does not know what to do unless 1321the owning SSDT has been loaded via the -e option. 1322#endif 1323 1324static char ExternalWarningPart1[600]; 1325static char ExternalWarningPart2[400]; 1326static char ExternalWarningPart3[400]; 1327static char ExternalWarningPart4[200]; 1328 1329void 1330AcpiDmUnresolvedWarning ( 1331 UINT8 Type) 1332{ 1333 char *Format; 1334 char Pad[] = " *"; 1335 char NoPad[] = ""; 1336 1337 1338 if (!AcpiGbl_NumExternalMethods) 1339 { 1340 return; 1341 } 1342 1343 if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods) 1344 { 1345 return; 1346 } 1347 1348 Format = Type ? Pad : NoPad; 1349 1350 sprintf (ExternalWarningPart1, 1351 "%s iASL Warning: There %s %u external control method%s found during\n" 1352 "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n" 1353 "%s ACPI tables may be required to properly disassemble the code. This\n" 1354 "%s resulting disassembler output file may not compile because the\n" 1355 "%s disassembler did not know how many arguments to assign to the\n" 1356 "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n" 1357 "%s runtime and may or may not be available via the host OS.\n", 1358 Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"), 1359 AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""), 1360 Format, AcpiGbl_ResolvedExternalMethods, 1361 (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"), 1362 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods), 1363 Format, Format, Format, Format, Format); 1364 1365 sprintf (ExternalWarningPart2, 1366 "%s To specify the tables needed to resolve external control method\n" 1367 "%s references, the -e option can be used to specify the filenames.\n" 1368 "%s Example iASL invocations:\n" 1369 "%s iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n" 1370 "%s iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n" 1371 "%s iasl -e ssdt*.aml -d dsdt.aml\n", 1372 Format, Format, Format, Format, Format, Format); 1373 1374 sprintf (ExternalWarningPart3, 1375 "%s In addition, the -fe option can be used to specify a file containing\n" 1376 "%s control method external declarations with the associated method\n" 1377 "%s argument counts. Each line of the file must be of the form:\n" 1378 "%s External (<method pathname>, MethodObj, <argument count>)\n" 1379 "%s Invocation:\n" 1380 "%s iasl -fe refs.txt -d dsdt.aml\n", 1381 Format, Format, Format, Format, Format, Format); 1382 1383 sprintf (ExternalWarningPart4, 1384 "%s The following methods were unresolved and many not compile properly\n" 1385 "%s because the disassembler had to guess at the number of arguments\n" 1386 "%s required for each:\n", 1387 Format, Format, Format); 1388 1389 if (Type) 1390 { 1391 if (!AcpiGbl_ExternalFileList) 1392 { 1393 /* The -e option was not specified */ 1394 1395 AcpiOsPrintf (" /*\n%s *\n%s *\n%s *\n%s */\n", 1396 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3, 1397 ExternalWarningPart4); 1398 } 1399 else 1400 { 1401 /* The -e option was specified, but there are still some unresolved externals */ 1402 1403 AcpiOsPrintf (" /*\n%s *\n%s *\n%s */\n", 1404 ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4); 1405 } 1406 } 1407 else 1408 { 1409 if (!AcpiGbl_ExternalFileList) 1410 { 1411 /* The -e option was not specified */ 1412 1413 fprintf (stderr, "\n%s\n%s\n%s\n", 1414 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3); 1415 } 1416 else 1417 { 1418 /* The -e option was specified, but there are still some unresolved externals */ 1419 1420 fprintf (stderr, "\n%s\n%s\n", 1421 ExternalWarningPart1, ExternalWarningPart3); 1422 } 1423 } 1424} 1425