1 /******************************************************************************
3 * Module Name: dmextern - Support for External() ASL statements
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2013, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
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>
55 * This module is used for application-level code (iASL disassembler) only.
57 * It contains the code to create and emit any necessary External() ASL
58 * statements for the module being disassembled.
60 #define _COMPONENT ACPI_CA_DISASSEMBLER
61 ACPI_MODULE_NAME ("dmextern")
65 * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
66 * ObjectTypeKeyword. Used to generate typed external declarations
68 static const char *AcpiGbl_DmTypeNames[] =
70 /* 00 */ "", /* Type ANY */
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"
92 #define METHOD_SEPARATORS " \t,()\n"
95 /* Local prototypes */
98 AcpiDmGetObjectTypeName (
99 ACPI_OBJECT_TYPE Type);
102 AcpiDmNormalizeParentPrefix (
103 ACPI_PARSE_OBJECT *Op,
107 AcpiDmAddToExternalListFromFile (
113 /*******************************************************************************
115 * FUNCTION: AcpiDmGetObjectTypeName
117 * PARAMETERS: Type - An ACPI_OBJECT_TYPE
119 * RETURN: Pointer to a string
121 * DESCRIPTION: Map an object type to the ASL object type string.
123 ******************************************************************************/
126 AcpiDmGetObjectTypeName (
127 ACPI_OBJECT_TYPE Type)
130 if (Type == ACPI_TYPE_LOCAL_SCOPE)
132 Type = ACPI_TYPE_DEVICE;
135 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
140 return (AcpiGbl_DmTypeNames[Type]);
144 /*******************************************************************************
146 * FUNCTION: AcpiDmNormalizeParentPrefix
148 * PARAMETERS: Op - Parse op
149 * Path - Path with parent prefix
151 * RETURN: The full pathname to the object (from the namespace root)
153 * DESCRIPTION: Returns the full pathname of a path with parent prefix
154 * The caller must free the fullpath returned.
156 ******************************************************************************/
159 AcpiDmNormalizeParentPrefix (
160 ACPI_PARSE_OBJECT *Op,
163 ACPI_NAMESPACE_NODE *Node;
175 /* Search upwards in the parse tree until we reach the next namespace node */
177 Op = Op->Common.Parent;
185 Op = Op->Common.Parent;
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)
198 Node = Op->Common.Node;
199 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
210 /* Get the full pathname for the parent node */
212 ParentPath = AcpiNsGetExternalPathname (Node);
218 Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1);
222 * If ParentPath is not just a simple '\', increment the length
223 * for the required dot separator (ParentPath.Path)
227 /* For External() statements, we do not want a leading '\' */
229 if (*ParentPath == AML_ROOT_PREFIX)
235 Fullpath = ACPI_ALLOCATE_ZEROED (Length);
242 * Concatenate parent fullpath and path. For example,
243 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
245 * Copy the parent path
247 ACPI_STRCPY (Fullpath, &ParentPath[Index]);
251 * (don't need dot if parent fullpath is a single backslash)
255 ACPI_STRCAT (Fullpath, ".");
258 /* Copy child path (carat parent prefix(es) were skipped above) */
260 ACPI_STRCAT (Fullpath, Path);
263 ACPI_FREE (ParentPath);
268 /*******************************************************************************
270 * FUNCTION: AcpiDmAddToExternalFileList
272 * PARAMETERS: PathList - Single path or list separated by comma
276 * DESCRIPTION: Add external files to global list
278 ******************************************************************************/
281 AcpiDmAddToExternalFileList (
284 ACPI_EXTERNAL_FILE *ExternalFile;
294 Path = strtok (PathList, ",");
298 TmpPath = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (Path) + 1);
301 return (AE_NO_MEMORY);
304 ACPI_STRCPY (TmpPath, Path);
306 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
310 return (AE_NO_MEMORY);
313 ExternalFile->Path = TmpPath;
315 if (AcpiGbl_ExternalFileList)
317 ExternalFile->Next = AcpiGbl_ExternalFileList;
320 AcpiGbl_ExternalFileList = ExternalFile;
321 Path = strtok (NULL, ",");
328 /*******************************************************************************
330 * FUNCTION: AcpiDmClearExternalFileList
336 * DESCRIPTION: Clear the external file list
338 ******************************************************************************/
341 AcpiDmClearExternalFileList (
344 ACPI_EXTERNAL_FILE *NextExternal;
347 while (AcpiGbl_ExternalFileList)
349 NextExternal = AcpiGbl_ExternalFileList->Next;
350 ACPI_FREE (AcpiGbl_ExternalFileList->Path);
351 ACPI_FREE (AcpiGbl_ExternalFileList);
352 AcpiGbl_ExternalFileList = NextExternal;
357 /*******************************************************************************
359 * FUNCTION: AcpiDmAddToExternalList
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
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.
372 ******************************************************************************/
375 AcpiDmAddToExternalList (
376 ACPI_PARSE_OBJECT *Op,
382 char *Fullpath = NULL;
383 ACPI_EXTERNAL_LIST *NewExternal;
384 ACPI_EXTERNAL_LIST *NextExternal;
385 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
387 BOOLEAN Resolved = FALSE;
395 if (Type == ACPI_TYPE_METHOD)
405 * We don't want External() statements to contain a leading '\'.
406 * This prevents duplicate external statements of the form:
411 * This would cause a compile time error when the disassembled
412 * output file is recompiled.
414 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
419 /* Externalize the ACPI pathname */
421 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
422 NULL, &ExternalPath);
423 if (ACPI_FAILURE (Status))
429 * Get the full pathname from the root if "Path" has one or more
430 * parent prefixes (^). Note: path will not contain a leading '\'.
432 if (*Path == (UINT8) AML_PARENT_PREFIX)
434 Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
437 /* Set new external path */
439 ACPI_FREE (ExternalPath);
440 ExternalPath = Fullpath;
444 /* Check all existing externals to ensure no duplicates */
446 NextExternal = AcpiGbl_ExternalList;
449 if (!ACPI_STRCMP (ExternalPath, NextExternal->Path))
451 /* Duplicate method, check that the Value (ArgCount) is the same */
453 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
454 (NextExternal->Value != Value))
456 ACPI_ERROR ((AE_INFO,
457 "External method arg count mismatch %s: Current %u, attempted %u",
458 NextExternal->Path, NextExternal->Value, Value));
461 /* Allow upgrade of type from ANY */
463 else if (NextExternal->Type == ACPI_TYPE_ANY)
465 NextExternal->Type = Type;
466 NextExternal->Value = Value;
469 ACPI_FREE (ExternalPath);
473 NextExternal = NextExternal->Next;
476 /* Allocate and init a new External() descriptor */
478 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
481 ACPI_FREE (ExternalPath);
485 NewExternal->Path = ExternalPath;
486 NewExternal->Type = Type;
487 NewExternal->Value = Value;
488 NewExternal->Resolved = Resolved;
489 NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath);
491 /* Was the external path with parent prefix normalized to a fullpath? */
493 if (Fullpath == ExternalPath)
495 /* Get new internal path */
497 Status = AcpiNsInternalizeName (ExternalPath, &Path);
498 if (ACPI_FAILURE (Status))
500 ACPI_FREE (ExternalPath);
501 ACPI_FREE (NewExternal);
505 /* Set flag to indicate External->InternalPath need to be freed */
507 NewExternal->Flags |= ACPI_IPATH_ALLOCATED;
510 NewExternal->InternalPath = Path;
512 /* Link the new descriptor into the global list, alphabetically ordered */
514 NextExternal = AcpiGbl_ExternalList;
517 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
521 PrevExternal->Next = NewExternal;
525 AcpiGbl_ExternalList = NewExternal;
528 NewExternal->Next = NextExternal;
532 PrevExternal = NextExternal;
533 NextExternal = NextExternal->Next;
538 PrevExternal->Next = NewExternal;
542 AcpiGbl_ExternalList = NewExternal;
547 /*******************************************************************************
549 * FUNCTION: AcpiDmGetExternalsFromFile
555 * DESCRIPTION: Process the optional external reference file.
557 * Each line in the file should be of the form:
558 * External (<Method namepath>, MethodObj, <ArgCount>)
561 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
563 ******************************************************************************/
566 AcpiDmGetExternalsFromFile (
569 FILE *ExternalRefFile;
573 UINT32 ImportCount = 0;
576 if (!Gbl_ExternalRefFilename)
583 ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
584 if (!ExternalRefFile)
586 fprintf (stderr, "Could not open external reference file \"%s\"\n",
587 Gbl_ExternalRefFilename);
591 /* Each line defines a method */
593 while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
595 Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */
596 if (!Token) continue;
597 if (strcmp (Token, "External")) continue;
599 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */
600 if (!MethodName) continue;
602 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */
603 if (!Token) continue;
604 if (strcmp (Token, "MethodObj")) continue;
606 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */
607 if (!Token) continue;
609 /* Convert arg count string to an integer */
612 ArgCount = strtoul (Token, NULL, 0);
615 fprintf (stderr, "Invalid argument count (%s)\n", Token);
620 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
624 /* Add this external to the global list */
626 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
627 Gbl_ExternalRefFilename, ArgCount, MethodName);
629 AcpiDmAddToExternalListFromFile (MethodName, ACPI_TYPE_METHOD, ArgCount | 0x80);
635 fprintf (stderr, "Did not find any external methods in reference file \"%s\"\n",
636 Gbl_ExternalRefFilename);
640 /* Add the external(s) to the namespace */
642 AcpiDmAddExternalsToNamespace ();
644 AcpiOsPrintf ("%s: Imported %u external method definitions\n",
645 Gbl_ExternalRefFilename, ImportCount);
648 fclose (ExternalRefFile);
652 /*******************************************************************************
654 * FUNCTION: AcpiDmAddToExternalListFromFile
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
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.
666 ******************************************************************************/
669 AcpiDmAddToExternalListFromFile (
676 ACPI_EXTERNAL_LIST *NewExternal;
677 ACPI_EXTERNAL_LIST *NextExternal;
678 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
680 BOOLEAN Resolved = FALSE;
688 /* TBD: Add a flags parameter */
690 if (Type == ACPI_TYPE_METHOD)
700 * We don't want External() statements to contain a leading '\'.
701 * This prevents duplicate external statements of the form:
706 * This would cause a compile time error when the disassembled
707 * output file is recompiled.
709 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
714 /* Check all existing externals to ensure no duplicates */
716 NextExternal = AcpiGbl_ExternalList;
719 if (!ACPI_STRCMP (Path, NextExternal->Path))
721 /* Duplicate method, check that the Value (ArgCount) is the same */
723 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
724 (NextExternal->Value != Value))
726 ACPI_ERROR ((AE_INFO,
727 "(File) External method arg count mismatch %s: Current %u, override to %u",
728 NextExternal->Path, NextExternal->Value, Value));
730 /* Override, since new value came from external reference file */
732 NextExternal->Value = Value;
735 /* Allow upgrade of type from ANY */
737 else if (NextExternal->Type == ACPI_TYPE_ANY)
739 NextExternal->Type = Type;
740 NextExternal->Value = Value;
746 NextExternal = NextExternal->Next;
749 /* Get the internal pathname (AML format) */
751 Status = AcpiNsInternalizeName (Path, &InternalPath);
752 if (ACPI_FAILURE (Status))
757 /* Allocate and init a new External() descriptor */
759 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
762 ACPI_FREE (InternalPath);
766 /* Must copy and normalize the input path */
768 AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, NULL, &ExternalPath);
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;
777 /* Set flag to indicate External->InternalPath needs to be freed */
779 NewExternal->Flags |= ACPI_IPATH_ALLOCATED | ACPI_FROM_REFERENCE_FILE;
781 /* Link the new descriptor into the global list, alphabetically ordered */
783 NextExternal = AcpiGbl_ExternalList;
786 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
790 PrevExternal->Next = NewExternal;
794 AcpiGbl_ExternalList = NewExternal;
797 NewExternal->Next = NextExternal;
801 PrevExternal = NextExternal;
802 NextExternal = NextExternal->Next;
807 PrevExternal->Next = NewExternal;
811 AcpiGbl_ExternalList = NewExternal;
816 /*******************************************************************************
818 * FUNCTION: AcpiDmAddExternalsToNamespace
824 * DESCRIPTION: Add all externals to the namespace. Allows externals to be
827 ******************************************************************************/
830 AcpiDmAddExternalsToNamespace (
834 ACPI_NAMESPACE_NODE *Node;
835 ACPI_OPERAND_OBJECT *ObjDesc;
836 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
841 /* Add the external name (object) into the namespace */
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,
848 if (ACPI_FAILURE (Status))
850 ACPI_EXCEPTION ((AE_INFO, Status,
851 "while adding external to namespace [%s]",
855 else switch (External->Type)
857 case ACPI_TYPE_METHOD:
859 /* For methods, we need to save the argument count */
861 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
862 ObjDesc->Method.ParamCount = (UINT8) External->Value;
863 Node->Object = ObjDesc;
866 case ACPI_TYPE_REGION:
868 /* Regions require a region sub-object */
870 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
871 ObjDesc->Region.Node = Node;
872 Node->Object = ObjDesc;
880 External = External->Next;
885 /*******************************************************************************
887 * FUNCTION: AcpiDmGetExternalMethodCount
891 * RETURN: The number of control method externals in the external list
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.
900 ******************************************************************************/
903 AcpiDmGetExternalMethodCount (
906 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
912 if (External->Type == ACPI_TYPE_METHOD)
917 External = External->Next;
924 /*******************************************************************************
926 * FUNCTION: AcpiDmClearExternalList
932 * DESCRIPTION: Free the entire External info list
934 ******************************************************************************/
937 AcpiDmClearExternalList (
940 ACPI_EXTERNAL_LIST *NextExternal;
943 while (AcpiGbl_ExternalList)
945 NextExternal = AcpiGbl_ExternalList->Next;
946 ACPI_FREE (AcpiGbl_ExternalList->Path);
947 ACPI_FREE (AcpiGbl_ExternalList);
948 AcpiGbl_ExternalList = NextExternal;
953 /*******************************************************************************
955 * FUNCTION: AcpiDmEmitExternals
961 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
962 * the global external info list.
964 ******************************************************************************/
967 AcpiDmEmitExternals (
970 ACPI_EXTERNAL_LIST *NextExternal;
973 if (!AcpiGbl_ExternalList)
979 * Determine the number of control methods in the external list, and
980 * also how many of those externals were resolved via the namespace.
982 NextExternal = AcpiGbl_ExternalList;
985 if (NextExternal->Type == ACPI_TYPE_METHOD)
987 AcpiGbl_NumExternalMethods++;
988 if (NextExternal->Resolved)
990 AcpiGbl_ResolvedExternalMethods++;
994 NextExternal = NextExternal->Next;
997 /* Check if any control methods were unresolved */
999 AcpiDmUnresolvedWarning (1);
1001 /* Emit any unresolved method externals in a single text block */
1003 NextExternal = AcpiGbl_ExternalList;
1004 while (NextExternal)
1006 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
1007 (!NextExternal->Resolved))
1009 AcpiOsPrintf (" External (%s%s",
1011 AcpiDmGetObjectTypeName (NextExternal->Type));
1014 ") // Warning: Unresolved Method, "
1015 "guessing %u arguments (may be incorrect, see warning above)\n",
1016 NextExternal->Value);
1018 NextExternal->Emitted = TRUE;
1021 NextExternal = NextExternal->Next;
1024 AcpiOsPrintf ("\n");
1027 /* Emit externals that were imported from a file */
1029 if (Gbl_ExternalRefFilename)
1032 " /*\n * External declarations that were imported from\n"
1033 " * the reference file [%s]\n */\n",
1034 Gbl_ExternalRefFilename);
1036 NextExternal = AcpiGbl_ExternalList;
1037 while (NextExternal)
1039 if (!NextExternal->Emitted && (NextExternal->Flags & ACPI_FROM_REFERENCE_FILE))
1041 AcpiOsPrintf (" External (%s%s",
1043 AcpiDmGetObjectTypeName (NextExternal->Type));
1045 if (NextExternal->Type == ACPI_TYPE_METHOD)
1047 AcpiOsPrintf (") // %u Arguments\n",
1048 NextExternal->Value);
1052 AcpiOsPrintf (")\n");
1054 NextExternal->Emitted = TRUE;
1057 NextExternal = NextExternal->Next;
1060 AcpiOsPrintf ("\n");
1064 * Walk the list of externals found during the AML parsing
1066 while (AcpiGbl_ExternalList)
1068 if (!AcpiGbl_ExternalList->Emitted)
1070 AcpiOsPrintf (" External (%s%s",
1071 AcpiGbl_ExternalList->Path,
1072 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1074 /* For methods, add a comment with the number of arguments */
1076 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1078 AcpiOsPrintf (") // %u Arguments\n",
1079 AcpiGbl_ExternalList->Value);
1083 AcpiOsPrintf (")\n");
1087 /* Free this external info block and move on to next external */
1089 NextExternal = AcpiGbl_ExternalList->Next;
1090 if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED)
1092 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1095 ACPI_FREE (AcpiGbl_ExternalList->Path);
1096 ACPI_FREE (AcpiGbl_ExternalList);
1097 AcpiGbl_ExternalList = NextExternal;
1100 AcpiOsPrintf ("\n");
1104 /*******************************************************************************
1106 * FUNCTION: AcpiDmUnresolvedWarning
1108 * PARAMETERS: Type - Where to output the warning.
1109 * 0 means write to stderr
1110 * 1 means write to AcpiOsPrintf
1114 * DESCRIPTION: Issue warning message if there are unresolved external control
1115 * methods within the disassembly.
1117 ******************************************************************************/
1120 Summary of the external control method problem:
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).
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 .
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.
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:
1145 ABCD (Add (2, 7, Local0))
1153 Here is the AML code that is generated for T1 and T2:
1157 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1160 187: ABCD (Add (2, 7, Local0))
1162 00000353: 41 42 43 44 ............ "ABCD"
1163 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1169 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1174 00000364: 45 46 47 48 ............ "EFGH"
1176 193: Add (2, 7, Local0)
1178 00000368: 72 0A 02 0A 07 60 ...... "r....`"
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.
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.
1191 AcpiDmUnresolvedWarning (
1195 if (!AcpiGbl_NumExternalMethods)
1202 if (!AcpiGbl_ExternalFileList)
1204 /* The -e option was not specified */
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"
1217 AcpiGbl_NumExternalMethods);
1219 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1221 /* The -e option was specified, but there are still some unresolved externals */
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"
1231 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1232 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1233 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));
1238 if (!AcpiGbl_ExternalFileList)
1240 /* The -e option was not specified */
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);
1254 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1256 /* The -e option was specified, but there are still some unresolved externals */
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));