Indentation fix, cleanup.
[AROS.git] / arch / all-pc / acpica / source / common / dmextern.c
blob002d08860af6ddb24152359207b643f35ac7594e
1 /******************************************************************************
3 * Module Name: dmextern - Support for External() ASL statements
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
30 * NO WARRANTY
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 "acpi.h"
45 #include "accommon.h"
46 #include "amlcode.h"
47 #include "acnamesp.h"
48 #include "acdisasm.h"
49 #include "aslcompiler.h"
50 #include <stdio.h>
51 #include <errno.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 */
71 /* 01 */ ", IntObj",
72 /* 02 */ ", StrObj",
73 /* 03 */ ", BuffObj",
74 /* 04 */ ", PkgObj",
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 */
97 static const char *
98 AcpiDmGetObjectTypeName (
99 ACPI_OBJECT_TYPE Type);
101 static char *
102 AcpiDmNormalizeParentPrefix (
103 ACPI_PARSE_OBJECT *Op,
104 char *Path);
106 static void
107 AcpiDmAddToExternalListFromFile (
108 char *Path,
109 UINT8 Type,
110 UINT32 Value);
113 /*******************************************************************************
115 * FUNCTION: AcpiDmGetObjectTypeName
117 * PARAMETERS: Type - An ACPI_OBJECT_TYPE
119 * RETURN: Pointer to a string
121 * DESCRIPTION: Map an object type to the ASL object type string.
123 ******************************************************************************/
125 static const char *
126 AcpiDmGetObjectTypeName (
127 ACPI_OBJECT_TYPE Type)
130 if (Type == ACPI_TYPE_LOCAL_SCOPE)
132 Type = ACPI_TYPE_DEVICE;
135 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
137 return ("");
140 return (AcpiGbl_DmTypeNames[Type]);
144 /*******************************************************************************
146 * FUNCTION: AcpiDmNormalizeParentPrefix
148 * PARAMETERS: Op - Parse op
149 * Path - Path with parent prefix
151 * RETURN: The full pathname to the object (from the namespace root)
153 * DESCRIPTION: Returns the full pathname of a path with parent prefix
154 * The caller must free the fullpath returned.
156 ******************************************************************************/
158 static char *
159 AcpiDmNormalizeParentPrefix (
160 ACPI_PARSE_OBJECT *Op,
161 char *Path)
163 ACPI_NAMESPACE_NODE *Node;
164 char *Fullpath;
165 char *ParentPath;
166 ACPI_SIZE Length;
167 UINT32 Index = 0;
170 if (!Op)
172 return (NULL);
175 /* Search upwards in the parse tree until we reach the next namespace node */
177 Op = Op->Common.Parent;
178 while (Op)
180 if (Op->Common.Node)
182 break;
185 Op = Op->Common.Parent;
188 if (!Op)
190 return (NULL);
194 * Find the actual parent node for the reference:
195 * Remove all carat prefixes from the input path.
196 * There may be multiple parent prefixes (For example, ^^^M000)
198 Node = Op->Common.Node;
199 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
201 Node = Node->Parent;
202 Path++;
205 if (!Node)
207 return (NULL);
210 /* Get the full pathname for the parent node */
212 ParentPath = AcpiNsGetExternalPathname (Node);
213 if (!ParentPath)
215 return (NULL);
218 Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1);
219 if (ParentPath[1])
222 * If ParentPath is not just a simple '\', increment the length
223 * for the required dot separator (ParentPath.Path)
225 Length++;
227 /* For External() statements, we do not want a leading '\' */
229 if (*ParentPath == AML_ROOT_PREFIX)
231 Index = 1;
235 Fullpath = ACPI_ALLOCATE_ZEROED (Length);
236 if (!Fullpath)
238 goto Cleanup;
242 * Concatenate parent fullpath and path. For example,
243 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
245 * Copy the parent path
247 ACPI_STRCPY (Fullpath, &ParentPath[Index]);
250 * Add dot separator
251 * (don't need dot if parent fullpath is a single backslash)
253 if (ParentPath[1])
255 ACPI_STRCAT (Fullpath, ".");
258 /* Copy child path (carat parent prefix(es) were skipped above) */
260 ACPI_STRCAT (Fullpath, Path);
262 Cleanup:
263 ACPI_FREE (ParentPath);
264 return (Fullpath);
268 /*******************************************************************************
270 * FUNCTION: AcpiDmAddToExternalFileList
272 * PARAMETERS: PathList - Single path or list separated by comma
274 * RETURN: None
276 * DESCRIPTION: Add external files to global list
278 ******************************************************************************/
280 ACPI_STATUS
281 AcpiDmAddToExternalFileList (
282 char *Pathname)
284 ACPI_EXTERNAL_FILE *ExternalFile;
285 char *LocalPathname;
288 if (!Pathname)
290 return (AE_OK);
293 LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
294 if (!LocalPathname)
296 return (AE_NO_MEMORY);
299 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
300 if (!ExternalFile)
302 ACPI_FREE (LocalPathname);
303 return (AE_NO_MEMORY);
306 /* Take a copy of the file pathname */
308 strcpy (LocalPathname, Pathname);
309 ExternalFile->Path = LocalPathname;
311 if (AcpiGbl_ExternalFileList)
313 ExternalFile->Next = AcpiGbl_ExternalFileList;
316 AcpiGbl_ExternalFileList = ExternalFile;
317 return (AE_OK);
321 /*******************************************************************************
323 * FUNCTION: AcpiDmClearExternalFileList
325 * PARAMETERS: None
327 * RETURN: None
329 * DESCRIPTION: Clear the external file list
331 ******************************************************************************/
333 void
334 AcpiDmClearExternalFileList (
335 void)
337 ACPI_EXTERNAL_FILE *NextExternal;
340 while (AcpiGbl_ExternalFileList)
342 NextExternal = AcpiGbl_ExternalFileList->Next;
343 ACPI_FREE (AcpiGbl_ExternalFileList->Path);
344 ACPI_FREE (AcpiGbl_ExternalFileList);
345 AcpiGbl_ExternalFileList = NextExternal;
350 /*******************************************************************************
352 * FUNCTION: AcpiDmAddToExternalList
354 * PARAMETERS: Op - Current parser Op
355 * Path - Internal (AML) path to the object
356 * Type - ACPI object type to be added
357 * Value - Arg count if adding a Method object
359 * RETURN: None
361 * DESCRIPTION: Insert a new name into the global list of Externals which
362 * will in turn be later emitted as an External() declaration
363 * in the disassembled output.
365 ******************************************************************************/
367 void
368 AcpiDmAddToExternalList (
369 ACPI_PARSE_OBJECT *Op,
370 char *Path,
371 UINT8 Type,
372 UINT32 Value)
374 char *ExternalPath;
375 char *Fullpath = NULL;
376 ACPI_EXTERNAL_LIST *NewExternal;
377 ACPI_EXTERNAL_LIST *NextExternal;
378 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
379 ACPI_STATUS Status;
380 BOOLEAN Resolved = FALSE;
383 if (!Path)
385 return;
388 if (Type == ACPI_TYPE_METHOD)
390 if (Value & 0x80)
392 Resolved = TRUE;
394 Value &= 0x07;
398 * We don't want External() statements to contain a leading '\'.
399 * This prevents duplicate external statements of the form:
401 * External (\ABCD)
402 * External (ABCD)
404 * This would cause a compile time error when the disassembled
405 * output file is recompiled.
407 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
409 Path++;
412 /* Externalize the ACPI pathname */
414 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
415 NULL, &ExternalPath);
416 if (ACPI_FAILURE (Status))
418 return;
422 * Get the full pathname from the root if "Path" has one or more
423 * parent prefixes (^). Note: path will not contain a leading '\'.
425 if (*Path == (UINT8) AML_PARENT_PREFIX)
427 Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
428 if (Fullpath)
430 /* Set new external path */
432 ACPI_FREE (ExternalPath);
433 ExternalPath = Fullpath;
437 /* Check all existing externals to ensure no duplicates */
439 NextExternal = AcpiGbl_ExternalList;
440 while (NextExternal)
442 if (!ACPI_STRCMP (ExternalPath, NextExternal->Path))
444 /* Duplicate method, check that the Value (ArgCount) is the same */
446 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
447 (NextExternal->Value != Value))
449 ACPI_ERROR ((AE_INFO,
450 "External method arg count mismatch %s: Current %u, attempted %u",
451 NextExternal->Path, NextExternal->Value, Value));
454 /* Allow upgrade of type from ANY */
456 else if (NextExternal->Type == ACPI_TYPE_ANY)
458 NextExternal->Type = Type;
459 NextExternal->Value = Value;
462 ACPI_FREE (ExternalPath);
463 return;
466 NextExternal = NextExternal->Next;
469 /* Allocate and init a new External() descriptor */
471 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
472 if (!NewExternal)
474 ACPI_FREE (ExternalPath);
475 return;
478 NewExternal->Path = ExternalPath;
479 NewExternal->Type = Type;
480 NewExternal->Value = Value;
481 NewExternal->Resolved = Resolved;
482 NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath);
484 /* Was the external path with parent prefix normalized to a fullpath? */
486 if (Fullpath == ExternalPath)
488 /* Get new internal path */
490 Status = AcpiNsInternalizeName (ExternalPath, &Path);
491 if (ACPI_FAILURE (Status))
493 ACPI_FREE (ExternalPath);
494 ACPI_FREE (NewExternal);
495 return;
498 /* Set flag to indicate External->InternalPath need to be freed */
500 NewExternal->Flags |= ACPI_IPATH_ALLOCATED;
503 NewExternal->InternalPath = Path;
505 /* Link the new descriptor into the global list, alphabetically ordered */
507 NextExternal = AcpiGbl_ExternalList;
508 while (NextExternal)
510 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
512 if (PrevExternal)
514 PrevExternal->Next = NewExternal;
516 else
518 AcpiGbl_ExternalList = NewExternal;
521 NewExternal->Next = NextExternal;
522 return;
525 PrevExternal = NextExternal;
526 NextExternal = NextExternal->Next;
529 if (PrevExternal)
531 PrevExternal->Next = NewExternal;
533 else
535 AcpiGbl_ExternalList = NewExternal;
540 /*******************************************************************************
542 * FUNCTION: AcpiDmGetExternalsFromFile
544 * PARAMETERS: None
546 * RETURN: None
548 * DESCRIPTION: Process the optional external reference file.
550 * Each line in the file should be of the form:
551 * External (<Method namepath>, MethodObj, <ArgCount>)
553 * Example:
554 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
556 ******************************************************************************/
558 void
559 AcpiDmGetExternalsFromFile (
560 void)
562 FILE *ExternalRefFile;
563 char *Token;
564 char *MethodName;
565 UINT32 ArgCount;
566 UINT32 ImportCount = 0;
569 if (!Gbl_ExternalRefFilename)
571 return;
574 /* Open the file */
576 ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
577 if (!ExternalRefFile)
579 fprintf (stderr, "Could not open external reference file \"%s\"\n",
580 Gbl_ExternalRefFilename);
581 return;
584 /* Each line defines a method */
586 while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
588 Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */
589 if (!Token) continue;
590 if (strcmp (Token, "External")) continue;
592 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */
593 if (!MethodName) continue;
595 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */
596 if (!Token) continue;
597 if (strcmp (Token, "MethodObj")) continue;
599 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */
600 if (!Token) continue;
602 /* Convert arg count string to an integer */
604 errno = 0;
605 ArgCount = strtoul (Token, NULL, 0);
606 if (errno)
608 fprintf (stderr, "Invalid argument count (%s)\n", Token);
609 continue;
611 if (ArgCount > 7)
613 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
614 continue;
617 /* Add this external to the global list */
619 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
620 Gbl_ExternalRefFilename, ArgCount, MethodName);
622 AcpiDmAddToExternalListFromFile (MethodName, ACPI_TYPE_METHOD, ArgCount | 0x80);
623 ImportCount++;
626 if (!ImportCount)
628 fprintf (stderr, "Did not find any external methods in reference file \"%s\"\n",
629 Gbl_ExternalRefFilename);
631 else
633 /* Add the external(s) to the namespace */
635 AcpiDmAddExternalsToNamespace ();
637 AcpiOsPrintf ("%s: Imported %u external method definitions\n",
638 Gbl_ExternalRefFilename, ImportCount);
641 fclose (ExternalRefFile);
645 /*******************************************************************************
647 * FUNCTION: AcpiDmAddToExternalListFromFile
649 * PARAMETERS: Path - Internal (AML) path to the object
650 * Type - ACPI object type to be added
651 * Value - Arg count if adding a Method object
653 * RETURN: None
655 * DESCRIPTION: Insert a new name into the global list of Externals which
656 * will in turn be later emitted as an External() declaration
657 * in the disassembled output.
659 ******************************************************************************/
661 static void
662 AcpiDmAddToExternalListFromFile (
663 char *Path,
664 UINT8 Type,
665 UINT32 Value)
667 char *InternalPath;
668 char *ExternalPath;
669 ACPI_EXTERNAL_LIST *NewExternal;
670 ACPI_EXTERNAL_LIST *NextExternal;
671 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
672 ACPI_STATUS Status;
673 BOOLEAN Resolved = FALSE;
676 if (!Path)
678 return;
681 /* TBD: Add a flags parameter */
683 if (Type == ACPI_TYPE_METHOD)
685 if (Value & 0x80)
687 Resolved = TRUE;
689 Value &= 0x07;
693 * We don't want External() statements to contain a leading '\'.
694 * This prevents duplicate external statements of the form:
696 * External (\ABCD)
697 * External (ABCD)
699 * This would cause a compile time error when the disassembled
700 * output file is recompiled.
702 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
704 Path++;
707 /* Check all existing externals to ensure no duplicates */
709 NextExternal = AcpiGbl_ExternalList;
710 while (NextExternal)
712 if (!ACPI_STRCMP (Path, NextExternal->Path))
714 /* Duplicate method, check that the Value (ArgCount) is the same */
716 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
717 (NextExternal->Value != Value))
719 ACPI_ERROR ((AE_INFO,
720 "(File) External method arg count mismatch %s: Current %u, override to %u",
721 NextExternal->Path, NextExternal->Value, Value));
723 /* Override, since new value came from external reference file */
725 NextExternal->Value = Value;
728 /* Allow upgrade of type from ANY */
730 else if (NextExternal->Type == ACPI_TYPE_ANY)
732 NextExternal->Type = Type;
733 NextExternal->Value = Value;
736 return;
739 NextExternal = NextExternal->Next;
742 /* Get the internal pathname (AML format) */
744 Status = AcpiNsInternalizeName (Path, &InternalPath);
745 if (ACPI_FAILURE (Status))
747 return;
750 /* Allocate and init a new External() descriptor */
752 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
753 if (!NewExternal)
755 ACPI_FREE (InternalPath);
756 return;
759 /* Must copy and normalize the input path */
761 AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, NULL, &ExternalPath);
763 NewExternal->Path = ExternalPath;
764 NewExternal->Type = Type;
765 NewExternal->Value = Value;
766 NewExternal->Resolved = Resolved;
767 NewExternal->Length = (UINT16) ACPI_STRLEN (Path);
768 NewExternal->InternalPath = InternalPath;
770 /* Set flag to indicate External->InternalPath needs to be freed */
772 NewExternal->Flags |= ACPI_IPATH_ALLOCATED | ACPI_FROM_REFERENCE_FILE;
774 /* Link the new descriptor into the global list, alphabetically ordered */
776 NextExternal = AcpiGbl_ExternalList;
777 while (NextExternal)
779 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
781 if (PrevExternal)
783 PrevExternal->Next = NewExternal;
785 else
787 AcpiGbl_ExternalList = NewExternal;
790 NewExternal->Next = NextExternal;
791 return;
794 PrevExternal = NextExternal;
795 NextExternal = NextExternal->Next;
798 if (PrevExternal)
800 PrevExternal->Next = NewExternal;
802 else
804 AcpiGbl_ExternalList = NewExternal;
809 /*******************************************************************************
811 * FUNCTION: AcpiDmAddExternalsToNamespace
813 * PARAMETERS: None
815 * RETURN: None
817 * DESCRIPTION: Add all externals to the namespace. Allows externals to be
818 * "resolved".
820 ******************************************************************************/
822 void
823 AcpiDmAddExternalsToNamespace (
824 void)
826 ACPI_STATUS Status;
827 ACPI_NAMESPACE_NODE *Node;
828 ACPI_OPERAND_OBJECT *ObjDesc;
829 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
832 while (External)
834 /* Add the external name (object) into the namespace */
836 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
837 ACPI_IMODE_LOAD_PASS1,
838 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
839 NULL, &Node);
841 if (ACPI_FAILURE (Status))
843 ACPI_EXCEPTION ((AE_INFO, Status,
844 "while adding external to namespace [%s]",
845 External->Path));
848 else switch (External->Type)
850 case ACPI_TYPE_METHOD:
852 /* For methods, we need to save the argument count */
854 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
855 ObjDesc->Method.ParamCount = (UINT8) External->Value;
856 Node->Object = ObjDesc;
857 break;
859 case ACPI_TYPE_REGION:
861 /* Regions require a region sub-object */
863 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
864 ObjDesc->Region.Node = Node;
865 Node->Object = ObjDesc;
866 break;
868 default:
870 break;
873 External = External->Next;
878 /*******************************************************************************
880 * FUNCTION: AcpiDmGetExternalMethodCount
882 * PARAMETERS: None
884 * RETURN: The number of control method externals in the external list
886 * DESCRIPTION: Return the number of method externals that have been generated.
887 * If any control method externals have been found, we must
888 * re-parse the entire definition block with the new information
889 * (number of arguments for the methods.) This is limitation of
890 * AML, we don't know the number of arguments from the control
891 * method invocation itself.
893 ******************************************************************************/
895 UINT32
896 AcpiDmGetExternalMethodCount (
897 void)
899 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
900 UINT32 Count = 0;
903 while (External)
905 if (External->Type == ACPI_TYPE_METHOD)
907 Count++;
910 External = External->Next;
913 return (Count);
917 /*******************************************************************************
919 * FUNCTION: AcpiDmClearExternalList
921 * PARAMETERS: None
923 * RETURN: None
925 * DESCRIPTION: Free the entire External info list
927 ******************************************************************************/
929 void
930 AcpiDmClearExternalList (
931 void)
933 ACPI_EXTERNAL_LIST *NextExternal;
936 while (AcpiGbl_ExternalList)
938 NextExternal = AcpiGbl_ExternalList->Next;
939 ACPI_FREE (AcpiGbl_ExternalList->Path);
940 ACPI_FREE (AcpiGbl_ExternalList);
941 AcpiGbl_ExternalList = NextExternal;
946 /*******************************************************************************
948 * FUNCTION: AcpiDmEmitExternals
950 * PARAMETERS: None
952 * RETURN: None
954 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
955 * the global external info list.
957 ******************************************************************************/
959 void
960 AcpiDmEmitExternals (
961 void)
963 ACPI_EXTERNAL_LIST *NextExternal;
966 if (!AcpiGbl_ExternalList)
968 return;
972 * Determine the number of control methods in the external list, and
973 * also how many of those externals were resolved via the namespace.
975 NextExternal = AcpiGbl_ExternalList;
976 while (NextExternal)
978 if (NextExternal->Type == ACPI_TYPE_METHOD)
980 AcpiGbl_NumExternalMethods++;
981 if (NextExternal->Resolved)
983 AcpiGbl_ResolvedExternalMethods++;
987 NextExternal = NextExternal->Next;
990 /* Check if any control methods were unresolved */
992 AcpiDmUnresolvedWarning (1);
994 /* Emit any unresolved method externals in a single text block */
996 NextExternal = AcpiGbl_ExternalList;
997 while (NextExternal)
999 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
1000 (!NextExternal->Resolved))
1002 AcpiOsPrintf (" External (%s%s",
1003 NextExternal->Path,
1004 AcpiDmGetObjectTypeName (NextExternal->Type));
1006 AcpiOsPrintf (
1007 ") // Warning: Unresolved Method, "
1008 "guessing %u arguments (may be incorrect, see warning above)\n",
1009 NextExternal->Value);
1011 NextExternal->Emitted = TRUE;
1014 NextExternal = NextExternal->Next;
1017 AcpiOsPrintf ("\n");
1020 /* Emit externals that were imported from a file */
1022 if (Gbl_ExternalRefFilename)
1024 AcpiOsPrintf (
1025 " /*\n * External declarations that were imported from\n"
1026 " * the reference file [%s]\n */\n",
1027 Gbl_ExternalRefFilename);
1029 NextExternal = AcpiGbl_ExternalList;
1030 while (NextExternal)
1032 if (!NextExternal->Emitted && (NextExternal->Flags & ACPI_FROM_REFERENCE_FILE))
1034 AcpiOsPrintf (" External (%s%s",
1035 NextExternal->Path,
1036 AcpiDmGetObjectTypeName (NextExternal->Type));
1038 if (NextExternal->Type == ACPI_TYPE_METHOD)
1040 AcpiOsPrintf (") // %u Arguments\n",
1041 NextExternal->Value);
1043 else
1045 AcpiOsPrintf (")\n");
1047 NextExternal->Emitted = TRUE;
1050 NextExternal = NextExternal->Next;
1053 AcpiOsPrintf ("\n");
1057 * Walk the list of externals found during the AML parsing
1059 while (AcpiGbl_ExternalList)
1061 if (!AcpiGbl_ExternalList->Emitted)
1063 AcpiOsPrintf (" External (%s%s",
1064 AcpiGbl_ExternalList->Path,
1065 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1067 /* For methods, add a comment with the number of arguments */
1069 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1071 AcpiOsPrintf (") // %u Arguments\n",
1072 AcpiGbl_ExternalList->Value);
1074 else
1076 AcpiOsPrintf (")\n");
1080 /* Free this external info block and move on to next external */
1082 NextExternal = AcpiGbl_ExternalList->Next;
1083 if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED)
1085 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1088 ACPI_FREE (AcpiGbl_ExternalList->Path);
1089 ACPI_FREE (AcpiGbl_ExternalList);
1090 AcpiGbl_ExternalList = NextExternal;
1093 AcpiOsPrintf ("\n");
1097 /*******************************************************************************
1099 * FUNCTION: AcpiDmUnresolvedWarning
1101 * PARAMETERS: Type - Where to output the warning.
1102 * 0 means write to stderr
1103 * 1 means write to AcpiOsPrintf
1105 * RETURN: None
1107 * DESCRIPTION: Issue warning message if there are unresolved external control
1108 * methods within the disassembly.
1110 ******************************************************************************/
1112 #if 0
1113 Summary of the external control method problem:
1115 When the -e option is used with disassembly, the various SSDTs are simply
1116 loaded into a global namespace for the disassembler to use in order to
1117 resolve control method references (invocations).
1119 The disassembler tracks any such references, and will emit an External()
1120 statement for these types of methods, with the proper number of arguments .
1122 Without the SSDTs, the AML does not contain enough information to properly
1123 disassemble the control method invocation -- because the disassembler does
1124 not know how many arguments to parse.
1126 An example: Assume we have two control methods. ABCD has one argument, and
1127 EFGH has zero arguments. Further, we have two additional control methods
1128 that invoke ABCD and EFGH, named T1 and T2:
1130 Method (ABCD, 1)
1133 Method (EFGH, 0)
1136 Method (T1)
1138 ABCD (Add (2, 7, Local0))
1140 Method (T2)
1142 EFGH ()
1143 Add (2, 7, Local0)
1146 Here is the AML code that is generated for T1 and T2:
1148 185: Method (T1)
1150 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1152 186: {
1153 187: ABCD (Add (2, 7, Local0))
1155 00000353: 41 42 43 44 ............ "ABCD"
1156 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1158 188: }
1160 190: Method (T2)
1162 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1164 191: {
1165 192: EFGH ()
1167 00000364: 45 46 47 48 ............ "EFGH"
1169 193: Add (2, 7, Local0)
1171 00000368: 72 0A 02 0A 07 60 ...... "r....`"
1172 194: }
1174 Note that the AML code for T1 and T2 is essentially identical. When
1175 disassembling this code, the methods ABCD and EFGH must be known to the
1176 disassembler, otherwise it does not know how to handle the method invocations.
1178 In other words, if ABCD and EFGH are actually external control methods
1179 appearing in an SSDT, the disassembler does not know what to do unless
1180 the owning SSDT has been loaded via the -e option.
1181 #endif
1183 void
1184 AcpiDmUnresolvedWarning (
1185 UINT8 Type)
1188 if (!AcpiGbl_NumExternalMethods)
1190 return;
1193 if (Type)
1195 if (!AcpiGbl_ExternalFileList)
1197 /* The -e option was not specified */
1199 AcpiOsPrintf (" /*\n"
1200 " * iASL Warning: There were %u external control methods found during\n"
1201 " * disassembly, but additional ACPI tables to resolve these externals\n"
1202 " * were not specified. This resulting disassembler output file may not\n"
1203 " * compile because the disassembler did not know how many arguments\n"
1204 " * to assign to these methods. To specify the tables needed to resolve\n"
1205 " * external control method references, use the one of the following\n"
1206 " * example iASL invocations:\n"
1207 " * iasl -e <ssdt1.aml,ssdt2.aml...> -d <dsdt.aml>\n"
1208 " * iasl -e <dsdt.aml,ssdt2.aml...> -d <ssdt1.aml>\n"
1209 " */\n",
1210 AcpiGbl_NumExternalMethods);
1212 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1214 /* The -e option was specified, but there are still some unresolved externals */
1216 AcpiOsPrintf (" /*\n"
1217 " * iASL Warning: There were %u external control methods found during\n"
1218 " * disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1219 " * ACPI tables are required to properly disassemble the code. This\n"
1220 " * resulting disassembler output file may not compile because the\n"
1221 " * disassembler did not know how many arguments to assign to the\n"
1222 " * unresolved methods.\n"
1223 " */\n",
1224 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1225 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1226 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));
1229 else
1231 if (!AcpiGbl_ExternalFileList)
1233 /* The -e option was not specified */
1235 fprintf (stderr, "\n"
1236 "iASL Warning: There were %u external control methods found during\n"
1237 "disassembly, but additional ACPI tables to resolve these externals\n"
1238 "were not specified. The resulting disassembler output file may not\n"
1239 "compile because the disassembler did not know how many arguments\n"
1240 "to assign to these methods. To specify the tables needed to resolve\n"
1241 "external control method references, use the one of the following\n"
1242 "example iASL invocations:\n"
1243 " iasl -e <ssdt1.aml,ssdt2.aml...> -d <dsdt.aml>\n"
1244 " iasl -e <dsdt.aml,ssdt2.aml...> -d <ssdt1.aml>\n",
1245 AcpiGbl_NumExternalMethods);
1247 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1249 /* The -e option was specified, but there are still some unresolved externals */
1251 fprintf (stderr, "\n"
1252 "iASL Warning: There were %u external control methods found during\n"
1253 "disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1254 "ACPI tables are required to properly disassemble the code. The\n"
1255 "resulting disassembler output file may not compile because the\n"
1256 "disassembler did not know how many arguments to assign to the\n"
1257 "unresolved methods.\n",
1258 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1259 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1260 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));