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;
143 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
148 return (AcpiGbl_DmTypeNames[Type]);
152 /*******************************************************************************
154 * FUNCTION: AcpiDmNormalizeParentPrefix
156 * PARAMETERS: Op - Parse op
157 * Path - Path with parent prefix
159 * RETURN: The full pathname to the object (from the namespace root)
161 * DESCRIPTION: Returns the full pathname of a path with parent prefix
162 * The caller must free the fullpath returned.
164 ******************************************************************************/
167 AcpiDmNormalizeParentPrefix (
168 ACPI_PARSE_OBJECT *Op,
171 ACPI_NAMESPACE_NODE *Node;
183 /* Search upwards in the parse tree until we reach the next namespace node */
185 Op = Op->Common.Parent;
193 Op = Op->Common.Parent;
202 * Find the actual parent node for the reference:
203 * Remove all carat prefixes from the input path.
204 * There may be multiple parent prefixes (For example, ^^^M000)
206 Node = Op->Common.Node;
207 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
218 /* Get the full pathname for the parent node */
220 ParentPath = AcpiNsGetExternalPathname (Node);
226 Length = (strlen (ParentPath) + strlen (Path) + 1);
230 * If ParentPath is not just a simple '\', increment the length
231 * for the required dot separator (ParentPath.Path)
235 /* For External() statements, we do not want a leading '\' */
237 if (*ParentPath == AML_ROOT_PREFIX)
243 Fullpath = ACPI_ALLOCATE_ZEROED (Length);
250 * Concatenate parent fullpath and path. For example,
251 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
253 * Copy the parent path
255 strcpy (Fullpath, &ParentPath[Index]);
259 * (don't need dot if parent fullpath is a single backslash)
263 strcat (Fullpath, ".");
266 /* Copy child path (carat parent prefix(es) were skipped above) */
268 strcat (Fullpath, Path);
271 ACPI_FREE (ParentPath);
276 /*******************************************************************************
278 * FUNCTION: AcpiDmAddToExternalFileList
280 * PARAMETERS: PathList - Single path or list separated by comma
284 * DESCRIPTION: Add external files to global list
286 ******************************************************************************/
289 AcpiDmAddToExternalFileList (
292 ACPI_EXTERNAL_FILE *ExternalFile;
301 LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
304 return (AE_NO_MEMORY);
307 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
310 ACPI_FREE (LocalPathname);
311 return (AE_NO_MEMORY);
314 /* Take a copy of the file pathname */
316 strcpy (LocalPathname, Pathname);
317 ExternalFile->Path = LocalPathname;
319 if (AcpiGbl_ExternalFileList)
321 ExternalFile->Next = AcpiGbl_ExternalFileList;
324 AcpiGbl_ExternalFileList = ExternalFile;
329 /*******************************************************************************
331 * FUNCTION: AcpiDmClearExternalFileList
337 * DESCRIPTION: Clear the external file list
339 ******************************************************************************/
342 AcpiDmClearExternalFileList (
345 ACPI_EXTERNAL_FILE *NextExternal;
348 while (AcpiGbl_ExternalFileList)
350 NextExternal = AcpiGbl_ExternalFileList->Next;
351 ACPI_FREE (AcpiGbl_ExternalFileList->Path);
352 ACPI_FREE (AcpiGbl_ExternalFileList);
353 AcpiGbl_ExternalFileList = NextExternal;
358 /*******************************************************************************
360 * FUNCTION: AcpiDmGetExternalsFromFile
366 * DESCRIPTION: Process the optional external reference file.
368 * Each line in the file should be of the form:
369 * External (<Method namepath>, MethodObj, <ArgCount>)
372 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
374 ******************************************************************************/
377 AcpiDmGetExternalsFromFile (
380 FILE *ExternalRefFile;
384 UINT32 ImportCount = 0;
387 if (!Gbl_ExternalRefFilename)
394 ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
395 if (!ExternalRefFile)
397 fprintf (stderr, "Could not open external reference file \"%s\"\n",
398 Gbl_ExternalRefFilename);
403 /* Each line defines a method */
405 while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
407 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);
453 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
457 /* Add this external to the global list */
459 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
460 Gbl_ExternalRefFilename, ArgCount, MethodName);
462 AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
463 ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
470 "Did not find any external methods in reference file \"%s\"\n",
471 Gbl_ExternalRefFilename);
475 /* Add the external(s) to the namespace */
477 AcpiDmAddExternalsToNamespace ();
479 AcpiOsPrintf ("%s: Imported %u external method definitions\n",
480 Gbl_ExternalRefFilename, ImportCount);
483 fclose (ExternalRefFile);
487 /*******************************************************************************
489 * FUNCTION: AcpiDmAddOpToExternalList
491 * PARAMETERS: Op - Current parser Op
492 * Path - Internal (AML) path to the object
493 * Type - ACPI object type to be added
494 * Value - Arg count if adding a Method object
495 * Flags - To be passed to the external object
499 * DESCRIPTION: Insert a new name into the global list of Externals which
500 * will in turn be later emitted as an External() declaration
501 * in the disassembled output.
503 * This function handles the most common case where the referenced
504 * name is simply not found in the constructed namespace.
506 ******************************************************************************/
509 AcpiDmAddOpToExternalList (
510 ACPI_PARSE_OBJECT *Op,
517 char *InternalPath = Path;
522 ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
530 /* Remove a root backslash if present */
532 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
537 /* Externalize the pathname */
539 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
540 NULL, &ExternalPath);
541 if (ACPI_FAILURE (Status))
547 * Get the full pathname from the root if "Path" has one or more
548 * parent prefixes (^). Note: path will not contain a leading '\'.
550 if (*Path == (UINT8) AML_PARENT_PREFIX)
552 Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
554 /* Set new external path */
556 ACPI_FREE (ExternalPath);
563 /* Create the new internal pathname */
565 Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
566 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
567 if (ACPI_FAILURE (Status))
569 ACPI_FREE (ExternalPath);
574 /* Create the new External() declaration node */
576 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
578 if (ACPI_FAILURE (Status))
580 ACPI_FREE (ExternalPath);
581 if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
583 ACPI_FREE (InternalPath);
591 /*******************************************************************************
593 * FUNCTION: AcpiDmAddNodeToExternalList
595 * PARAMETERS: Node - Namespace node for object to be added
596 * Type - ACPI object type to be added
597 * Value - Arg count if adding a Method object
598 * Flags - To be passed to the external object
602 * DESCRIPTION: Insert a new name into the global list of Externals which
603 * will in turn be later emitted as an External() declaration
604 * in the disassembled output.
606 * This function handles the case where the referenced name has
607 * been found in the namespace, but the name originated in a
608 * table other than the one that is being disassembled (such
609 * as a table that is added via the iASL -e option).
611 ******************************************************************************/
614 AcpiDmAddNodeToExternalList (
615 ACPI_NAMESPACE_NODE *Node,
626 ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
634 /* Get the full external and internal pathnames to the node */
636 ExternalPath = AcpiNsGetExternalPathname (Node);
642 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
643 if (ACPI_FAILURE (Status))
645 ACPI_FREE (ExternalPath);
649 /* Remove the root backslash */
651 if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1]))
653 Temp = ACPI_ALLOCATE_ZEROED (strlen (ExternalPath) + 1);
659 strcpy (Temp, &ExternalPath[1]);
660 ACPI_FREE (ExternalPath);
664 /* Create the new External() declaration node */
666 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
667 Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
668 if (ACPI_FAILURE (Status))
670 ACPI_FREE (ExternalPath);
671 ACPI_FREE (InternalPath);
678 /*******************************************************************************
680 * FUNCTION: AcpiDmAddPathToExternalList
682 * PARAMETERS: Path - External name of the object to be added
683 * Type - ACPI object type to be added
684 * Value - Arg count if adding a Method object
685 * Flags - To be passed to the external object
689 * DESCRIPTION: Insert a new name into the global list of Externals which
690 * will in turn be later emitted as an External() declaration
691 * in the disassembled output.
693 * This function currently is used to add externals via a
694 * reference file (via the -fe iASL option).
696 ******************************************************************************/
699 AcpiDmAddPathToExternalList (
710 ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
718 /* Remove a root backslash if present */
720 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
725 /* Create the internal and external pathnames */
727 Status = AcpiNsInternalizeName (Path, &InternalPath);
728 if (ACPI_FAILURE (Status))
733 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
734 NULL, &ExternalPath);
735 if (ACPI_FAILURE (Status))
737 ACPI_FREE (InternalPath);
741 /* Create the new External() declaration node */
743 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
744 Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
745 if (ACPI_FAILURE (Status))
747 ACPI_FREE (ExternalPath);
748 ACPI_FREE (InternalPath);
755 /*******************************************************************************
757 * FUNCTION: AcpiDmCreateNewExternal
759 * PARAMETERS: ExternalPath - External path to the object
760 * InternalPath - Internal (AML) path to the object
761 * Type - ACPI object type to be added
762 * Value - Arg count if adding a Method object
763 * Flags - To be passed to the external object
767 * DESCRIPTION: Common low-level function to insert a new name into the global
768 * list of Externals which will in turn be later emitted as
769 * External() declarations in the disassembled output.
771 * Note: The external name should not include a root prefix
772 * (backslash). We do not want External() statements to contain
773 * a leading '\', as this prevents duplicate external statements
779 * This would cause a compile time error when the disassembled
780 * output file is recompiled.
782 * There are two cases that are handled here. For both, we emit
783 * an External() statement:
784 * 1) The name was simply not found in the namespace.
785 * 2) The name was found, but it originated in a table other than
786 * the table that is being disassembled.
788 ******************************************************************************/
791 AcpiDmCreateNewExternal (
798 ACPI_EXTERNAL_LIST *NewExternal;
799 ACPI_EXTERNAL_LIST *NextExternal;
800 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
803 ACPI_FUNCTION_TRACE (DmCreateNewExternal);
806 /* Check all existing externals to ensure no duplicates */
808 NextExternal = AcpiGbl_ExternalList;
811 if (!strcmp (ExternalPath, NextExternal->Path))
813 /* Duplicate method, check that the Value (ArgCount) is the same */
815 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
816 (NextExternal->Value != Value) &&
819 ACPI_ERROR ((AE_INFO,
820 "External method arg count mismatch %s: "
821 "Current %u, attempted %u",
822 NextExternal->Path, NextExternal->Value, Value));
825 /* Allow upgrade of type from ANY */
827 else if (NextExternal->Type == ACPI_TYPE_ANY)
829 NextExternal->Type = Type;
830 NextExternal->Value = Value;
833 return_ACPI_STATUS (AE_ALREADY_EXISTS);
836 NextExternal = NextExternal->Next;
839 /* Allocate and init a new External() descriptor */
841 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
844 return_ACPI_STATUS (AE_NO_MEMORY);
847 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
848 "Adding external reference node (%s) type [%s]\n",
849 ExternalPath, AcpiUtGetTypeName (Type)));
851 NewExternal->Flags = Flags;
852 NewExternal->Value = Value;
853 NewExternal->Path = ExternalPath;
854 NewExternal->Type = Type;
855 NewExternal->Length = (UINT16) strlen (ExternalPath);
856 NewExternal->InternalPath = InternalPath;
858 /* Link the new descriptor into the global list, alphabetically ordered */
860 NextExternal = AcpiGbl_ExternalList;
863 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
867 PrevExternal->Next = NewExternal;
871 AcpiGbl_ExternalList = NewExternal;
874 NewExternal->Next = NextExternal;
875 return_ACPI_STATUS (AE_OK);
878 PrevExternal = NextExternal;
879 NextExternal = NextExternal->Next;
884 PrevExternal->Next = NewExternal;
888 AcpiGbl_ExternalList = NewExternal;
891 return_ACPI_STATUS (AE_OK);
895 /*******************************************************************************
897 * FUNCTION: AcpiDmAddExternalsToNamespace
903 * DESCRIPTION: Add all externals to the namespace. Allows externals to be
906 ******************************************************************************/
909 AcpiDmAddExternalsToNamespace (
913 ACPI_NAMESPACE_NODE *Node;
914 ACPI_OPERAND_OBJECT *ObjDesc;
915 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
920 /* Add the external name (object) into the namespace */
922 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
923 ACPI_IMODE_LOAD_PASS1,
924 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
927 if (ACPI_FAILURE (Status))
929 ACPI_EXCEPTION ((AE_INFO, Status,
930 "while adding external to namespace [%s]",
934 else switch (External->Type)
936 case ACPI_TYPE_METHOD:
938 /* For methods, we need to save the argument count */
940 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
941 ObjDesc->Method.ParamCount = (UINT8) External->Value;
942 Node->Object = ObjDesc;
945 case ACPI_TYPE_REGION:
947 /* Regions require a region sub-object */
949 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
950 ObjDesc->Region.Node = Node;
951 Node->Object = ObjDesc;
959 External = External->Next;
964 /*******************************************************************************
966 * FUNCTION: AcpiDmGetExternalMethodCount
970 * RETURN: The number of control method externals in the external list
972 * DESCRIPTION: Return the number of method externals that have been generated.
973 * If any control method externals have been found, we must
974 * re-parse the entire definition block with the new information
975 * (number of arguments for the methods.) This is limitation of
976 * AML, we don't know the number of arguments from the control
977 * method invocation itself.
979 ******************************************************************************/
982 AcpiDmGetExternalMethodCount (
985 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
991 if (External->Type == ACPI_TYPE_METHOD)
996 External = External->Next;
1003 /*******************************************************************************
1005 * FUNCTION: AcpiDmClearExternalList
1011 * DESCRIPTION: Free the entire External info list
1013 ******************************************************************************/
1016 AcpiDmClearExternalList (
1019 ACPI_EXTERNAL_LIST *NextExternal;
1022 while (AcpiGbl_ExternalList)
1024 NextExternal = AcpiGbl_ExternalList->Next;
1025 ACPI_FREE (AcpiGbl_ExternalList->Path);
1026 ACPI_FREE (AcpiGbl_ExternalList);
1027 AcpiGbl_ExternalList = NextExternal;
1032 /*******************************************************************************
1034 * FUNCTION: AcpiDmEmitExternals
1040 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1041 * the global external info list.
1043 ******************************************************************************/
1046 AcpiDmEmitExternals (
1049 ACPI_EXTERNAL_LIST *NextExternal;
1052 if (!AcpiGbl_ExternalList)
1058 * Determine the number of control methods in the external list, and
1059 * also how many of those externals were resolved via the namespace.
1061 NextExternal = AcpiGbl_ExternalList;
1062 while (NextExternal)
1064 if (NextExternal->Type == ACPI_TYPE_METHOD)
1066 AcpiGbl_NumExternalMethods++;
1067 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1069 AcpiGbl_ResolvedExternalMethods++;
1073 NextExternal = NextExternal->Next;
1076 /* Check if any control methods were unresolved */
1078 AcpiDmUnresolvedWarning (1);
1080 /* Emit any unresolved method externals in a single text block */
1082 NextExternal = AcpiGbl_ExternalList;
1083 while (NextExternal)
1085 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
1086 (!(NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1088 AcpiOsPrintf (" External (%s%s",
1090 AcpiDmGetObjectTypeName (NextExternal->Type));
1092 AcpiOsPrintf (") // Warning: Unresolved method, "
1093 "guessing %u arguments\n",
1094 NextExternal->Value);
1096 NextExternal->Flags |= ACPI_EXT_EXTERNAL_EMITTED;
1099 NextExternal = NextExternal->Next;
1102 AcpiOsPrintf ("\n");
1105 /* Emit externals that were imported from a file */
1107 if (Gbl_ExternalRefFilename)
1110 " /*\n * External declarations that were imported from\n"
1111 " * the reference file [%s]\n */\n",
1112 Gbl_ExternalRefFilename);
1114 NextExternal = AcpiGbl_ExternalList;
1115 while (NextExternal)
1117 if (!(NextExternal->Flags & ACPI_EXT_EXTERNAL_EMITTED) &&
1118 (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_FILE))
1120 AcpiOsPrintf (" External (%s%s",
1122 AcpiDmGetObjectTypeName (NextExternal->Type));
1124 if (NextExternal->Type == ACPI_TYPE_METHOD)
1126 AcpiOsPrintf (") // %u Arguments\n",
1127 NextExternal->Value);
1131 AcpiOsPrintf (")\n");
1133 NextExternal->Flags |= ACPI_EXT_EXTERNAL_EMITTED;
1136 NextExternal = NextExternal->Next;
1139 AcpiOsPrintf ("\n");
1143 * Walk the list of externals found during the AML parsing
1145 while (AcpiGbl_ExternalList)
1147 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1149 AcpiOsPrintf (" External (%s%s",
1150 AcpiGbl_ExternalList->Path,
1151 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1153 /* For methods, add a comment with the number of arguments */
1155 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1157 AcpiOsPrintf (") // %u Arguments\n",
1158 AcpiGbl_ExternalList->Value);
1162 AcpiOsPrintf (")\n");
1166 /* Free this external info block and move on to next external */
1168 NextExternal = AcpiGbl_ExternalList->Next;
1169 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1171 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1174 ACPI_FREE (AcpiGbl_ExternalList->Path);
1175 ACPI_FREE (AcpiGbl_ExternalList);
1176 AcpiGbl_ExternalList = NextExternal;
1179 AcpiOsPrintf ("\n");
1183 /*******************************************************************************
1185 * FUNCTION: AcpiDmUnresolvedWarning
1187 * PARAMETERS: Type - Where to output the warning.
1188 * 0 means write to stderr
1189 * 1 means write to AcpiOsPrintf
1193 * DESCRIPTION: Issue warning message if there are unresolved external control
1194 * methods within the disassembly.
1196 ******************************************************************************/
1199 Summary of the external control method problem:
1201 When the -e option is used with disassembly, the various SSDTs are simply
1202 loaded into a global namespace for the disassembler to use in order to
1203 resolve control method references (invocations).
1205 The disassembler tracks any such references, and will emit an External()
1206 statement for these types of methods, with the proper number of arguments .
1208 Without the SSDTs, the AML does not contain enough information to properly
1209 disassemble the control method invocation -- because the disassembler does
1210 not know how many arguments to parse.
1212 An example: Assume we have two control methods. ABCD has one argument, and
1213 EFGH has zero arguments. Further, we have two additional control methods
1214 that invoke ABCD and EFGH, named T1 and T2:
1224 ABCD (Add (2, 7, Local0))
1232 Here is the AML code that is generated for T1 and T2:
1236 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1239 187: ABCD (Add (2, 7, Local0))
1241 00000353: 41 42 43 44 ............ "ABCD"
1242 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1248 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1253 00000364: 45 46 47 48 ............ "EFGH"
1255 193: Add (2, 7, Local0)
1257 00000368: 72 0A 02 0A 07 60 ...... "r....`"
1260 Note that the AML code for T1 and T2 is essentially identical. When
1261 disassembling this code, the methods ABCD and EFGH must be known to the
1262 disassembler, otherwise it does not know how to handle the method invocations.
1264 In other words, if ABCD and EFGH are actually external control methods
1265 appearing in an SSDT, the disassembler does not know what to do unless
1266 the owning SSDT has been loaded via the -e option.
1270 AcpiDmUnresolvedWarning (
1274 if (!AcpiGbl_NumExternalMethods)
1281 if (!AcpiGbl_ExternalFileList)
1283 /* The -e option was not specified */
1285 AcpiOsPrintf (" /*\n"
1286 " * iASL Warning: There were %u external control methods found during\n"
1287 " * disassembly, but additional ACPI tables to resolve these externals\n"
1288 " * were not specified. This resulting disassembler output file may not\n"
1289 " * compile because the disassembler did not know how many arguments\n"
1290 " * to assign to these methods. To specify the tables needed to resolve\n"
1291 " * external control method references, the -e option can be used to\n"
1292 " * specify the filenames. Note: SSDTs can be dynamically loaded at\n"
1293 " * runtime and may or may not be available via the host OS.\n"
1294 " * Example iASL invocations:\n"
1295 " * iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1296 " * iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1297 " * iasl -e ssdt*.aml -d dsdt.aml\n"
1299 " * In addition, the -fe option can be used to specify a file containing\n"
1300 " * control method external declarations with the associated method\n"
1301 " * argument counts. Each line of the file must be of the form:\n"
1302 " * External (<method pathname>, MethodObj, <argument count>)\n"
1304 " * iasl -fe refs.txt -d dsdt.aml\n"
1306 " * The following methods were unresolved and many not compile properly\n"
1307 " * because the disassembler had to guess at the number of arguments\n"
1308 " * required for each:\n"
1310 AcpiGbl_NumExternalMethods);
1312 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1314 /* The -e option was specified, but there are still some unresolved externals */
1316 AcpiOsPrintf (" /*\n"
1317 " * iASL Warning: There were %u external control methods found during\n"
1318 " * disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1319 " * ACPI tables may be required to properly disassemble the code. This\n"
1320 " * resulting disassembler output file may not compile because the\n"
1321 " * disassembler did not know how many arguments to assign to the\n"
1322 " * unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1323 " * runtime and may or may not be available via the host OS.\n"
1325 " * If necessary, the -fe option can be used to specify a file containing\n"
1326 " * control method external declarations with the associated method\n"
1327 " * argument counts. Each line of the file must be of the form:\n"
1328 " * External (<method pathname>, MethodObj, <argument count>)\n"
1330 " * iasl -fe refs.txt -d dsdt.aml\n"
1332 " * The following methods were unresolved and many not compile properly\n"
1333 " * because the disassembler had to guess at the number of arguments\n"
1334 " * required for each:\n"
1336 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1337 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1338 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));
1343 if (!AcpiGbl_ExternalFileList)
1345 /* The -e option was not specified */
1347 fprintf (stderr, "\n"
1348 "iASL Warning: There were %u external control methods found during\n"
1349 "disassembly, but additional ACPI tables to resolve these externals\n"
1350 "were not specified. The resulting disassembler output file may not\n"
1351 "compile because the disassembler did not know how many arguments\n"
1352 "to assign to these methods. To specify the tables needed to resolve\n"
1353 "external control method references, the -e option can be used to\n"
1354 "specify the filenames. Note: SSDTs can be dynamically loaded at\n"
1355 "runtime and may or may not be available via the host OS.\n"
1356 "Example iASL invocations:\n"
1357 " iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1358 " iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1359 " iasl -e ssdt*.aml -d dsdt.aml\n"
1361 "In addition, the -fe option can be used to specify a file containing\n"
1362 "control method external declarations with the associated method\n"
1363 "argument counts. Each line of the file must be of the form:\n"
1364 " External (<method pathname>, MethodObj, <argument count>)\n"
1366 " iasl -fe refs.txt -d dsdt.aml\n",
1367 AcpiGbl_NumExternalMethods);
1369 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1371 /* The -e option was specified, but there are still some unresolved externals */
1373 fprintf (stderr, "\n"
1374 "iASL Warning: There were %u external control methods found during\n"
1375 "disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1376 "ACPI tables may be required to properly disassemble the code. The\n"
1377 "resulting disassembler output file may not compile because the\n"
1378 "disassembler did not know how many arguments to assign to the\n"
1379 "unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1380 "runtime and may or may not be available via the host OS.\n"
1382 "If necessary, the -fe option can be used to specify a file containing\n"
1383 "control method external declarations with the associated method\n"
1384 "argument counts. Each line of the file must be of the form:\n"
1385 " External (<method pathname>, MethodObj, <argument count>)\n"
1387 " iasl -fe refs.txt -d dsdt.aml\n",
1388 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1389 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1390 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));