1 /******************************************************************************
3 * Module Name: dmextern - Support for External() ASL statements
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2015, 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.
49 #include "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 */ ", UnknownObj", /* 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 AcpiDmAddPathToExternalList (
114 AcpiDmCreateNewExternal (
122 /*******************************************************************************
124 * FUNCTION: AcpiDmGetObjectTypeName
126 * PARAMETERS: Type - An ACPI_OBJECT_TYPE
128 * RETURN: Pointer to a string
130 * DESCRIPTION: Map an object type to the ASL object type string.
132 ******************************************************************************/
135 AcpiDmGetObjectTypeName (
136 ACPI_OBJECT_TYPE Type)
139 if (Type == ACPI_TYPE_LOCAL_SCOPE)
141 Type = ACPI_TYPE_DEVICE;
144 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
149 return (AcpiGbl_DmTypeNames[Type]);
153 /*******************************************************************************
155 * FUNCTION: AcpiDmNormalizeParentPrefix
157 * PARAMETERS: Op - Parse op
158 * Path - Path with parent prefix
160 * RETURN: The full pathname to the object (from the namespace root)
162 * DESCRIPTION: Returns the full pathname of a path with parent prefix
163 * The caller must free the fullpath returned.
165 ******************************************************************************/
168 AcpiDmNormalizeParentPrefix (
169 ACPI_PARSE_OBJECT *Op,
172 ACPI_NAMESPACE_NODE *Node;
184 /* Search upwards in the parse tree until we reach the next namespace node */
186 Op = Op->Common.Parent;
194 Op = Op->Common.Parent;
203 * Find the actual parent node for the reference:
204 * Remove all carat prefixes from the input path.
205 * There may be multiple parent prefixes (For example, ^^^M000)
207 Node = Op->Common.Node;
208 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
219 /* Get the full pathname for the parent node */
221 ParentPath = AcpiNsGetExternalPathname (Node);
227 Length = (strlen (ParentPath) + strlen (Path) + 1);
231 * If ParentPath is not just a simple '\', increment the length
232 * for the required dot separator (ParentPath.Path)
236 /* For External() statements, we do not want a leading '\' */
238 if (*ParentPath == AML_ROOT_PREFIX)
244 Fullpath = ACPI_ALLOCATE_ZEROED (Length);
251 * Concatenate parent fullpath and path. For example,
252 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
254 * Copy the parent path
256 strcpy (Fullpath, &ParentPath[Index]);
260 * (don't need dot if parent fullpath is a single backslash)
264 strcat (Fullpath, ".");
267 /* Copy child path (carat parent prefix(es) were skipped above) */
269 strcat (Fullpath, Path);
272 ACPI_FREE (ParentPath);
277 /*******************************************************************************
279 * FUNCTION: AcpiDmAddToExternalFileList
281 * PARAMETERS: PathList - Single path or list separated by comma
285 * DESCRIPTION: Add external files to global list
287 ******************************************************************************/
290 AcpiDmAddToExternalFileList (
293 ACPI_EXTERNAL_FILE *ExternalFile;
302 LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
305 return (AE_NO_MEMORY);
308 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
311 ACPI_FREE (LocalPathname);
312 return (AE_NO_MEMORY);
315 /* Take a copy of the file pathname */
317 strcpy (LocalPathname, Pathname);
318 ExternalFile->Path = LocalPathname;
320 if (AcpiGbl_ExternalFileList)
322 ExternalFile->Next = AcpiGbl_ExternalFileList;
325 AcpiGbl_ExternalFileList = ExternalFile;
330 /*******************************************************************************
332 * FUNCTION: AcpiDmClearExternalFileList
338 * DESCRIPTION: Clear the external file list
340 ******************************************************************************/
343 AcpiDmClearExternalFileList (
346 ACPI_EXTERNAL_FILE *NextExternal;
349 while (AcpiGbl_ExternalFileList)
351 NextExternal = AcpiGbl_ExternalFileList->Next;
352 ACPI_FREE (AcpiGbl_ExternalFileList->Path);
353 ACPI_FREE (AcpiGbl_ExternalFileList);
354 AcpiGbl_ExternalFileList = NextExternal;
359 /*******************************************************************************
361 * FUNCTION: AcpiDmGetExternalsFromFile
367 * DESCRIPTION: Process the optional external reference file.
369 * Each line in the file should be of the form:
370 * External (<Method namepath>, MethodObj, <ArgCount>)
373 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
375 ******************************************************************************/
378 AcpiDmGetExternalsFromFile (
381 FILE *ExternalRefFile;
385 UINT32 ImportCount = 0;
388 if (!Gbl_ExternalRefFilename)
395 ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
396 if (!ExternalRefFile)
398 fprintf (stderr, "Could not open external reference file \"%s\"\n",
399 Gbl_ExternalRefFilename);
404 /* Each line defines a method */
406 while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
408 Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */
413 if (strcmp (Token, "External"))
418 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */
424 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */
430 if (strcmp (Token, "MethodObj"))
435 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */
441 /* Convert arg count string to an integer */
444 ArgCount = strtoul (Token, NULL, 0);
447 fprintf (stderr, "Invalid argument count (%s)\n", Token);
452 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
456 /* Add this external to the global list */
458 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
459 Gbl_ExternalRefFilename, ArgCount, MethodName);
461 AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
462 ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
468 fprintf (stderr, "Did not find any external methods in reference file \"%s\"\n",
469 Gbl_ExternalRefFilename);
473 /* Add the external(s) to the namespace */
475 AcpiDmAddExternalsToNamespace ();
477 AcpiOsPrintf ("%s: Imported %u external method definitions\n",
478 Gbl_ExternalRefFilename, ImportCount);
481 fclose (ExternalRefFile);
485 /*******************************************************************************
487 * FUNCTION: AcpiDmAddOpToExternalList
489 * PARAMETERS: Op - Current parser Op
490 * Path - Internal (AML) path to the object
491 * Type - ACPI object type to be added
492 * Value - Arg count if adding a Method object
493 * Flags - To be passed to the external object
497 * DESCRIPTION: Insert a new name into the global list of Externals which
498 * will in turn be later emitted as an External() declaration
499 * in the disassembled output.
501 * This function handles the most common case where the referenced
502 * name is simply not found in the constructed namespace.
504 ******************************************************************************/
507 AcpiDmAddOpToExternalList (
508 ACPI_PARSE_OBJECT *Op,
515 char *InternalPath = Path;
520 ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
528 /* Remove a root backslash if present */
530 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
535 /* Externalize the pathname */
537 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
538 NULL, &ExternalPath);
539 if (ACPI_FAILURE (Status))
545 * Get the full pathname from the root if "Path" has one or more
546 * parent prefixes (^). Note: path will not contain a leading '\'.
548 if (*Path == (UINT8) AML_PARENT_PREFIX)
550 Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
552 /* Set new external path */
554 ACPI_FREE (ExternalPath);
561 /* Create the new internal pathname */
563 Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
564 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
565 if (ACPI_FAILURE (Status))
567 ACPI_FREE (ExternalPath);
572 /* Create the new External() declaration node */
574 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
576 if (ACPI_FAILURE (Status))
578 ACPI_FREE (ExternalPath);
579 if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
581 ACPI_FREE (InternalPath);
589 /*******************************************************************************
591 * FUNCTION: AcpiDmAddNodeToExternalList
593 * PARAMETERS: Node - Namespace node for object to be added
594 * Type - ACPI object type to be added
595 * Value - Arg count if adding a Method object
596 * Flags - To be passed to the external object
600 * DESCRIPTION: Insert a new name into the global list of Externals which
601 * will in turn be later emitted as an External() declaration
602 * in the disassembled output.
604 * This function handles the case where the referenced name has
605 * been found in the namespace, but the name originated in a
606 * table other than the one that is being disassembled (such
607 * as a table that is added via the iASL -e option).
609 ******************************************************************************/
612 AcpiDmAddNodeToExternalList (
613 ACPI_NAMESPACE_NODE *Node,
624 ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
632 /* Get the full external and internal pathnames to the node */
634 ExternalPath = AcpiNsGetExternalPathname (Node);
640 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
641 if (ACPI_FAILURE (Status))
643 ACPI_FREE (ExternalPath);
647 /* Remove the root backslash */
649 if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1]))
651 Temp = ACPI_ALLOCATE_ZEROED (strlen (ExternalPath) + 1);
657 strcpy (Temp, &ExternalPath[1]);
658 ACPI_FREE (ExternalPath);
662 /* Create the new External() declaration node */
664 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
665 Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
666 if (ACPI_FAILURE (Status))
668 ACPI_FREE (ExternalPath);
669 ACPI_FREE (InternalPath);
676 /*******************************************************************************
678 * FUNCTION: AcpiDmAddPathToExternalList
680 * PARAMETERS: Path - External name of the object to be added
681 * Type - ACPI object type to be added
682 * Value - Arg count if adding a Method object
683 * Flags - To be passed to the external object
687 * DESCRIPTION: Insert a new name into the global list of Externals which
688 * will in turn be later emitted as an External() declaration
689 * in the disassembled output.
691 * This function currently is used to add externals via a
692 * reference file (via the -fe iASL option).
694 ******************************************************************************/
697 AcpiDmAddPathToExternalList (
708 ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
716 /* Remove a root backslash if present */
718 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
723 /* Create the internal and external pathnames */
725 Status = AcpiNsInternalizeName (Path, &InternalPath);
726 if (ACPI_FAILURE (Status))
731 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
732 NULL, &ExternalPath);
733 if (ACPI_FAILURE (Status))
735 ACPI_FREE (InternalPath);
739 /* Create the new External() declaration node */
741 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
742 Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
743 if (ACPI_FAILURE (Status))
745 ACPI_FREE (ExternalPath);
746 ACPI_FREE (InternalPath);
753 /*******************************************************************************
755 * FUNCTION: AcpiDmCreateNewExternal
757 * PARAMETERS: ExternalPath - External path to the object
758 * InternalPath - Internal (AML) path to the object
759 * Type - ACPI object type to be added
760 * Value - Arg count if adding a Method object
761 * Flags - To be passed to the external object
765 * DESCRIPTION: Common low-level function to insert a new name into the global
766 * list of Externals which will in turn be later emitted as
767 * External() declarations in the disassembled output.
769 * Note: The external name should not include a root prefix
770 * (backslash). We do not want External() statements to contain
771 * a leading '\', as this prevents duplicate external statements
777 * This would cause a compile time error when the disassembled
778 * output file is recompiled.
780 * There are two cases that are handled here. For both, we emit
781 * an External() statement:
782 * 1) The name was simply not found in the namespace.
783 * 2) The name was found, but it originated in a table other than
784 * the table that is being disassembled.
786 ******************************************************************************/
789 AcpiDmCreateNewExternal (
796 ACPI_EXTERNAL_LIST *NewExternal;
797 ACPI_EXTERNAL_LIST *NextExternal;
798 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
801 ACPI_FUNCTION_TRACE (DmCreateNewExternal);
804 /* Check all existing externals to ensure no duplicates */
806 NextExternal = AcpiGbl_ExternalList;
809 if (!strcmp (ExternalPath, NextExternal->Path))
811 /* Duplicate method, check that the Value (ArgCount) is the same */
813 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
814 (NextExternal->Value != Value) &&
817 ACPI_ERROR ((AE_INFO,
818 "External method arg count mismatch %s: Current %u, attempted %u",
819 NextExternal->Path, NextExternal->Value, Value));
822 /* Allow upgrade of type from ANY */
824 else if (NextExternal->Type == ACPI_TYPE_ANY)
826 NextExternal->Type = Type;
827 NextExternal->Value = Value;
830 return_ACPI_STATUS (AE_ALREADY_EXISTS);
833 NextExternal = NextExternal->Next;
836 /* Allocate and init a new External() descriptor */
838 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
841 return_ACPI_STATUS (AE_NO_MEMORY);
844 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
845 "Adding external reference node (%s) type [%s]\n",
846 ExternalPath, AcpiUtGetTypeName (Type)));
848 NewExternal->Flags = Flags;
849 NewExternal->Value = Value;
850 NewExternal->Path = ExternalPath;
851 NewExternal->Type = Type;
852 NewExternal->Length = (UINT16) strlen (ExternalPath);
853 NewExternal->InternalPath = InternalPath;
855 /* Link the new descriptor into the global list, alphabetically ordered */
857 NextExternal = AcpiGbl_ExternalList;
860 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
864 PrevExternal->Next = NewExternal;
868 AcpiGbl_ExternalList = NewExternal;
871 NewExternal->Next = NextExternal;
872 return_ACPI_STATUS (AE_OK);
875 PrevExternal = NextExternal;
876 NextExternal = NextExternal->Next;
881 PrevExternal->Next = NewExternal;
885 AcpiGbl_ExternalList = NewExternal;
888 return_ACPI_STATUS (AE_OK);
892 /*******************************************************************************
894 * FUNCTION: AcpiDmAddExternalsToNamespace
900 * DESCRIPTION: Add all externals to the namespace. Allows externals to be
903 ******************************************************************************/
906 AcpiDmAddExternalsToNamespace (
910 ACPI_NAMESPACE_NODE *Node;
911 ACPI_OPERAND_OBJECT *ObjDesc;
912 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
917 /* Add the external name (object) into the namespace */
919 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
920 ACPI_IMODE_LOAD_PASS1,
921 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
924 if (ACPI_FAILURE (Status))
926 ACPI_EXCEPTION ((AE_INFO, Status,
927 "while adding external to namespace [%s]",
931 else switch (External->Type)
933 case ACPI_TYPE_METHOD:
935 /* For methods, we need to save the argument count */
937 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
938 ObjDesc->Method.ParamCount = (UINT8) External->Value;
939 Node->Object = ObjDesc;
942 case ACPI_TYPE_REGION:
944 /* Regions require a region sub-object */
946 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
947 ObjDesc->Region.Node = Node;
948 Node->Object = ObjDesc;
956 External = External->Next;
961 /*******************************************************************************
963 * FUNCTION: AcpiDmGetExternalMethodCount
967 * RETURN: The number of control method externals in the external list
969 * DESCRIPTION: Return the number of method externals that have been generated.
970 * If any control method externals have been found, we must
971 * re-parse the entire definition block with the new information
972 * (number of arguments for the methods.) This is limitation of
973 * AML, we don't know the number of arguments from the control
974 * method invocation itself.
976 ******************************************************************************/
979 AcpiDmGetExternalMethodCount (
982 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
988 if (External->Type == ACPI_TYPE_METHOD)
993 External = External->Next;
1000 /*******************************************************************************
1002 * FUNCTION: AcpiDmClearExternalList
1008 * DESCRIPTION: Free the entire External info list
1010 ******************************************************************************/
1013 AcpiDmClearExternalList (
1016 ACPI_EXTERNAL_LIST *NextExternal;
1019 while (AcpiGbl_ExternalList)
1021 NextExternal = AcpiGbl_ExternalList->Next;
1022 ACPI_FREE (AcpiGbl_ExternalList->Path);
1023 ACPI_FREE (AcpiGbl_ExternalList);
1024 AcpiGbl_ExternalList = NextExternal;
1029 /*******************************************************************************
1031 * FUNCTION: AcpiDmEmitExternals
1037 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1038 * the global external info list.
1040 ******************************************************************************/
1043 AcpiDmEmitExternals (
1046 ACPI_EXTERNAL_LIST *NextExternal;
1049 if (!AcpiGbl_ExternalList)
1055 * Determine the number of control methods in the external list, and
1056 * also how many of those externals were resolved via the namespace.
1058 NextExternal = AcpiGbl_ExternalList;
1059 while (NextExternal)
1061 if (NextExternal->Type == ACPI_TYPE_METHOD)
1063 AcpiGbl_NumExternalMethods++;
1064 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1066 AcpiGbl_ResolvedExternalMethods++;
1070 NextExternal = NextExternal->Next;
1073 /* Check if any control methods were unresolved */
1075 AcpiDmUnresolvedWarning (1);
1077 /* Emit any unresolved method externals in a single text block */
1079 NextExternal = AcpiGbl_ExternalList;
1080 while (NextExternal)
1082 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
1083 (!(NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1085 AcpiOsPrintf (" External (%s%s",
1087 AcpiDmGetObjectTypeName (NextExternal->Type));
1089 AcpiOsPrintf (") // Warning: Unresolved method, "
1090 "guessing %u arguments\n",
1091 NextExternal->Value);
1093 NextExternal->Flags |= ACPI_EXT_EXTERNAL_EMITTED;
1096 NextExternal = NextExternal->Next;
1099 AcpiOsPrintf ("\n");
1102 /* Emit externals that were imported from a file */
1104 if (Gbl_ExternalRefFilename)
1107 " /*\n * External declarations that were imported from\n"
1108 " * the reference file [%s]\n */\n",
1109 Gbl_ExternalRefFilename);
1111 NextExternal = AcpiGbl_ExternalList;
1112 while (NextExternal)
1114 if (!(NextExternal->Flags & ACPI_EXT_EXTERNAL_EMITTED) &&
1115 (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_FILE))
1117 AcpiOsPrintf (" External (%s%s",
1119 AcpiDmGetObjectTypeName (NextExternal->Type));
1121 if (NextExternal->Type == ACPI_TYPE_METHOD)
1123 AcpiOsPrintf (") // %u Arguments\n",
1124 NextExternal->Value);
1128 AcpiOsPrintf (")\n");
1130 NextExternal->Flags |= ACPI_EXT_EXTERNAL_EMITTED;
1133 NextExternal = NextExternal->Next;
1136 AcpiOsPrintf ("\n");
1140 * Walk the list of externals found during the AML parsing
1142 while (AcpiGbl_ExternalList)
1144 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1146 AcpiOsPrintf (" External (%s%s",
1147 AcpiGbl_ExternalList->Path,
1148 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1150 /* For methods, add a comment with the number of arguments */
1152 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1154 AcpiOsPrintf (") // %u Arguments\n",
1155 AcpiGbl_ExternalList->Value);
1159 AcpiOsPrintf (")\n");
1163 /* Free this external info block and move on to next external */
1165 NextExternal = AcpiGbl_ExternalList->Next;
1166 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1168 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1171 ACPI_FREE (AcpiGbl_ExternalList->Path);
1172 ACPI_FREE (AcpiGbl_ExternalList);
1173 AcpiGbl_ExternalList = NextExternal;
1176 AcpiOsPrintf ("\n");
1180 /*******************************************************************************
1182 * FUNCTION: AcpiDmUnresolvedWarning
1184 * PARAMETERS: Type - Where to output the warning.
1185 * 0 means write to stderr
1186 * 1 means write to AcpiOsPrintf
1190 * DESCRIPTION: Issue warning message if there are unresolved external control
1191 * methods within the disassembly.
1193 ******************************************************************************/
1196 Summary of the external control method problem:
1198 When the -e option is used with disassembly, the various SSDTs are simply
1199 loaded into a global namespace for the disassembler to use in order to
1200 resolve control method references (invocations).
1202 The disassembler tracks any such references, and will emit an External()
1203 statement for these types of methods, with the proper number of arguments .
1205 Without the SSDTs, the AML does not contain enough information to properly
1206 disassemble the control method invocation -- because the disassembler does
1207 not know how many arguments to parse.
1209 An example: Assume we have two control methods. ABCD has one argument, and
1210 EFGH has zero arguments. Further, we have two additional control methods
1211 that invoke ABCD and EFGH, named T1 and T2:
1221 ABCD (Add (2, 7, Local0))
1229 Here is the AML code that is generated for T1 and T2:
1233 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1236 187: ABCD (Add (2, 7, Local0))
1238 00000353: 41 42 43 44 ............ "ABCD"
1239 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1245 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1250 00000364: 45 46 47 48 ............ "EFGH"
1252 193: Add (2, 7, Local0)
1254 00000368: 72 0A 02 0A 07 60 ...... "r....`"
1257 Note that the AML code for T1 and T2 is essentially identical. When
1258 disassembling this code, the methods ABCD and EFGH must be known to the
1259 disassembler, otherwise it does not know how to handle the method invocations.
1261 In other words, if ABCD and EFGH are actually external control methods
1262 appearing in an SSDT, the disassembler does not know what to do unless
1263 the owning SSDT has been loaded via the -e option.
1267 AcpiDmUnresolvedWarning (
1271 if (!AcpiGbl_NumExternalMethods)
1278 if (!AcpiGbl_ExternalFileList)
1280 /* The -e option was not specified */
1282 AcpiOsPrintf (" /*\n"
1283 " * iASL Warning: There were %u external control methods found during\n"
1284 " * disassembly, but additional ACPI tables to resolve these externals\n"
1285 " * were not specified. This resulting disassembler output file may not\n"
1286 " * compile because the disassembler did not know how many arguments\n"
1287 " * to assign to these methods. To specify the tables needed to resolve\n"
1288 " * external control method references, the -e option can be used to\n"
1289 " * specify the filenames. Note: SSDTs can be dynamically loaded at\n"
1290 " * runtime and may or may not be available via the host OS.\n"
1291 " * Example iASL invocations:\n"
1292 " * iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1293 " * iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1294 " * iasl -e ssdt*.aml -d dsdt.aml\n"
1296 " * In addition, the -fe option can be used to specify a file containing\n"
1297 " * control method external declarations with the associated method\n"
1298 " * argument counts. Each line of the file must be of the form:\n"
1299 " * External (<method pathname>, MethodObj, <argument count>)\n"
1301 " * iasl -fe refs.txt -d dsdt.aml\n"
1303 " * The following methods were unresolved and many not compile properly\n"
1304 " * because the disassembler had to guess at the number of arguments\n"
1305 " * required for each:\n"
1307 AcpiGbl_NumExternalMethods);
1309 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1311 /* The -e option was specified, but there are still some unresolved externals */
1313 AcpiOsPrintf (" /*\n"
1314 " * iASL Warning: There were %u external control methods found during\n"
1315 " * disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1316 " * ACPI tables may be required to properly disassemble the code. This\n"
1317 " * resulting disassembler output file may not compile because the\n"
1318 " * disassembler did not know how many arguments to assign to the\n"
1319 " * unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1320 " * runtime and may or may not be available via the host OS.\n"
1322 " * If necessary, the -fe option can be used to specify a file containing\n"
1323 " * control method external declarations with the associated method\n"
1324 " * argument counts. Each line of the file must be of the form:\n"
1325 " * External (<method pathname>, MethodObj, <argument count>)\n"
1327 " * iasl -fe refs.txt -d dsdt.aml\n"
1329 " * The following methods were unresolved and many not compile properly\n"
1330 " * because the disassembler had to guess at the number of arguments\n"
1331 " * required for each:\n"
1333 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1334 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1335 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));
1340 if (!AcpiGbl_ExternalFileList)
1342 /* The -e option was not specified */
1344 fprintf (stderr, "\n"
1345 "iASL Warning: There were %u external control methods found during\n"
1346 "disassembly, but additional ACPI tables to resolve these externals\n"
1347 "were not specified. The resulting disassembler output file may not\n"
1348 "compile because the disassembler did not know how many arguments\n"
1349 "to assign to these methods. To specify the tables needed to resolve\n"
1350 "external control method references, the -e option can be used to\n"
1351 "specify the filenames. Note: SSDTs can be dynamically loaded at\n"
1352 "runtime and may or may not be available via the host OS.\n"
1353 "Example iASL invocations:\n"
1354 " iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1355 " iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1356 " iasl -e ssdt*.aml -d dsdt.aml\n"
1358 "In addition, the -fe option can be used to specify a file containing\n"
1359 "control method external declarations with the associated method\n"
1360 "argument counts. Each line of the file must be of the form:\n"
1361 " External (<method pathname>, MethodObj, <argument count>)\n"
1363 " iasl -fe refs.txt -d dsdt.aml\n",
1364 AcpiGbl_NumExternalMethods);
1366 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1368 /* The -e option was specified, but there are still some unresolved externals */
1370 fprintf (stderr, "\n"
1371 "iASL Warning: There were %u external control methods found during\n"
1372 "disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1373 "ACPI tables may be required to properly disassemble the code. The\n"
1374 "resulting disassembler output file may not compile because the\n"
1375 "disassembler did not know how many arguments to assign to the\n"
1376 "unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1377 "runtime and may or may not be available via the host OS.\n"
1379 "If necessary, the -fe option can be used to specify a file containing\n"
1380 "control method external declarations with the associated method\n"
1381 "argument counts. Each line of the file must be of the form:\n"
1382 " External (<method pathname>, MethodObj, <argument count>)\n"
1384 " iasl -fe refs.txt -d dsdt.aml\n",
1385 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1386 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1387 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));