1 /******************************************************************************
3 * Module Name: dmextern - Support for External() ASL statements
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2016, 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 */ ", 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 /* Check for duplicates */
813 if (!strcmp (ExternalPath, NextExternal->Path))
816 * If this external came from an External() opcode, we are
817 * finished with this one. (No need to check any further).
819 if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)
821 return_ACPI_STATUS (AE_ALREADY_EXISTS);
824 /* Allow upgrade of type from ANY */
826 else if ((NextExternal->Type == ACPI_TYPE_ANY) &&
827 (Type != ACPI_TYPE_ANY))
829 NextExternal->Type = Type;
832 /* Update the argument count as necessary */
834 if (Value < NextExternal->Value)
836 NextExternal->Value = Value;
841 NextExternal->Flags |= Flags;
842 NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED;
844 return_ACPI_STATUS (AE_ALREADY_EXISTS);
847 NextExternal = NextExternal->Next;
850 /* Allocate and init a new External() descriptor */
852 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
855 return_ACPI_STATUS (AE_NO_MEMORY);
858 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
859 "Adding external reference node (%s) type [%s]\n",
860 ExternalPath, AcpiUtGetTypeName (Type)));
862 NewExternal->Flags = Flags;
863 NewExternal->Value = Value;
864 NewExternal->Path = ExternalPath;
865 NewExternal->Type = Type;
866 NewExternal->Length = (UINT16) strlen (ExternalPath);
867 NewExternal->InternalPath = InternalPath;
869 /* Link the new descriptor into the global list, alphabetically ordered */
871 NextExternal = AcpiGbl_ExternalList;
874 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
878 PrevExternal->Next = NewExternal;
882 AcpiGbl_ExternalList = NewExternal;
885 NewExternal->Next = NextExternal;
886 return_ACPI_STATUS (AE_OK);
889 PrevExternal = NextExternal;
890 NextExternal = NextExternal->Next;
895 PrevExternal->Next = NewExternal;
899 AcpiGbl_ExternalList = NewExternal;
902 return_ACPI_STATUS (AE_OK);
906 /*******************************************************************************
908 * FUNCTION: AcpiDmAddExternalsToNamespace
914 * DESCRIPTION: Add all externals to the namespace. Allows externals to be
917 ******************************************************************************/
920 AcpiDmAddExternalsToNamespace (
924 ACPI_NAMESPACE_NODE *Node;
925 ACPI_OPERAND_OBJECT *ObjDesc;
926 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
931 /* Add the external name (object) into the namespace */
933 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
934 ACPI_IMODE_LOAD_PASS1,
935 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
938 if (ACPI_FAILURE (Status))
940 ACPI_EXCEPTION ((AE_INFO, Status,
941 "while adding external to namespace [%s]",
945 else switch (External->Type)
947 case ACPI_TYPE_METHOD:
949 /* For methods, we need to save the argument count */
951 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
952 ObjDesc->Method.ParamCount = (UINT8) External->Value;
953 Node->Object = ObjDesc;
956 case ACPI_TYPE_REGION:
958 /* Regions require a region sub-object */
960 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
961 ObjDesc->Region.Node = Node;
962 Node->Object = ObjDesc;
970 External = External->Next;
975 /*******************************************************************************
977 * FUNCTION: AcpiDmGetExternalMethodCount
981 * RETURN: The number of control method externals in the external list
983 * DESCRIPTION: Return the number of method externals that have been generated.
984 * If any control method externals have been found, we must
985 * re-parse the entire definition block with the new information
986 * (number of arguments for the methods.) This is limitation of
987 * AML, we don't know the number of arguments from the control
988 * method invocation itself.
990 ******************************************************************************/
993 AcpiDmGetExternalMethodCount (
996 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
1002 if (External->Type == ACPI_TYPE_METHOD)
1007 External = External->Next;
1014 /*******************************************************************************
1016 * FUNCTION: AcpiDmClearExternalList
1022 * DESCRIPTION: Free the entire External info list
1024 ******************************************************************************/
1027 AcpiDmClearExternalList (
1030 ACPI_EXTERNAL_LIST *NextExternal;
1033 while (AcpiGbl_ExternalList)
1035 NextExternal = AcpiGbl_ExternalList->Next;
1036 ACPI_FREE (AcpiGbl_ExternalList->Path);
1037 ACPI_FREE (AcpiGbl_ExternalList);
1038 AcpiGbl_ExternalList = NextExternal;
1043 /*******************************************************************************
1045 * FUNCTION: AcpiDmEmitExternals
1051 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1052 * the global external info list.
1054 ******************************************************************************/
1057 AcpiDmEmitExternals (
1060 ACPI_EXTERNAL_LIST *NextExternal;
1063 if (!AcpiGbl_ExternalList)
1069 * Determine the number of control methods in the external list, and
1070 * also how many of those externals were resolved via the namespace.
1072 NextExternal = AcpiGbl_ExternalList;
1073 while (NextExternal)
1075 if (NextExternal->Type == ACPI_TYPE_METHOD)
1077 AcpiGbl_NumExternalMethods++;
1078 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1080 AcpiGbl_ResolvedExternalMethods++;
1084 NextExternal = NextExternal->Next;
1087 /* Check if any control methods were unresolved */
1089 AcpiDmUnresolvedWarning (1);
1091 if (Gbl_ExternalRefFilename)
1094 " /*\n * External declarations were imported from\n"
1095 " * a reference file -- %s\n */\n\n",
1096 Gbl_ExternalRefFilename);
1100 * Walk and emit the list of externals found during the AML parsing
1102 while (AcpiGbl_ExternalList)
1104 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1106 AcpiOsPrintf (" External (%s%s)",
1107 AcpiGbl_ExternalList->Path,
1108 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1110 /* Check for "unresolved" method reference */
1112 if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) &&
1113 (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1115 AcpiOsPrintf (" // Warning: Unknown method, "
1116 "guessing %u arguments",
1117 AcpiGbl_ExternalList->Value);
1120 /* Check for external from a external references file */
1122 else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE)
1124 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1126 AcpiOsPrintf (" // %u Arguments",
1127 AcpiGbl_ExternalList->Value);
1130 AcpiOsPrintf (" // From external reference file");
1133 /* This is the normal external case */
1137 /* For methods, add a comment with the number of arguments */
1139 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1141 AcpiOsPrintf (" // %u Arguments",
1142 AcpiGbl_ExternalList->Value);
1146 AcpiOsPrintf ("\n");
1149 /* Free this external info block and move on to next external */
1151 NextExternal = AcpiGbl_ExternalList->Next;
1152 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1154 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1157 ACPI_FREE (AcpiGbl_ExternalList->Path);
1158 ACPI_FREE (AcpiGbl_ExternalList);
1159 AcpiGbl_ExternalList = NextExternal;
1162 AcpiOsPrintf ("\n");
1166 /*******************************************************************************
1168 * FUNCTION: AcpiDmUnresolvedWarning
1170 * PARAMETERS: Type - Where to output the warning.
1171 * 0 means write to stderr
1172 * 1 means write to AcpiOsPrintf
1176 * DESCRIPTION: Issue warning message if there are unresolved external control
1177 * methods within the disassembly.
1179 ******************************************************************************/
1182 Summary of the external control method problem:
1184 When the -e option is used with disassembly, the various SSDTs are simply
1185 loaded into a global namespace for the disassembler to use in order to
1186 resolve control method references (invocations).
1188 The disassembler tracks any such references, and will emit an External()
1189 statement for these types of methods, with the proper number of arguments .
1191 Without the SSDTs, the AML does not contain enough information to properly
1192 disassemble the control method invocation -- because the disassembler does
1193 not know how many arguments to parse.
1195 An example: Assume we have two control methods. ABCD has one argument, and
1196 EFGH has zero arguments. Further, we have two additional control methods
1197 that invoke ABCD and EFGH, named T1 and T2:
1207 ABCD (Add (2, 7, Local0))
1215 Here is the AML code that is generated for T1 and T2:
1219 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1222 187: ABCD (Add (2, 7, Local0))
1224 00000353: 41 42 43 44 ............ "ABCD"
1225 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1231 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1236 00000364: 45 46 47 48 ............ "EFGH"
1238 193: Add (2, 7, Local0)
1240 00000368: 72 0A 02 0A 07 60 ...... "r....`"
1243 Note that the AML code for T1 and T2 is essentially identical. When
1244 disassembling this code, the methods ABCD and EFGH must be known to the
1245 disassembler, otherwise it does not know how to handle the method invocations.
1247 In other words, if ABCD and EFGH are actually external control methods
1248 appearing in an SSDT, the disassembler does not know what to do unless
1249 the owning SSDT has been loaded via the -e option.
1252 static char ExternalWarningPart1[600];
1253 static char ExternalWarningPart2[400];
1254 static char ExternalWarningPart3[400];
1255 static char ExternalWarningPart4[200];
1258 AcpiDmUnresolvedWarning (
1266 if (!AcpiGbl_NumExternalMethods)
1271 if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
1276 Format = Type ? Pad : NoPad;
1278 sprintf (ExternalWarningPart1,
1279 "%s iASL Warning: There %s %u external control method%s found during\n"
1280 "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1281 "%s ACPI tables may be required to properly disassemble the code. This\n"
1282 "%s resulting disassembler output file may not compile because the\n"
1283 "%s disassembler did not know how many arguments to assign to the\n"
1284 "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1285 "%s runtime and may or may not be available via the host OS.\n",
1286 Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
1287 AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
1288 Format, AcpiGbl_ResolvedExternalMethods,
1289 (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
1290 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
1291 Format, Format, Format, Format, Format);
1293 sprintf (ExternalWarningPart2,
1294 "%s To specify the tables needed to resolve external control method\n"
1295 "%s references, the -e option can be used to specify the filenames.\n"
1296 "%s Example iASL invocations:\n"
1297 "%s iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1298 "%s iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1299 "%s iasl -e ssdt*.aml -d dsdt.aml\n",
1300 Format, Format, Format, Format, Format, Format);
1302 sprintf (ExternalWarningPart3,
1303 "%s In addition, the -fe option can be used to specify a file containing\n"
1304 "%s control method external declarations with the associated method\n"
1305 "%s argument counts. Each line of the file must be of the form:\n"
1306 "%s External (<method pathname>, MethodObj, <argument count>)\n"
1308 "%s iasl -fe refs.txt -d dsdt.aml\n",
1309 Format, Format, Format, Format, Format, Format);
1311 sprintf (ExternalWarningPart4,
1312 "%s The following methods were unresolved and many not compile properly\n"
1313 "%s because the disassembler had to guess at the number of arguments\n"
1314 "%s required for each:\n",
1315 Format, Format, Format);
1319 if (!AcpiGbl_ExternalFileList)
1321 /* The -e option was not specified */
1323 AcpiOsPrintf (" /*\n%s *\n%s *\n%s *\n%s */\n",
1324 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
1325 ExternalWarningPart4);
1329 /* The -e option was specified, but there are still some unresolved externals */
1331 AcpiOsPrintf (" /*\n%s *\n%s *\n%s */\n",
1332 ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
1337 if (!AcpiGbl_ExternalFileList)
1339 /* The -e option was not specified */
1341 fprintf (stderr, "\n%s\n%s\n%s\n",
1342 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
1346 /* The -e option was specified, but there are still some unresolved externals */
1348 fprintf (stderr, "\n%s\n%s\n",
1349 ExternalWarningPart1, ExternalWarningPart3);