1198054Sjkim/******************************************************************************
2198054Sjkim *
3198054Sjkim * Module Name: dmextern - Support for External() ASL statements
4198054Sjkim *
5198054Sjkim *****************************************************************************/
6198054Sjkim
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9198054Sjkim * All rights reserved.
10198054Sjkim *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25198054Sjkim *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29198054Sjkim *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43198054Sjkim
44198237Sjkim#include <contrib/dev/acpica/include/acpi.h>
45198237Sjkim#include <contrib/dev/acpica/include/accommon.h>
46198237Sjkim#include <contrib/dev/acpica/include/amlcode.h>
47198237Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48198237Sjkim#include <contrib/dev/acpica/include/acdisasm.h>
49254745Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
50246849Sjkim#include <stdio.h>
51254745Sjkim#include <errno.h>
52198054Sjkim
53198054Sjkim
54198054Sjkim/*
55198054Sjkim * This module is used for application-level code (iASL disassembler) only.
56198054Sjkim *
57198054Sjkim * It contains the code to create and emit any necessary External() ASL
58198054Sjkim * statements for the module being disassembled.
59198054Sjkim */
60198054Sjkim#define _COMPONENT          ACPI_CA_DISASSEMBLER
61198054Sjkim        ACPI_MODULE_NAME    ("dmextern")
62198054Sjkim
63198054Sjkim
64198054Sjkim/*
65198054Sjkim * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
66198054Sjkim * ObjectTypeKeyword. Used to generate typed external declarations
67198054Sjkim */
68198054Sjkimstatic const char           *AcpiGbl_DmTypeNames[] =
69198054Sjkim{
70281075Sdim    /* 00 */ ", UnknownObj",        /* Type ANY */
71198054Sjkim    /* 01 */ ", IntObj",
72198054Sjkim    /* 02 */ ", StrObj",
73198054Sjkim    /* 03 */ ", BuffObj",
74198054Sjkim    /* 04 */ ", PkgObj",
75198054Sjkim    /* 05 */ ", FieldUnitObj",
76198054Sjkim    /* 06 */ ", DeviceObj",
77198054Sjkim    /* 07 */ ", EventObj",
78198054Sjkim    /* 08 */ ", MethodObj",
79198054Sjkim    /* 09 */ ", MutexObj",
80198054Sjkim    /* 10 */ ", OpRegionObj",
81198054Sjkim    /* 11 */ ", PowerResObj",
82198054Sjkim    /* 12 */ ", ProcessorObj",
83198054Sjkim    /* 13 */ ", ThermalZoneObj",
84198054Sjkim    /* 14 */ ", BuffFieldObj",
85198054Sjkim    /* 15 */ ", DDBHandleObj",
86198054Sjkim    /* 16 */ "",                    /* Debug object */
87198054Sjkim    /* 17 */ ", FieldUnitObj",
88198054Sjkim    /* 18 */ ", FieldUnitObj",
89198054Sjkim    /* 19 */ ", FieldUnitObj"
90198054Sjkim};
91198054Sjkim
92254745Sjkim#define METHOD_SEPARATORS           " \t,()\n"
93198054Sjkim
94254745Sjkim
95198054Sjkim/* Local prototypes */
96198054Sjkim
97198054Sjkimstatic const char *
98198054SjkimAcpiDmGetObjectTypeName (
99198054Sjkim    ACPI_OBJECT_TYPE        Type);
100198054Sjkim
101198054Sjkimstatic char *
102198054SjkimAcpiDmNormalizeParentPrefix (
103198054Sjkim    ACPI_PARSE_OBJECT       *Op,
104198054Sjkim    char                    *Path);
105198054Sjkim
106254745Sjkimstatic void
107281075SdimAcpiDmAddPathToExternalList (
108254745Sjkim    char                    *Path,
109254745Sjkim    UINT8                   Type,
110281075Sdim    UINT32                  Value,
111281075Sdim    UINT16                  Flags);
112198054Sjkim
113281075Sdimstatic ACPI_STATUS
114281075SdimAcpiDmCreateNewExternal (
115281075Sdim    char                    *ExternalPath,
116281075Sdim    char                    *InternalPath,
117281075Sdim    UINT8                   Type,
118281075Sdim    UINT32                  Value,
119281075Sdim    UINT16                  Flags);
120254745Sjkim
121281075Sdim
122198054Sjkim/*******************************************************************************
123198054Sjkim *
124198054Sjkim * FUNCTION:    AcpiDmGetObjectTypeName
125198054Sjkim *
126198054Sjkim * PARAMETERS:  Type                - An ACPI_OBJECT_TYPE
127198054Sjkim *
128198054Sjkim * RETURN:      Pointer to a string
129198054Sjkim *
130198054Sjkim * DESCRIPTION: Map an object type to the ASL object type string.
131198054Sjkim *
132198054Sjkim ******************************************************************************/
133198054Sjkim
134198054Sjkimstatic const char *
135198054SjkimAcpiDmGetObjectTypeName (
136198054Sjkim    ACPI_OBJECT_TYPE        Type)
137198054Sjkim{
138198054Sjkim
139198054Sjkim    if (Type == ACPI_TYPE_LOCAL_SCOPE)
140198054Sjkim    {
141198054Sjkim        Type = ACPI_TYPE_DEVICE;
142198054Sjkim    }
143198054Sjkim    else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
144198054Sjkim    {
145198054Sjkim        return ("");
146198054Sjkim    }
147198054Sjkim
148198054Sjkim    return (AcpiGbl_DmTypeNames[Type]);
149198054Sjkim}
150198054Sjkim
151198054Sjkim
152198054Sjkim/*******************************************************************************
153198054Sjkim *
154198054Sjkim * FUNCTION:    AcpiDmNormalizeParentPrefix
155198054Sjkim *
156198054Sjkim * PARAMETERS:  Op                  - Parse op
157198054Sjkim *              Path                - Path with parent prefix
158198054Sjkim *
159198054Sjkim * RETURN:      The full pathname to the object (from the namespace root)
160198054Sjkim *
161198054Sjkim * DESCRIPTION: Returns the full pathname of a path with parent prefix
162198054Sjkim *              The caller must free the fullpath returned.
163198054Sjkim *
164198054Sjkim ******************************************************************************/
165198054Sjkim
166198054Sjkimstatic char *
167198054SjkimAcpiDmNormalizeParentPrefix (
168198054Sjkim    ACPI_PARSE_OBJECT       *Op,
169198054Sjkim    char                    *Path)
170198054Sjkim{
171198054Sjkim    ACPI_NAMESPACE_NODE     *Node;
172198054Sjkim    char                    *Fullpath;
173198054Sjkim    char                    *ParentPath;
174198054Sjkim    ACPI_SIZE               Length;
175243347Sjkim    UINT32                  Index = 0;
176198054Sjkim
177198054Sjkim
178243347Sjkim    if (!Op)
179243347Sjkim    {
180243347Sjkim        return (NULL);
181243347Sjkim    }
182198054Sjkim
183243347Sjkim    /* Search upwards in the parse tree until we reach the next namespace node */
184243347Sjkim
185243347Sjkim    Op = Op->Common.Parent;
186198054Sjkim    while (Op)
187198054Sjkim    {
188198054Sjkim        if (Op->Common.Node)
189198054Sjkim        {
190198054Sjkim            break;
191198054Sjkim        }
192198054Sjkim
193198054Sjkim        Op = Op->Common.Parent;
194198054Sjkim    }
195198054Sjkim
196198054Sjkim    if (!Op)
197198054Sjkim    {
198198054Sjkim        return (NULL);
199198054Sjkim    }
200198054Sjkim
201198054Sjkim    /*
202198054Sjkim     * Find the actual parent node for the reference:
203198054Sjkim     * Remove all carat prefixes from the input path.
204198054Sjkim     * There may be multiple parent prefixes (For example, ^^^M000)
205198054Sjkim     */
206198054Sjkim    Node = Op->Common.Node;
207198054Sjkim    while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
208198054Sjkim    {
209209746Sjkim        Node = Node->Parent;
210198054Sjkim        Path++;
211198054Sjkim    }
212198054Sjkim
213198054Sjkim    if (!Node)
214198054Sjkim    {
215198054Sjkim        return (NULL);
216198054Sjkim    }
217198054Sjkim
218198054Sjkim    /* Get the full pathname for the parent node */
219198054Sjkim
220198054Sjkim    ParentPath = AcpiNsGetExternalPathname (Node);
221198054Sjkim    if (!ParentPath)
222198054Sjkim    {
223198054Sjkim        return (NULL);
224198054Sjkim    }
225198054Sjkim
226306536Sjkim    Length = (strlen (ParentPath) + strlen (Path) + 1);
227206117Sjkim    if (ParentPath[1])
228206117Sjkim    {
229206117Sjkim        /*
230206117Sjkim         * If ParentPath is not just a simple '\', increment the length
231206117Sjkim         * for the required dot separator (ParentPath.Path)
232206117Sjkim         */
233206117Sjkim        Length++;
234243347Sjkim
235243347Sjkim        /* For External() statements, we do not want a leading '\' */
236243347Sjkim
237243347Sjkim        if (*ParentPath == AML_ROOT_PREFIX)
238243347Sjkim        {
239243347Sjkim            Index = 1;
240243347Sjkim        }
241206117Sjkim    }
242206117Sjkim
243198054Sjkim    Fullpath = ACPI_ALLOCATE_ZEROED (Length);
244198054Sjkim    if (!Fullpath)
245198054Sjkim    {
246198054Sjkim        goto Cleanup;
247198054Sjkim    }
248198054Sjkim
249198054Sjkim    /*
250198054Sjkim     * Concatenate parent fullpath and path. For example,
251198054Sjkim     * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
252198054Sjkim     *
253198054Sjkim     * Copy the parent path
254198054Sjkim     */
255306536Sjkim    strcpy (Fullpath, &ParentPath[Index]);
256198054Sjkim
257237412Sjkim    /*
258237412Sjkim     * Add dot separator
259237412Sjkim     * (don't need dot if parent fullpath is a single backslash)
260237412Sjkim     */
261198054Sjkim    if (ParentPath[1])
262198054Sjkim    {
263306536Sjkim        strcat (Fullpath, ".");
264198054Sjkim    }
265198054Sjkim
266198054Sjkim    /* Copy child path (carat parent prefix(es) were skipped above) */
267198054Sjkim
268306536Sjkim    strcat (Fullpath, Path);
269198054Sjkim
270198054SjkimCleanup:
271198054Sjkim    ACPI_FREE (ParentPath);
272198054Sjkim    return (Fullpath);
273198054Sjkim}
274198054Sjkim
275198054Sjkim
276198054Sjkim/*******************************************************************************
277198054Sjkim *
278210976Sjkim * FUNCTION:    AcpiDmAddToExternalFileList
279210976Sjkim *
280210976Sjkim * PARAMETERS:  PathList            - Single path or list separated by comma
281210976Sjkim *
282210976Sjkim * RETURN:      None
283210976Sjkim *
284210976Sjkim * DESCRIPTION: Add external files to global list
285210976Sjkim *
286210976Sjkim ******************************************************************************/
287210976Sjkim
288210976SjkimACPI_STATUS
289210976SjkimAcpiDmAddToExternalFileList (
290281075Sdim    char                    *Pathname)
291210976Sjkim{
292210976Sjkim    ACPI_EXTERNAL_FILE      *ExternalFile;
293281075Sdim    char                    *LocalPathname;
294210976Sjkim
295210976Sjkim
296281075Sdim    if (!Pathname)
297210976Sjkim    {
298210976Sjkim        return (AE_OK);
299210976Sjkim    }
300210976Sjkim
301281075Sdim    LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
302281075Sdim    if (!LocalPathname)
303281075Sdim    {
304281075Sdim        return (AE_NO_MEMORY);
305281075Sdim    }
306210976Sjkim
307281075Sdim    ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
308281075Sdim    if (!ExternalFile)
309210976Sjkim    {
310281075Sdim        ACPI_FREE (LocalPathname);
311281075Sdim        return (AE_NO_MEMORY);
312281075Sdim    }
313210976Sjkim
314281075Sdim    /* Take a copy of the file pathname */
315210976Sjkim
316281075Sdim    strcpy (LocalPathname, Pathname);
317281075Sdim    ExternalFile->Path = LocalPathname;
318210976Sjkim
319281075Sdim    if (AcpiGbl_ExternalFileList)
320281075Sdim    {
321281075Sdim        ExternalFile->Next = AcpiGbl_ExternalFileList;
322210976Sjkim    }
323210976Sjkim
324281075Sdim    AcpiGbl_ExternalFileList = ExternalFile;
325210976Sjkim    return (AE_OK);
326210976Sjkim}
327210976Sjkim
328210976Sjkim
329210976Sjkim/*******************************************************************************
330210976Sjkim *
331210976Sjkim * FUNCTION:    AcpiDmClearExternalFileList
332210976Sjkim *
333210976Sjkim * PARAMETERS:  None
334210976Sjkim *
335210976Sjkim * RETURN:      None
336210976Sjkim *
337210976Sjkim * DESCRIPTION: Clear the external file list
338210976Sjkim *
339210976Sjkim ******************************************************************************/
340210976Sjkim
341210976Sjkimvoid
342210976SjkimAcpiDmClearExternalFileList (
343210976Sjkim    void)
344210976Sjkim{
345210976Sjkim    ACPI_EXTERNAL_FILE      *NextExternal;
346210976Sjkim
347210976Sjkim
348210976Sjkim    while (AcpiGbl_ExternalFileList)
349210976Sjkim    {
350210976Sjkim        NextExternal = AcpiGbl_ExternalFileList->Next;
351210976Sjkim        ACPI_FREE (AcpiGbl_ExternalFileList->Path);
352210976Sjkim        ACPI_FREE (AcpiGbl_ExternalFileList);
353210976Sjkim        AcpiGbl_ExternalFileList = NextExternal;
354210976Sjkim    }
355210976Sjkim}
356210976Sjkim
357210976Sjkim
358210976Sjkim/*******************************************************************************
359210976Sjkim *
360281075Sdim * FUNCTION:    AcpiDmGetExternalsFromFile
361198054Sjkim *
362281075Sdim * PARAMETERS:  None
363281075Sdim *
364281075Sdim * RETURN:      None
365281075Sdim *
366281075Sdim * DESCRIPTION: Process the optional external reference file.
367281075Sdim *
368281075Sdim * Each line in the file should be of the form:
369281075Sdim *      External (<Method namepath>, MethodObj, <ArgCount>)
370281075Sdim *
371281075Sdim * Example:
372281075Sdim *      External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
373281075Sdim *
374281075Sdim ******************************************************************************/
375281075Sdim
376281075Sdimvoid
377281075SdimAcpiDmGetExternalsFromFile (
378281075Sdim    void)
379281075Sdim{
380281075Sdim    FILE                    *ExternalRefFile;
381281075Sdim    char                    *Token;
382281075Sdim    char                    *MethodName;
383281075Sdim    UINT32                  ArgCount;
384281075Sdim    UINT32                  ImportCount = 0;
385281075Sdim
386281075Sdim
387281075Sdim    if (!Gbl_ExternalRefFilename)
388281075Sdim    {
389281075Sdim        return;
390281075Sdim    }
391281075Sdim
392281075Sdim    /* Open the file */
393281075Sdim
394281075Sdim    ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
395281075Sdim    if (!ExternalRefFile)
396281075Sdim    {
397281075Sdim        fprintf (stderr, "Could not open external reference file \"%s\"\n",
398281075Sdim            Gbl_ExternalRefFilename);
399281075Sdim        AslAbort ();
400281075Sdim        return;
401281075Sdim    }
402281075Sdim
403281075Sdim    /* Each line defines a method */
404281075Sdim
405281075Sdim    while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
406281075Sdim    {
407281075Sdim        Token = strtok (StringBuffer, METHOD_SEPARATORS);   /* "External" */
408281075Sdim        if (!Token)
409281075Sdim        {
410281075Sdim            continue;
411281075Sdim        }
412306536Sjkim
413281075Sdim        if (strcmp (Token, "External"))
414281075Sdim        {
415281075Sdim            continue;
416281075Sdim        }
417281075Sdim
418281075Sdim        MethodName = strtok (NULL, METHOD_SEPARATORS);      /* Method namepath */
419281075Sdim        if (!MethodName)
420281075Sdim        {
421281075Sdim            continue;
422281075Sdim        }
423281075Sdim
424281075Sdim        Token = strtok (NULL, METHOD_SEPARATORS);           /* "MethodObj" */
425281075Sdim        if (!Token)
426281075Sdim        {
427281075Sdim            continue;
428281075Sdim        }
429281075Sdim
430281075Sdim        if (strcmp (Token, "MethodObj"))
431281075Sdim        {
432281075Sdim            continue;
433281075Sdim        }
434281075Sdim
435281075Sdim        Token = strtok (NULL, METHOD_SEPARATORS);           /* Arg count */
436281075Sdim        if (!Token)
437281075Sdim        {
438281075Sdim            continue;
439281075Sdim        }
440281075Sdim
441281075Sdim        /* Convert arg count string to an integer */
442281075Sdim
443281075Sdim        errno = 0;
444281075Sdim        ArgCount = strtoul (Token, NULL, 0);
445281075Sdim        if (errno)
446281075Sdim        {
447281075Sdim            fprintf (stderr, "Invalid argument count (%s)\n", Token);
448281075Sdim            continue;
449281075Sdim        }
450306536Sjkim
451281075Sdim        if (ArgCount > 7)
452281075Sdim        {
453281075Sdim            fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
454281075Sdim            continue;
455281075Sdim        }
456281075Sdim
457281075Sdim        /* Add this external to the global list */
458281075Sdim
459281075Sdim        AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
460281075Sdim            Gbl_ExternalRefFilename, ArgCount, MethodName);
461281075Sdim
462281075Sdim        AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
463281075Sdim            ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
464281075Sdim        ImportCount++;
465281075Sdim    }
466281075Sdim
467281075Sdim    if (!ImportCount)
468281075Sdim    {
469306536Sjkim        fprintf (stderr,
470306536Sjkim            "Did not find any external methods in reference file \"%s\"\n",
471281075Sdim            Gbl_ExternalRefFilename);
472281075Sdim    }
473281075Sdim    else
474281075Sdim    {
475281075Sdim        /* Add the external(s) to the namespace */
476281075Sdim
477281075Sdim        AcpiDmAddExternalsToNamespace ();
478281075Sdim
479281075Sdim        AcpiOsPrintf ("%s: Imported %u external method definitions\n",
480281075Sdim            Gbl_ExternalRefFilename, ImportCount);
481281075Sdim    }
482281075Sdim
483281075Sdim    fclose (ExternalRefFile);
484281075Sdim}
485281075Sdim
486281075Sdim
487281075Sdim/*******************************************************************************
488281075Sdim *
489281075Sdim * FUNCTION:    AcpiDmAddOpToExternalList
490281075Sdim *
491198054Sjkim * PARAMETERS:  Op                  - Current parser Op
492198054Sjkim *              Path                - Internal (AML) path to the object
493198054Sjkim *              Type                - ACPI object type to be added
494198054Sjkim *              Value               - Arg count if adding a Method object
495281075Sdim *              Flags               - To be passed to the external object
496198054Sjkim *
497198054Sjkim * RETURN:      None
498198054Sjkim *
499198054Sjkim * DESCRIPTION: Insert a new name into the global list of Externals which
500198054Sjkim *              will in turn be later emitted as an External() declaration
501198054Sjkim *              in the disassembled output.
502198054Sjkim *
503281075Sdim *              This function handles the most common case where the referenced
504281075Sdim *              name is simply not found in the constructed namespace.
505281075Sdim *
506198054Sjkim ******************************************************************************/
507198054Sjkim
508198054Sjkimvoid
509281075SdimAcpiDmAddOpToExternalList (
510198054Sjkim    ACPI_PARSE_OBJECT       *Op,
511198054Sjkim    char                    *Path,
512198054Sjkim    UINT8                   Type,
513281075Sdim    UINT32                  Value,
514281075Sdim    UINT16                  Flags)
515198054Sjkim{
516198054Sjkim    char                    *ExternalPath;
517281075Sdim    char                    *InternalPath = Path;
518281075Sdim    char                    *Temp;
519198054Sjkim    ACPI_STATUS             Status;
520198054Sjkim
521198054Sjkim
522281075Sdim    ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
523281075Sdim
524281075Sdim
525198054Sjkim    if (!Path)
526198054Sjkim    {
527281075Sdim        return_VOID;
528198054Sjkim    }
529198054Sjkim
530281075Sdim    /* Remove a root backslash if present */
531246849Sjkim
532243347Sjkim    if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
533243347Sjkim    {
534243347Sjkim        Path++;
535243347Sjkim    }
536198054Sjkim
537281075Sdim    /* Externalize the pathname */
538243347Sjkim
539198054Sjkim    Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
540281075Sdim        NULL, &ExternalPath);
541198054Sjkim    if (ACPI_FAILURE (Status))
542198054Sjkim    {
543281075Sdim        return_VOID;
544198054Sjkim    }
545198054Sjkim
546243347Sjkim    /*
547243347Sjkim     * Get the full pathname from the root if "Path" has one or more
548243347Sjkim     * parent prefixes (^). Note: path will not contain a leading '\'.
549243347Sjkim     */
550198054Sjkim    if (*Path == (UINT8) AML_PARENT_PREFIX)
551198054Sjkim    {
552281075Sdim        Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
553198054Sjkim
554281075Sdim        /* Set new external path */
555198054Sjkim
556281075Sdim        ACPI_FREE (ExternalPath);
557281075Sdim        ExternalPath = Temp;
558281075Sdim        if (!Temp)
559198054Sjkim        {
560281075Sdim            return_VOID;
561198054Sjkim        }
562198054Sjkim
563281075Sdim        /* Create the new internal pathname */
564198054Sjkim
565281075Sdim        Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
566281075Sdim        Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
567198054Sjkim        if (ACPI_FAILURE (Status))
568198054Sjkim        {
569198054Sjkim            ACPI_FREE (ExternalPath);
570281075Sdim            return_VOID;
571198054Sjkim        }
572198054Sjkim    }
573198054Sjkim
574281075Sdim    /* Create the new External() declaration node */
575198054Sjkim
576281075Sdim    Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
577281075Sdim        Type, Value, Flags);
578281075Sdim    if (ACPI_FAILURE (Status))
579198054Sjkim    {
580281075Sdim        ACPI_FREE (ExternalPath);
581281075Sdim        if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
582198054Sjkim        {
583281075Sdim            ACPI_FREE (InternalPath);
584198054Sjkim        }
585198054Sjkim    }
586198054Sjkim
587281075Sdim    return_VOID;
588198054Sjkim}
589198054Sjkim
590198054Sjkim
591198054Sjkim/*******************************************************************************
592198054Sjkim *
593281075Sdim * FUNCTION:    AcpiDmAddNodeToExternalList
594254745Sjkim *
595281075Sdim * PARAMETERS:  Node                - Namespace node for object to be added
596281075Sdim *              Type                - ACPI object type to be added
597281075Sdim *              Value               - Arg count if adding a Method object
598281075Sdim *              Flags               - To be passed to the external object
599254745Sjkim *
600254745Sjkim * RETURN:      None
601254745Sjkim *
602281075Sdim * DESCRIPTION: Insert a new name into the global list of Externals which
603281075Sdim *              will in turn be later emitted as an External() declaration
604281075Sdim *              in the disassembled output.
605254745Sjkim *
606281075Sdim *              This function handles the case where the referenced name has
607281075Sdim *              been found in the namespace, but the name originated in a
608281075Sdim *              table other than the one that is being disassembled (such
609281075Sdim *              as a table that is added via the iASL -e option).
610254745Sjkim *
611254745Sjkim ******************************************************************************/
612254745Sjkim
613254745Sjkimvoid
614281075SdimAcpiDmAddNodeToExternalList (
615281075Sdim    ACPI_NAMESPACE_NODE     *Node,
616281075Sdim    UINT8                   Type,
617281075Sdim    UINT32                  Value,
618281075Sdim    UINT16                  Flags)
619254745Sjkim{
620281075Sdim    char                    *ExternalPath;
621281075Sdim    char                    *InternalPath;
622281075Sdim    char                    *Temp;
623281075Sdim    ACPI_STATUS             Status;
624254745Sjkim
625254745Sjkim
626281075Sdim    ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
627281075Sdim
628281075Sdim
629281075Sdim    if (!Node)
630254745Sjkim    {
631281075Sdim        return_VOID;
632254745Sjkim    }
633254745Sjkim
634281075Sdim    /* Get the full external and internal pathnames to the node */
635254745Sjkim
636281075Sdim    ExternalPath = AcpiNsGetExternalPathname (Node);
637281075Sdim    if (!ExternalPath)
638254745Sjkim    {
639281075Sdim        return_VOID;
640254745Sjkim    }
641254745Sjkim
642281075Sdim    Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
643281075Sdim    if (ACPI_FAILURE (Status))
644254745Sjkim    {
645281075Sdim        ACPI_FREE (ExternalPath);
646281075Sdim        return_VOID;
647281075Sdim    }
648254745Sjkim
649281075Sdim    /* Remove the root backslash */
650254745Sjkim
651281075Sdim    if ((*ExternalPath == AML_ROOT_PREFIX) && (ExternalPath[1]))
652281075Sdim    {
653306536Sjkim        Temp = ACPI_ALLOCATE_ZEROED (strlen (ExternalPath) + 1);
654281075Sdim        if (!Temp)
655254745Sjkim        {
656281075Sdim            return_VOID;
657254745Sjkim        }
658254745Sjkim
659306536Sjkim        strcpy (Temp, &ExternalPath[1]);
660281075Sdim        ACPI_FREE (ExternalPath);
661281075Sdim        ExternalPath = Temp;
662281075Sdim    }
663254745Sjkim
664281075Sdim    /* Create the new External() declaration node */
665254745Sjkim
666281075Sdim    Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
667281075Sdim        Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
668281075Sdim    if (ACPI_FAILURE (Status))
669254745Sjkim    {
670281075Sdim        ACPI_FREE (ExternalPath);
671281075Sdim        ACPI_FREE (InternalPath);
672254745Sjkim    }
673254745Sjkim
674281075Sdim    return_VOID;
675254745Sjkim}
676254745Sjkim
677254745Sjkim
678254745Sjkim/*******************************************************************************
679254745Sjkim *
680281075Sdim * FUNCTION:    AcpiDmAddPathToExternalList
681254745Sjkim *
682281075Sdim * PARAMETERS:  Path                - External name of the object to be added
683254745Sjkim *              Type                - ACPI object type to be added
684254745Sjkim *              Value               - Arg count if adding a Method object
685281075Sdim *              Flags               - To be passed to the external object
686254745Sjkim *
687254745Sjkim * RETURN:      None
688254745Sjkim *
689254745Sjkim * DESCRIPTION: Insert a new name into the global list of Externals which
690254745Sjkim *              will in turn be later emitted as an External() declaration
691254745Sjkim *              in the disassembled output.
692254745Sjkim *
693281075Sdim *              This function currently is used to add externals via a
694281075Sdim *              reference file (via the -fe iASL option).
695281075Sdim *
696254745Sjkim ******************************************************************************/
697254745Sjkim
698254745Sjkimstatic void
699281075SdimAcpiDmAddPathToExternalList (
700254745Sjkim    char                    *Path,
701254745Sjkim    UINT8                   Type,
702281075Sdim    UINT32                  Value,
703281075Sdim    UINT16                  Flags)
704254745Sjkim{
705254745Sjkim    char                    *InternalPath;
706254745Sjkim    char                    *ExternalPath;
707254745Sjkim    ACPI_STATUS             Status;
708254745Sjkim
709254745Sjkim
710281075Sdim    ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
711281075Sdim
712281075Sdim
713254745Sjkim    if (!Path)
714254745Sjkim    {
715281075Sdim        return_VOID;
716254745Sjkim    }
717254745Sjkim
718281075Sdim    /* Remove a root backslash if present */
719254745Sjkim
720281075Sdim    if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
721254745Sjkim    {
722281075Sdim        Path++;
723254745Sjkim    }
724254745Sjkim
725281075Sdim    /* Create the internal and external pathnames */
726281075Sdim
727281075Sdim    Status = AcpiNsInternalizeName (Path, &InternalPath);
728281075Sdim    if (ACPI_FAILURE (Status))
729254745Sjkim    {
730281075Sdim        return_VOID;
731254745Sjkim    }
732254745Sjkim
733281075Sdim    Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
734281075Sdim        NULL, &ExternalPath);
735281075Sdim    if (ACPI_FAILURE (Status))
736281075Sdim    {
737281075Sdim        ACPI_FREE (InternalPath);
738281075Sdim        return_VOID;
739281075Sdim    }
740281075Sdim
741281075Sdim    /* Create the new External() declaration node */
742281075Sdim
743281075Sdim    Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
744281075Sdim        Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
745281075Sdim    if (ACPI_FAILURE (Status))
746281075Sdim    {
747281075Sdim        ACPI_FREE (ExternalPath);
748281075Sdim        ACPI_FREE (InternalPath);
749281075Sdim    }
750281075Sdim
751281075Sdim    return_VOID;
752281075Sdim}
753281075Sdim
754281075Sdim
755281075Sdim/*******************************************************************************
756281075Sdim *
757281075Sdim * FUNCTION:    AcpiDmCreateNewExternal
758281075Sdim *
759281075Sdim * PARAMETERS:  ExternalPath        - External path to the object
760281075Sdim *              InternalPath        - Internal (AML) path to the object
761281075Sdim *              Type                - ACPI object type to be added
762281075Sdim *              Value               - Arg count if adding a Method object
763281075Sdim *              Flags               - To be passed to the external object
764281075Sdim *
765281075Sdim * RETURN:      Status
766281075Sdim *
767281075Sdim * DESCRIPTION: Common low-level function to insert a new name into the global
768281075Sdim *              list of Externals which will in turn be later emitted as
769281075Sdim *              External() declarations in the disassembled output.
770281075Sdim *
771281075Sdim *              Note: The external name should not include a root prefix
772281075Sdim *              (backslash). We do not want External() statements to contain
773281075Sdim *              a leading '\', as this prevents duplicate external statements
774281075Sdim *              of the form:
775281075Sdim *
776281075Sdim *                  External (\ABCD)
777281075Sdim *                  External (ABCD)
778281075Sdim *
779281075Sdim *              This would cause a compile time error when the disassembled
780281075Sdim *              output file is recompiled.
781281075Sdim *
782281075Sdim *              There are two cases that are handled here. For both, we emit
783281075Sdim *              an External() statement:
784281075Sdim *              1) The name was simply not found in the namespace.
785281075Sdim *              2) The name was found, but it originated in a table other than
786281075Sdim *              the table that is being disassembled.
787281075Sdim *
788281075Sdim ******************************************************************************/
789281075Sdim
790281075Sdimstatic ACPI_STATUS
791281075SdimAcpiDmCreateNewExternal (
792281075Sdim    char                    *ExternalPath,
793281075Sdim    char                    *InternalPath,
794281075Sdim    UINT8                   Type,
795281075Sdim    UINT32                  Value,
796281075Sdim    UINT16                  Flags)
797281075Sdim{
798281075Sdim    ACPI_EXTERNAL_LIST      *NewExternal;
799281075Sdim    ACPI_EXTERNAL_LIST      *NextExternal;
800281075Sdim    ACPI_EXTERNAL_LIST      *PrevExternal = NULL;
801281075Sdim
802281075Sdim
803281075Sdim    ACPI_FUNCTION_TRACE (DmCreateNewExternal);
804281075Sdim
805281075Sdim
806254745Sjkim    /* Check all existing externals to ensure no duplicates */
807254745Sjkim
808254745Sjkim    NextExternal = AcpiGbl_ExternalList;
809254745Sjkim    while (NextExternal)
810254745Sjkim    {
811306536Sjkim        /* Check for duplicates */
812306536Sjkim
813306536Sjkim        if (!strcmp (ExternalPath, NextExternal->Path))
814254745Sjkim        {
815306536Sjkim            /*
816306536Sjkim             * If this external came from an External() opcode, we are
817306536Sjkim             * finished with this one. (No need to check any further).
818306536Sjkim             */
819306536Sjkim            if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)
820254745Sjkim            {
821306536Sjkim                return_ACPI_STATUS (AE_ALREADY_EXISTS);
822254745Sjkim            }
823254745Sjkim
824254745Sjkim            /* Allow upgrade of type from ANY */
825254745Sjkim
826306536Sjkim            else if ((NextExternal->Type == ACPI_TYPE_ANY) &&
827306536Sjkim                (Type != ACPI_TYPE_ANY))
828254745Sjkim            {
829254745Sjkim                NextExternal->Type = Type;
830306536Sjkim            }
831306536Sjkim
832306536Sjkim            /* Update the argument count as necessary */
833306536Sjkim
834306536Sjkim            if (Value < NextExternal->Value)
835306536Sjkim            {
836254745Sjkim                NextExternal->Value = Value;
837254745Sjkim            }
838254745Sjkim
839306536Sjkim            /* Update flags. */
840306536Sjkim
841306536Sjkim            NextExternal->Flags |= Flags;
842306536Sjkim            NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED;
843306536Sjkim
844281075Sdim            return_ACPI_STATUS (AE_ALREADY_EXISTS);
845254745Sjkim        }
846254745Sjkim
847254745Sjkim        NextExternal = NextExternal->Next;
848254745Sjkim    }
849254745Sjkim
850254745Sjkim    /* Allocate and init a new External() descriptor */
851254745Sjkim
852254745Sjkim    NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
853254745Sjkim    if (!NewExternal)
854254745Sjkim    {
855281075Sdim        return_ACPI_STATUS (AE_NO_MEMORY);
856254745Sjkim    }
857254745Sjkim
858281075Sdim    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
859281075Sdim        "Adding external reference node (%s) type [%s]\n",
860281075Sdim        ExternalPath, AcpiUtGetTypeName (Type)));
861254745Sjkim
862281075Sdim    NewExternal->Flags = Flags;
863281075Sdim    NewExternal->Value = Value;
864254745Sjkim    NewExternal->Path = ExternalPath;
865254745Sjkim    NewExternal->Type = Type;
866306536Sjkim    NewExternal->Length = (UINT16) strlen (ExternalPath);
867254745Sjkim    NewExternal->InternalPath = InternalPath;
868254745Sjkim
869254745Sjkim    /* Link the new descriptor into the global list, alphabetically ordered */
870254745Sjkim
871254745Sjkim    NextExternal = AcpiGbl_ExternalList;
872254745Sjkim    while (NextExternal)
873254745Sjkim    {
874254745Sjkim        if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
875254745Sjkim        {
876254745Sjkim            if (PrevExternal)
877254745Sjkim            {
878254745Sjkim                PrevExternal->Next = NewExternal;
879254745Sjkim            }
880254745Sjkim            else
881254745Sjkim            {
882254745Sjkim                AcpiGbl_ExternalList = NewExternal;
883254745Sjkim            }
884254745Sjkim
885254745Sjkim            NewExternal->Next = NextExternal;
886281075Sdim            return_ACPI_STATUS (AE_OK);
887254745Sjkim        }
888254745Sjkim
889254745Sjkim        PrevExternal = NextExternal;
890254745Sjkim        NextExternal = NextExternal->Next;
891254745Sjkim    }
892254745Sjkim
893254745Sjkim    if (PrevExternal)
894254745Sjkim    {
895254745Sjkim        PrevExternal->Next = NewExternal;
896254745Sjkim    }
897254745Sjkim    else
898254745Sjkim    {
899254745Sjkim        AcpiGbl_ExternalList = NewExternal;
900254745Sjkim    }
901281075Sdim
902281075Sdim    return_ACPI_STATUS (AE_OK);
903254745Sjkim}
904254745Sjkim
905254745Sjkim
906254745Sjkim/*******************************************************************************
907254745Sjkim *
908198054Sjkim * FUNCTION:    AcpiDmAddExternalsToNamespace
909198054Sjkim *
910198054Sjkim * PARAMETERS:  None
911198054Sjkim *
912198054Sjkim * RETURN:      None
913198054Sjkim *
914198054Sjkim * DESCRIPTION: Add all externals to the namespace. Allows externals to be
915198054Sjkim *              "resolved".
916198054Sjkim *
917198054Sjkim ******************************************************************************/
918198054Sjkim
919198054Sjkimvoid
920198054SjkimAcpiDmAddExternalsToNamespace (
921198054Sjkim    void)
922198054Sjkim{
923198054Sjkim    ACPI_STATUS             Status;
924198054Sjkim    ACPI_NAMESPACE_NODE     *Node;
925235945Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
926198054Sjkim    ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
927198054Sjkim
928198054Sjkim
929198054Sjkim    while (External)
930198054Sjkim    {
931198054Sjkim        /* Add the external name (object) into the namespace */
932198054Sjkim
933198054Sjkim        Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
934306536Sjkim            ACPI_IMODE_LOAD_PASS1,
935306536Sjkim            ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
936306536Sjkim            NULL, &Node);
937198054Sjkim
938198054Sjkim        if (ACPI_FAILURE (Status))
939198054Sjkim        {
940198054Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
941198054Sjkim                "while adding external to namespace [%s]",
942198054Sjkim                External->Path));
943198054Sjkim        }
944235945Sjkim
945235945Sjkim        else switch (External->Type)
946198054Sjkim        {
947235945Sjkim        case ACPI_TYPE_METHOD:
948235945Sjkim
949198054Sjkim            /* For methods, we need to save the argument count */
950198054Sjkim
951235945Sjkim            ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
952235945Sjkim            ObjDesc->Method.ParamCount = (UINT8) External->Value;
953235945Sjkim            Node->Object = ObjDesc;
954235945Sjkim            break;
955235945Sjkim
956235945Sjkim        case ACPI_TYPE_REGION:
957235945Sjkim
958235945Sjkim            /* Regions require a region sub-object */
959235945Sjkim
960235945Sjkim            ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
961235945Sjkim            ObjDesc->Region.Node = Node;
962235945Sjkim            Node->Object = ObjDesc;
963235945Sjkim            break;
964235945Sjkim
965235945Sjkim        default:
966250838Sjkim
967235945Sjkim            break;
968198054Sjkim        }
969198054Sjkim
970198054Sjkim        External = External->Next;
971198054Sjkim    }
972198054Sjkim}
973198054Sjkim
974198054Sjkim
975198054Sjkim/*******************************************************************************
976198054Sjkim *
977198054Sjkim * FUNCTION:    AcpiDmGetExternalMethodCount
978198054Sjkim *
979198054Sjkim * PARAMETERS:  None
980198054Sjkim *
981198054Sjkim * RETURN:      The number of control method externals in the external list
982198054Sjkim *
983198054Sjkim * DESCRIPTION: Return the number of method externals that have been generated.
984198054Sjkim *              If any control method externals have been found, we must
985198054Sjkim *              re-parse the entire definition block with the new information
986198054Sjkim *              (number of arguments for the methods.) This is limitation of
987198054Sjkim *              AML, we don't know the number of arguments from the control
988198054Sjkim *              method invocation itself.
989198054Sjkim *
990198054Sjkim ******************************************************************************/
991198054Sjkim
992198054SjkimUINT32
993198054SjkimAcpiDmGetExternalMethodCount (
994198054Sjkim    void)
995198054Sjkim{
996198054Sjkim    ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
997198054Sjkim    UINT32                  Count = 0;
998198054Sjkim
999198054Sjkim
1000198054Sjkim    while (External)
1001198054Sjkim    {
1002198054Sjkim        if (External->Type == ACPI_TYPE_METHOD)
1003198054Sjkim        {
1004198054Sjkim            Count++;
1005198054Sjkim        }
1006198054Sjkim
1007198054Sjkim        External = External->Next;
1008198054Sjkim    }
1009198054Sjkim
1010198054Sjkim    return (Count);
1011198054Sjkim}
1012198054Sjkim
1013198054Sjkim
1014198054Sjkim/*******************************************************************************
1015198054Sjkim *
1016198054Sjkim * FUNCTION:    AcpiDmClearExternalList
1017198054Sjkim *
1018198054Sjkim * PARAMETERS:  None
1019198054Sjkim *
1020198054Sjkim * RETURN:      None
1021198054Sjkim *
1022198054Sjkim * DESCRIPTION: Free the entire External info list
1023198054Sjkim *
1024198054Sjkim ******************************************************************************/
1025198054Sjkim
1026198054Sjkimvoid
1027198054SjkimAcpiDmClearExternalList (
1028198054Sjkim    void)
1029198054Sjkim{
1030198054Sjkim    ACPI_EXTERNAL_LIST      *NextExternal;
1031198054Sjkim
1032198054Sjkim
1033198054Sjkim    while (AcpiGbl_ExternalList)
1034198054Sjkim    {
1035198054Sjkim        NextExternal = AcpiGbl_ExternalList->Next;
1036198054Sjkim        ACPI_FREE (AcpiGbl_ExternalList->Path);
1037198054Sjkim        ACPI_FREE (AcpiGbl_ExternalList);
1038198054Sjkim        AcpiGbl_ExternalList = NextExternal;
1039198054Sjkim    }
1040198054Sjkim}
1041198054Sjkim
1042198054Sjkim
1043198054Sjkim/*******************************************************************************
1044198054Sjkim *
1045198054Sjkim * FUNCTION:    AcpiDmEmitExternals
1046198054Sjkim *
1047198054Sjkim * PARAMETERS:  None
1048198054Sjkim *
1049198054Sjkim * RETURN:      None
1050198054Sjkim *
1051198054Sjkim * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1052198054Sjkim *              the global external info list.
1053198054Sjkim *
1054198054Sjkim ******************************************************************************/
1055198054Sjkim
1056198054Sjkimvoid
1057198054SjkimAcpiDmEmitExternals (
1058198054Sjkim    void)
1059198054Sjkim{
1060198054Sjkim    ACPI_EXTERNAL_LIST      *NextExternal;
1061198054Sjkim
1062198054Sjkim
1063198054Sjkim    if (!AcpiGbl_ExternalList)
1064198054Sjkim    {
1065198054Sjkim        return;
1066198054Sjkim    }
1067198054Sjkim
1068198054Sjkim    /*
1069246849Sjkim     * Determine the number of control methods in the external list, and
1070246849Sjkim     * also how many of those externals were resolved via the namespace.
1071246849Sjkim     */
1072246849Sjkim    NextExternal = AcpiGbl_ExternalList;
1073246849Sjkim    while (NextExternal)
1074246849Sjkim    {
1075246849Sjkim        if (NextExternal->Type == ACPI_TYPE_METHOD)
1076246849Sjkim        {
1077246849Sjkim            AcpiGbl_NumExternalMethods++;
1078281075Sdim            if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1079246849Sjkim            {
1080246849Sjkim                AcpiGbl_ResolvedExternalMethods++;
1081246849Sjkim            }
1082246849Sjkim        }
1083246849Sjkim
1084246849Sjkim        NextExternal = NextExternal->Next;
1085246849Sjkim    }
1086246849Sjkim
1087246849Sjkim    /* Check if any control methods were unresolved */
1088246849Sjkim
1089246849Sjkim    AcpiDmUnresolvedWarning (1);
1090246849Sjkim
1091254745Sjkim    if (Gbl_ExternalRefFilename)
1092254745Sjkim    {
1093254745Sjkim        AcpiOsPrintf (
1094306536Sjkim            "    /*\n     * External declarations were imported from\n"
1095306536Sjkim            "     * a reference file -- %s\n     */\n\n",
1096254745Sjkim            Gbl_ExternalRefFilename);
1097254745Sjkim    }
1098254745Sjkim
1099246849Sjkim    /*
1100306536Sjkim     * Walk and emit the list of externals found during the AML parsing
1101198054Sjkim     */
1102198054Sjkim    while (AcpiGbl_ExternalList)
1103198054Sjkim    {
1104281075Sdim        if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1105253690Sjkim        {
1106306536Sjkim            AcpiOsPrintf ("    External (%s%s)",
1107253690Sjkim                AcpiGbl_ExternalList->Path,
1108253690Sjkim                AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1109198054Sjkim
1110306536Sjkim            /* Check for "unresolved" method reference */
1111253690Sjkim
1112306536Sjkim            if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) &&
1113306536Sjkim                (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1114246849Sjkim            {
1115306536Sjkim                AcpiOsPrintf ("    // Warning: Unknown method, "
1116306536Sjkim                    "guessing %u arguments",
1117246849Sjkim                    AcpiGbl_ExternalList->Value);
1118246849Sjkim            }
1119306536Sjkim
1120306536Sjkim            /* Check for external from a external references file */
1121306536Sjkim
1122306536Sjkim            else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE)
1123306536Sjkim            {
1124306536Sjkim                if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1125306536Sjkim                {
1126306536Sjkim                    AcpiOsPrintf ("    // %u Arguments",
1127306536Sjkim                        AcpiGbl_ExternalList->Value);
1128306536Sjkim                }
1129306536Sjkim
1130306536Sjkim                AcpiOsPrintf ("    // From external reference file");
1131306536Sjkim            }
1132306536Sjkim
1133306536Sjkim            /* This is the normal external case */
1134306536Sjkim
1135246849Sjkim            else
1136246849Sjkim            {
1137306536Sjkim                /* For methods, add a comment with the number of arguments */
1138306536Sjkim
1139306536Sjkim                if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1140306536Sjkim                {
1141306536Sjkim                    AcpiOsPrintf ("    // %u Arguments",
1142306536Sjkim                        AcpiGbl_ExternalList->Value);
1143306536Sjkim                }
1144246849Sjkim            }
1145306536Sjkim
1146306536Sjkim            AcpiOsPrintf ("\n");
1147198054Sjkim        }
1148198054Sjkim
1149198054Sjkim        /* Free this external info block and move on to next external */
1150198054Sjkim
1151198054Sjkim        NextExternal = AcpiGbl_ExternalList->Next;
1152281075Sdim        if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1153198054Sjkim        {
1154198054Sjkim            ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1155198054Sjkim        }
1156198054Sjkim
1157198054Sjkim        ACPI_FREE (AcpiGbl_ExternalList->Path);
1158198054Sjkim        ACPI_FREE (AcpiGbl_ExternalList);
1159198054Sjkim        AcpiGbl_ExternalList = NextExternal;
1160198054Sjkim    }
1161198054Sjkim
1162198054Sjkim    AcpiOsPrintf ("\n");
1163198054Sjkim}
1164246849Sjkim
1165246849Sjkim
1166246849Sjkim/*******************************************************************************
1167246849Sjkim *
1168246849Sjkim * FUNCTION:    AcpiDmUnresolvedWarning
1169246849Sjkim *
1170246849Sjkim * PARAMETERS:  Type                - Where to output the warning.
1171246849Sjkim *                                    0 means write to stderr
1172246849Sjkim *                                    1 means write to AcpiOsPrintf
1173246849Sjkim *
1174246849Sjkim * RETURN:      None
1175246849Sjkim *
1176246849Sjkim * DESCRIPTION: Issue warning message if there are unresolved external control
1177246849Sjkim *              methods within the disassembly.
1178246849Sjkim *
1179246849Sjkim ******************************************************************************/
1180246849Sjkim
1181246849Sjkim#if 0
1182246849SjkimSummary of the external control method problem:
1183246849Sjkim
1184246849SjkimWhen the -e option is used with disassembly, the various SSDTs are simply
1185246849Sjkimloaded into a global namespace for the disassembler to use in order to
1186246849Sjkimresolve control method references (invocations).
1187246849Sjkim
1188246849SjkimThe disassembler tracks any such references, and will emit an External()
1189246849Sjkimstatement for these types of methods, with the proper number of arguments .
1190246849Sjkim
1191246849SjkimWithout the SSDTs, the AML does not contain enough information to properly
1192246849Sjkimdisassemble the control method invocation -- because the disassembler does
1193246849Sjkimnot know how many arguments to parse.
1194246849Sjkim
1195246849SjkimAn example: Assume we have two control methods. ABCD has one argument, and
1196246849SjkimEFGH has zero arguments. Further, we have two additional control methods
1197246849Sjkimthat invoke ABCD and EFGH, named T1 and T2:
1198246849Sjkim
1199246849Sjkim    Method (ABCD, 1)
1200246849Sjkim    {
1201246849Sjkim    }
1202246849Sjkim    Method (EFGH, 0)
1203246849Sjkim    {
1204246849Sjkim    }
1205246849Sjkim    Method (T1)
1206246849Sjkim    {
1207246849Sjkim        ABCD (Add (2, 7, Local0))
1208246849Sjkim    }
1209246849Sjkim    Method (T2)
1210246849Sjkim    {
1211246849Sjkim        EFGH ()
1212246849Sjkim        Add (2, 7, Local0)
1213246849Sjkim    }
1214246849Sjkim
1215246849SjkimHere is the AML code that is generated for T1 and T2:
1216246849Sjkim
1217246849Sjkim     185:      Method (T1)
1218246849Sjkim
1219246849Sjkim0000034C:  14 10 54 31 5F 5F 00 ...    "..T1__."
1220246849Sjkim
1221246849Sjkim     186:      {
1222246849Sjkim     187:          ABCD (Add (2, 7, Local0))
1223246849Sjkim
1224246849Sjkim00000353:  41 42 43 44 ............    "ABCD"
1225246849Sjkim00000357:  72 0A 02 0A 07 60 ......    "r....`"
1226246849Sjkim
1227246849Sjkim     188:      }
1228246849Sjkim
1229246849Sjkim     190:      Method (T2)
1230246849Sjkim
1231246849Sjkim0000035D:  14 10 54 32 5F 5F 00 ...    "..T2__."
1232246849Sjkim
1233246849Sjkim     191:      {
1234246849Sjkim     192:          EFGH ()
1235246849Sjkim
1236246849Sjkim00000364:  45 46 47 48 ............    "EFGH"
1237246849Sjkim
1238246849Sjkim     193:          Add (2, 7, Local0)
1239246849Sjkim
1240246849Sjkim00000368:  72 0A 02 0A 07 60 ......    "r....`"
1241246849Sjkim     194:      }
1242246849Sjkim
1243246849SjkimNote that the AML code for T1 and T2 is essentially identical. When
1244246849Sjkimdisassembling this code, the methods ABCD and EFGH must be known to the
1245246849Sjkimdisassembler, otherwise it does not know how to handle the method invocations.
1246246849Sjkim
1247246849SjkimIn other words, if ABCD and EFGH are actually external control methods
1248246849Sjkimappearing in an SSDT, the disassembler does not know what to do unless
1249246849Sjkimthe owning SSDT has been loaded via the -e option.
1250246849Sjkim#endif
1251246849Sjkim
1252306536Sjkimstatic char             ExternalWarningPart1[600];
1253306536Sjkimstatic char             ExternalWarningPart2[400];
1254306536Sjkimstatic char             ExternalWarningPart3[400];
1255306536Sjkimstatic char             ExternalWarningPart4[200];
1256306536Sjkim
1257246849Sjkimvoid
1258246849SjkimAcpiDmUnresolvedWarning (
1259246849Sjkim    UINT8                   Type)
1260246849Sjkim{
1261306536Sjkim    char                    *Format;
1262306536Sjkim    char                    Pad[] = "     *";
1263306536Sjkim    char                    NoPad[] = "";
1264246849Sjkim
1265306536Sjkim
1266246849Sjkim    if (!AcpiGbl_NumExternalMethods)
1267246849Sjkim    {
1268246849Sjkim        return;
1269246849Sjkim    }
1270246849Sjkim
1271306536Sjkim    if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
1272306536Sjkim    {
1273306536Sjkim        return;
1274306536Sjkim    }
1275306536Sjkim
1276306536Sjkim    Format = Type ? Pad : NoPad;
1277306536Sjkim
1278306536Sjkim    sprintf (ExternalWarningPart1,
1279306536Sjkim        "%s iASL Warning: There %s %u external control method%s found during\n"
1280306536Sjkim        "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1281306536Sjkim        "%s ACPI tables may be required to properly disassemble the code. This\n"
1282306536Sjkim        "%s resulting disassembler output file may not compile because the\n"
1283306536Sjkim        "%s disassembler did not know how many arguments to assign to the\n"
1284306536Sjkim        "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1285306536Sjkim        "%s runtime and may or may not be available via the host OS.\n",
1286306536Sjkim        Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
1287306536Sjkim        AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
1288306536Sjkim        Format, AcpiGbl_ResolvedExternalMethods,
1289306536Sjkim        (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
1290306536Sjkim        (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
1291306536Sjkim        Format, Format, Format, Format, Format);
1292306536Sjkim
1293306536Sjkim    sprintf (ExternalWarningPart2,
1294306536Sjkim        "%s To specify the tables needed to resolve external control method\n"
1295306536Sjkim        "%s references, the -e option can be used to specify the filenames.\n"
1296306536Sjkim        "%s Example iASL invocations:\n"
1297306536Sjkim        "%s     iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1298306536Sjkim        "%s     iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1299306536Sjkim        "%s     iasl -e ssdt*.aml -d dsdt.aml\n",
1300306536Sjkim        Format, Format, Format, Format, Format, Format);
1301306536Sjkim
1302306536Sjkim    sprintf (ExternalWarningPart3,
1303306536Sjkim        "%s In addition, the -fe option can be used to specify a file containing\n"
1304306536Sjkim        "%s control method external declarations with the associated method\n"
1305306536Sjkim        "%s argument counts. Each line of the file must be of the form:\n"
1306306536Sjkim        "%s     External (<method pathname>, MethodObj, <argument count>)\n"
1307306536Sjkim        "%s Invocation:\n"
1308306536Sjkim        "%s     iasl -fe refs.txt -d dsdt.aml\n",
1309306536Sjkim        Format, Format, Format, Format, Format, Format);
1310306536Sjkim
1311306536Sjkim    sprintf (ExternalWarningPart4,
1312306536Sjkim        "%s The following methods were unresolved and many not compile properly\n"
1313306536Sjkim        "%s because the disassembler had to guess at the number of arguments\n"
1314306536Sjkim        "%s required for each:\n",
1315306536Sjkim        Format, Format, Format);
1316306536Sjkim
1317246849Sjkim    if (Type)
1318246849Sjkim    {
1319246849Sjkim        if (!AcpiGbl_ExternalFileList)
1320246849Sjkim        {
1321246849Sjkim            /* The -e option was not specified */
1322246849Sjkim
1323306536Sjkim           AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     *\n%s     */\n",
1324306536Sjkim               ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
1325306536Sjkim               ExternalWarningPart4);
1326246849Sjkim        }
1327306536Sjkim        else
1328246849Sjkim        {
1329246849Sjkim            /* The -e option was specified, but there are still some unresolved externals */
1330246849Sjkim
1331306536Sjkim            AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     */\n",
1332306536Sjkim               ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
1333246849Sjkim        }
1334246849Sjkim    }
1335246849Sjkim    else
1336246849Sjkim    {
1337246849Sjkim        if (!AcpiGbl_ExternalFileList)
1338246849Sjkim        {
1339246849Sjkim            /* The -e option was not specified */
1340246849Sjkim
1341306536Sjkim            fprintf (stderr, "\n%s\n%s\n%s\n",
1342306536Sjkim               ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
1343246849Sjkim        }
1344306536Sjkim        else
1345246849Sjkim        {
1346246849Sjkim            /* The -e option was specified, but there are still some unresolved externals */
1347246849Sjkim
1348306536Sjkim            fprintf (stderr, "\n%s\n%s\n",
1349306536Sjkim               ExternalWarningPart1, ExternalWarningPart3);
1350246849Sjkim        }
1351246849Sjkim    }
1352246849Sjkim}
1353