1 /******************************************************************************
3 * Module Name: dmextern - Support for External() ASL statements
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2014, 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 */ "", /* 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 = (ACPI_STRLEN (ParentPath) + ACPI_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 ACPI_STRCPY (Fullpath, &ParentPath[Index]);
260 * (don't need dot if parent fullpath is a single backslash)
264 ACPI_STRCAT (Fullpath, ".");
267 /* Copy child path (carat parent prefix(es) were skipped above) */
269 ACPI_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);
403 /* Each line defines a method */
405 while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
407 Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */
408 if (!Token) continue;
409 if (strcmp (Token, "External")) continue;
411 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */
412 if (!MethodName) continue;
414 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */
415 if (!Token) continue;
416 if (strcmp (Token, "MethodObj")) continue;
418 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */
419 if (!Token) continue;
421 /* Convert arg count string to an integer */
424 ArgCount = strtoul (Token, NULL, 0);
427 fprintf (stderr, "Invalid argument count (%s)\n", Token);
432 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
436 /* Add this external to the global list */
438 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
439 Gbl_ExternalRefFilename, ArgCount, MethodName);
441 AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
442 ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
448 fprintf (stderr, "Did not find any external methods in reference file \"%s\"\n",
449 Gbl_ExternalRefFilename);
453 /* Add the external(s) to the namespace */
455 AcpiDmAddExternalsToNamespace ();
457 AcpiOsPrintf ("%s: Imported %u external method definitions\n",
458 Gbl_ExternalRefFilename, ImportCount);
461 fclose (ExternalRefFile);
465 /*******************************************************************************
467 * FUNCTION: AcpiDmAddOpToExternalList
469 * PARAMETERS: Op - Current parser Op
470 * Path - Internal (AML) path to the object
471 * Type - ACPI object type to be added
472 * Value - Arg count if adding a Method object
473 * Flags - To be passed to the external object
477 * DESCRIPTION: Insert a new name into the global list of Externals which
478 * will in turn be later emitted as an External() declaration
479 * in the disassembled output.
481 * This function handles the most common case where the referenced
482 * name is simply not found in the constructed namespace.
484 ******************************************************************************/
487 AcpiDmAddOpToExternalList (
488 ACPI_PARSE_OBJECT *Op,
495 char *InternalPath = Path;
500 ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
508 /* Remove a root backslash if present */
510 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
515 /* Externalize the pathname */
517 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
518 NULL, &ExternalPath);
519 if (ACPI_FAILURE (Status))
525 * Get the full pathname from the root if "Path" has one or more
526 * parent prefixes (^). Note: path will not contain a leading '\'.
528 if (*Path == (UINT8) AML_PARENT_PREFIX)
530 Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
532 /* Set new external path */
534 ACPI_FREE (ExternalPath);
541 /* Create the new internal pathname */
543 Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
544 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
545 if (ACPI_FAILURE (Status))
547 ACPI_FREE (ExternalPath);
552 /* Create the new External() declaration node */
554 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
556 if (ACPI_FAILURE (Status))
558 ACPI_FREE (ExternalPath);
559 if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
561 ACPI_FREE (InternalPath);
569 /*******************************************************************************
571 * FUNCTION: AcpiDmAddNodeToExternalList
573 * PARAMETERS: Node - Namespace node for object to be added
574 * Type - ACPI object type to be added
575 * Value - Arg count if adding a Method object
576 * Flags - To be passed to the external object
580 * DESCRIPTION: Insert a new name into the global list of Externals which
581 * will in turn be later emitted as an External() declaration
582 * in the disassembled output.
584 * This function handles the case where the referenced name has
585 * been found in the namespace, but the name originated in a
586 * table other than the one that is being disassembled (such
587 * as a table that is added via the iASL -e option).
589 ******************************************************************************/
592 AcpiDmAddNodeToExternalList (
593 ACPI_NAMESPACE_NODE *Node,
604 ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
612 /* Get the full external and internal pathnames to the node */
614 ExternalPath = AcpiNsGetExternalPathname (Node);
620 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
621 if (ACPI_FAILURE (Status))
623 ACPI_FREE (ExternalPath);
627 /* Remove the root backslash */
629 if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1]))
631 Temp = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (ExternalPath) + 1);
637 ACPI_STRCPY (Temp, &ExternalPath[1]);
638 ACPI_FREE (ExternalPath);
642 /* Create the new External() declaration node */
644 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
645 Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
646 if (ACPI_FAILURE (Status))
648 ACPI_FREE (ExternalPath);
649 ACPI_FREE (InternalPath);
656 /*******************************************************************************
658 * FUNCTION: AcpiDmAddPathToExternalList
660 * PARAMETERS: Path - External name of the object to be added
661 * Type - ACPI object type to be added
662 * Value - Arg count if adding a Method object
663 * Flags - To be passed to the external object
667 * DESCRIPTION: Insert a new name into the global list of Externals which
668 * will in turn be later emitted as an External() declaration
669 * in the disassembled output.
671 * This function currently is used to add externals via a
672 * reference file (via the -fe iASL option).
674 ******************************************************************************/
677 AcpiDmAddPathToExternalList (
688 ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
696 /* Remove a root backslash if present */
698 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
703 /* Create the internal and external pathnames */
705 Status = AcpiNsInternalizeName (Path, &InternalPath);
706 if (ACPI_FAILURE (Status))
711 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
712 NULL, &ExternalPath);
713 if (ACPI_FAILURE (Status))
715 ACPI_FREE (InternalPath);
719 /* Create the new External() declaration node */
721 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
722 Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
723 if (ACPI_FAILURE (Status))
725 ACPI_FREE (ExternalPath);
726 ACPI_FREE (InternalPath);
733 /*******************************************************************************
735 * FUNCTION: AcpiDmCreateNewExternal
737 * PARAMETERS: ExternalPath - External path to the object
738 * InternalPath - Internal (AML) path to the object
739 * Type - ACPI object type to be added
740 * Value - Arg count if adding a Method object
741 * Flags - To be passed to the external object
745 * DESCRIPTION: Common low-level function to insert a new name into the global
746 * list of Externals which will in turn be later emitted as
747 * External() declarations in the disassembled output.
749 * Note: The external name should not include a root prefix
750 * (backslash). We do not want External() statements to contain
751 * a leading '\', as this prevents duplicate external statements
757 * This would cause a compile time error when the disassembled
758 * output file is recompiled.
760 * There are two cases that are handled here. For both, we emit
761 * an External() statement:
762 * 1) The name was simply not found in the namespace.
763 * 2) The name was found, but it originated in a table other than
764 * the table that is being disassembled.
766 ******************************************************************************/
769 AcpiDmCreateNewExternal (
776 ACPI_EXTERNAL_LIST *NewExternal;
777 ACPI_EXTERNAL_LIST *NextExternal;
778 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
781 ACPI_FUNCTION_TRACE (DmCreateNewExternal);
784 /* Check all existing externals to ensure no duplicates */
786 NextExternal = AcpiGbl_ExternalList;
789 if (!ACPI_STRCMP (ExternalPath, NextExternal->Path))
791 /* Duplicate method, check that the Value (ArgCount) is the same */
793 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
794 (NextExternal->Value != Value))
796 ACPI_ERROR ((AE_INFO,
797 "External method arg count mismatch %s: Current %u, attempted %u",
798 NextExternal->Path, NextExternal->Value, Value));
801 /* Allow upgrade of type from ANY */
803 else if (NextExternal->Type == ACPI_TYPE_ANY)
805 NextExternal->Type = Type;
806 NextExternal->Value = Value;
809 return_ACPI_STATUS (AE_ALREADY_EXISTS);
812 NextExternal = NextExternal->Next;
815 /* Allocate and init a new External() descriptor */
817 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
820 return_ACPI_STATUS (AE_NO_MEMORY);
823 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
824 "Adding external reference node (%s) type [%s]\n",
825 ExternalPath, AcpiUtGetTypeName (Type)));
827 NewExternal->Flags = Flags;
828 NewExternal->Value = Value;
829 NewExternal->Path = ExternalPath;
830 NewExternal->Type = Type;
831 NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath);
832 NewExternal->InternalPath = InternalPath;
834 /* Link the new descriptor into the global list, alphabetically ordered */
836 NextExternal = AcpiGbl_ExternalList;
839 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
843 PrevExternal->Next = NewExternal;
847 AcpiGbl_ExternalList = NewExternal;
850 NewExternal->Next = NextExternal;
851 return_ACPI_STATUS (AE_OK);
854 PrevExternal = NextExternal;
855 NextExternal = NextExternal->Next;
860 PrevExternal->Next = NewExternal;
864 AcpiGbl_ExternalList = NewExternal;
867 return_ACPI_STATUS (AE_OK);
871 /*******************************************************************************
873 * FUNCTION: AcpiDmAddExternalsToNamespace
879 * DESCRIPTION: Add all externals to the namespace. Allows externals to be
882 ******************************************************************************/
885 AcpiDmAddExternalsToNamespace (
889 ACPI_NAMESPACE_NODE *Node;
890 ACPI_OPERAND_OBJECT *ObjDesc;
891 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
896 /* Add the external name (object) into the namespace */
898 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
899 ACPI_IMODE_LOAD_PASS1,
900 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
903 if (ACPI_FAILURE (Status))
905 ACPI_EXCEPTION ((AE_INFO, Status,
906 "while adding external to namespace [%s]",
910 else switch (External->Type)
912 case ACPI_TYPE_METHOD:
914 /* For methods, we need to save the argument count */
916 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
917 ObjDesc->Method.ParamCount = (UINT8) External->Value;
918 Node->Object = ObjDesc;
921 case ACPI_TYPE_REGION:
923 /* Regions require a region sub-object */
925 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
926 ObjDesc->Region.Node = Node;
927 Node->Object = ObjDesc;
935 External = External->Next;
940 /*******************************************************************************
942 * FUNCTION: AcpiDmGetExternalMethodCount
946 * RETURN: The number of control method externals in the external list
948 * DESCRIPTION: Return the number of method externals that have been generated.
949 * If any control method externals have been found, we must
950 * re-parse the entire definition block with the new information
951 * (number of arguments for the methods.) This is limitation of
952 * AML, we don't know the number of arguments from the control
953 * method invocation itself.
955 ******************************************************************************/
958 AcpiDmGetExternalMethodCount (
961 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
967 if (External->Type == ACPI_TYPE_METHOD)
972 External = External->Next;
979 /*******************************************************************************
981 * FUNCTION: AcpiDmClearExternalList
987 * DESCRIPTION: Free the entire External info list
989 ******************************************************************************/
992 AcpiDmClearExternalList (
995 ACPI_EXTERNAL_LIST *NextExternal;
998 while (AcpiGbl_ExternalList)
1000 NextExternal = AcpiGbl_ExternalList->Next;
1001 ACPI_FREE (AcpiGbl_ExternalList->Path);
1002 ACPI_FREE (AcpiGbl_ExternalList);
1003 AcpiGbl_ExternalList = NextExternal;
1008 /*******************************************************************************
1010 * FUNCTION: AcpiDmEmitExternals
1016 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1017 * the global external info list.
1019 ******************************************************************************/
1022 AcpiDmEmitExternals (
1025 ACPI_EXTERNAL_LIST *NextExternal;
1028 if (!AcpiGbl_ExternalList)
1034 * Determine the number of control methods in the external list, and
1035 * also how many of those externals were resolved via the namespace.
1037 NextExternal = AcpiGbl_ExternalList;
1038 while (NextExternal)
1040 if (NextExternal->Type == ACPI_TYPE_METHOD)
1042 AcpiGbl_NumExternalMethods++;
1043 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1045 AcpiGbl_ResolvedExternalMethods++;
1049 NextExternal = NextExternal->Next;
1052 /* Check if any control methods were unresolved */
1054 AcpiDmUnresolvedWarning (1);
1056 /* Emit any unresolved method externals in a single text block */
1058 NextExternal = AcpiGbl_ExternalList;
1059 while (NextExternal)
1061 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
1062 (!(NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1064 AcpiOsPrintf (" External (%s%s",
1066 AcpiDmGetObjectTypeName (NextExternal->Type));
1069 ") // Warning: Unresolved Method, "
1070 "guessing %u arguments (may be incorrect, see warning above)\n",
1071 NextExternal->Value);
1073 NextExternal->Flags |= ACPI_EXT_EXTERNAL_EMITTED;
1076 NextExternal = NextExternal->Next;
1079 AcpiOsPrintf ("\n");
1082 /* Emit externals that were imported from a file */
1084 if (Gbl_ExternalRefFilename)
1087 " /*\n * External declarations that were imported from\n"
1088 " * the reference file [%s]\n */\n",
1089 Gbl_ExternalRefFilename);
1091 NextExternal = AcpiGbl_ExternalList;
1092 while (NextExternal)
1094 if (!(NextExternal->Flags & ACPI_EXT_EXTERNAL_EMITTED) &&
1095 (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_FILE))
1097 AcpiOsPrintf (" External (%s%s",
1099 AcpiDmGetObjectTypeName (NextExternal->Type));
1101 if (NextExternal->Type == ACPI_TYPE_METHOD)
1103 AcpiOsPrintf (") // %u Arguments\n",
1104 NextExternal->Value);
1108 AcpiOsPrintf (")\n");
1110 NextExternal->Flags |= ACPI_EXT_EXTERNAL_EMITTED;
1113 NextExternal = NextExternal->Next;
1116 AcpiOsPrintf ("\n");
1120 * Walk the list of externals found during the AML parsing
1122 while (AcpiGbl_ExternalList)
1124 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1126 AcpiOsPrintf (" External (%s%s",
1127 AcpiGbl_ExternalList->Path,
1128 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1130 /* For methods, add a comment with the number of arguments */
1132 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1134 AcpiOsPrintf (") // %u Arguments\n",
1135 AcpiGbl_ExternalList->Value);
1139 AcpiOsPrintf (")\n");
1143 /* Free this external info block and move on to next external */
1145 NextExternal = AcpiGbl_ExternalList->Next;
1146 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1148 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1151 ACPI_FREE (AcpiGbl_ExternalList->Path);
1152 ACPI_FREE (AcpiGbl_ExternalList);
1153 AcpiGbl_ExternalList = NextExternal;
1156 AcpiOsPrintf ("\n");
1160 /*******************************************************************************
1162 * FUNCTION: AcpiDmUnresolvedWarning
1164 * PARAMETERS: Type - Where to output the warning.
1165 * 0 means write to stderr
1166 * 1 means write to AcpiOsPrintf
1170 * DESCRIPTION: Issue warning message if there are unresolved external control
1171 * methods within the disassembly.
1173 ******************************************************************************/
1176 Summary of the external control method problem:
1178 When the -e option is used with disassembly, the various SSDTs are simply
1179 loaded into a global namespace for the disassembler to use in order to
1180 resolve control method references (invocations).
1182 The disassembler tracks any such references, and will emit an External()
1183 statement for these types of methods, with the proper number of arguments .
1185 Without the SSDTs, the AML does not contain enough information to properly
1186 disassemble the control method invocation -- because the disassembler does
1187 not know how many arguments to parse.
1189 An example: Assume we have two control methods. ABCD has one argument, and
1190 EFGH has zero arguments. Further, we have two additional control methods
1191 that invoke ABCD and EFGH, named T1 and T2:
1201 ABCD (Add (2, 7, Local0))
1209 Here is the AML code that is generated for T1 and T2:
1213 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1216 187: ABCD (Add (2, 7, Local0))
1218 00000353: 41 42 43 44 ............ "ABCD"
1219 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1225 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1230 00000364: 45 46 47 48 ............ "EFGH"
1232 193: Add (2, 7, Local0)
1234 00000368: 72 0A 02 0A 07 60 ...... "r....`"
1237 Note that the AML code for T1 and T2 is essentially identical. When
1238 disassembling this code, the methods ABCD and EFGH must be known to the
1239 disassembler, otherwise it does not know how to handle the method invocations.
1241 In other words, if ABCD and EFGH are actually external control methods
1242 appearing in an SSDT, the disassembler does not know what to do unless
1243 the owning SSDT has been loaded via the -e option.
1247 AcpiDmUnresolvedWarning (
1251 if (!AcpiGbl_NumExternalMethods)
1258 if (!AcpiGbl_ExternalFileList)
1260 /* The -e option was not specified */
1262 AcpiOsPrintf (" /*\n"
1263 " * iASL Warning: There were %u external control methods found during\n"
1264 " * disassembly, but additional ACPI tables to resolve these externals\n"
1265 " * were not specified. This resulting disassembler output file may not\n"
1266 " * compile because the disassembler did not know how many arguments\n"
1267 " * to assign to these methods. To specify the tables needed to resolve\n"
1268 " * external control method references, the -e option can be used to\n"
1269 " * specify the filenames. Example iASL invocations:\n"
1270 " * iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1271 " * iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1272 " * iasl -e ssdt*.aml -d dsdt.aml\n"
1274 " * In addition, the -fe option can be used to specify a file containing\n"
1275 " * control method external declarations with the associated method\n"
1276 " * argument counts. Each line of the file must be of the form:\n"
1277 " * External (<method pathname>, MethodObj, <argument count>)\n"
1279 AcpiGbl_NumExternalMethods);
1281 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1283 /* The -e option was specified, but there are still some unresolved externals */
1285 AcpiOsPrintf (" /*\n"
1286 " * iASL Warning: There were %u external control methods found during\n"
1287 " * disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1288 " * ACPI tables may be required to properly disassemble the code. This\n"
1289 " * resulting disassembler output file may not compile because the\n"
1290 " * disassembler did not know how many arguments to assign to the\n"
1291 " * unresolved methods.\n"
1293 " * If necessary, the -fe option can be used to specify a file containing\n"
1294 " * control method external declarations with the associated method\n"
1295 " * argument counts. Each line of the file must be of the form:\n"
1296 " * External (<method pathname>, MethodObj, <argument count>)\n"
1298 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1299 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1300 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));
1305 if (!AcpiGbl_ExternalFileList)
1307 /* The -e option was not specified */
1309 fprintf (stderr, "\n"
1310 "iASL Warning: There were %u external control methods found during\n"
1311 "disassembly, but additional ACPI tables to resolve these externals\n"
1312 "were not specified. The resulting disassembler output file may not\n"
1313 "compile because the disassembler did not know how many arguments\n"
1314 "to assign to these methods. To specify the tables needed to resolve\n"
1315 "external control method references, the -e option can be used to\n"
1316 "specify the filenames. Example iASL invocations:\n"
1317 " iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1318 " iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1319 " iasl -e ssdt*.aml -d dsdt.aml\n"
1321 "In addition, the -fe option can be used to specify a file containing\n"
1322 "control method external declarations with the associated method\n"
1323 "argument counts. Each line of the file must be of the form:\n"
1324 " External (<method pathname>, MethodObj, <argument count>)\n",
1325 AcpiGbl_NumExternalMethods);
1327 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1329 /* The -e option was specified, but there are still some unresolved externals */
1331 fprintf (stderr, "\n"
1332 "iASL Warning: There were %u external control methods found during\n"
1333 "disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1334 "ACPI tables may be required to properly disassemble the code. The\n"
1335 "resulting disassembler output file may not compile because the\n"
1336 "disassembler did not know how many arguments to assign to the\n"
1337 "unresolved methods.\n"
1339 "If necessary, the -fe option can be used to specify a file containing\n"
1340 "control method external declarations with the associated method\n"
1341 "argument counts. Each line of the file must be of the form:\n"
1342 " External (<method pathname>, MethodObj, <argument count>)\n",
1343 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1344 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1345 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));