BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / bus_managers / acpi / acpica / common / dmextern.c
blob30196dff04356137bfb46c39b79a1582c93cb6c7
1 /******************************************************************************
3 * Module Name: dmextern - Support for External() ASL statements
5 *****************************************************************************/
7 /******************************************************************************
9 * 1. Copyright Notice
11 * Some or all of this work - Copyright (c) 1999 - 2014, Intel Corp.
12 * All rights reserved.
14 * 2. License
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
40 * 3. Conditions
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
80 * 4. Disclaimer and Export Compliance
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
114 *****************************************************************************/
116 #include "acpi.h"
117 #include "accommon.h"
118 #include "amlcode.h"
119 #include "acnamesp.h"
120 #include "acdisasm.h"
121 #include "aslcompiler.h"
122 #include <stdio.h>
123 #include <errno.h>
127 * This module is used for application-level code (iASL disassembler) only.
129 * It contains the code to create and emit any necessary External() ASL
130 * statements for the module being disassembled.
132 #define _COMPONENT ACPI_CA_DISASSEMBLER
133 ACPI_MODULE_NAME ("dmextern")
137 * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
138 * ObjectTypeKeyword. Used to generate typed external declarations
140 static const char *AcpiGbl_DmTypeNames[] =
142 /* 00 */ ", UnknownObj", /* Type ANY */
143 /* 01 */ ", IntObj",
144 /* 02 */ ", StrObj",
145 /* 03 */ ", BuffObj",
146 /* 04 */ ", PkgObj",
147 /* 05 */ ", FieldUnitObj",
148 /* 06 */ ", DeviceObj",
149 /* 07 */ ", EventObj",
150 /* 08 */ ", MethodObj",
151 /* 09 */ ", MutexObj",
152 /* 10 */ ", OpRegionObj",
153 /* 11 */ ", PowerResObj",
154 /* 12 */ ", ProcessorObj",
155 /* 13 */ ", ThermalZoneObj",
156 /* 14 */ ", BuffFieldObj",
157 /* 15 */ ", DDBHandleObj",
158 /* 16 */ "", /* Debug object */
159 /* 17 */ ", FieldUnitObj",
160 /* 18 */ ", FieldUnitObj",
161 /* 19 */ ", FieldUnitObj"
164 #define METHOD_SEPARATORS " \t,()\n"
167 /* Local prototypes */
169 static const char *
170 AcpiDmGetObjectTypeName (
171 ACPI_OBJECT_TYPE Type);
173 static char *
174 AcpiDmNormalizeParentPrefix (
175 ACPI_PARSE_OBJECT *Op,
176 char *Path);
178 static void
179 AcpiDmAddPathToExternalList (
180 char *Path,
181 UINT8 Type,
182 UINT32 Value,
183 UINT16 Flags);
185 static ACPI_STATUS
186 AcpiDmCreateNewExternal (
187 char *ExternalPath,
188 char *InternalPath,
189 UINT8 Type,
190 UINT32 Value,
191 UINT16 Flags);
194 /*******************************************************************************
196 * FUNCTION: AcpiDmGetObjectTypeName
198 * PARAMETERS: Type - An ACPI_OBJECT_TYPE
200 * RETURN: Pointer to a string
202 * DESCRIPTION: Map an object type to the ASL object type string.
204 ******************************************************************************/
206 static const char *
207 AcpiDmGetObjectTypeName (
208 ACPI_OBJECT_TYPE Type)
211 if (Type == ACPI_TYPE_LOCAL_SCOPE)
213 Type = ACPI_TYPE_DEVICE;
216 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
218 return ("");
221 return (AcpiGbl_DmTypeNames[Type]);
225 /*******************************************************************************
227 * FUNCTION: AcpiDmNormalizeParentPrefix
229 * PARAMETERS: Op - Parse op
230 * Path - Path with parent prefix
232 * RETURN: The full pathname to the object (from the namespace root)
234 * DESCRIPTION: Returns the full pathname of a path with parent prefix
235 * The caller must free the fullpath returned.
237 ******************************************************************************/
239 static char *
240 AcpiDmNormalizeParentPrefix (
241 ACPI_PARSE_OBJECT *Op,
242 char *Path)
244 ACPI_NAMESPACE_NODE *Node;
245 char *Fullpath;
246 char *ParentPath;
247 ACPI_SIZE Length;
248 UINT32 Index = 0;
251 if (!Op)
253 return (NULL);
256 /* Search upwards in the parse tree until we reach the next namespace node */
258 Op = Op->Common.Parent;
259 while (Op)
261 if (Op->Common.Node)
263 break;
266 Op = Op->Common.Parent;
269 if (!Op)
271 return (NULL);
275 * Find the actual parent node for the reference:
276 * Remove all carat prefixes from the input path.
277 * There may be multiple parent prefixes (For example, ^^^M000)
279 Node = Op->Common.Node;
280 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
282 Node = Node->Parent;
283 Path++;
286 if (!Node)
288 return (NULL);
291 /* Get the full pathname for the parent node */
293 ParentPath = AcpiNsGetExternalPathname (Node);
294 if (!ParentPath)
296 return (NULL);
299 Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1);
300 if (ParentPath[1])
303 * If ParentPath is not just a simple '\', increment the length
304 * for the required dot separator (ParentPath.Path)
306 Length++;
308 /* For External() statements, we do not want a leading '\' */
310 if (*ParentPath == AML_ROOT_PREFIX)
312 Index = 1;
316 Fullpath = ACPI_ALLOCATE_ZEROED (Length);
317 if (!Fullpath)
319 goto Cleanup;
323 * Concatenate parent fullpath and path. For example,
324 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
326 * Copy the parent path
328 ACPI_STRCPY (Fullpath, &ParentPath[Index]);
331 * Add dot separator
332 * (don't need dot if parent fullpath is a single backslash)
334 if (ParentPath[1])
336 ACPI_STRCAT (Fullpath, ".");
339 /* Copy child path (carat parent prefix(es) were skipped above) */
341 ACPI_STRCAT (Fullpath, Path);
343 Cleanup:
344 ACPI_FREE (ParentPath);
345 return (Fullpath);
349 /*******************************************************************************
351 * FUNCTION: AcpiDmAddToExternalFileList
353 * PARAMETERS: PathList - Single path or list separated by comma
355 * RETURN: None
357 * DESCRIPTION: Add external files to global list
359 ******************************************************************************/
361 ACPI_STATUS
362 AcpiDmAddToExternalFileList (
363 char *Pathname)
365 ACPI_EXTERNAL_FILE *ExternalFile;
366 char *LocalPathname;
369 if (!Pathname)
371 return (AE_OK);
374 LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
375 if (!LocalPathname)
377 return (AE_NO_MEMORY);
380 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
381 if (!ExternalFile)
383 ACPI_FREE (LocalPathname);
384 return (AE_NO_MEMORY);
387 /* Take a copy of the file pathname */
389 strcpy (LocalPathname, Pathname);
390 ExternalFile->Path = LocalPathname;
392 if (AcpiGbl_ExternalFileList)
394 ExternalFile->Next = AcpiGbl_ExternalFileList;
397 AcpiGbl_ExternalFileList = ExternalFile;
398 return (AE_OK);
402 /*******************************************************************************
404 * FUNCTION: AcpiDmClearExternalFileList
406 * PARAMETERS: None
408 * RETURN: None
410 * DESCRIPTION: Clear the external file list
412 ******************************************************************************/
414 void
415 AcpiDmClearExternalFileList (
416 void)
418 ACPI_EXTERNAL_FILE *NextExternal;
421 while (AcpiGbl_ExternalFileList)
423 NextExternal = AcpiGbl_ExternalFileList->Next;
424 ACPI_FREE (AcpiGbl_ExternalFileList->Path);
425 ACPI_FREE (AcpiGbl_ExternalFileList);
426 AcpiGbl_ExternalFileList = NextExternal;
431 /*******************************************************************************
433 * FUNCTION: AcpiDmGetExternalsFromFile
435 * PARAMETERS: None
437 * RETURN: None
439 * DESCRIPTION: Process the optional external reference file.
441 * Each line in the file should be of the form:
442 * External (<Method namepath>, MethodObj, <ArgCount>)
444 * Example:
445 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
447 ******************************************************************************/
449 void
450 AcpiDmGetExternalsFromFile (
451 void)
453 FILE *ExternalRefFile;
454 char *Token;
455 char *MethodName;
456 UINT32 ArgCount;
457 UINT32 ImportCount = 0;
460 if (!Gbl_ExternalRefFilename)
462 return;
465 /* Open the file */
467 ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
468 if (!ExternalRefFile)
470 fprintf (stderr, "Could not open external reference file \"%s\"\n",
471 Gbl_ExternalRefFilename);
472 AslAbort ();
473 return;
476 /* Each line defines a method */
478 while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
480 Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */
481 if (!Token)
483 continue;
485 if (strcmp (Token, "External"))
487 continue;
490 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */
491 if (!MethodName)
493 continue;
496 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */
497 if (!Token)
499 continue;
502 if (strcmp (Token, "MethodObj"))
504 continue;
507 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */
508 if (!Token)
510 continue;
513 /* Convert arg count string to an integer */
515 errno = 0;
516 ArgCount = strtoul (Token, NULL, 0);
517 if (errno)
519 fprintf (stderr, "Invalid argument count (%s)\n", Token);
520 continue;
522 if (ArgCount > 7)
524 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
525 continue;
528 /* Add this external to the global list */
530 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
531 Gbl_ExternalRefFilename, ArgCount, MethodName);
533 AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
534 ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
535 ImportCount++;
538 if (!ImportCount)
540 fprintf (stderr, "Did not find any external methods in reference file \"%s\"\n",
541 Gbl_ExternalRefFilename);
543 else
545 /* Add the external(s) to the namespace */
547 AcpiDmAddExternalsToNamespace ();
549 AcpiOsPrintf ("%s: Imported %u external method definitions\n",
550 Gbl_ExternalRefFilename, ImportCount);
553 fclose (ExternalRefFile);
557 /*******************************************************************************
559 * FUNCTION: AcpiDmAddOpToExternalList
561 * PARAMETERS: Op - Current parser Op
562 * Path - Internal (AML) path to the object
563 * Type - ACPI object type to be added
564 * Value - Arg count if adding a Method object
565 * Flags - To be passed to the external object
567 * RETURN: None
569 * DESCRIPTION: Insert a new name into the global list of Externals which
570 * will in turn be later emitted as an External() declaration
571 * in the disassembled output.
573 * This function handles the most common case where the referenced
574 * name is simply not found in the constructed namespace.
576 ******************************************************************************/
578 void
579 AcpiDmAddOpToExternalList (
580 ACPI_PARSE_OBJECT *Op,
581 char *Path,
582 UINT8 Type,
583 UINT32 Value,
584 UINT16 Flags)
586 char *ExternalPath;
587 char *InternalPath = Path;
588 char *Temp;
589 ACPI_STATUS Status;
592 ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
595 if (!Path)
597 return_VOID;
600 /* Remove a root backslash if present */
602 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
604 Path++;
607 /* Externalize the pathname */
609 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
610 NULL, &ExternalPath);
611 if (ACPI_FAILURE (Status))
613 return_VOID;
617 * Get the full pathname from the root if "Path" has one or more
618 * parent prefixes (^). Note: path will not contain a leading '\'.
620 if (*Path == (UINT8) AML_PARENT_PREFIX)
622 Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
624 /* Set new external path */
626 ACPI_FREE (ExternalPath);
627 ExternalPath = Temp;
628 if (!Temp)
630 return_VOID;
633 /* Create the new internal pathname */
635 Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
636 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
637 if (ACPI_FAILURE (Status))
639 ACPI_FREE (ExternalPath);
640 return_VOID;
644 /* Create the new External() declaration node */
646 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
647 Type, Value, Flags);
648 if (ACPI_FAILURE (Status))
650 ACPI_FREE (ExternalPath);
651 if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
653 ACPI_FREE (InternalPath);
657 return_VOID;
661 /*******************************************************************************
663 * FUNCTION: AcpiDmAddNodeToExternalList
665 * PARAMETERS: Node - Namespace node for object to be added
666 * Type - ACPI object type to be added
667 * Value - Arg count if adding a Method object
668 * Flags - To be passed to the external object
670 * RETURN: None
672 * DESCRIPTION: Insert a new name into the global list of Externals which
673 * will in turn be later emitted as an External() declaration
674 * in the disassembled output.
676 * This function handles the case where the referenced name has
677 * been found in the namespace, but the name originated in a
678 * table other than the one that is being disassembled (such
679 * as a table that is added via the iASL -e option).
681 ******************************************************************************/
683 void
684 AcpiDmAddNodeToExternalList (
685 ACPI_NAMESPACE_NODE *Node,
686 UINT8 Type,
687 UINT32 Value,
688 UINT16 Flags)
690 char *ExternalPath;
691 char *InternalPath;
692 char *Temp;
693 ACPI_STATUS Status;
696 ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
699 if (!Node)
701 return_VOID;
704 /* Get the full external and internal pathnames to the node */
706 ExternalPath = AcpiNsGetExternalPathname (Node);
707 if (!ExternalPath)
709 return_VOID;
712 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
713 if (ACPI_FAILURE (Status))
715 ACPI_FREE (ExternalPath);
716 return_VOID;
719 /* Remove the root backslash */
721 if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1]))
723 Temp = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (ExternalPath) + 1);
724 if (!Temp)
726 return_VOID;
729 ACPI_STRCPY (Temp, &ExternalPath[1]);
730 ACPI_FREE (ExternalPath);
731 ExternalPath = Temp;
734 /* Create the new External() declaration node */
736 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
737 Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
738 if (ACPI_FAILURE (Status))
740 ACPI_FREE (ExternalPath);
741 ACPI_FREE (InternalPath);
744 return_VOID;
748 /*******************************************************************************
750 * FUNCTION: AcpiDmAddPathToExternalList
752 * PARAMETERS: Path - External name of the object to be added
753 * Type - ACPI object type to be added
754 * Value - Arg count if adding a Method object
755 * Flags - To be passed to the external object
757 * RETURN: None
759 * DESCRIPTION: Insert a new name into the global list of Externals which
760 * will in turn be later emitted as an External() declaration
761 * in the disassembled output.
763 * This function currently is used to add externals via a
764 * reference file (via the -fe iASL option).
766 ******************************************************************************/
768 static void
769 AcpiDmAddPathToExternalList (
770 char *Path,
771 UINT8 Type,
772 UINT32 Value,
773 UINT16 Flags)
775 char *InternalPath;
776 char *ExternalPath;
777 ACPI_STATUS Status;
780 ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
783 if (!Path)
785 return_VOID;
788 /* Remove a root backslash if present */
790 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
792 Path++;
795 /* Create the internal and external pathnames */
797 Status = AcpiNsInternalizeName (Path, &InternalPath);
798 if (ACPI_FAILURE (Status))
800 return_VOID;
803 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
804 NULL, &ExternalPath);
805 if (ACPI_FAILURE (Status))
807 ACPI_FREE (InternalPath);
808 return_VOID;
811 /* Create the new External() declaration node */
813 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
814 Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
815 if (ACPI_FAILURE (Status))
817 ACPI_FREE (ExternalPath);
818 ACPI_FREE (InternalPath);
821 return_VOID;
825 /*******************************************************************************
827 * FUNCTION: AcpiDmCreateNewExternal
829 * PARAMETERS: ExternalPath - External path to the object
830 * InternalPath - Internal (AML) path to the object
831 * Type - ACPI object type to be added
832 * Value - Arg count if adding a Method object
833 * Flags - To be passed to the external object
835 * RETURN: Status
837 * DESCRIPTION: Common low-level function to insert a new name into the global
838 * list of Externals which will in turn be later emitted as
839 * External() declarations in the disassembled output.
841 * Note: The external name should not include a root prefix
842 * (backslash). We do not want External() statements to contain
843 * a leading '\', as this prevents duplicate external statements
844 * of the form:
846 * External (\ABCD)
847 * External (ABCD)
849 * This would cause a compile time error when the disassembled
850 * output file is recompiled.
852 * There are two cases that are handled here. For both, we emit
853 * an External() statement:
854 * 1) The name was simply not found in the namespace.
855 * 2) The name was found, but it originated in a table other than
856 * the table that is being disassembled.
858 ******************************************************************************/
860 static ACPI_STATUS
861 AcpiDmCreateNewExternal (
862 char *ExternalPath,
863 char *InternalPath,
864 UINT8 Type,
865 UINT32 Value,
866 UINT16 Flags)
868 ACPI_EXTERNAL_LIST *NewExternal;
869 ACPI_EXTERNAL_LIST *NextExternal;
870 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
873 ACPI_FUNCTION_TRACE (DmCreateNewExternal);
876 /* Check all existing externals to ensure no duplicates */
878 NextExternal = AcpiGbl_ExternalList;
879 while (NextExternal)
881 if (!ACPI_STRCMP (ExternalPath, NextExternal->Path))
883 /* Duplicate method, check that the Value (ArgCount) is the same */
885 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
886 (NextExternal->Value != Value) &&
887 (Value > 0))
889 ACPI_ERROR ((AE_INFO,
890 "External method arg count mismatch %s: Current %u, attempted %u",
891 NextExternal->Path, NextExternal->Value, Value));
894 /* Allow upgrade of type from ANY */
896 else if (NextExternal->Type == ACPI_TYPE_ANY)
898 NextExternal->Type = Type;
899 NextExternal->Value = Value;
902 return_ACPI_STATUS (AE_ALREADY_EXISTS);
905 NextExternal = NextExternal->Next;
908 /* Allocate and init a new External() descriptor */
910 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
911 if (!NewExternal)
913 return_ACPI_STATUS (AE_NO_MEMORY);
916 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
917 "Adding external reference node (%s) type [%s]\n",
918 ExternalPath, AcpiUtGetTypeName (Type)));
920 NewExternal->Flags = Flags;
921 NewExternal->Value = Value;
922 NewExternal->Path = ExternalPath;
923 NewExternal->Type = Type;
924 NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath);
925 NewExternal->InternalPath = InternalPath;
927 /* Link the new descriptor into the global list, alphabetically ordered */
929 NextExternal = AcpiGbl_ExternalList;
930 while (NextExternal)
932 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
934 if (PrevExternal)
936 PrevExternal->Next = NewExternal;
938 else
940 AcpiGbl_ExternalList = NewExternal;
943 NewExternal->Next = NextExternal;
944 return_ACPI_STATUS (AE_OK);
947 PrevExternal = NextExternal;
948 NextExternal = NextExternal->Next;
951 if (PrevExternal)
953 PrevExternal->Next = NewExternal;
955 else
957 AcpiGbl_ExternalList = NewExternal;
960 return_ACPI_STATUS (AE_OK);
964 /*******************************************************************************
966 * FUNCTION: AcpiDmAddExternalsToNamespace
968 * PARAMETERS: None
970 * RETURN: None
972 * DESCRIPTION: Add all externals to the namespace. Allows externals to be
973 * "resolved".
975 ******************************************************************************/
977 void
978 AcpiDmAddExternalsToNamespace (
979 void)
981 ACPI_STATUS Status;
982 ACPI_NAMESPACE_NODE *Node;
983 ACPI_OPERAND_OBJECT *ObjDesc;
984 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
987 while (External)
989 /* Add the external name (object) into the namespace */
991 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
992 ACPI_IMODE_LOAD_PASS1,
993 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
994 NULL, &Node);
996 if (ACPI_FAILURE (Status))
998 ACPI_EXCEPTION ((AE_INFO, Status,
999 "while adding external to namespace [%s]",
1000 External->Path));
1003 else switch (External->Type)
1005 case ACPI_TYPE_METHOD:
1007 /* For methods, we need to save the argument count */
1009 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
1010 ObjDesc->Method.ParamCount = (UINT8) External->Value;
1011 Node->Object = ObjDesc;
1012 break;
1014 case ACPI_TYPE_REGION:
1016 /* Regions require a region sub-object */
1018 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
1019 ObjDesc->Region.Node = Node;
1020 Node->Object = ObjDesc;
1021 break;
1023 default:
1025 break;
1028 External = External->Next;
1033 /*******************************************************************************
1035 * FUNCTION: AcpiDmGetExternalMethodCount
1037 * PARAMETERS: None
1039 * RETURN: The number of control method externals in the external list
1041 * DESCRIPTION: Return the number of method externals that have been generated.
1042 * If any control method externals have been found, we must
1043 * re-parse the entire definition block with the new information
1044 * (number of arguments for the methods.) This is limitation of
1045 * AML, we don't know the number of arguments from the control
1046 * method invocation itself.
1048 ******************************************************************************/
1050 UINT32
1051 AcpiDmGetExternalMethodCount (
1052 void)
1054 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
1055 UINT32 Count = 0;
1058 while (External)
1060 if (External->Type == ACPI_TYPE_METHOD)
1062 Count++;
1065 External = External->Next;
1068 return (Count);
1072 /*******************************************************************************
1074 * FUNCTION: AcpiDmClearExternalList
1076 * PARAMETERS: None
1078 * RETURN: None
1080 * DESCRIPTION: Free the entire External info list
1082 ******************************************************************************/
1084 void
1085 AcpiDmClearExternalList (
1086 void)
1088 ACPI_EXTERNAL_LIST *NextExternal;
1091 while (AcpiGbl_ExternalList)
1093 NextExternal = AcpiGbl_ExternalList->Next;
1094 ACPI_FREE (AcpiGbl_ExternalList->Path);
1095 ACPI_FREE (AcpiGbl_ExternalList);
1096 AcpiGbl_ExternalList = NextExternal;
1101 /*******************************************************************************
1103 * FUNCTION: AcpiDmEmitExternals
1105 * PARAMETERS: None
1107 * RETURN: None
1109 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1110 * the global external info list.
1112 ******************************************************************************/
1114 void
1115 AcpiDmEmitExternals (
1116 void)
1118 ACPI_EXTERNAL_LIST *NextExternal;
1121 if (!AcpiGbl_ExternalList)
1123 return;
1127 * Determine the number of control methods in the external list, and
1128 * also how many of those externals were resolved via the namespace.
1130 NextExternal = AcpiGbl_ExternalList;
1131 while (NextExternal)
1133 if (NextExternal->Type == ACPI_TYPE_METHOD)
1135 AcpiGbl_NumExternalMethods++;
1136 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1138 AcpiGbl_ResolvedExternalMethods++;
1142 NextExternal = NextExternal->Next;
1145 /* Check if any control methods were unresolved */
1147 AcpiDmUnresolvedWarning (1);
1149 /* Emit any unresolved method externals in a single text block */
1151 NextExternal = AcpiGbl_ExternalList;
1152 while (NextExternal)
1154 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
1155 (!(NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1157 AcpiOsPrintf (" External (%s%s",
1158 NextExternal->Path,
1159 AcpiDmGetObjectTypeName (NextExternal->Type));
1161 AcpiOsPrintf (") // Warning: Unresolved method, "
1162 "guessing %u arguments\n",
1163 NextExternal->Value);
1165 NextExternal->Flags |= ACPI_EXT_EXTERNAL_EMITTED;
1168 NextExternal = NextExternal->Next;
1171 AcpiOsPrintf ("\n");
1174 /* Emit externals that were imported from a file */
1176 if (Gbl_ExternalRefFilename)
1178 AcpiOsPrintf (
1179 " /*\n * External declarations that were imported from\n"
1180 " * the reference file [%s]\n */\n",
1181 Gbl_ExternalRefFilename);
1183 NextExternal = AcpiGbl_ExternalList;
1184 while (NextExternal)
1186 if (!(NextExternal->Flags & ACPI_EXT_EXTERNAL_EMITTED) &&
1187 (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_FILE))
1189 AcpiOsPrintf (" External (%s%s",
1190 NextExternal->Path,
1191 AcpiDmGetObjectTypeName (NextExternal->Type));
1193 if (NextExternal->Type == ACPI_TYPE_METHOD)
1195 AcpiOsPrintf (") // %u Arguments\n",
1196 NextExternal->Value);
1198 else
1200 AcpiOsPrintf (")\n");
1202 NextExternal->Flags |= ACPI_EXT_EXTERNAL_EMITTED;
1205 NextExternal = NextExternal->Next;
1208 AcpiOsPrintf ("\n");
1212 * Walk the list of externals found during the AML parsing
1214 while (AcpiGbl_ExternalList)
1216 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1218 AcpiOsPrintf (" External (%s%s",
1219 AcpiGbl_ExternalList->Path,
1220 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1222 /* For methods, add a comment with the number of arguments */
1224 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1226 AcpiOsPrintf (") // %u Arguments\n",
1227 AcpiGbl_ExternalList->Value);
1229 else
1231 AcpiOsPrintf (")\n");
1235 /* Free this external info block and move on to next external */
1237 NextExternal = AcpiGbl_ExternalList->Next;
1238 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1240 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1243 ACPI_FREE (AcpiGbl_ExternalList->Path);
1244 ACPI_FREE (AcpiGbl_ExternalList);
1245 AcpiGbl_ExternalList = NextExternal;
1248 AcpiOsPrintf ("\n");
1252 /*******************************************************************************
1254 * FUNCTION: AcpiDmUnresolvedWarning
1256 * PARAMETERS: Type - Where to output the warning.
1257 * 0 means write to stderr
1258 * 1 means write to AcpiOsPrintf
1260 * RETURN: None
1262 * DESCRIPTION: Issue warning message if there are unresolved external control
1263 * methods within the disassembly.
1265 ******************************************************************************/
1267 #if 0
1268 Summary of the external control method problem:
1270 When the -e option is used with disassembly, the various SSDTs are simply
1271 loaded into a global namespace for the disassembler to use in order to
1272 resolve control method references (invocations).
1274 The disassembler tracks any such references, and will emit an External()
1275 statement for these types of methods, with the proper number of arguments .
1277 Without the SSDTs, the AML does not contain enough information to properly
1278 disassemble the control method invocation -- because the disassembler does
1279 not know how many arguments to parse.
1281 An example: Assume we have two control methods. ABCD has one argument, and
1282 EFGH has zero arguments. Further, we have two additional control methods
1283 that invoke ABCD and EFGH, named T1 and T2:
1285 Method (ABCD, 1)
1288 Method (EFGH, 0)
1291 Method (T1)
1293 ABCD (Add (2, 7, Local0))
1295 Method (T2)
1297 EFGH ()
1298 Add (2, 7, Local0)
1301 Here is the AML code that is generated for T1 and T2:
1303 185: Method (T1)
1305 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1307 186: {
1308 187: ABCD (Add (2, 7, Local0))
1310 00000353: 41 42 43 44 ............ "ABCD"
1311 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1313 188: }
1315 190: Method (T2)
1317 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1319 191: {
1320 192: EFGH ()
1322 00000364: 45 46 47 48 ............ "EFGH"
1324 193: Add (2, 7, Local0)
1326 00000368: 72 0A 02 0A 07 60 ...... "r....`"
1327 194: }
1329 Note that the AML code for T1 and T2 is essentially identical. When
1330 disassembling this code, the methods ABCD and EFGH must be known to the
1331 disassembler, otherwise it does not know how to handle the method invocations.
1333 In other words, if ABCD and EFGH are actually external control methods
1334 appearing in an SSDT, the disassembler does not know what to do unless
1335 the owning SSDT has been loaded via the -e option.
1336 #endif
1338 void
1339 AcpiDmUnresolvedWarning (
1340 UINT8 Type)
1343 if (!AcpiGbl_NumExternalMethods)
1345 return;
1348 if (Type)
1350 if (!AcpiGbl_ExternalFileList)
1352 /* The -e option was not specified */
1354 AcpiOsPrintf (" /*\n"
1355 " * iASL Warning: There were %u external control methods found during\n"
1356 " * disassembly, but additional ACPI tables to resolve these externals\n"
1357 " * were not specified. This resulting disassembler output file may not\n"
1358 " * compile because the disassembler did not know how many arguments\n"
1359 " * to assign to these methods. To specify the tables needed to resolve\n"
1360 " * external control method references, the -e option can be used to\n"
1361 " * specify the filenames. Example iASL invocations:\n"
1362 " * iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1363 " * iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1364 " * iasl -e ssdt*.aml -d dsdt.aml\n"
1365 " *\n"
1366 " * In addition, the -fe option can be used to specify a file containing\n"
1367 " * control method external declarations with the associated method\n"
1368 " * argument counts. Each line of the file must be of the form:\n"
1369 " * External (<method pathname>, MethodObj, <argument count>)\n"
1370 " * Invocation:\n"
1371 " * iasl -fe refs.txt -d dsdt.aml\n"
1372 " *\n"
1373 " * The following methods were unresolved and many not compile properly\n"
1374 " * because the disassembler had to guess at the number of arguments\n"
1375 " * required for each:\n"
1376 " */\n",
1377 AcpiGbl_NumExternalMethods);
1379 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1381 /* The -e option was specified, but there are still some unresolved externals */
1383 AcpiOsPrintf (" /*\n"
1384 " * iASL Warning: There were %u external control methods found during\n"
1385 " * disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1386 " * ACPI tables may be required to properly disassemble the code. This\n"
1387 " * resulting disassembler output file may not compile because the\n"
1388 " * disassembler did not know how many arguments to assign to the\n"
1389 " * unresolved methods.\n"
1390 " *\n"
1391 " * If necessary, the -fe option can be used to specify a file containing\n"
1392 " * control method external declarations with the associated method\n"
1393 " * argument counts. Each line of the file must be of the form:\n"
1394 " * External (<method pathname>, MethodObj, <argument count>)\n"
1395 " * Invocation:\n"
1396 " * iasl -fe refs.txt -d dsdt.aml\n"
1397 " *\n"
1398 " * The following methods were unresolved and many not compile properly\n"
1399 " * because the disassembler had to guess at the number of arguments\n"
1400 " * required for each:\n"
1401 " */\n",
1402 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1403 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1404 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));
1407 else
1409 if (!AcpiGbl_ExternalFileList)
1411 /* The -e option was not specified */
1413 fprintf (stderr, "\n"
1414 "iASL Warning: There were %u external control methods found during\n"
1415 "disassembly, but additional ACPI tables to resolve these externals\n"
1416 "were not specified. The resulting disassembler output file may not\n"
1417 "compile because the disassembler did not know how many arguments\n"
1418 "to assign to these methods. To specify the tables needed to resolve\n"
1419 "external control method references, the -e option can be used to\n"
1420 "specify the filenames. Example iASL invocations:\n"
1421 " iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1422 " iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1423 " iasl -e ssdt*.aml -d dsdt.aml\n"
1424 "\n"
1425 "In addition, the -fe option can be used to specify a file containing\n"
1426 "control method external declarations with the associated method\n"
1427 "argument counts. Each line of the file must be of the form:\n"
1428 " External (<method pathname>, MethodObj, <argument count>)\n"
1429 "Invocation:\n"
1430 " iasl -fe refs.txt -d dsdt.aml\n",
1431 AcpiGbl_NumExternalMethods);
1433 else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
1435 /* The -e option was specified, but there are still some unresolved externals */
1437 fprintf (stderr, "\n"
1438 "iASL Warning: There were %u external control methods found during\n"
1439 "disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1440 "ACPI tables may be required to properly disassemble the code. The\n"
1441 "resulting disassembler output file may not compile because the\n"
1442 "disassembler did not know how many arguments to assign to the\n"
1443 "unresolved methods.\n"
1444 "\n"
1445 "If necessary, the -fe option can be used to specify a file containing\n"
1446 "control method external declarations with the associated method\n"
1447 "argument counts. Each line of the file must be of the form:\n"
1448 " External (<method pathname>, MethodObj, <argument count>)\n"
1449 "Invocation:\n"
1450 " iasl -fe refs.txt -d dsdt.aml\n",
1451 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
1452 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
1453 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));