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