xref: /freebsd/sys/contrib/dev/acpica/common/dmextern.c (revision 56e53cb8ef000c3ef72337a4095987a932cdedef)
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 - 2018, 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 <contrib/dev/acpica/include/acpi.h>
153 #include <contrib/dev/acpica/include/accommon.h>
154 #include <contrib/dev/acpica/include/amlcode.h>
155 #include <contrib/dev/acpica/include/acnamesp.h>
156 #include <contrib/dev/acpica/include/acdisasm.h>
157 #include <contrib/dev/acpica/compiler/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 (!Gbl_ExternalRefFilename)
524     {
525         return;
526     }
527 
528     /* Open the file */
529 
530     ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
531     if (!ExternalRefFile)
532     {
533         fprintf (stderr, "Could not open external reference file \"%s\"\n",
534             Gbl_ExternalRefFilename);
535         AslAbort ();
536         return;
537     }
538 
539     /* Each line defines a method */
540 
541     while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
542     {
543         Token = strtok (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             Gbl_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             Gbl_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             Gbl_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 approperiate 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 (Gbl_ExternalRefFilename)
1398     {
1399         AcpiOsPrintf (
1400             "    /*\n     * External declarations were imported from\n"
1401             "     * a reference file -- %s\n     */\n\n",
1402             Gbl_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 }
1852