nrelease - fix/improve livecd
[dragonfly.git] / sys / contrib / dev / acpica / source / common / dmextern.c
1 /******************************************************************************
2  *
3  * Module Name: dmextern - Support for External() ASL statements
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2021, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
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.
20  *
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
27  *
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;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
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.
53  *
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.
65  *
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.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
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.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
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.
89  *
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.
98  *
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.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151
152 #include "acpi.h"
153 #include "accommon.h"
154 #include "amlcode.h"
155 #include "acnamesp.h"
156 #include "acdisasm.h"
157 #include "aslcompiler.h"
158 #include <stdio.h>
159 #include <errno.h>
160
161
162 /*
163  * This module is used for application-level code (iASL disassembler) only.
164  *
165  * It contains the code to create and emit any necessary External() ASL
166  * statements for the module being disassembled.
167  */
168 #define _COMPONENT          ACPI_CA_DISASSEMBLER
169         ACPI_MODULE_NAME    ("dmextern")
170
171
172 /*
173  * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
174  * ObjectTypeKeyword. Used to generate typed external declarations
175  */
176 static const char           *AcpiGbl_DmTypeNames[] =
177 {
178     /* 00 */ ", UnknownObj",        /* Type ANY */
179     /* 01 */ ", IntObj",
180     /* 02 */ ", StrObj",
181     /* 03 */ ", BuffObj",
182     /* 04 */ ", PkgObj",
183     /* 05 */ ", FieldUnitObj",
184     /* 06 */ ", DeviceObj",
185     /* 07 */ ", EventObj",
186     /* 08 */ ", MethodObj",
187     /* 09 */ ", MutexObj",
188     /* 10 */ ", OpRegionObj",
189     /* 11 */ ", PowerResObj",
190     /* 12 */ ", ProcessorObj",
191     /* 13 */ ", ThermalZoneObj",
192     /* 14 */ ", BuffFieldObj",
193     /* 15 */ ", DDBHandleObj",
194     /* 16 */ "",                    /* Debug object */
195     /* 17 */ ", FieldUnitObj",
196     /* 18 */ ", FieldUnitObj",
197     /* 19 */ ", FieldUnitObj"
198 };
199
200 #define METHOD_SEPARATORS           " \t,()\n"
201
202 static const char          *ExternalConflictMessage =
203     "    // Conflicts with a later declaration";
204
205
206 /* Local prototypes */
207
208 static const char *
209 AcpiDmGetObjectTypeName (
210     ACPI_OBJECT_TYPE        Type);
211
212 static char *
213 AcpiDmNormalizeParentPrefix (
214     ACPI_PARSE_OBJECT       *Op,
215     char                    *Path);
216
217 static ACPI_STATUS
218 AcpiDmGetExternalAndInternalPath (
219     ACPI_NAMESPACE_NODE     *Node,
220     char                    **ExternalPath,
221     char                    **InternalPath);
222
223 static ACPI_STATUS
224 AcpiDmRemoveRootPrefix (
225     char                    **Path);
226
227 static void
228 AcpiDmAddPathToExternalList (
229     char                    *Path,
230     UINT8                   Type,
231     UINT32                  Value,
232     UINT16                  Flags);
233
234 static ACPI_STATUS
235 AcpiDmCreateNewExternal (
236     char                    *ExternalPath,
237     char                    *InternalPath,
238     UINT8                   Type,
239     UINT32                  Value,
240     UINT16                  Flags);
241
242 static void
243 AcpiDmCheckForExternalConflict (
244     char                    *Path);
245
246 static ACPI_STATUS
247 AcpiDmResolveExternal (
248     char                    *Path,
249     UINT8                   Type,
250     ACPI_NAMESPACE_NODE     **Node);
251
252
253 static void
254 AcpiDmConflictingDeclaration (
255     char                    *Path);
256
257
258 /*******************************************************************************
259  *
260  * FUNCTION:    AcpiDmGetObjectTypeName
261  *
262  * PARAMETERS:  Type                - An ACPI_OBJECT_TYPE
263  *
264  * RETURN:      Pointer to a string
265  *
266  * DESCRIPTION: Map an object type to the ASL object type string.
267  *
268  ******************************************************************************/
269
270 static const char *
271 AcpiDmGetObjectTypeName (
272     ACPI_OBJECT_TYPE        Type)
273 {
274
275     if (Type == ACPI_TYPE_LOCAL_SCOPE)
276     {
277         Type = ACPI_TYPE_DEVICE;
278     }
279     else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
280     {
281         return ("");
282     }
283
284     return (AcpiGbl_DmTypeNames[Type]);
285 }
286
287
288 /*******************************************************************************
289  *
290  * FUNCTION:    AcpiDmNormalizeParentPrefix
291  *
292  * PARAMETERS:  Op                  - Parse op
293  *              Path                - Path with parent prefix
294  *
295  * RETURN:      The full pathname to the object (from the namespace root)
296  *
297  * DESCRIPTION: Returns the full pathname of a path with parent prefix
298  *              The caller must free the fullpath returned.
299  *
300  ******************************************************************************/
301
302 static char *
303 AcpiDmNormalizeParentPrefix (
304     ACPI_PARSE_OBJECT       *Op,
305     char                    *Path)
306 {
307     ACPI_NAMESPACE_NODE     *Node;
308     char                    *Fullpath;
309     char                    *ParentPath;
310     ACPI_SIZE               Length;
311     UINT32                  Index = 0;
312
313
314     if (!Op)
315     {
316         return (NULL);
317     }
318
319     /* Search upwards in the parse tree until we reach the next namespace node */
320
321     Op = Op->Common.Parent;
322     while (Op)
323     {
324         if (Op->Common.Node)
325         {
326             break;
327         }
328
329         Op = Op->Common.Parent;
330     }
331
332     if (!Op)
333     {
334         return (NULL);
335     }
336
337     /*
338      * Find the actual parent node for the reference:
339      * Remove all carat prefixes from the input path.
340      * There may be multiple parent prefixes (For example, ^^^M000)
341      */
342     Node = Op->Common.Node;
343     while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
344     {
345         Node = Node->Parent;
346         Path++;
347     }
348
349     if (!Node)
350     {
351         return (NULL);
352     }
353
354     /* Get the full pathname for the parent node */
355
356     ParentPath = AcpiNsGetExternalPathname (Node);
357     if (!ParentPath)
358     {
359         return (NULL);
360     }
361
362     Length = (strlen (ParentPath) + strlen (Path) + 1);
363     if (ParentPath[1])
364     {
365         /*
366          * If ParentPath is not just a simple '\', increment the length
367          * for the required dot separator (ParentPath.Path)
368          */
369         Length++;
370
371         /* For External() statements, we do not want a leading '\' */
372
373         if (*ParentPath == AML_ROOT_PREFIX)
374         {
375             Index = 1;
376         }
377     }
378
379     Fullpath = ACPI_ALLOCATE_ZEROED (Length);
380     if (!Fullpath)
381     {
382         goto Cleanup;
383     }
384
385     /*
386      * Concatenate parent fullpath and path. For example,
387      * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
388      *
389      * Copy the parent path
390      */
391     strcpy (Fullpath, &ParentPath[Index]);
392
393     /*
394      * Add dot separator
395      * (don't need dot if parent fullpath is a single backslash)
396      */
397     if (ParentPath[1])
398     {
399         strcat (Fullpath, ".");
400     }
401
402     /* Copy child path (carat parent prefix(es) were skipped above) */
403
404     strcat (Fullpath, Path);
405
406 Cleanup:
407     ACPI_FREE (ParentPath);
408     return (Fullpath);
409 }
410
411
412 /*******************************************************************************
413  *
414  * FUNCTION:    AcpiDmAddToExternalFileList
415  *
416  * PARAMETERS:  PathList            - Single path or list separated by comma
417  *
418  * RETURN:      None
419  *
420  * DESCRIPTION: Add external files to global list
421  *
422  ******************************************************************************/
423
424 ACPI_STATUS
425 AcpiDmAddToExternalFileList (
426     char                    *Pathname)
427 {
428     ACPI_EXTERNAL_FILE      *ExternalFile;
429     char                    *LocalPathname;
430
431
432     if (!Pathname)
433     {
434         return (AE_OK);
435     }
436
437     LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
438     if (!LocalPathname)
439     {
440         return (AE_NO_MEMORY);
441     }
442
443     ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
444     if (!ExternalFile)
445     {
446         ACPI_FREE (LocalPathname);
447         return (AE_NO_MEMORY);
448     }
449
450     /* Take a copy of the file pathname */
451
452     strcpy (LocalPathname, Pathname);
453     ExternalFile->Path = LocalPathname;
454
455     if (AcpiGbl_ExternalFileList)
456     {
457         ExternalFile->Next = AcpiGbl_ExternalFileList;
458     }
459
460     AcpiGbl_ExternalFileList = ExternalFile;
461     return (AE_OK);
462 }
463
464
465 /*******************************************************************************
466  *
467  * FUNCTION:    AcpiDmClearExternalFileList
468  *
469  * PARAMETERS:  None
470  *
471  * RETURN:      None
472  *
473  * DESCRIPTION: Clear the external file list
474  *
475  ******************************************************************************/
476
477 void
478 AcpiDmClearExternalFileList (
479     void)
480 {
481     ACPI_EXTERNAL_FILE      *NextExternal;
482
483
484     while (AcpiGbl_ExternalFileList)
485     {
486         NextExternal = AcpiGbl_ExternalFileList->Next;
487         ACPI_FREE (AcpiGbl_ExternalFileList->Path);
488         ACPI_FREE (AcpiGbl_ExternalFileList);
489         AcpiGbl_ExternalFileList = NextExternal;
490     }
491 }
492
493
494 /*******************************************************************************
495  *
496  * FUNCTION:    AcpiDmGetExternalsFromFile
497  *
498  * PARAMETERS:  None
499  *
500  * RETURN:      None
501  *
502  * DESCRIPTION: Process the optional external reference file.
503  *
504  * Each line in the file should be of the form:
505  *      External (<Method namepath>, MethodObj, <ArgCount>)
506  *
507  * Example:
508  *      External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
509  *
510  ******************************************************************************/
511
512 void
513 AcpiDmGetExternalsFromFile (
514     void)
515 {
516     FILE                    *ExternalRefFile;
517     char                    *Token;
518     char                    *MethodName;
519     UINT32                  ArgCount;
520     UINT32                  ImportCount = 0;
521
522
523     if (!AslGbl_ExternalRefFilename)
524     {
525         return;
526     }
527
528     /* Open the file */
529
530     ExternalRefFile = fopen (AslGbl_ExternalRefFilename, "r");
531     if (!ExternalRefFile)
532     {
533         fprintf (stderr, "Could not open external reference file \"%s\"\n",
534             AslGbl_ExternalRefFilename);
535         AslAbort ();
536         return;
537     }
538
539     /* Each line defines a method */
540
541     while (fgets (AslGbl_StringBuffer, ASL_STRING_BUFFER_SIZE, ExternalRefFile))
542     {
543         Token = strtok (AslGbl_StringBuffer, METHOD_SEPARATORS);   /* "External" */
544         if (!Token)
545         {
546             continue;
547         }
548
549         if (strcmp (Token, "External"))
550         {
551             continue;
552         }
553
554         MethodName = strtok (NULL, METHOD_SEPARATORS);      /* Method namepath */
555         if (!MethodName)
556         {
557             continue;
558         }
559
560         Token = strtok (NULL, METHOD_SEPARATORS);           /* "MethodObj" */
561         if (!Token)
562         {
563             continue;
564         }
565
566         if (strcmp (Token, "MethodObj"))
567         {
568             continue;
569         }
570
571         Token = strtok (NULL, METHOD_SEPARATORS);           /* Arg count */
572         if (!Token)
573         {
574             continue;
575         }
576
577         /* Convert arg count string to an integer */
578
579         errno = 0;
580         ArgCount = strtoul (Token, NULL, 0);
581         if (errno)
582         {
583             fprintf (stderr, "Invalid argument count (%s)\n", Token);
584             continue;
585         }
586
587         if (ArgCount > 7)
588         {
589             fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
590             continue;
591         }
592
593         /* Add this external to the global list */
594
595         AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
596             AslGbl_ExternalRefFilename, ArgCount, MethodName);
597
598         AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
599             ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
600         ImportCount++;
601     }
602
603     if (!ImportCount)
604     {
605         fprintf (stderr,
606             "Did not find any external methods in reference file \"%s\"\n",
607             AslGbl_ExternalRefFilename);
608     }
609     else
610     {
611         /* Add the external(s) to the namespace */
612
613         AcpiDmAddExternalListToNamespace ();
614
615         AcpiOsPrintf ("%s: Imported %u external method definitions\n",
616             AslGbl_ExternalRefFilename, ImportCount);
617     }
618
619     fclose (ExternalRefFile);
620 }
621
622
623 /*******************************************************************************
624  *
625  * FUNCTION:    AcpiDmAddOpToExternalList
626  *
627  * PARAMETERS:  Op                  - Current parser Op
628  *              Path                - Internal (AML) path to the object
629  *              Type                - ACPI object type to be added
630  *              Value               - Arg count if adding a Method object
631  *              Flags               - To be passed to the external object
632  *
633  * RETURN:      None
634  *
635  * DESCRIPTION: Insert a new name into the global list of Externals which
636  *              will in turn be later emitted as an External() declaration
637  *              in the disassembled output.
638  *
639  *              This function handles the most common case where the referenced
640  *              name is simply not found in the constructed namespace.
641  *
642  ******************************************************************************/
643
644 void
645 AcpiDmAddOpToExternalList (
646     ACPI_PARSE_OBJECT       *Op,
647     char                    *Path,
648     UINT8                   Type,
649     UINT32                  Value,
650     UINT16                  Flags)
651 {
652     char                    *ExternalPath;
653     char                    *InternalPath = Path;
654     char                    *Temp;
655     ACPI_STATUS             Status;
656
657
658     ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
659
660
661     if (!Path)
662     {
663         return_VOID;
664     }
665
666     /* Remove a root backslash if present */
667
668     if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
669     {
670         Path++;
671     }
672
673     /* Externalize the pathname */
674
675     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
676         NULL, &ExternalPath);
677     if (ACPI_FAILURE (Status))
678     {
679         return_VOID;
680     }
681
682     /*
683      * Get the full pathname from the root if "Path" has one or more
684      * parent prefixes (^). Note: path will not contain a leading '\'.
685      */
686     if (*Path == (UINT8) AML_PARENT_PREFIX)
687     {
688         Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
689
690         /* Set new external path */
691
692         ACPI_FREE (ExternalPath);
693         ExternalPath = Temp;
694         if (!Temp)
695         {
696             return_VOID;
697         }
698
699         /* Create the new internal pathname */
700
701         Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
702         Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
703         if (ACPI_FAILURE (Status))
704         {
705             ACPI_FREE (ExternalPath);
706             return_VOID;
707         }
708     }
709
710     /* Create the new External() declaration node */
711
712     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
713         Type, Value, Flags);
714     if (ACPI_FAILURE (Status))
715     {
716         ACPI_FREE (ExternalPath);
717         if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
718         {
719             ACPI_FREE (InternalPath);
720         }
721     }
722
723     return_VOID;
724 }
725
726
727 /*******************************************************************************
728  *
729  * FUNCTION:    AcpiDmGetExternalAndInternalPath
730  *
731  * PARAMETERS:  Node                - Namespace node for object to be added
732  *              ExternalPath        - Will contain the external path of the node
733  *              InternalPath        - Will contain the internal path of the node
734  *
735  * RETURN:      None
736  *
737  * DESCRIPTION: Get the External and Internal path from the given node.
738  *
739  ******************************************************************************/
740
741 static ACPI_STATUS
742 AcpiDmGetExternalAndInternalPath (
743     ACPI_NAMESPACE_NODE     *Node,
744     char                    **ExternalPath,
745     char                    **InternalPath)
746 {
747     ACPI_STATUS             Status;
748
749
750     if (!Node)
751     {
752         return (AE_BAD_PARAMETER);
753     }
754
755     /* Get the full external and internal pathnames to the node */
756
757     *ExternalPath = AcpiNsGetExternalPathname (Node);
758     if (!*ExternalPath)
759     {
760         return (AE_BAD_PATHNAME);
761     }
762
763     Status = AcpiNsInternalizeName (*ExternalPath, InternalPath);
764     if (ACPI_FAILURE (Status))
765     {
766         ACPI_FREE (*ExternalPath);
767         return (Status);
768     }
769
770     return (AE_OK);
771 }
772
773
774 /*******************************************************************************
775  *
776  * FUNCTION:    AcpiDmRemoveRootPrefix
777  *
778  * PARAMETERS:  Path                - Remove Root prefix from this Path
779  *
780  * RETURN:      None
781  *
782  * DESCRIPTION: Remove the root prefix character '\' from Path.
783  *
784  ******************************************************************************/
785
786 static ACPI_STATUS
787 AcpiDmRemoveRootPrefix (
788     char                    **Path)
789 {
790     char                    *InputPath = *Path;
791
792
793     if ((*InputPath == AML_ROOT_PREFIX) && (InputPath[1]))
794     {
795         if (!memmove(InputPath, InputPath+1, strlen(InputPath)))
796         {
797             return (AE_ERROR);
798         }
799
800         *Path = InputPath;
801     }
802
803     return (AE_OK);
804 }
805
806
807 /*******************************************************************************
808  *
809  * FUNCTION:    AcpiDmAddNodeToExternalList
810  *
811  * PARAMETERS:  Node                - Namespace node for object to be added
812  *              Type                - ACPI object type to be added
813  *              Value               - Arg count if adding a Method object
814  *              Flags               - To be passed to the external object
815  *
816  * RETURN:      None
817  *
818  * DESCRIPTION: Insert a new name into the global list of Externals which
819  *              will in turn be later emitted as an External() declaration
820  *              in the disassembled output.
821  *
822  *              This function handles the case where the referenced name has
823  *              been found in the namespace, but the name originated in a
824  *              table other than the one that is being disassembled (such
825  *              as a table that is added via the iASL -e option).
826  *
827  ******************************************************************************/
828
829 void
830 AcpiDmAddNodeToExternalList (
831     ACPI_NAMESPACE_NODE     *Node,
832     UINT8                   Type,
833     UINT32                  Value,
834     UINT16                  Flags)
835 {
836     char                    *ExternalPath;
837     char                    *InternalPath;
838     ACPI_STATUS             Status;
839
840
841     ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
842
843     /* Get the full external and internal pathnames to the node */
844
845     Status = AcpiDmGetExternalAndInternalPath (Node, &ExternalPath, &InternalPath);
846     if (ACPI_FAILURE (Status))
847     {
848         return_VOID;
849     }
850
851     /* Remove the root backslash */
852
853     Status = AcpiDmRemoveRootPrefix (&ExternalPath);
854     if (ACPI_FAILURE (Status))
855     {
856         ACPI_FREE (ExternalPath);
857         ACPI_FREE (InternalPath);
858         return_VOID;
859     }
860
861     /* Create the new External() declaration node */
862
863     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
864         Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
865     if (ACPI_FAILURE (Status))
866     {
867         ACPI_FREE (ExternalPath);
868         ACPI_FREE (InternalPath);
869     }
870
871     return_VOID;
872 }
873
874
875 /*******************************************************************************
876  *
877  * FUNCTION:    AcpiDmAddPathToExternalList
878  *
879  * PARAMETERS:  Path                - External name of the object to be added
880  *              Type                - ACPI object type to be added
881  *              Value               - Arg count if adding a Method object
882  *              Flags               - To be passed to the external object
883  *
884  * RETURN:      None
885  *
886  * DESCRIPTION: Insert a new name into the global list of Externals which
887  *              will in turn be later emitted as an External() declaration
888  *              in the disassembled output.
889  *
890  *              This function currently is used to add externals via a
891  *              reference file (via the -fe iASL option).
892  *
893  ******************************************************************************/
894
895 static void
896 AcpiDmAddPathToExternalList (
897     char                    *Path,
898     UINT8                   Type,
899     UINT32                  Value,
900     UINT16                  Flags)
901 {
902     char                    *InternalPath;
903     char                    *ExternalPath;
904     ACPI_STATUS             Status;
905
906
907     ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
908
909
910     if (!Path)
911     {
912         return_VOID;
913     }
914
915     /* Remove a root backslash if present */
916
917     if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
918     {
919         Path++;
920     }
921
922     /* Create the internal and external pathnames */
923
924     Status = AcpiNsInternalizeName (Path, &InternalPath);
925     if (ACPI_FAILURE (Status))
926     {
927         return_VOID;
928     }
929
930     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
931         NULL, &ExternalPath);
932     if (ACPI_FAILURE (Status))
933     {
934         ACPI_FREE (InternalPath);
935         return_VOID;
936     }
937
938     /* Create the new External() declaration node */
939
940     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
941         Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
942     if (ACPI_FAILURE (Status))
943     {
944         ACPI_FREE (ExternalPath);
945         ACPI_FREE (InternalPath);
946     }
947
948     return_VOID;
949 }
950
951
952 /*******************************************************************************
953  *
954  * FUNCTION:    AcpiDmCreateNewExternal
955  *
956  * PARAMETERS:  ExternalPath        - External path to the object
957  *              InternalPath        - Internal (AML) path to the object
958  *              Type                - ACPI object type to be added
959  *              Value               - Arg count if adding a Method object
960  *              Flags               - To be passed to the external object
961  *
962  * RETURN:      Status
963  *
964  * DESCRIPTION: Common low-level function to insert a new name into the global
965  *              list of Externals which will in turn be later emitted as
966  *              External() declarations in the disassembled output.
967  *
968  *              Note: The external name should not include a root prefix
969  *              (backslash). We do not want External() statements to contain
970  *              a leading '\', as this prevents duplicate external statements
971  *              of the form:
972  *
973  *                  External (\ABCD)
974  *                  External (ABCD)
975  *
976  *              This would cause a compile time error when the disassembled
977  *              output file is recompiled.
978  *
979  *              There are two cases that are handled here. For both, we emit
980  *              an External() statement:
981  *              1) The name was simply not found in the namespace.
982  *              2) The name was found, but it originated in a table other than
983  *              the table that is being disassembled.
984  *
985  ******************************************************************************/
986
987 static ACPI_STATUS
988 AcpiDmCreateNewExternal (
989     char                    *ExternalPath,
990     char                    *InternalPath,
991     UINT8                   Type,
992     UINT32                  Value,
993     UINT16                  Flags)
994 {
995     ACPI_EXTERNAL_LIST      *NewExternal;
996     ACPI_EXTERNAL_LIST      *NextExternal;
997     ACPI_EXTERNAL_LIST      *PrevExternal = NULL;
998
999
1000     ACPI_FUNCTION_TRACE (DmCreateNewExternal);
1001
1002
1003     /* Check all existing externals to ensure no duplicates */
1004
1005     NextExternal = AcpiGbl_ExternalList;
1006     while (NextExternal)
1007     {
1008         /* Check for duplicates */
1009
1010         if (!strcmp (ExternalPath, NextExternal->Path))
1011         {
1012             /*
1013              * If this external came from an External() opcode, we are
1014              * finished with this one. (No need to check any further).
1015              */
1016             if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)
1017             {
1018                 return_ACPI_STATUS (AE_ALREADY_EXISTS);
1019             }
1020
1021             /* Allow upgrade of type from ANY */
1022
1023             else if ((NextExternal->Type == ACPI_TYPE_ANY) &&
1024                 (Type != ACPI_TYPE_ANY))
1025             {
1026                 NextExternal->Type = Type;
1027             }
1028
1029             /* Update the argument count as necessary */
1030
1031             if (Value < NextExternal->Value)
1032             {
1033                 NextExternal->Value = Value;
1034             }
1035
1036             /* Update flags. */
1037
1038             NextExternal->Flags |= Flags;
1039             NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED;
1040
1041             return_ACPI_STATUS (AE_ALREADY_EXISTS);
1042         }
1043
1044         NextExternal = NextExternal->Next;
1045     }
1046
1047     /* Allocate and init a new External() descriptor */
1048
1049     NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
1050     if (!NewExternal)
1051     {
1052         return_ACPI_STATUS (AE_NO_MEMORY);
1053     }
1054
1055     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
1056         "Adding external reference node (%s) type [%s]\n",
1057         ExternalPath, AcpiUtGetTypeName (Type)));
1058
1059     NewExternal->Flags = Flags;
1060     NewExternal->Value = Value;
1061     NewExternal->Path = ExternalPath;
1062     NewExternal->Type = Type;
1063     NewExternal->Length = (UINT16) strlen (ExternalPath);
1064     NewExternal->InternalPath = InternalPath;
1065
1066     /* Link the new descriptor into the global list, alphabetically ordered */
1067
1068     NextExternal = AcpiGbl_ExternalList;
1069     while (NextExternal)
1070     {
1071         if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
1072         {
1073             if (PrevExternal)
1074             {
1075                 PrevExternal->Next = NewExternal;
1076             }
1077             else
1078             {
1079                 AcpiGbl_ExternalList = NewExternal;
1080             }
1081
1082             NewExternal->Next = NextExternal;
1083             return_ACPI_STATUS (AE_OK);
1084         }
1085
1086         PrevExternal = NextExternal;
1087         NextExternal = NextExternal->Next;
1088     }
1089
1090     if (PrevExternal)
1091     {
1092         PrevExternal->Next = NewExternal;
1093     }
1094     else
1095     {
1096         AcpiGbl_ExternalList = NewExternal;
1097     }
1098
1099     return_ACPI_STATUS (AE_OK);
1100 }
1101
1102
1103 /*******************************************************************************
1104  *
1105  * FUNCTION:    AcpiDmResolveExternal
1106  *
1107  * PARAMETERS:  Path               - Path of the external
1108  *              Type               - Type of the external
1109  *              Node               - Input node for AcpiNsLookup
1110  *
1111  * RETURN:      Status
1112  *
1113  * DESCRIPTION: Resolve the external within the namespace by AcpiNsLookup.
1114  *              If the returned node is an external and has the same type
1115  *              we assume that it was either an existing external or a
1116  *
1117  ******************************************************************************/
1118
1119 static ACPI_STATUS
1120 AcpiDmResolveExternal (
1121     char                    *Path,
1122     UINT8                   Type,
1123     ACPI_NAMESPACE_NODE     **Node)
1124 {
1125     ACPI_STATUS             Status;
1126
1127
1128     Status = AcpiNsLookup (NULL, Path, Type,
1129         ACPI_IMODE_LOAD_PASS1,
1130         ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
1131         NULL, Node);
1132
1133     if (!Node)
1134     {
1135         ACPI_EXCEPTION ((AE_INFO, Status,
1136             "while adding external to namespace [%s]", Path));
1137     }
1138
1139     /* Note the asl code "external(a) external(a)" is acceptable ASL */
1140
1141     else if ((*Node)->Type == Type &&
1142         (*Node)->Flags & ANOBJ_IS_EXTERNAL)
1143     {
1144         return (AE_OK);
1145     }
1146     else
1147     {
1148         ACPI_EXCEPTION ((AE_INFO, AE_ERROR,
1149             "[%s] has conflicting declarations", Path));
1150     }
1151
1152     return (AE_ERROR);
1153 }
1154
1155
1156 /*******************************************************************************
1157  *
1158  * FUNCTION:    AcpiDmCreateSubobjectForExternal
1159  *
1160  * PARAMETERS:  Type                  - Type of the external
1161  *              Node                  - Namespace node from AcpiNsLookup
1162  *              ParamCount            - Value to be used for Method
1163  *
1164  * RETURN:      None
1165  *
1166  * DESCRIPTION: Add one external to the namespace. Allows external to be
1167  *              "resolved".
1168  *
1169  ******************************************************************************/
1170
1171 void
1172 AcpiDmCreateSubobjectForExternal (
1173     UINT8                   Type,
1174     ACPI_NAMESPACE_NODE     **Node,
1175     UINT32                  ParamCount)
1176 {
1177     ACPI_OPERAND_OBJECT     *ObjDesc;
1178
1179
1180     switch (Type)
1181     {
1182     case ACPI_TYPE_METHOD:
1183
1184         /* For methods, we need to save the argument count */
1185
1186         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
1187         ObjDesc->Method.ParamCount = (UINT8) ParamCount;
1188         (*Node)->Object = ObjDesc;
1189         break;
1190
1191     case ACPI_TYPE_REGION:
1192
1193         /* Regions require a region sub-object */
1194
1195         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
1196         ObjDesc->Region.Node = *Node;
1197         (*Node)->Object = ObjDesc;
1198         break;
1199
1200     default:
1201
1202         break;
1203     }
1204 }
1205
1206
1207 /*******************************************************************************
1208  *
1209  * FUNCTION:    AcpiDmAddOneExternalToNamespace
1210  *
1211  * PARAMETERS:  Path                   - External parse object
1212  *              Type                   - Type of parse object
1213  *              ParamCount             - External method parameter count
1214  *
1215  * RETURN:      None
1216  *
1217  * DESCRIPTION: Add one external to the namespace by resolvign the external
1218  *              (by performing a namespace lookup) and annotating the resulting
1219  *              namespace node with the appropriate information if the type
1220  *              is ACPI_TYPE_REGION or ACPI_TYPE_METHOD.
1221  *
1222  ******************************************************************************/
1223
1224 void
1225 AcpiDmAddOneExternalToNamespace (
1226     char                    *Path,
1227     UINT8                   Type,
1228     UINT32                  ParamCount)
1229 {
1230     ACPI_STATUS             Status;
1231     ACPI_NAMESPACE_NODE     *Node;
1232
1233
1234     Status = AcpiDmResolveExternal (Path, Type, &Node);
1235
1236     if (ACPI_FAILURE (Status))
1237     {
1238         return;
1239     }
1240
1241     AcpiDmCreateSubobjectForExternal (Type, &Node, ParamCount);
1242
1243 }
1244
1245
1246 /*******************************************************************************
1247  *
1248  * FUNCTION:    AcpiDmAddExternalListToNamespace
1249  *
1250  * PARAMETERS:  None
1251  *
1252  * RETURN:      None
1253  *
1254  * DESCRIPTION: Add all externals within AcpiGbl_ExternalList to the namespace.
1255  *              Allows externals to be "resolved".
1256  *
1257  ******************************************************************************/
1258
1259 void
1260 AcpiDmAddExternalListToNamespace (
1261     void)
1262 {
1263     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
1264
1265
1266     while (External)
1267     {
1268         AcpiDmAddOneExternalToNamespace (External->InternalPath,
1269             External->Type, External->Value);
1270         External = External->Next;
1271     }
1272 }
1273
1274
1275 /*******************************************************************************
1276  *
1277  * FUNCTION:    AcpiDmGetUnresolvedExternalMethodCount
1278  *
1279  * PARAMETERS:  None
1280  *
1281  * RETURN:      The number of unresolved control method externals in the
1282  *              external list
1283  *
1284  * DESCRIPTION: Return the number of unresolved external methods that have been
1285  *              generated. If any unresolved control method externals have been
1286  *              found, we must re-parse the entire definition block with the new
1287  *              information (number of arguments for the methods.)
1288  *              This is limitation of AML, we don't know the number of arguments
1289  *              from the control method invocation itself.
1290  *
1291  *              Note: resolved external control methods are external control
1292  *              methods encoded with the AML_EXTERNAL_OP bytecode within the
1293  *              AML being disassembled.
1294  *
1295  ******************************************************************************/
1296
1297 UINT32
1298 AcpiDmGetUnresolvedExternalMethodCount (
1299     void)
1300 {
1301     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
1302     UINT32                  Count = 0;
1303
1304
1305     while (External)
1306     {
1307         if (External->Type == ACPI_TYPE_METHOD &&
1308             !(External->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE))
1309         {
1310             Count++;
1311         }
1312
1313         External = External->Next;
1314     }
1315
1316     return (Count);
1317 }
1318
1319
1320 /*******************************************************************************
1321  *
1322  * FUNCTION:    AcpiDmClearExternalList
1323  *
1324  * PARAMETERS:  None
1325  *
1326  * RETURN:      None
1327  *
1328  * DESCRIPTION: Free the entire External info list
1329  *
1330  ******************************************************************************/
1331
1332 void
1333 AcpiDmClearExternalList (
1334     void)
1335 {
1336     ACPI_EXTERNAL_LIST      *NextExternal;
1337
1338
1339     while (AcpiGbl_ExternalList)
1340     {
1341         NextExternal = AcpiGbl_ExternalList->Next;
1342         ACPI_FREE (AcpiGbl_ExternalList->Path);
1343         ACPI_FREE (AcpiGbl_ExternalList);
1344         AcpiGbl_ExternalList = NextExternal;
1345     }
1346 }
1347
1348
1349 /*******************************************************************************
1350  *
1351  * FUNCTION:    AcpiDmEmitExternals
1352  *
1353  * PARAMETERS:  None
1354  *
1355  * RETURN:      None
1356  *
1357  * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1358  *              the global external info list.
1359  *
1360  ******************************************************************************/
1361
1362 void
1363 AcpiDmEmitExternals (
1364     void)
1365 {
1366     ACPI_EXTERNAL_LIST      *NextExternal;
1367
1368
1369     if (!AcpiGbl_ExternalList)
1370     {
1371         return;
1372     }
1373
1374     /*
1375      * Determine the number of control methods in the external list, and
1376      * also how many of those externals were resolved via the namespace.
1377      */
1378     NextExternal = AcpiGbl_ExternalList;
1379     while (NextExternal)
1380     {
1381         if (NextExternal->Type == ACPI_TYPE_METHOD)
1382         {
1383             AcpiGbl_NumExternalMethods++;
1384             if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1385             {
1386                 AcpiGbl_ResolvedExternalMethods++;
1387             }
1388         }
1389
1390         NextExternal = NextExternal->Next;
1391     }
1392
1393     /* Check if any control methods were unresolved */
1394
1395     AcpiDmUnresolvedWarning (1);
1396
1397     if (AslGbl_ExternalRefFilename)
1398     {
1399         AcpiOsPrintf (
1400             "    /*\n     * External declarations were imported from\n"
1401             "     * a reference file -- %s\n     */\n\n",
1402             AslGbl_ExternalRefFilename);
1403     }
1404
1405     /*
1406      * Walk and emit the list of externals found during the AML parsing
1407      */
1408     while (AcpiGbl_ExternalList)
1409     {
1410         if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1411         {
1412             AcpiOsPrintf ("    External (%s%s)",
1413                 AcpiGbl_ExternalList->Path,
1414                 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1415
1416             /* Check for "unresolved" method reference */
1417
1418             if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) &&
1419                 (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1420             {
1421                 AcpiOsPrintf ("    // Warning: Unknown method, "
1422                     "guessing %u arguments",
1423                     AcpiGbl_ExternalList->Value);
1424             }
1425
1426             /* Check for external from a external references file */
1427
1428             else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE)
1429             {
1430                 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1431                 {
1432                     AcpiOsPrintf ("    // %u Arguments",
1433                         AcpiGbl_ExternalList->Value);
1434                 }
1435
1436                 AcpiOsPrintf ("    // From external reference file");
1437             }
1438
1439             /* This is the normal external case */
1440
1441             else
1442             {
1443                 /* For methods, add a comment with the number of arguments */
1444
1445                 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1446                 {
1447                     AcpiOsPrintf ("    // %u Arguments",
1448                         AcpiGbl_ExternalList->Value);
1449                 }
1450             }
1451
1452             if (AcpiGbl_ExternalList->Flags &= ACPI_EXT_CONFLICTING_DECLARATION)
1453             {
1454                 AcpiOsPrintf ("%s", ExternalConflictMessage);
1455                 AcpiDmConflictingDeclaration (AcpiGbl_ExternalList->Path);
1456             }
1457             AcpiOsPrintf ("\n");
1458         }
1459
1460         /* Free this external info block and move on to next external */
1461
1462         NextExternal = AcpiGbl_ExternalList->Next;
1463         if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1464         {
1465             ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1466         }
1467
1468         ACPI_FREE (AcpiGbl_ExternalList->Path);
1469         ACPI_FREE (AcpiGbl_ExternalList);
1470         AcpiGbl_ExternalList = NextExternal;
1471     }
1472
1473     AcpiOsPrintf ("\n");
1474 }
1475
1476
1477 /*******************************************************************************
1478  *
1479  * FUNCTION:    AcpiDmMarkExternalConflict
1480  *
1481  * PARAMETERS:  Path          - Namepath to search
1482  *
1483  * RETURN:      ExternalList
1484  *
1485  * DESCRIPTION: Search the AcpiGbl_ExternalList for a matching path
1486  *
1487  ******************************************************************************/
1488
1489 void
1490 AcpiDmMarkExternalConflict (
1491     ACPI_NAMESPACE_NODE     *Node)
1492 {
1493     ACPI_EXTERNAL_LIST      *ExternalList = AcpiGbl_ExternalList;
1494     char                    *ExternalPath;
1495     char                    *InternalPath;
1496     char                    *Temp;
1497     ACPI_STATUS             Status;
1498
1499
1500     ACPI_FUNCTION_TRACE (DmMarkExternalConflict);
1501
1502
1503     if (Node->Flags & ANOBJ_IS_EXTERNAL)
1504     {
1505         return_VOID;
1506     }
1507
1508     /* Get the full external and internal pathnames to the node */
1509
1510     Status = AcpiDmGetExternalAndInternalPath (Node,
1511         &ExternalPath, &InternalPath);
1512     if (ACPI_FAILURE (Status))
1513     {
1514         return_VOID;
1515     }
1516
1517     /* Remove the root backslash */
1518
1519     Status = AcpiDmRemoveRootPrefix (&InternalPath);
1520     if (ACPI_FAILURE (Status))
1521     {
1522         ACPI_FREE (InternalPath);
1523         ACPI_FREE (ExternalPath);
1524         return_VOID;
1525     }
1526
1527     while (ExternalList)
1528     {
1529         Temp = ExternalList->InternalPath;
1530         if ((*ExternalList->InternalPath == AML_ROOT_PREFIX) &&
1531             (ExternalList->InternalPath[1]))
1532         {
1533             Temp++;
1534         }
1535
1536         if (!strcmp (ExternalList->InternalPath, InternalPath))
1537         {
1538             ExternalList->Flags |= ACPI_EXT_CONFLICTING_DECLARATION;
1539         }
1540         ExternalList = ExternalList->Next;
1541     }
1542
1543     ACPI_FREE (InternalPath);
1544     ACPI_FREE (ExternalPath);
1545
1546     return_VOID;
1547 }
1548
1549
1550 /*******************************************************************************
1551  *
1552  * FUNCTION:    AcpiDmConflictingDeclaration
1553  *
1554  * PARAMETERS:  Path                - Path with conflicting declaration
1555  *
1556  * RETURN:      None
1557  *
1558  * DESCRIPTION: Emit a warning when printing conflicting ASL external
1559  *              declarations.
1560  *
1561  ******************************************************************************/
1562
1563 static void
1564 AcpiDmConflictingDeclaration (
1565     char                    *Path)
1566 {
1567     fprintf (stderr,
1568         " Warning - Emitting ASL code \"External (%s)\"\n"
1569         "           This is a conflicting declaration with some "
1570         "other declaration within the ASL code.\n"
1571         "           This external declaration may need to be "
1572         "deleted in order to recompile the dsl file.\n\n",
1573         Path);
1574 }
1575
1576
1577 /*******************************************************************************
1578  *
1579  * FUNCTION:    AcpiDmEmitExternal
1580  *
1581  * PARAMETERS:  Op                  External Parse Object
1582  *
1583  * RETURN:      None
1584  *
1585  * DESCRIPTION: Emit an External() ASL statement for the current External
1586  *              parse object. Note: External Ops are named types so the
1587  *              namepath is contained within NameOp->Name.Path.
1588  *
1589  ******************************************************************************/
1590
1591 void
1592 AcpiDmEmitExternal (
1593     ACPI_PARSE_OBJECT       *NameOp,
1594     ACPI_PARSE_OBJECT       *TypeOp)
1595 {
1596     AcpiOsPrintf ("External (");
1597     AcpiDmNamestring (NameOp->Named.Path);
1598     AcpiOsPrintf ("%s)",
1599         AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer));
1600     AcpiDmCheckForExternalConflict (NameOp->Named.Path);
1601     AcpiOsPrintf ("\n");
1602 }
1603
1604
1605 /*******************************************************************************
1606  *
1607  * FUNCTION:    AcpiDmCheckForExternalConflict
1608  *
1609  * PARAMETERS:  Path                - Path to check
1610  *
1611  * RETURN:      None
1612  *
1613  * DESCRIPTION: Search the External List to see if the input Path has a
1614  *              conflicting declaration.
1615  *
1616  ******************************************************************************/
1617
1618 static void
1619 AcpiDmCheckForExternalConflict (
1620     char                    *Path)
1621 {
1622     ACPI_EXTERNAL_LIST      *ExternalList = AcpiGbl_ExternalList;
1623     char                    *ListItemPath;
1624     char                    *InputPath;
1625
1626
1627     if (!Path)
1628     {
1629         return;
1630     }
1631
1632     /* Move past the root prefix '\' */
1633
1634     InputPath = Path;
1635     if ((*InputPath == AML_ROOT_PREFIX) && InputPath[1])
1636     {
1637         InputPath++;
1638     }
1639
1640     while (ExternalList)
1641     {
1642         ListItemPath = ExternalList->Path;
1643         if (ListItemPath)
1644         {
1645             /* Move past the root prefix '\' */
1646
1647             if ((*ListItemPath == AML_ROOT_PREFIX) &&
1648                 ListItemPath[1])
1649             {
1650                 ListItemPath++;
1651             }
1652
1653             if (!strcmp (ListItemPath, InputPath) &&
1654                 (ExternalList->Flags & ACPI_EXT_CONFLICTING_DECLARATION))
1655             {
1656                 AcpiOsPrintf ("%s", ExternalConflictMessage);
1657                 AcpiDmConflictingDeclaration (Path);
1658
1659                 return;
1660             }
1661         }
1662         ExternalList = ExternalList->Next;
1663     }
1664 }
1665 /*******************************************************************************
1666  *
1667  * FUNCTION:    AcpiDmUnresolvedWarning
1668  *
1669  * PARAMETERS:  Type                - Where to output the warning.
1670  *                                    0 means write to stderr
1671  *                                    1 means write to AcpiOsPrintf
1672  *
1673  * RETURN:      None
1674  *
1675  * DESCRIPTION: Issue warning message if there are unresolved external control
1676  *              methods within the disassembly.
1677  *
1678  ******************************************************************************/
1679
1680 /*
1681 Summary of the external control method problem:
1682
1683 When the -e option is used with disassembly, the various SSDTs are simply
1684 loaded into a global namespace for the disassembler to use in order to
1685 resolve control method references (invocations).
1686
1687 The disassembler tracks any such references, and will emit an External()
1688 statement for these types of methods, with the proper number of arguments .
1689
1690 Without the SSDTs, the AML does not contain enough information to properly
1691 disassemble the control method invocation -- because the disassembler does
1692 not know how many arguments to parse.
1693
1694 An example: Assume we have two control methods. ABCD has one argument, and
1695 EFGH has zero arguments. Further, we have two additional control methods
1696 that invoke ABCD and EFGH, named T1 and T2:
1697
1698     Method (ABCD, 1)
1699     {
1700     }
1701     Method (EFGH, 0)
1702     {
1703     }
1704     Method (T1)
1705     {
1706         ABCD (Add (2, 7, Local0))
1707     }
1708     Method (T2)
1709     {
1710         EFGH ()
1711         Add (2, 7, Local0)
1712     }
1713
1714 Here is the AML code that is generated for T1 and T2:
1715
1716      185:      Method (T1)
1717
1718 0000034C:  14 10 54 31 5F 5F 00 ...    "..T1__."
1719
1720      186:      {
1721      187:          ABCD (Add (2, 7, Local0))
1722
1723 00000353:  41 42 43 44 ............    "ABCD"
1724 00000357:  72 0A 02 0A 07 60 ......    "r....`"
1725
1726      188:      }
1727
1728      190:      Method (T2)
1729
1730 0000035D:  14 10 54 32 5F 5F 00 ...    "..T2__."
1731
1732      191:      {
1733      192:          EFGH ()
1734
1735 00000364:  45 46 47 48 ............    "EFGH"
1736
1737      193:          Add (2, 7, Local0)
1738
1739 00000368:  72 0A 02 0A 07 60 ......    "r....`"
1740      194:      }
1741
1742 Note that the AML code for T1 and T2 is essentially identical. When
1743 disassembling this code, the methods ABCD and EFGH must be known to the
1744 disassembler, otherwise it does not know how to handle the method invocations.
1745
1746 In other words, if ABCD and EFGH are actually external control methods
1747 appearing in an SSDT, the disassembler does not know what to do unless
1748 the owning SSDT has been loaded via the -e option.
1749 */
1750
1751 static char             ExternalWarningPart1[600];
1752 static char             ExternalWarningPart2[400];
1753 static char             ExternalWarningPart3[400];
1754 static char             ExternalWarningPart4[200];
1755
1756 void
1757 AcpiDmUnresolvedWarning (
1758     UINT8                   Type)
1759 {
1760     char                    *Format;
1761     char                    Pad[] = "     *";
1762     char                    NoPad[] = "";
1763
1764
1765     if (!AcpiGbl_NumExternalMethods)
1766     {
1767         return;
1768     }
1769
1770     if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
1771     {
1772         return;
1773     }
1774
1775     Format = Type ? Pad : NoPad;
1776
1777     sprintf (ExternalWarningPart1,
1778         "%s iASL Warning: There %s %u external control method%s found during\n"
1779         "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1780         "%s ACPI tables may be required to properly disassemble the code. This\n"
1781         "%s resulting disassembler output file may not compile because the\n"
1782         "%s disassembler did not know how many arguments to assign to the\n"
1783         "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1784         "%s runtime and may or may not be available via the host OS.\n",
1785         Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
1786         AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
1787         Format, AcpiGbl_ResolvedExternalMethods,
1788         (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
1789         (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
1790         Format, Format, Format, Format, Format);
1791
1792     sprintf (ExternalWarningPart2,
1793         "%s To specify the tables needed to resolve external control method\n"
1794         "%s references, the -e option can be used to specify the filenames.\n"
1795         "%s Example iASL invocations:\n"
1796         "%s     iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1797         "%s     iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1798         "%s     iasl -e ssdt*.aml -d dsdt.aml\n",
1799         Format, Format, Format, Format, Format, Format);
1800
1801     sprintf (ExternalWarningPart3,
1802         "%s In addition, the -fe option can be used to specify a file containing\n"
1803         "%s control method external declarations with the associated method\n"
1804         "%s argument counts. Each line of the file must be of the form:\n"
1805         "%s     External (<method pathname>, MethodObj, <argument count>)\n"
1806         "%s Invocation:\n"
1807         "%s     iasl -fe refs.txt -d dsdt.aml\n",
1808         Format, Format, Format, Format, Format, Format);
1809
1810     sprintf (ExternalWarningPart4,
1811         "%s The following methods were unresolved and many not compile properly\n"
1812         "%s because the disassembler had to guess at the number of arguments\n"
1813         "%s required for each:\n",
1814         Format, Format, Format);
1815
1816     if (Type)
1817     {
1818         if (!AcpiGbl_ExternalFileList)
1819         {
1820             /* The -e option was not specified */
1821
1822            AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     *\n%s     */\n",
1823                ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
1824                ExternalWarningPart4);
1825         }
1826         else
1827         {
1828             /* The -e option was specified, but there are still some unresolved externals */
1829
1830             AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     */\n",
1831                ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
1832         }
1833     }
1834     else
1835     {
1836         if (!AcpiGbl_ExternalFileList)
1837         {
1838             /* The -e option was not specified */
1839
1840             fprintf (stderr, "\n%s\n%s\n%s\n",
1841                ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
1842         }
1843         else
1844         {
1845             /* The -e option was specified, but there are still some unresolved externals */
1846
1847             fprintf (stderr, "\n%s\n%s\n",
1848                ExternalWarningPart1, ExternalWarningPart3);
1849         }
1850     }
1851 }