xref: /freebsd/sys/contrib/dev/acpica/common/dmextern.c (revision a35f04fba2ebb8f86d4cbdc710c89a094572b08e)
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 - 2017, 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 
203 /* Local prototypes */
204 
205 static const char *
206 AcpiDmGetObjectTypeName (
207     ACPI_OBJECT_TYPE        Type);
208 
209 static char *
210 AcpiDmNormalizeParentPrefix (
211     ACPI_PARSE_OBJECT       *Op,
212     char                    *Path);
213 
214 static void
215 AcpiDmAddPathToExternalList (
216     char                    *Path,
217     UINT8                   Type,
218     UINT32                  Value,
219     UINT16                  Flags);
220 
221 static ACPI_STATUS
222 AcpiDmCreateNewExternal (
223     char                    *ExternalPath,
224     char                    *InternalPath,
225     UINT8                   Type,
226     UINT32                  Value,
227     UINT16                  Flags);
228 
229 
230 /*******************************************************************************
231  *
232  * FUNCTION:    AcpiDmGetObjectTypeName
233  *
234  * PARAMETERS:  Type                - An ACPI_OBJECT_TYPE
235  *
236  * RETURN:      Pointer to a string
237  *
238  * DESCRIPTION: Map an object type to the ASL object type string.
239  *
240  ******************************************************************************/
241 
242 static const char *
243 AcpiDmGetObjectTypeName (
244     ACPI_OBJECT_TYPE        Type)
245 {
246 
247     if (Type == ACPI_TYPE_LOCAL_SCOPE)
248     {
249         Type = ACPI_TYPE_DEVICE;
250     }
251     else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
252     {
253         return ("");
254     }
255 
256     return (AcpiGbl_DmTypeNames[Type]);
257 }
258 
259 
260 /*******************************************************************************
261  *
262  * FUNCTION:    AcpiDmNormalizeParentPrefix
263  *
264  * PARAMETERS:  Op                  - Parse op
265  *              Path                - Path with parent prefix
266  *
267  * RETURN:      The full pathname to the object (from the namespace root)
268  *
269  * DESCRIPTION: Returns the full pathname of a path with parent prefix
270  *              The caller must free the fullpath returned.
271  *
272  ******************************************************************************/
273 
274 static char *
275 AcpiDmNormalizeParentPrefix (
276     ACPI_PARSE_OBJECT       *Op,
277     char                    *Path)
278 {
279     ACPI_NAMESPACE_NODE     *Node;
280     char                    *Fullpath;
281     char                    *ParentPath;
282     ACPI_SIZE               Length;
283     UINT32                  Index = 0;
284 
285 
286     if (!Op)
287     {
288         return (NULL);
289     }
290 
291     /* Search upwards in the parse tree until we reach the next namespace node */
292 
293     Op = Op->Common.Parent;
294     while (Op)
295     {
296         if (Op->Common.Node)
297         {
298             break;
299         }
300 
301         Op = Op->Common.Parent;
302     }
303 
304     if (!Op)
305     {
306         return (NULL);
307     }
308 
309     /*
310      * Find the actual parent node for the reference:
311      * Remove all carat prefixes from the input path.
312      * There may be multiple parent prefixes (For example, ^^^M000)
313      */
314     Node = Op->Common.Node;
315     while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
316     {
317         Node = Node->Parent;
318         Path++;
319     }
320 
321     if (!Node)
322     {
323         return (NULL);
324     }
325 
326     /* Get the full pathname for the parent node */
327 
328     ParentPath = AcpiNsGetExternalPathname (Node);
329     if (!ParentPath)
330     {
331         return (NULL);
332     }
333 
334     Length = (strlen (ParentPath) + strlen (Path) + 1);
335     if (ParentPath[1])
336     {
337         /*
338          * If ParentPath is not just a simple '\', increment the length
339          * for the required dot separator (ParentPath.Path)
340          */
341         Length++;
342 
343         /* For External() statements, we do not want a leading '\' */
344 
345         if (*ParentPath == AML_ROOT_PREFIX)
346         {
347             Index = 1;
348         }
349     }
350 
351     Fullpath = ACPI_ALLOCATE_ZEROED (Length);
352     if (!Fullpath)
353     {
354         goto Cleanup;
355     }
356 
357     /*
358      * Concatenate parent fullpath and path. For example,
359      * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
360      *
361      * Copy the parent path
362      */
363     strcpy (Fullpath, &ParentPath[Index]);
364 
365     /*
366      * Add dot separator
367      * (don't need dot if parent fullpath is a single backslash)
368      */
369     if (ParentPath[1])
370     {
371         strcat (Fullpath, ".");
372     }
373 
374     /* Copy child path (carat parent prefix(es) were skipped above) */
375 
376     strcat (Fullpath, Path);
377 
378 Cleanup:
379     ACPI_FREE (ParentPath);
380     return (Fullpath);
381 }
382 
383 
384 /*******************************************************************************
385  *
386  * FUNCTION:    AcpiDmAddToExternalFileList
387  *
388  * PARAMETERS:  PathList            - Single path or list separated by comma
389  *
390  * RETURN:      None
391  *
392  * DESCRIPTION: Add external files to global list
393  *
394  ******************************************************************************/
395 
396 ACPI_STATUS
397 AcpiDmAddToExternalFileList (
398     char                    *Pathname)
399 {
400     ACPI_EXTERNAL_FILE      *ExternalFile;
401     char                    *LocalPathname;
402 
403 
404     if (!Pathname)
405     {
406         return (AE_OK);
407     }
408 
409     LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
410     if (!LocalPathname)
411     {
412         return (AE_NO_MEMORY);
413     }
414 
415     ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
416     if (!ExternalFile)
417     {
418         ACPI_FREE (LocalPathname);
419         return (AE_NO_MEMORY);
420     }
421 
422     /* Take a copy of the file pathname */
423 
424     strcpy (LocalPathname, Pathname);
425     ExternalFile->Path = LocalPathname;
426 
427     if (AcpiGbl_ExternalFileList)
428     {
429         ExternalFile->Next = AcpiGbl_ExternalFileList;
430     }
431 
432     AcpiGbl_ExternalFileList = ExternalFile;
433     return (AE_OK);
434 }
435 
436 
437 /*******************************************************************************
438  *
439  * FUNCTION:    AcpiDmClearExternalFileList
440  *
441  * PARAMETERS:  None
442  *
443  * RETURN:      None
444  *
445  * DESCRIPTION: Clear the external file list
446  *
447  ******************************************************************************/
448 
449 void
450 AcpiDmClearExternalFileList (
451     void)
452 {
453     ACPI_EXTERNAL_FILE      *NextExternal;
454 
455 
456     while (AcpiGbl_ExternalFileList)
457     {
458         NextExternal = AcpiGbl_ExternalFileList->Next;
459         ACPI_FREE (AcpiGbl_ExternalFileList->Path);
460         ACPI_FREE (AcpiGbl_ExternalFileList);
461         AcpiGbl_ExternalFileList = NextExternal;
462     }
463 }
464 
465 
466 /*******************************************************************************
467  *
468  * FUNCTION:    AcpiDmGetExternalsFromFile
469  *
470  * PARAMETERS:  None
471  *
472  * RETURN:      None
473  *
474  * DESCRIPTION: Process the optional external reference file.
475  *
476  * Each line in the file should be of the form:
477  *      External (<Method namepath>, MethodObj, <ArgCount>)
478  *
479  * Example:
480  *      External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
481  *
482  ******************************************************************************/
483 
484 void
485 AcpiDmGetExternalsFromFile (
486     void)
487 {
488     FILE                    *ExternalRefFile;
489     char                    *Token;
490     char                    *MethodName;
491     UINT32                  ArgCount;
492     UINT32                  ImportCount = 0;
493 
494 
495     if (!Gbl_ExternalRefFilename)
496     {
497         return;
498     }
499 
500     /* Open the file */
501 
502     ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
503     if (!ExternalRefFile)
504     {
505         fprintf (stderr, "Could not open external reference file \"%s\"\n",
506             Gbl_ExternalRefFilename);
507         AslAbort ();
508         return;
509     }
510 
511     /* Each line defines a method */
512 
513     while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
514     {
515         Token = strtok (StringBuffer, METHOD_SEPARATORS);   /* "External" */
516         if (!Token)
517         {
518             continue;
519         }
520 
521         if (strcmp (Token, "External"))
522         {
523             continue;
524         }
525 
526         MethodName = strtok (NULL, METHOD_SEPARATORS);      /* Method namepath */
527         if (!MethodName)
528         {
529             continue;
530         }
531 
532         Token = strtok (NULL, METHOD_SEPARATORS);           /* "MethodObj" */
533         if (!Token)
534         {
535             continue;
536         }
537 
538         if (strcmp (Token, "MethodObj"))
539         {
540             continue;
541         }
542 
543         Token = strtok (NULL, METHOD_SEPARATORS);           /* Arg count */
544         if (!Token)
545         {
546             continue;
547         }
548 
549         /* Convert arg count string to an integer */
550 
551         errno = 0;
552         ArgCount = strtoul (Token, NULL, 0);
553         if (errno)
554         {
555             fprintf (stderr, "Invalid argument count (%s)\n", Token);
556             continue;
557         }
558 
559         if (ArgCount > 7)
560         {
561             fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
562             continue;
563         }
564 
565         /* Add this external to the global list */
566 
567         AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
568             Gbl_ExternalRefFilename, ArgCount, MethodName);
569 
570         AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
571             ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
572         ImportCount++;
573     }
574 
575     if (!ImportCount)
576     {
577         fprintf (stderr,
578             "Did not find any external methods in reference file \"%s\"\n",
579             Gbl_ExternalRefFilename);
580     }
581     else
582     {
583         /* Add the external(s) to the namespace */
584 
585         AcpiDmAddExternalsToNamespace ();
586 
587         AcpiOsPrintf ("%s: Imported %u external method definitions\n",
588             Gbl_ExternalRefFilename, ImportCount);
589     }
590 
591     fclose (ExternalRefFile);
592 }
593 
594 
595 /*******************************************************************************
596  *
597  * FUNCTION:    AcpiDmAddOpToExternalList
598  *
599  * PARAMETERS:  Op                  - Current parser Op
600  *              Path                - Internal (AML) path to the object
601  *              Type                - ACPI object type to be added
602  *              Value               - Arg count if adding a Method object
603  *              Flags               - To be passed to the external object
604  *
605  * RETURN:      None
606  *
607  * DESCRIPTION: Insert a new name into the global list of Externals which
608  *              will in turn be later emitted as an External() declaration
609  *              in the disassembled output.
610  *
611  *              This function handles the most common case where the referenced
612  *              name is simply not found in the constructed namespace.
613  *
614  ******************************************************************************/
615 
616 void
617 AcpiDmAddOpToExternalList (
618     ACPI_PARSE_OBJECT       *Op,
619     char                    *Path,
620     UINT8                   Type,
621     UINT32                  Value,
622     UINT16                  Flags)
623 {
624     char                    *ExternalPath;
625     char                    *InternalPath = Path;
626     char                    *Temp;
627     ACPI_STATUS             Status;
628 
629 
630     ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
631 
632 
633     if (!Path)
634     {
635         return_VOID;
636     }
637 
638     /* Remove a root backslash if present */
639 
640     if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
641     {
642         Path++;
643     }
644 
645     /* Externalize the pathname */
646 
647     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
648         NULL, &ExternalPath);
649     if (ACPI_FAILURE (Status))
650     {
651         return_VOID;
652     }
653 
654     /*
655      * Get the full pathname from the root if "Path" has one or more
656      * parent prefixes (^). Note: path will not contain a leading '\'.
657      */
658     if (*Path == (UINT8) AML_PARENT_PREFIX)
659     {
660         Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
661 
662         /* Set new external path */
663 
664         ACPI_FREE (ExternalPath);
665         ExternalPath = Temp;
666         if (!Temp)
667         {
668             return_VOID;
669         }
670 
671         /* Create the new internal pathname */
672 
673         Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
674         Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
675         if (ACPI_FAILURE (Status))
676         {
677             ACPI_FREE (ExternalPath);
678             return_VOID;
679         }
680     }
681 
682     /* Create the new External() declaration node */
683 
684     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
685         Type, Value, Flags);
686     if (ACPI_FAILURE (Status))
687     {
688         ACPI_FREE (ExternalPath);
689         if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
690         {
691             ACPI_FREE (InternalPath);
692         }
693     }
694 
695     return_VOID;
696 }
697 
698 
699 /*******************************************************************************
700  *
701  * FUNCTION:    AcpiDmAddNodeToExternalList
702  *
703  * PARAMETERS:  Node                - Namespace node for object to be added
704  *              Type                - ACPI object type to be added
705  *              Value               - Arg count if adding a Method object
706  *              Flags               - To be passed to the external object
707  *
708  * RETURN:      None
709  *
710  * DESCRIPTION: Insert a new name into the global list of Externals which
711  *              will in turn be later emitted as an External() declaration
712  *              in the disassembled output.
713  *
714  *              This function handles the case where the referenced name has
715  *              been found in the namespace, but the name originated in a
716  *              table other than the one that is being disassembled (such
717  *              as a table that is added via the iASL -e option).
718  *
719  ******************************************************************************/
720 
721 void
722 AcpiDmAddNodeToExternalList (
723     ACPI_NAMESPACE_NODE     *Node,
724     UINT8                   Type,
725     UINT32                  Value,
726     UINT16                  Flags)
727 {
728     char                    *ExternalPath;
729     char                    *InternalPath;
730     char                    *Temp;
731     ACPI_STATUS             Status;
732 
733 
734     ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
735 
736 
737     if (!Node)
738     {
739         return_VOID;
740     }
741 
742     /* Get the full external and internal pathnames to the node */
743 
744     ExternalPath = AcpiNsGetExternalPathname (Node);
745     if (!ExternalPath)
746     {
747         return_VOID;
748     }
749 
750     Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
751     if (ACPI_FAILURE (Status))
752     {
753         ACPI_FREE (ExternalPath);
754         return_VOID;
755     }
756 
757     /* Remove the root backslash */
758 
759     if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1]))
760     {
761         Temp = ACPI_ALLOCATE_ZEROED (strlen (ExternalPath) + 1);
762         if (!Temp)
763         {
764             return_VOID;
765         }
766 
767         strcpy (Temp, &ExternalPath[1]);
768         ACPI_FREE (ExternalPath);
769         ExternalPath = Temp;
770     }
771 
772     /* Create the new External() declaration node */
773 
774     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
775         Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
776     if (ACPI_FAILURE (Status))
777     {
778         ACPI_FREE (ExternalPath);
779         ACPI_FREE (InternalPath);
780     }
781 
782     return_VOID;
783 }
784 
785 
786 /*******************************************************************************
787  *
788  * FUNCTION:    AcpiDmAddPathToExternalList
789  *
790  * PARAMETERS:  Path                - External name of the object to be added
791  *              Type                - ACPI object type to be added
792  *              Value               - Arg count if adding a Method object
793  *              Flags               - To be passed to the external object
794  *
795  * RETURN:      None
796  *
797  * DESCRIPTION: Insert a new name into the global list of Externals which
798  *              will in turn be later emitted as an External() declaration
799  *              in the disassembled output.
800  *
801  *              This function currently is used to add externals via a
802  *              reference file (via the -fe iASL option).
803  *
804  ******************************************************************************/
805 
806 static void
807 AcpiDmAddPathToExternalList (
808     char                    *Path,
809     UINT8                   Type,
810     UINT32                  Value,
811     UINT16                  Flags)
812 {
813     char                    *InternalPath;
814     char                    *ExternalPath;
815     ACPI_STATUS             Status;
816 
817 
818     ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
819 
820 
821     if (!Path)
822     {
823         return_VOID;
824     }
825 
826     /* Remove a root backslash if present */
827 
828     if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
829     {
830         Path++;
831     }
832 
833     /* Create the internal and external pathnames */
834 
835     Status = AcpiNsInternalizeName (Path, &InternalPath);
836     if (ACPI_FAILURE (Status))
837     {
838         return_VOID;
839     }
840 
841     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
842         NULL, &ExternalPath);
843     if (ACPI_FAILURE (Status))
844     {
845         ACPI_FREE (InternalPath);
846         return_VOID;
847     }
848 
849     /* Create the new External() declaration node */
850 
851     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
852         Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
853     if (ACPI_FAILURE (Status))
854     {
855         ACPI_FREE (ExternalPath);
856         ACPI_FREE (InternalPath);
857     }
858 
859     return_VOID;
860 }
861 
862 
863 /*******************************************************************************
864  *
865  * FUNCTION:    AcpiDmCreateNewExternal
866  *
867  * PARAMETERS:  ExternalPath        - External path to the object
868  *              InternalPath        - Internal (AML) path to the object
869  *              Type                - ACPI object type to be added
870  *              Value               - Arg count if adding a Method object
871  *              Flags               - To be passed to the external object
872  *
873  * RETURN:      Status
874  *
875  * DESCRIPTION: Common low-level function to insert a new name into the global
876  *              list of Externals which will in turn be later emitted as
877  *              External() declarations in the disassembled output.
878  *
879  *              Note: The external name should not include a root prefix
880  *              (backslash). We do not want External() statements to contain
881  *              a leading '\', as this prevents duplicate external statements
882  *              of the form:
883  *
884  *                  External (\ABCD)
885  *                  External (ABCD)
886  *
887  *              This would cause a compile time error when the disassembled
888  *              output file is recompiled.
889  *
890  *              There are two cases that are handled here. For both, we emit
891  *              an External() statement:
892  *              1) The name was simply not found in the namespace.
893  *              2) The name was found, but it originated in a table other than
894  *              the table that is being disassembled.
895  *
896  ******************************************************************************/
897 
898 static ACPI_STATUS
899 AcpiDmCreateNewExternal (
900     char                    *ExternalPath,
901     char                    *InternalPath,
902     UINT8                   Type,
903     UINT32                  Value,
904     UINT16                  Flags)
905 {
906     ACPI_EXTERNAL_LIST      *NewExternal;
907     ACPI_EXTERNAL_LIST      *NextExternal;
908     ACPI_EXTERNAL_LIST      *PrevExternal = NULL;
909 
910 
911     ACPI_FUNCTION_TRACE (DmCreateNewExternal);
912 
913 
914     /* Check all existing externals to ensure no duplicates */
915 
916     NextExternal = AcpiGbl_ExternalList;
917     while (NextExternal)
918     {
919         /* Check for duplicates */
920 
921         if (!strcmp (ExternalPath, NextExternal->Path))
922         {
923             /*
924              * If this external came from an External() opcode, we are
925              * finished with this one. (No need to check any further).
926              */
927             if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)
928             {
929                 return_ACPI_STATUS (AE_ALREADY_EXISTS);
930             }
931 
932             /* Allow upgrade of type from ANY */
933 
934             else if ((NextExternal->Type == ACPI_TYPE_ANY) &&
935                 (Type != ACPI_TYPE_ANY))
936             {
937                 NextExternal->Type = Type;
938             }
939 
940             /* Update the argument count as necessary */
941 
942             if (Value < NextExternal->Value)
943             {
944                 NextExternal->Value = Value;
945             }
946 
947             /* Update flags. */
948 
949             NextExternal->Flags |= Flags;
950             NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED;
951 
952             return_ACPI_STATUS (AE_ALREADY_EXISTS);
953         }
954 
955         NextExternal = NextExternal->Next;
956     }
957 
958     /* Allocate and init a new External() descriptor */
959 
960     NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
961     if (!NewExternal)
962     {
963         return_ACPI_STATUS (AE_NO_MEMORY);
964     }
965 
966     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
967         "Adding external reference node (%s) type [%s]\n",
968         ExternalPath, AcpiUtGetTypeName (Type)));
969 
970     NewExternal->Flags = Flags;
971     NewExternal->Value = Value;
972     NewExternal->Path = ExternalPath;
973     NewExternal->Type = Type;
974     NewExternal->Length = (UINT16) strlen (ExternalPath);
975     NewExternal->InternalPath = InternalPath;
976 
977     /* Link the new descriptor into the global list, alphabetically ordered */
978 
979     NextExternal = AcpiGbl_ExternalList;
980     while (NextExternal)
981     {
982         if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
983         {
984             if (PrevExternal)
985             {
986                 PrevExternal->Next = NewExternal;
987             }
988             else
989             {
990                 AcpiGbl_ExternalList = NewExternal;
991             }
992 
993             NewExternal->Next = NextExternal;
994             return_ACPI_STATUS (AE_OK);
995         }
996 
997         PrevExternal = NextExternal;
998         NextExternal = NextExternal->Next;
999     }
1000 
1001     if (PrevExternal)
1002     {
1003         PrevExternal->Next = NewExternal;
1004     }
1005     else
1006     {
1007         AcpiGbl_ExternalList = NewExternal;
1008     }
1009 
1010     return_ACPI_STATUS (AE_OK);
1011 }
1012 
1013 
1014 /*******************************************************************************
1015  *
1016  * FUNCTION:    AcpiDmAddExternalsToNamespace
1017  *
1018  * PARAMETERS:  None
1019  *
1020  * RETURN:      None
1021  *
1022  * DESCRIPTION: Add all externals to the namespace. Allows externals to be
1023  *              "resolved".
1024  *
1025  ******************************************************************************/
1026 
1027 void
1028 AcpiDmAddExternalsToNamespace (
1029     void)
1030 {
1031     ACPI_STATUS             Status;
1032     ACPI_NAMESPACE_NODE     *Node;
1033     ACPI_OPERAND_OBJECT     *ObjDesc;
1034     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
1035 
1036 
1037     while (External)
1038     {
1039         /* Add the external name (object) into the namespace */
1040 
1041         Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
1042             ACPI_IMODE_LOAD_PASS1,
1043             ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
1044             NULL, &Node);
1045 
1046         if (ACPI_FAILURE (Status))
1047         {
1048             ACPI_EXCEPTION ((AE_INFO, Status,
1049                 "while adding external to namespace [%s]",
1050                 External->Path));
1051         }
1052 
1053         else switch (External->Type)
1054         {
1055         case ACPI_TYPE_METHOD:
1056 
1057             /* For methods, we need to save the argument count */
1058 
1059             ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
1060             ObjDesc->Method.ParamCount = (UINT8) External->Value;
1061             Node->Object = ObjDesc;
1062             break;
1063 
1064         case ACPI_TYPE_REGION:
1065 
1066             /* Regions require a region sub-object */
1067 
1068             ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
1069             ObjDesc->Region.Node = Node;
1070             Node->Object = ObjDesc;
1071             break;
1072 
1073         default:
1074 
1075             break;
1076         }
1077 
1078         External = External->Next;
1079     }
1080 }
1081 
1082 
1083 /*******************************************************************************
1084  *
1085  * FUNCTION:    AcpiDmGetExternalMethodCount
1086  *
1087  * PARAMETERS:  None
1088  *
1089  * RETURN:      The number of control method externals in the external list
1090  *
1091  * DESCRIPTION: Return the number of method externals that have been generated.
1092  *              If any control method externals have been found, we must
1093  *              re-parse the entire definition block with the new information
1094  *              (number of arguments for the methods.) This is limitation of
1095  *              AML, we don't know the number of arguments from the control
1096  *              method invocation itself.
1097  *
1098  ******************************************************************************/
1099 
1100 UINT32
1101 AcpiDmGetExternalMethodCount (
1102     void)
1103 {
1104     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
1105     UINT32                  Count = 0;
1106 
1107 
1108     while (External)
1109     {
1110         if (External->Type == ACPI_TYPE_METHOD)
1111         {
1112             Count++;
1113         }
1114 
1115         External = External->Next;
1116     }
1117 
1118     return (Count);
1119 }
1120 
1121 
1122 /*******************************************************************************
1123  *
1124  * FUNCTION:    AcpiDmClearExternalList
1125  *
1126  * PARAMETERS:  None
1127  *
1128  * RETURN:      None
1129  *
1130  * DESCRIPTION: Free the entire External info list
1131  *
1132  ******************************************************************************/
1133 
1134 void
1135 AcpiDmClearExternalList (
1136     void)
1137 {
1138     ACPI_EXTERNAL_LIST      *NextExternal;
1139 
1140 
1141     while (AcpiGbl_ExternalList)
1142     {
1143         NextExternal = AcpiGbl_ExternalList->Next;
1144         ACPI_FREE (AcpiGbl_ExternalList->Path);
1145         ACPI_FREE (AcpiGbl_ExternalList);
1146         AcpiGbl_ExternalList = NextExternal;
1147     }
1148 }
1149 
1150 
1151 /*******************************************************************************
1152  *
1153  * FUNCTION:    AcpiDmEmitExternals
1154  *
1155  * PARAMETERS:  None
1156  *
1157  * RETURN:      None
1158  *
1159  * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1160  *              the global external info list.
1161  *
1162  ******************************************************************************/
1163 
1164 void
1165 AcpiDmEmitExternals (
1166     void)
1167 {
1168     ACPI_EXTERNAL_LIST      *NextExternal;
1169 
1170 
1171     if (!AcpiGbl_ExternalList)
1172     {
1173         return;
1174     }
1175 
1176     /*
1177      * Determine the number of control methods in the external list, and
1178      * also how many of those externals were resolved via the namespace.
1179      */
1180     NextExternal = AcpiGbl_ExternalList;
1181     while (NextExternal)
1182     {
1183         if (NextExternal->Type == ACPI_TYPE_METHOD)
1184         {
1185             AcpiGbl_NumExternalMethods++;
1186             if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1187             {
1188                 AcpiGbl_ResolvedExternalMethods++;
1189             }
1190         }
1191 
1192         NextExternal = NextExternal->Next;
1193     }
1194 
1195     /* Check if any control methods were unresolved */
1196 
1197     AcpiDmUnresolvedWarning (1);
1198 
1199     if (Gbl_ExternalRefFilename)
1200     {
1201         AcpiOsPrintf (
1202             "    /*\n     * External declarations were imported from\n"
1203             "     * a reference file -- %s\n     */\n\n",
1204             Gbl_ExternalRefFilename);
1205     }
1206 
1207     /*
1208      * Walk and emit the list of externals found during the AML parsing
1209      */
1210     while (AcpiGbl_ExternalList)
1211     {
1212         if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1213         {
1214             AcpiOsPrintf ("    External (%s%s)",
1215                 AcpiGbl_ExternalList->Path,
1216                 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1217 
1218             /* Check for "unresolved" method reference */
1219 
1220             if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) &&
1221                 (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1222             {
1223                 AcpiOsPrintf ("    // Warning: Unknown method, "
1224                     "guessing %u arguments",
1225                     AcpiGbl_ExternalList->Value);
1226             }
1227 
1228             /* Check for external from a external references file */
1229 
1230             else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE)
1231             {
1232                 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1233                 {
1234                     AcpiOsPrintf ("    // %u Arguments",
1235                         AcpiGbl_ExternalList->Value);
1236                 }
1237 
1238                 AcpiOsPrintf ("    // From external reference file");
1239             }
1240 
1241             /* This is the normal external case */
1242 
1243             else
1244             {
1245                 /* For methods, add a comment with the number of arguments */
1246 
1247                 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1248                 {
1249                     AcpiOsPrintf ("    // %u Arguments",
1250                         AcpiGbl_ExternalList->Value);
1251                 }
1252             }
1253 
1254             AcpiOsPrintf ("\n");
1255         }
1256 
1257         /* Free this external info block and move on to next external */
1258 
1259         NextExternal = AcpiGbl_ExternalList->Next;
1260         if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1261         {
1262             ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1263         }
1264 
1265         ACPI_FREE (AcpiGbl_ExternalList->Path);
1266         ACPI_FREE (AcpiGbl_ExternalList);
1267         AcpiGbl_ExternalList = NextExternal;
1268     }
1269 
1270     AcpiOsPrintf ("\n");
1271 }
1272 
1273 
1274 /*******************************************************************************
1275  *
1276  * FUNCTION:    AcpiDmEmitExternal
1277  *
1278  * PARAMETERS:  Op                  External Parse Object
1279  *
1280  * RETURN:      None
1281  *
1282  * DESCRIPTION: Emit an External() ASL statement for the current External
1283  *              parse object
1284  *
1285  ******************************************************************************/
1286 
1287 void
1288 AcpiDmEmitExternal (
1289     ACPI_PARSE_OBJECT       *NameOp,
1290     ACPI_PARSE_OBJECT       *TypeOp)
1291 {
1292     AcpiOsPrintf ("External (");
1293     AcpiDmNamestring (NameOp->Common.Value.Name);
1294     AcpiOsPrintf ("%s)\n",
1295         AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer));
1296 }
1297 
1298 
1299 /*******************************************************************************
1300  *
1301  * FUNCTION:    AcpiDmUnresolvedWarning
1302  *
1303  * PARAMETERS:  Type                - Where to output the warning.
1304  *                                    0 means write to stderr
1305  *                                    1 means write to AcpiOsPrintf
1306  *
1307  * RETURN:      None
1308  *
1309  * DESCRIPTION: Issue warning message if there are unresolved external control
1310  *              methods within the disassembly.
1311  *
1312  ******************************************************************************/
1313 
1314 #if 0
1315 Summary of the external control method problem:
1316 
1317 When the -e option is used with disassembly, the various SSDTs are simply
1318 loaded into a global namespace for the disassembler to use in order to
1319 resolve control method references (invocations).
1320 
1321 The disassembler tracks any such references, and will emit an External()
1322 statement for these types of methods, with the proper number of arguments .
1323 
1324 Without the SSDTs, the AML does not contain enough information to properly
1325 disassemble the control method invocation -- because the disassembler does
1326 not know how many arguments to parse.
1327 
1328 An example: Assume we have two control methods. ABCD has one argument, and
1329 EFGH has zero arguments. Further, we have two additional control methods
1330 that invoke ABCD and EFGH, named T1 and T2:
1331 
1332     Method (ABCD, 1)
1333     {
1334     }
1335     Method (EFGH, 0)
1336     {
1337     }
1338     Method (T1)
1339     {
1340         ABCD (Add (2, 7, Local0))
1341     }
1342     Method (T2)
1343     {
1344         EFGH ()
1345         Add (2, 7, Local0)
1346     }
1347 
1348 Here is the AML code that is generated for T1 and T2:
1349 
1350      185:      Method (T1)
1351 
1352 0000034C:  14 10 54 31 5F 5F 00 ...    "..T1__."
1353 
1354      186:      {
1355      187:          ABCD (Add (2, 7, Local0))
1356 
1357 00000353:  41 42 43 44 ............    "ABCD"
1358 00000357:  72 0A 02 0A 07 60 ......    "r....`"
1359 
1360      188:      }
1361 
1362      190:      Method (T2)
1363 
1364 0000035D:  14 10 54 32 5F 5F 00 ...    "..T2__."
1365 
1366      191:      {
1367      192:          EFGH ()
1368 
1369 00000364:  45 46 47 48 ............    "EFGH"
1370 
1371      193:          Add (2, 7, Local0)
1372 
1373 00000368:  72 0A 02 0A 07 60 ......    "r....`"
1374      194:      }
1375 
1376 Note that the AML code for T1 and T2 is essentially identical. When
1377 disassembling this code, the methods ABCD and EFGH must be known to the
1378 disassembler, otherwise it does not know how to handle the method invocations.
1379 
1380 In other words, if ABCD and EFGH are actually external control methods
1381 appearing in an SSDT, the disassembler does not know what to do unless
1382 the owning SSDT has been loaded via the -e option.
1383 #endif
1384 
1385 static char             ExternalWarningPart1[600];
1386 static char             ExternalWarningPart2[400];
1387 static char             ExternalWarningPart3[400];
1388 static char             ExternalWarningPart4[200];
1389 
1390 void
1391 AcpiDmUnresolvedWarning (
1392     UINT8                   Type)
1393 {
1394     char                    *Format;
1395     char                    Pad[] = "     *";
1396     char                    NoPad[] = "";
1397 
1398 
1399     if (!AcpiGbl_NumExternalMethods)
1400     {
1401         return;
1402     }
1403 
1404     if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
1405     {
1406         return;
1407     }
1408 
1409     Format = Type ? Pad : NoPad;
1410 
1411     sprintf (ExternalWarningPart1,
1412         "%s iASL Warning: There %s %u external control method%s found during\n"
1413         "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1414         "%s ACPI tables may be required to properly disassemble the code. This\n"
1415         "%s resulting disassembler output file may not compile because the\n"
1416         "%s disassembler did not know how many arguments to assign to the\n"
1417         "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1418         "%s runtime and may or may not be available via the host OS.\n",
1419         Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
1420         AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
1421         Format, AcpiGbl_ResolvedExternalMethods,
1422         (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
1423         (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
1424         Format, Format, Format, Format, Format);
1425 
1426     sprintf (ExternalWarningPart2,
1427         "%s To specify the tables needed to resolve external control method\n"
1428         "%s references, the -e option can be used to specify the filenames.\n"
1429         "%s Example iASL invocations:\n"
1430         "%s     iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1431         "%s     iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1432         "%s     iasl -e ssdt*.aml -d dsdt.aml\n",
1433         Format, Format, Format, Format, Format, Format);
1434 
1435     sprintf (ExternalWarningPart3,
1436         "%s In addition, the -fe option can be used to specify a file containing\n"
1437         "%s control method external declarations with the associated method\n"
1438         "%s argument counts. Each line of the file must be of the form:\n"
1439         "%s     External (<method pathname>, MethodObj, <argument count>)\n"
1440         "%s Invocation:\n"
1441         "%s     iasl -fe refs.txt -d dsdt.aml\n",
1442         Format, Format, Format, Format, Format, Format);
1443 
1444     sprintf (ExternalWarningPart4,
1445         "%s The following methods were unresolved and many not compile properly\n"
1446         "%s because the disassembler had to guess at the number of arguments\n"
1447         "%s required for each:\n",
1448         Format, Format, Format);
1449 
1450     if (Type)
1451     {
1452         if (!AcpiGbl_ExternalFileList)
1453         {
1454             /* The -e option was not specified */
1455 
1456            AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     *\n%s     */\n",
1457                ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
1458                ExternalWarningPart4);
1459         }
1460         else
1461         {
1462             /* The -e option was specified, but there are still some unresolved externals */
1463 
1464             AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     */\n",
1465                ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
1466         }
1467     }
1468     else
1469     {
1470         if (!AcpiGbl_ExternalFileList)
1471         {
1472             /* The -e option was not specified */
1473 
1474             fprintf (stderr, "\n%s\n%s\n%s\n",
1475                ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
1476         }
1477         else
1478         {
1479             /* The -e option was specified, but there are still some unresolved externals */
1480 
1481             fprintf (stderr, "\n%s\n%s\n",
1482                ExternalWarningPart1, ExternalWarningPart3);
1483         }
1484     }
1485 }
1486