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 - 2020, 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 */
176static 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
202static const char          *ExternalConflictMessage =
203    "    // Conflicts with a later declaration";
204
205
206/* Local prototypes */
207
208static const char *
209AcpiDmGetObjectTypeName (
210    ACPI_OBJECT_TYPE        Type);
211
212static char *
213AcpiDmNormalizeParentPrefix (
214    ACPI_PARSE_OBJECT       *Op,
215    char                    *Path);
216
217static ACPI_STATUS
218AcpiDmGetExternalAndInternalPath (
219    ACPI_NAMESPACE_NODE     *Node,
220    char                    **ExternalPath,
221    char                    **InternalPath);
222
223static ACPI_STATUS
224AcpiDmRemoveRootPrefix (
225    char                    **Path);
226
227static void
228AcpiDmAddPathToExternalList (
229    char                    *Path,
230    UINT8                   Type,
231    UINT32                  Value,
232    UINT16                  Flags);
233
234static ACPI_STATUS
235AcpiDmCreateNewExternal (
236    char                    *ExternalPath,
237    char                    *InternalPath,
238    UINT8                   Type,
239    UINT32                  Value,
240    UINT16                  Flags);
241
242static void
243AcpiDmCheckForExternalConflict (
244    char                    *Path);
245
246static ACPI_STATUS
247AcpiDmResolveExternal (
248    char                    *Path,
249    UINT8                   Type,
250    ACPI_NAMESPACE_NODE     **Node);
251
252
253static void
254AcpiDmConflictingDeclaration (
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
270static const char *
271AcpiDmGetObjectTypeName (
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
302static char *
303AcpiDmNormalizeParentPrefix (
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
406Cleanup:
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
424ACPI_STATUS
425AcpiDmAddToExternalFileList (
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
477void
478AcpiDmClearExternalFileList (
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
512void
513AcpiDmGetExternalsFromFile (
514    void)
515{
516    FILE                    *ExternalRefFile;
517    char                    *Token;
518    char                    *MethodName;
519    UINT32                  ArgCount;
520    UINT32                  ImportCount = 0;
521
522
523    if (!AslGbl_ExternalRefFilename)
524    {
525        return;
526    }
527
528    /* Open the file */
529
530    ExternalRefFile = fopen (AslGbl_ExternalRefFilename, "r");
531    if (!ExternalRefFile)
532    {
533        fprintf (stderr, "Could not open external reference file \"%s\"\n",
534            AslGbl_ExternalRefFilename);
535        AslAbort ();
536        return;
537    }
538
539    /* Each line defines a method */
540
541    while (fgets (AslGbl_StringBuffer, ASL_STRING_BUFFER_SIZE, ExternalRefFile))
542    {
543        Token = strtok (AslGbl_StringBuffer, METHOD_SEPARATORS);   /* "External" */
544        if (!Token)
545        {
546            continue;
547        }
548
549        if (strcmp (Token, "External"))
550        {
551            continue;
552        }
553
554        MethodName = strtok (NULL, METHOD_SEPARATORS);      /* Method namepath */
555        if (!MethodName)
556        {
557            continue;
558        }
559
560        Token = strtok (NULL, METHOD_SEPARATORS);           /* "MethodObj" */
561        if (!Token)
562        {
563            continue;
564        }
565
566        if (strcmp (Token, "MethodObj"))
567        {
568            continue;
569        }
570
571        Token = strtok (NULL, METHOD_SEPARATORS);           /* Arg count */
572        if (!Token)
573        {
574            continue;
575        }
576
577        /* Convert arg count string to an integer */
578
579        errno = 0;
580        ArgCount = strtoul (Token, NULL, 0);
581        if (errno)
582        {
583            fprintf (stderr, "Invalid argument count (%s)\n", Token);
584            continue;
585        }
586
587        if (ArgCount > 7)
588        {
589            fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
590            continue;
591        }
592
593        /* Add this external to the global list */
594
595        AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
596            AslGbl_ExternalRefFilename, ArgCount, MethodName);
597
598        AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
599            ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
600        ImportCount++;
601    }
602
603    if (!ImportCount)
604    {
605        fprintf (stderr,
606            "Did not find any external methods in reference file \"%s\"\n",
607            AslGbl_ExternalRefFilename);
608    }
609    else
610    {
611        /* Add the external(s) to the namespace */
612
613        AcpiDmAddExternalListToNamespace ();
614
615        AcpiOsPrintf ("%s: Imported %u external method definitions\n",
616            AslGbl_ExternalRefFilename, ImportCount);
617    }
618
619    fclose (ExternalRefFile);
620}
621
622
623/*******************************************************************************
624 *
625 * FUNCTION:    AcpiDmAddOpToExternalList
626 *
627 * PARAMETERS:  Op                  - Current parser Op
628 *              Path                - Internal (AML) path to the object
629 *              Type                - ACPI object type to be added
630 *              Value               - Arg count if adding a Method object
631 *              Flags               - To be passed to the external object
632 *
633 * RETURN:      None
634 *
635 * DESCRIPTION: Insert a new name into the global list of Externals which
636 *              will in turn be later emitted as an External() declaration
637 *              in the disassembled output.
638 *
639 *              This function handles the most common case where the referenced
640 *              name is simply not found in the constructed namespace.
641 *
642 ******************************************************************************/
643
644void
645AcpiDmAddOpToExternalList (
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
741static ACPI_STATUS
742AcpiDmGetExternalAndInternalPath (
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
786static ACPI_STATUS
787AcpiDmRemoveRootPrefix (
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
829void
830AcpiDmAddNodeToExternalList (
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
895static void
896AcpiDmAddPathToExternalList (
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
987static ACPI_STATUS
988AcpiDmCreateNewExternal (
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
1119static ACPI_STATUS
1120AcpiDmResolveExternal (
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
1171void
1172AcpiDmCreateSubobjectForExternal (
1173    UINT8                   Type,
1174    ACPI_NAMESPACE_NODE     **Node,
1175    UINT32                  ParamCount)
1176{
1177    ACPI_OPERAND_OBJECT     *ObjDesc;
1178
1179
1180    switch (Type)
1181    {
1182    case ACPI_TYPE_METHOD:
1183
1184        /* For methods, we need to save the argument count */
1185
1186        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
1187        ObjDesc->Method.ParamCount = (UINT8) ParamCount;
1188        (*Node)->Object = ObjDesc;
1189        break;
1190
1191    case ACPI_TYPE_REGION:
1192
1193        /* Regions require a region sub-object */
1194
1195        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
1196        ObjDesc->Region.Node = *Node;
1197        (*Node)->Object = ObjDesc;
1198        break;
1199
1200    default:
1201
1202        break;
1203    }
1204}
1205
1206
1207/*******************************************************************************
1208 *
1209 * FUNCTION:    AcpiDmAddOneExternalToNamespace
1210 *
1211 * PARAMETERS:  Path                   - External parse object
1212 *              Type                   - Type of parse object
1213 *              ParamCount             - External method parameter count
1214 *
1215 * RETURN:      None
1216 *
1217 * DESCRIPTION: Add one external to the namespace by resolvign the external
1218 *              (by performing a namespace lookup) and annotating the resulting
1219 *              namespace node with the appropriate information if the type
1220 *              is ACPI_TYPE_REGION or ACPI_TYPE_METHOD.
1221 *
1222 ******************************************************************************/
1223
1224void
1225AcpiDmAddOneExternalToNamespace (
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
1259void
1260AcpiDmAddExternalListToNamespace (
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
1297UINT32
1298AcpiDmGetUnresolvedExternalMethodCount (
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
1332void
1333AcpiDmClearExternalList (
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
1362void
1363AcpiDmEmitExternals (
1364    void)
1365{
1366    ACPI_EXTERNAL_LIST      *NextExternal;
1367
1368
1369    if (!AcpiGbl_ExternalList)
1370    {
1371        return;
1372    }
1373
1374    /*
1375     * Determine the number of control methods in the external list, and
1376     * also how many of those externals were resolved via the namespace.
1377     */
1378    NextExternal = AcpiGbl_ExternalList;
1379    while (NextExternal)
1380    {
1381        if (NextExternal->Type == ACPI_TYPE_METHOD)
1382        {
1383            AcpiGbl_NumExternalMethods++;
1384            if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1385            {
1386                AcpiGbl_ResolvedExternalMethods++;
1387            }
1388        }
1389
1390        NextExternal = NextExternal->Next;
1391    }
1392
1393    /* Check if any control methods were unresolved */
1394
1395    AcpiDmUnresolvedWarning (1);
1396
1397    if (AslGbl_ExternalRefFilename)
1398    {
1399        AcpiOsPrintf (
1400            "    /*\n     * External declarations were imported from\n"
1401            "     * a reference file -- %s\n     */\n\n",
1402            AslGbl_ExternalRefFilename);
1403    }
1404
1405    /*
1406     * Walk and emit the list of externals found during the AML parsing
1407     */
1408    while (AcpiGbl_ExternalList)
1409    {
1410        if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1411        {
1412            AcpiOsPrintf ("    External (%s%s)",
1413                AcpiGbl_ExternalList->Path,
1414                AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1415
1416            /* Check for "unresolved" method reference */
1417
1418            if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) &&
1419                (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1420            {
1421                AcpiOsPrintf ("    // Warning: Unknown method, "
1422                    "guessing %u arguments",
1423                    AcpiGbl_ExternalList->Value);
1424            }
1425
1426            /* Check for external from a external references file */
1427
1428            else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE)
1429            {
1430                if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1431                {
1432                    AcpiOsPrintf ("    // %u Arguments",
1433                        AcpiGbl_ExternalList->Value);
1434                }
1435
1436                AcpiOsPrintf ("    // From external reference file");
1437            }
1438
1439            /* This is the normal external case */
1440
1441            else
1442            {
1443                /* For methods, add a comment with the number of arguments */
1444
1445                if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1446                {
1447                    AcpiOsPrintf ("    // %u Arguments",
1448                        AcpiGbl_ExternalList->Value);
1449                }
1450            }
1451
1452            if (AcpiGbl_ExternalList->Flags &= ACPI_EXT_CONFLICTING_DECLARATION)
1453            {
1454                AcpiOsPrintf ("%s", ExternalConflictMessage);
1455                AcpiDmConflictingDeclaration (AcpiGbl_ExternalList->Path);
1456            }
1457            AcpiOsPrintf ("\n");
1458        }
1459
1460        /* Free this external info block and move on to next external */
1461
1462        NextExternal = AcpiGbl_ExternalList->Next;
1463        if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1464        {
1465            ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1466        }
1467
1468        ACPI_FREE (AcpiGbl_ExternalList->Path);
1469        ACPI_FREE (AcpiGbl_ExternalList);
1470        AcpiGbl_ExternalList = NextExternal;
1471    }
1472
1473    AcpiOsPrintf ("\n");
1474}
1475
1476
1477/*******************************************************************************
1478 *
1479 * FUNCTION:    AcpiDmMarkExternalConflict
1480 *
1481 * PARAMETERS:  Path          - Namepath to search
1482 *
1483 * RETURN:      ExternalList
1484 *
1485 * DESCRIPTION: Search the AcpiGbl_ExternalList for a matching path
1486 *
1487 ******************************************************************************/
1488
1489void
1490AcpiDmMarkExternalConflict (
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
1563static void
1564AcpiDmConflictingDeclaration (
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
1591void
1592AcpiDmEmitExternal (
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
1618static void
1619AcpiDmCheckForExternalConflict (
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/*
1681Summary of the external control method problem:
1682
1683When the -e option is used with disassembly, the various SSDTs are simply
1684loaded into a global namespace for the disassembler to use in order to
1685resolve control method references (invocations).
1686
1687The disassembler tracks any such references, and will emit an External()
1688statement for these types of methods, with the proper number of arguments .
1689
1690Without the SSDTs, the AML does not contain enough information to properly
1691disassemble the control method invocation -- because the disassembler does
1692not know how many arguments to parse.
1693
1694An example: Assume we have two control methods. ABCD has one argument, and
1695EFGH has zero arguments. Further, we have two additional control methods
1696that 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
1714Here is the AML code that is generated for T1 and T2:
1715
1716     185:      Method (T1)
1717
17180000034C:  14 10 54 31 5F 5F 00 ...    "..T1__."
1719
1720     186:      {
1721     187:          ABCD (Add (2, 7, Local0))
1722
172300000353:  41 42 43 44 ............    "ABCD"
172400000357:  72 0A 02 0A 07 60 ......    "r....`"
1725
1726     188:      }
1727
1728     190:      Method (T2)
1729
17300000035D:  14 10 54 32 5F 5F 00 ...    "..T2__."
1731
1732     191:      {
1733     192:          EFGH ()
1734
173500000364:  45 46 47 48 ............    "EFGH"
1736
1737     193:          Add (2, 7, Local0)
1738
173900000368:  72 0A 02 0A 07 60 ......    "r....`"
1740     194:      }
1741
1742Note that the AML code for T1 and T2 is essentially identical. When
1743disassembling this code, the methods ABCD and EFGH must be known to the
1744disassembler, otherwise it does not know how to handle the method invocations.
1745
1746In other words, if ABCD and EFGH are actually external control methods
1747appearing in an SSDT, the disassembler does not know what to do unless
1748the owning SSDT has been loaded via the -e option.
1749*/
1750
1751static char             ExternalWarningPart1[600];
1752static char             ExternalWarningPart2[400];
1753static char             ExternalWarningPart3[400];
1754static char             ExternalWarningPart4[200];
1755
1756void
1757AcpiDmUnresolvedWarning (
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