1198054Sjkim/******************************************************************************
2198054Sjkim *
3198054Sjkim * Module Name: dmextern - Support for External() ASL statements
4198054Sjkim *
5198054Sjkim *****************************************************************************/
6198054Sjkim
7316303Sjkim/******************************************************************************
8316303Sjkim *
9316303Sjkim * 1. Copyright Notice
10316303Sjkim *
11316303Sjkim * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp.
12198054Sjkim * All rights reserved.
13198054Sjkim *
14316303Sjkim * 2. License
15316303Sjkim *
16316303Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property
17316303Sjkim * rights. You may have additional license terms from the party that provided
18316303Sjkim * you this software, covering your right to use that party's intellectual
19316303Sjkim * property rights.
20316303Sjkim *
21316303Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22316303Sjkim * copy of the source code appearing in this file ("Covered Code") an
23316303Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24316303Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy,
25316303Sjkim * make derivatives, distribute, use and display any portion of the Covered
26316303Sjkim * Code in any form, with the right to sublicense such rights; and
27316303Sjkim *
28316303Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29316303Sjkim * license (with the right to sublicense), under only those claims of Intel
30316303Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell,
31316303Sjkim * offer to sell, and import the Covered Code and derivative works thereof
32316303Sjkim * solely to the minimum extent necessary to exercise the above copyright
33316303Sjkim * license, and in no event shall the patent license extend to any additions
34316303Sjkim * to or modifications of the Original Intel Code. No other license or right
35316303Sjkim * is granted directly or by implication, estoppel or otherwise;
36316303Sjkim *
37316303Sjkim * The above copyright and patent license is granted only if the following
38316303Sjkim * conditions are met:
39316303Sjkim *
40316303Sjkim * 3. Conditions
41316303Sjkim *
42316303Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43316303Sjkim * Redistribution of source code of any substantial portion of the Covered
44316303Sjkim * Code or modification with rights to further distribute source must include
45316303Sjkim * the above Copyright Notice, the above License, this list of Conditions,
46316303Sjkim * and the following Disclaimer and Export Compliance provision. In addition,
47316303Sjkim * Licensee must cause all Covered Code to which Licensee contributes to
48316303Sjkim * contain a file documenting the changes Licensee made to create that Covered
49316303Sjkim * Code and the date of any change. Licensee must include in that file the
50316303Sjkim * documentation of any changes made by any predecessor Licensee. Licensee
51316303Sjkim * must include a prominent statement that the modification is derived,
52316303Sjkim * directly or indirectly, from Original Intel Code.
53316303Sjkim *
54316303Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55316303Sjkim * Redistribution of source code of any substantial portion of the Covered
56316303Sjkim * Code or modification without rights to further distribute source must
57316303Sjkim * include the following Disclaimer and Export Compliance provision in the
58316303Sjkim * documentation and/or other materials provided with distribution. In
59316303Sjkim * addition, Licensee may not authorize further sublicense of source of any
60316303Sjkim * portion of the Covered Code, and must include terms to the effect that the
61316303Sjkim * license from Licensee to its licensee is limited to the intellectual
62316303Sjkim * property embodied in the software Licensee provides to its licensee, and
63316303Sjkim * not to intellectual property embodied in modifications its licensee may
64316303Sjkim * make.
65316303Sjkim *
66316303Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any
67316303Sjkim * substantial portion of the Covered Code or modification must reproduce the
68316303Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance
69316303Sjkim * provision in the documentation and/or other materials provided with the
70316303Sjkim * distribution.
71316303Sjkim *
72316303Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original
73316303Sjkim * Intel Code.
74316303Sjkim *
75316303Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76316303Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or
77316303Sjkim * other dealings in products derived from or relating to the Covered Code
78316303Sjkim * without prior written authorization from Intel.
79316303Sjkim *
80316303Sjkim * 4. Disclaimer and Export Compliance
81316303Sjkim *
82316303Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83316303Sjkim * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84316303Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85316303Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86316303Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87316303Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88316303Sjkim * PARTICULAR PURPOSE.
89316303Sjkim *
90316303Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91316303Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92316303Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93316303Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94316303Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95316303Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96316303Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97316303Sjkim * LIMITED REMEDY.
98316303Sjkim *
99316303Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
100316303Sjkim * software or system incorporating such software without first obtaining any
101316303Sjkim * required license or other approval from the U. S. Department of Commerce or
102316303Sjkim * any other agency or department of the United States Government. In the
103316303Sjkim * event Licensee exports any such software from the United States or
104316303Sjkim * re-exports any such software from a foreign destination, Licensee shall
105316303Sjkim * ensure that the distribution and export/re-export of the software is in
106316303Sjkim * compliance with all laws, regulations, orders, or other restrictions of the
107316303Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108316303Sjkim * any of its subsidiaries will export/re-export any technical data, process,
109316303Sjkim * software, or service, directly or indirectly, to any country for which the
110316303Sjkim * United States government or any agency thereof requires an export license,
111316303Sjkim * other governmental approval, or letter of assurance, without first obtaining
112316303Sjkim * such license, approval or letter.
113316303Sjkim *
114316303Sjkim *****************************************************************************
115316303Sjkim *
116316303Sjkim * Alternatively, you may choose to be licensed under the terms of the
117316303Sjkim * following license:
118316303Sjkim *
119217365Sjkim * Redistribution and use in source and binary forms, with or without
120217365Sjkim * modification, are permitted provided that the following conditions
121217365Sjkim * are met:
122217365Sjkim * 1. Redistributions of source code must retain the above copyright
123217365Sjkim *    notice, this list of conditions, and the following disclaimer,
124217365Sjkim *    without modification.
125217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
127217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
128217365Sjkim *    including a substantially similar Disclaimer requirement for further
129217365Sjkim *    binary redistribution.
130217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
131217365Sjkim *    of any contributors may be used to endorse or promote products derived
132217365Sjkim *    from this software without specific prior written permission.
133198054Sjkim *
134316303Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135316303Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136316303Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137316303Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138316303Sjkim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139316303Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140316303Sjkim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141316303Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142316303Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143316303Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144316303Sjkim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145316303Sjkim *
146316303Sjkim * Alternatively, you may choose to be licensed under the terms of the
147217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
148217365Sjkim * Software Foundation.
149198054Sjkim *
150316303Sjkim *****************************************************************************/
151198054Sjkim
152198237Sjkim#include <contrib/dev/acpica/include/acpi.h>
153198237Sjkim#include <contrib/dev/acpica/include/accommon.h>
154198237Sjkim#include <contrib/dev/acpica/include/amlcode.h>
155198237Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
156198237Sjkim#include <contrib/dev/acpica/include/acdisasm.h>
157254745Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
158246849Sjkim#include <stdio.h>
159254745Sjkim#include <errno.h>
160198054Sjkim
161198054Sjkim
162198054Sjkim/*
163198054Sjkim * This module is used for application-level code (iASL disassembler) only.
164198054Sjkim *
165198054Sjkim * It contains the code to create and emit any necessary External() ASL
166198054Sjkim * statements for the module being disassembled.
167198054Sjkim */
168198054Sjkim#define _COMPONENT          ACPI_CA_DISASSEMBLER
169198054Sjkim        ACPI_MODULE_NAME    ("dmextern")
170198054Sjkim
171198054Sjkim
172198054Sjkim/*
173198054Sjkim * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
174198054Sjkim * ObjectTypeKeyword. Used to generate typed external declarations
175198054Sjkim */
176198054Sjkimstatic const char           *AcpiGbl_DmTypeNames[] =
177198054Sjkim{
178272444Sjkim    /* 00 */ ", UnknownObj",        /* Type ANY */
179198054Sjkim    /* 01 */ ", IntObj",
180198054Sjkim    /* 02 */ ", StrObj",
181198054Sjkim    /* 03 */ ", BuffObj",
182198054Sjkim    /* 04 */ ", PkgObj",
183198054Sjkim    /* 05 */ ", FieldUnitObj",
184198054Sjkim    /* 06 */ ", DeviceObj",
185198054Sjkim    /* 07 */ ", EventObj",
186198054Sjkim    /* 08 */ ", MethodObj",
187198054Sjkim    /* 09 */ ", MutexObj",
188198054Sjkim    /* 10 */ ", OpRegionObj",
189198054Sjkim    /* 11 */ ", PowerResObj",
190198054Sjkim    /* 12 */ ", ProcessorObj",
191198054Sjkim    /* 13 */ ", ThermalZoneObj",
192198054Sjkim    /* 14 */ ", BuffFieldObj",
193198054Sjkim    /* 15 */ ", DDBHandleObj",
194198054Sjkim    /* 16 */ "",                    /* Debug object */
195198054Sjkim    /* 17 */ ", FieldUnitObj",
196198054Sjkim    /* 18 */ ", FieldUnitObj",
197198054Sjkim    /* 19 */ ", FieldUnitObj"
198198054Sjkim};
199198054Sjkim
200254745Sjkim#define METHOD_SEPARATORS           " \t,()\n"
201198054Sjkim
202322877Sjkimstatic const char          *ExternalConflictMessage =
203322877Sjkim    "    // Conflicts with a later declaration";
204254745Sjkim
205322877Sjkim
206198054Sjkim/* Local prototypes */
207198054Sjkim
208198054Sjkimstatic const char *
209198054SjkimAcpiDmGetObjectTypeName (
210198054Sjkim    ACPI_OBJECT_TYPE        Type);
211198054Sjkim
212198054Sjkimstatic char *
213198054SjkimAcpiDmNormalizeParentPrefix (
214198054Sjkim    ACPI_PARSE_OBJECT       *Op,
215198054Sjkim    char                    *Path);
216198054Sjkim
217322877Sjkimstatic ACPI_STATUS
218322877SjkimAcpiDmGetExternalAndInternalPath (
219322877Sjkim    ACPI_NAMESPACE_NODE     *Node,
220322877Sjkim    char                    **ExternalPath,
221322877Sjkim    char                    **InternalPath);
222322877Sjkim
223322877Sjkimstatic ACPI_STATUS
224322877SjkimAcpiDmRemoveRootPrefix (
225322877Sjkim    char                    **Path);
226322877Sjkim
227254745Sjkimstatic void
228272444SjkimAcpiDmAddPathToExternalList (
229254745Sjkim    char                    *Path,
230254745Sjkim    UINT8                   Type,
231272444Sjkim    UINT32                  Value,
232272444Sjkim    UINT16                  Flags);
233198054Sjkim
234272444Sjkimstatic ACPI_STATUS
235272444SjkimAcpiDmCreateNewExternal (
236272444Sjkim    char                    *ExternalPath,
237272444Sjkim    char                    *InternalPath,
238272444Sjkim    UINT8                   Type,
239272444Sjkim    UINT32                  Value,
240272444Sjkim    UINT16                  Flags);
241254745Sjkim
242322877Sjkimstatic void
243322877SjkimAcpiDmCheckForExternalConflict (
244322877Sjkim    char                    *Path);
245272444Sjkim
246322877Sjkimstatic ACPI_STATUS
247322877SjkimAcpiDmResolveExternal (
248322877Sjkim    char                    *Path,
249322877Sjkim    UINT8                   Type,
250322877Sjkim    ACPI_NAMESPACE_NODE     **Node);
251322877Sjkim
252322877Sjkim
253322877Sjkimstatic void
254322877SjkimAcpiDmConflictingDeclaration (
255322877Sjkim    char                    *Path);
256322877Sjkim
257322877Sjkim
258198054Sjkim/*******************************************************************************
259198054Sjkim *
260198054Sjkim * FUNCTION:    AcpiDmGetObjectTypeName
261198054Sjkim *
262198054Sjkim * PARAMETERS:  Type                - An ACPI_OBJECT_TYPE
263198054Sjkim *
264198054Sjkim * RETURN:      Pointer to a string
265198054Sjkim *
266198054Sjkim * DESCRIPTION: Map an object type to the ASL object type string.
267198054Sjkim *
268198054Sjkim ******************************************************************************/
269198054Sjkim
270198054Sjkimstatic const char *
271198054SjkimAcpiDmGetObjectTypeName (
272198054Sjkim    ACPI_OBJECT_TYPE        Type)
273198054Sjkim{
274198054Sjkim
275198054Sjkim    if (Type == ACPI_TYPE_LOCAL_SCOPE)
276198054Sjkim    {
277198054Sjkim        Type = ACPI_TYPE_DEVICE;
278198054Sjkim    }
279198054Sjkim    else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
280198054Sjkim    {
281198054Sjkim        return ("");
282198054Sjkim    }
283198054Sjkim
284198054Sjkim    return (AcpiGbl_DmTypeNames[Type]);
285198054Sjkim}
286198054Sjkim
287198054Sjkim
288198054Sjkim/*******************************************************************************
289198054Sjkim *
290198054Sjkim * FUNCTION:    AcpiDmNormalizeParentPrefix
291198054Sjkim *
292198054Sjkim * PARAMETERS:  Op                  - Parse op
293198054Sjkim *              Path                - Path with parent prefix
294198054Sjkim *
295198054Sjkim * RETURN:      The full pathname to the object (from the namespace root)
296198054Sjkim *
297198054Sjkim * DESCRIPTION: Returns the full pathname of a path with parent prefix
298198054Sjkim *              The caller must free the fullpath returned.
299198054Sjkim *
300198054Sjkim ******************************************************************************/
301198054Sjkim
302198054Sjkimstatic char *
303198054SjkimAcpiDmNormalizeParentPrefix (
304198054Sjkim    ACPI_PARSE_OBJECT       *Op,
305198054Sjkim    char                    *Path)
306198054Sjkim{
307198054Sjkim    ACPI_NAMESPACE_NODE     *Node;
308198054Sjkim    char                    *Fullpath;
309198054Sjkim    char                    *ParentPath;
310198054Sjkim    ACPI_SIZE               Length;
311243347Sjkim    UINT32                  Index = 0;
312198054Sjkim
313198054Sjkim
314243347Sjkim    if (!Op)
315243347Sjkim    {
316243347Sjkim        return (NULL);
317243347Sjkim    }
318198054Sjkim
319243347Sjkim    /* Search upwards in the parse tree until we reach the next namespace node */
320243347Sjkim
321243347Sjkim    Op = Op->Common.Parent;
322198054Sjkim    while (Op)
323198054Sjkim    {
324198054Sjkim        if (Op->Common.Node)
325198054Sjkim        {
326198054Sjkim            break;
327198054Sjkim        }
328198054Sjkim
329198054Sjkim        Op = Op->Common.Parent;
330198054Sjkim    }
331198054Sjkim
332198054Sjkim    if (!Op)
333198054Sjkim    {
334198054Sjkim        return (NULL);
335198054Sjkim    }
336198054Sjkim
337198054Sjkim    /*
338198054Sjkim     * Find the actual parent node for the reference:
339198054Sjkim     * Remove all carat prefixes from the input path.
340198054Sjkim     * There may be multiple parent prefixes (For example, ^^^M000)
341198054Sjkim     */
342198054Sjkim    Node = Op->Common.Node;
343198054Sjkim    while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
344198054Sjkim    {
345209746Sjkim        Node = Node->Parent;
346198054Sjkim        Path++;
347198054Sjkim    }
348198054Sjkim
349198054Sjkim    if (!Node)
350198054Sjkim    {
351198054Sjkim        return (NULL);
352198054Sjkim    }
353198054Sjkim
354198054Sjkim    /* Get the full pathname for the parent node */
355198054Sjkim
356198054Sjkim    ParentPath = AcpiNsGetExternalPathname (Node);
357198054Sjkim    if (!ParentPath)
358198054Sjkim    {
359198054Sjkim        return (NULL);
360198054Sjkim    }
361198054Sjkim
362284583Sjkim    Length = (strlen (ParentPath) + strlen (Path) + 1);
363206117Sjkim    if (ParentPath[1])
364206117Sjkim    {
365206117Sjkim        /*
366206117Sjkim         * If ParentPath is not just a simple '\', increment the length
367206117Sjkim         * for the required dot separator (ParentPath.Path)
368206117Sjkim         */
369206117Sjkim        Length++;
370243347Sjkim
371243347Sjkim        /* For External() statements, we do not want a leading '\' */
372243347Sjkim
373243347Sjkim        if (*ParentPath == AML_ROOT_PREFIX)
374243347Sjkim        {
375243347Sjkim            Index = 1;
376243347Sjkim        }
377206117Sjkim    }
378206117Sjkim
379198054Sjkim    Fullpath = ACPI_ALLOCATE_ZEROED (Length);
380198054Sjkim    if (!Fullpath)
381198054Sjkim    {
382198054Sjkim        goto Cleanup;
383198054Sjkim    }
384198054Sjkim
385198054Sjkim    /*
386198054Sjkim     * Concatenate parent fullpath and path. For example,
387198054Sjkim     * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
388198054Sjkim     *
389198054Sjkim     * Copy the parent path
390198054Sjkim     */
391284583Sjkim    strcpy (Fullpath, &ParentPath[Index]);
392198054Sjkim
393237412Sjkim    /*
394237412Sjkim     * Add dot separator
395237412Sjkim     * (don't need dot if parent fullpath is a single backslash)
396237412Sjkim     */
397198054Sjkim    if (ParentPath[1])
398198054Sjkim    {
399284583Sjkim        strcat (Fullpath, ".");
400198054Sjkim    }
401198054Sjkim
402198054Sjkim    /* Copy child path (carat parent prefix(es) were skipped above) */
403198054Sjkim
404284583Sjkim    strcat (Fullpath, Path);
405198054Sjkim
406198054SjkimCleanup:
407198054Sjkim    ACPI_FREE (ParentPath);
408198054Sjkim    return (Fullpath);
409198054Sjkim}
410198054Sjkim
411198054Sjkim
412198054Sjkim/*******************************************************************************
413198054Sjkim *
414210976Sjkim * FUNCTION:    AcpiDmAddToExternalFileList
415210976Sjkim *
416210976Sjkim * PARAMETERS:  PathList            - Single path or list separated by comma
417210976Sjkim *
418210976Sjkim * RETURN:      None
419210976Sjkim *
420210976Sjkim * DESCRIPTION: Add external files to global list
421210976Sjkim *
422210976Sjkim ******************************************************************************/
423210976Sjkim
424210976SjkimACPI_STATUS
425210976SjkimAcpiDmAddToExternalFileList (
426272444Sjkim    char                    *Pathname)
427210976Sjkim{
428210976Sjkim    ACPI_EXTERNAL_FILE      *ExternalFile;
429272444Sjkim    char                    *LocalPathname;
430210976Sjkim
431210976Sjkim
432272444Sjkim    if (!Pathname)
433210976Sjkim    {
434210976Sjkim        return (AE_OK);
435210976Sjkim    }
436210976Sjkim
437272444Sjkim    LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
438272444Sjkim    if (!LocalPathname)
439272444Sjkim    {
440272444Sjkim        return (AE_NO_MEMORY);
441272444Sjkim    }
442210976Sjkim
443272444Sjkim    ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
444272444Sjkim    if (!ExternalFile)
445210976Sjkim    {
446272444Sjkim        ACPI_FREE (LocalPathname);
447272444Sjkim        return (AE_NO_MEMORY);
448272444Sjkim    }
449210976Sjkim
450272444Sjkim    /* Take a copy of the file pathname */
451210976Sjkim
452272444Sjkim    strcpy (LocalPathname, Pathname);
453272444Sjkim    ExternalFile->Path = LocalPathname;
454210976Sjkim
455272444Sjkim    if (AcpiGbl_ExternalFileList)
456272444Sjkim    {
457272444Sjkim        ExternalFile->Next = AcpiGbl_ExternalFileList;
458210976Sjkim    }
459210976Sjkim
460272444Sjkim    AcpiGbl_ExternalFileList = ExternalFile;
461210976Sjkim    return (AE_OK);
462210976Sjkim}
463210976Sjkim
464210976Sjkim
465210976Sjkim/*******************************************************************************
466210976Sjkim *
467210976Sjkim * FUNCTION:    AcpiDmClearExternalFileList
468210976Sjkim *
469210976Sjkim * PARAMETERS:  None
470210976Sjkim *
471210976Sjkim * RETURN:      None
472210976Sjkim *
473210976Sjkim * DESCRIPTION: Clear the external file list
474210976Sjkim *
475210976Sjkim ******************************************************************************/
476210976Sjkim
477210976Sjkimvoid
478210976SjkimAcpiDmClearExternalFileList (
479210976Sjkim    void)
480210976Sjkim{
481210976Sjkim    ACPI_EXTERNAL_FILE      *NextExternal;
482210976Sjkim
483210976Sjkim
484210976Sjkim    while (AcpiGbl_ExternalFileList)
485210976Sjkim    {
486210976Sjkim        NextExternal = AcpiGbl_ExternalFileList->Next;
487210976Sjkim        ACPI_FREE (AcpiGbl_ExternalFileList->Path);
488210976Sjkim        ACPI_FREE (AcpiGbl_ExternalFileList);
489210976Sjkim        AcpiGbl_ExternalFileList = NextExternal;
490210976Sjkim    }
491210976Sjkim}
492210976Sjkim
493210976Sjkim
494210976Sjkim/*******************************************************************************
495210976Sjkim *
496272444Sjkim * FUNCTION:    AcpiDmGetExternalsFromFile
497198054Sjkim *
498272444Sjkim * PARAMETERS:  None
499272444Sjkim *
500272444Sjkim * RETURN:      None
501272444Sjkim *
502272444Sjkim * DESCRIPTION: Process the optional external reference file.
503272444Sjkim *
504272444Sjkim * Each line in the file should be of the form:
505272444Sjkim *      External (<Method namepath>, MethodObj, <ArgCount>)
506272444Sjkim *
507272444Sjkim * Example:
508272444Sjkim *      External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
509272444Sjkim *
510272444Sjkim ******************************************************************************/
511272444Sjkim
512272444Sjkimvoid
513272444SjkimAcpiDmGetExternalsFromFile (
514272444Sjkim    void)
515272444Sjkim{
516272444Sjkim    FILE                    *ExternalRefFile;
517272444Sjkim    char                    *Token;
518272444Sjkim    char                    *MethodName;
519272444Sjkim    UINT32                  ArgCount;
520272444Sjkim    UINT32                  ImportCount = 0;
521272444Sjkim
522272444Sjkim
523272444Sjkim    if (!Gbl_ExternalRefFilename)
524272444Sjkim    {
525272444Sjkim        return;
526272444Sjkim    }
527272444Sjkim
528272444Sjkim    /* Open the file */
529272444Sjkim
530272444Sjkim    ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
531272444Sjkim    if (!ExternalRefFile)
532272444Sjkim    {
533272444Sjkim        fprintf (stderr, "Could not open external reference file \"%s\"\n",
534272444Sjkim            Gbl_ExternalRefFilename);
535272444Sjkim        AslAbort ();
536272444Sjkim        return;
537272444Sjkim    }
538272444Sjkim
539272444Sjkim    /* Each line defines a method */
540272444Sjkim
541272444Sjkim    while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
542272444Sjkim    {
543272444Sjkim        Token = strtok (StringBuffer, METHOD_SEPARATORS);   /* "External" */
544272444Sjkim        if (!Token)
545272444Sjkim        {
546272444Sjkim            continue;
547272444Sjkim        }
548298714Sjkim
549272444Sjkim        if (strcmp (Token, "External"))
550272444Sjkim        {
551272444Sjkim            continue;
552272444Sjkim        }
553272444Sjkim
554272444Sjkim        MethodName = strtok (NULL, METHOD_SEPARATORS);      /* Method namepath */
555272444Sjkim        if (!MethodName)
556272444Sjkim        {
557272444Sjkim            continue;
558272444Sjkim        }
559272444Sjkim
560272444Sjkim        Token = strtok (NULL, METHOD_SEPARATORS);           /* "MethodObj" */
561272444Sjkim        if (!Token)
562272444Sjkim        {
563272444Sjkim            continue;
564272444Sjkim        }
565272444Sjkim
566272444Sjkim        if (strcmp (Token, "MethodObj"))
567272444Sjkim        {
568272444Sjkim            continue;
569272444Sjkim        }
570272444Sjkim
571272444Sjkim        Token = strtok (NULL, METHOD_SEPARATORS);           /* Arg count */
572272444Sjkim        if (!Token)
573272444Sjkim        {
574272444Sjkim            continue;
575272444Sjkim        }
576272444Sjkim
577272444Sjkim        /* Convert arg count string to an integer */
578272444Sjkim
579272444Sjkim        errno = 0;
580272444Sjkim        ArgCount = strtoul (Token, NULL, 0);
581272444Sjkim        if (errno)
582272444Sjkim        {
583272444Sjkim            fprintf (stderr, "Invalid argument count (%s)\n", Token);
584272444Sjkim            continue;
585272444Sjkim        }
586298714Sjkim
587272444Sjkim        if (ArgCount > 7)
588272444Sjkim        {
589272444Sjkim            fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
590272444Sjkim            continue;
591272444Sjkim        }
592272444Sjkim
593272444Sjkim        /* Add this external to the global list */
594272444Sjkim
595272444Sjkim        AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
596272444Sjkim            Gbl_ExternalRefFilename, ArgCount, MethodName);
597272444Sjkim
598272444Sjkim        AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
599272444Sjkim            ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
600272444Sjkim        ImportCount++;
601272444Sjkim    }
602272444Sjkim
603272444Sjkim    if (!ImportCount)
604272444Sjkim    {
605298714Sjkim        fprintf (stderr,
606298714Sjkim            "Did not find any external methods in reference file \"%s\"\n",
607272444Sjkim            Gbl_ExternalRefFilename);
608272444Sjkim    }
609272444Sjkim    else
610272444Sjkim    {
611272444Sjkim        /* Add the external(s) to the namespace */
612272444Sjkim
613322877Sjkim        AcpiDmAddExternalListToNamespace ();
614272444Sjkim
615272444Sjkim        AcpiOsPrintf ("%s: Imported %u external method definitions\n",
616272444Sjkim            Gbl_ExternalRefFilename, ImportCount);
617272444Sjkim    }
618272444Sjkim
619272444Sjkim    fclose (ExternalRefFile);
620272444Sjkim}
621272444Sjkim
622272444Sjkim
623272444Sjkim/*******************************************************************************
624272444Sjkim *
625272444Sjkim * FUNCTION:    AcpiDmAddOpToExternalList
626272444Sjkim *
627198054Sjkim * PARAMETERS:  Op                  - Current parser Op
628198054Sjkim *              Path                - Internal (AML) path to the object
629198054Sjkim *              Type                - ACPI object type to be added
630198054Sjkim *              Value               - Arg count if adding a Method object
631272444Sjkim *              Flags               - To be passed to the external object
632198054Sjkim *
633198054Sjkim * RETURN:      None
634198054Sjkim *
635198054Sjkim * DESCRIPTION: Insert a new name into the global list of Externals which
636198054Sjkim *              will in turn be later emitted as an External() declaration
637198054Sjkim *              in the disassembled output.
638198054Sjkim *
639272444Sjkim *              This function handles the most common case where the referenced
640272444Sjkim *              name is simply not found in the constructed namespace.
641272444Sjkim *
642198054Sjkim ******************************************************************************/
643198054Sjkim
644198054Sjkimvoid
645272444SjkimAcpiDmAddOpToExternalList (
646198054Sjkim    ACPI_PARSE_OBJECT       *Op,
647198054Sjkim    char                    *Path,
648198054Sjkim    UINT8                   Type,
649272444Sjkim    UINT32                  Value,
650272444Sjkim    UINT16                  Flags)
651198054Sjkim{
652198054Sjkim    char                    *ExternalPath;
653272444Sjkim    char                    *InternalPath = Path;
654272444Sjkim    char                    *Temp;
655198054Sjkim    ACPI_STATUS             Status;
656198054Sjkim
657198054Sjkim
658272444Sjkim    ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
659272444Sjkim
660272444Sjkim
661198054Sjkim    if (!Path)
662198054Sjkim    {
663272444Sjkim        return_VOID;
664198054Sjkim    }
665198054Sjkim
666272444Sjkim    /* Remove a root backslash if present */
667246849Sjkim
668243347Sjkim    if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
669243347Sjkim    {
670243347Sjkim        Path++;
671243347Sjkim    }
672198054Sjkim
673272444Sjkim    /* Externalize the pathname */
674243347Sjkim
675198054Sjkim    Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
676272444Sjkim        NULL, &ExternalPath);
677198054Sjkim    if (ACPI_FAILURE (Status))
678198054Sjkim    {
679272444Sjkim        return_VOID;
680198054Sjkim    }
681198054Sjkim
682243347Sjkim    /*
683243347Sjkim     * Get the full pathname from the root if "Path" has one or more
684243347Sjkim     * parent prefixes (^). Note: path will not contain a leading '\'.
685243347Sjkim     */
686198054Sjkim    if (*Path == (UINT8) AML_PARENT_PREFIX)
687198054Sjkim    {
688272444Sjkim        Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
689198054Sjkim
690272444Sjkim        /* Set new external path */
691198054Sjkim
692272444Sjkim        ACPI_FREE (ExternalPath);
693272444Sjkim        ExternalPath = Temp;
694272444Sjkim        if (!Temp)
695198054Sjkim        {
696272444Sjkim            return_VOID;
697198054Sjkim        }
698198054Sjkim
699272444Sjkim        /* Create the new internal pathname */
700198054Sjkim
701272444Sjkim        Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
702272444Sjkim        Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
703198054Sjkim        if (ACPI_FAILURE (Status))
704198054Sjkim        {
705198054Sjkim            ACPI_FREE (ExternalPath);
706272444Sjkim            return_VOID;
707198054Sjkim        }
708198054Sjkim    }
709198054Sjkim
710272444Sjkim    /* Create the new External() declaration node */
711198054Sjkim
712272444Sjkim    Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
713272444Sjkim        Type, Value, Flags);
714272444Sjkim    if (ACPI_FAILURE (Status))
715198054Sjkim    {
716272444Sjkim        ACPI_FREE (ExternalPath);
717272444Sjkim        if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
718198054Sjkim        {
719272444Sjkim            ACPI_FREE (InternalPath);
720198054Sjkim        }
721198054Sjkim    }
722198054Sjkim
723272444Sjkim    return_VOID;
724198054Sjkim}
725198054Sjkim
726198054Sjkim
727198054Sjkim/*******************************************************************************
728198054Sjkim *
729322877Sjkim * FUNCTION:    AcpiDmGetExternalAndInternalPath
730322877Sjkim *
731322877Sjkim * PARAMETERS:  Node                - Namespace node for object to be added
732322877Sjkim *              ExternalPath        - Will contain the external path of the node
733322877Sjkim *              InternalPath        - Will contain the internal path of the node
734322877Sjkim *
735322877Sjkim * RETURN:      None
736322877Sjkim *
737322877Sjkim * DESCRIPTION: Get the External and Internal path from the given node.
738322877Sjkim *
739322877Sjkim ******************************************************************************/
740322877Sjkim
741322877Sjkimstatic ACPI_STATUS
742322877SjkimAcpiDmGetExternalAndInternalPath (
743322877Sjkim    ACPI_NAMESPACE_NODE     *Node,
744322877Sjkim    char                    **ExternalPath,
745322877Sjkim    char                    **InternalPath)
746322877Sjkim{
747322877Sjkim    ACPI_STATUS             Status;
748322877Sjkim
749322877Sjkim
750322877Sjkim    if (!Node)
751322877Sjkim    {
752322877Sjkim        return (AE_BAD_PARAMETER);
753322877Sjkim    }
754322877Sjkim
755322877Sjkim    /* Get the full external and internal pathnames to the node */
756322877Sjkim
757322877Sjkim    *ExternalPath = AcpiNsGetExternalPathname (Node);
758322877Sjkim    if (!*ExternalPath)
759322877Sjkim    {
760322877Sjkim        return (AE_BAD_PATHNAME);
761322877Sjkim    }
762322877Sjkim
763322877Sjkim    Status = AcpiNsInternalizeName (*ExternalPath, InternalPath);
764322877Sjkim    if (ACPI_FAILURE (Status))
765322877Sjkim    {
766322877Sjkim        ACPI_FREE (*ExternalPath);
767322877Sjkim        return (Status);
768322877Sjkim    }
769322877Sjkim
770322877Sjkim    return (AE_OK);
771322877Sjkim}
772322877Sjkim
773322877Sjkim
774322877Sjkim/*******************************************************************************
775322877Sjkim *
776322877Sjkim * FUNCTION:    AcpiDmRemoveRootPrefix
777322877Sjkim *
778322877Sjkim * PARAMETERS:  Path                - Remove Root prefix from this Path
779322877Sjkim *
780322877Sjkim * RETURN:      None
781322877Sjkim *
782322877Sjkim * DESCRIPTION: Remove the root prefix character '\' from Path.
783322877Sjkim *
784322877Sjkim ******************************************************************************/
785322877Sjkim
786322877Sjkimstatic ACPI_STATUS
787322877SjkimAcpiDmRemoveRootPrefix (
788322877Sjkim    char                    **Path)
789322877Sjkim{
790322877Sjkim    char                    *InputPath = *Path;
791322877Sjkim
792322877Sjkim
793322877Sjkim    if ((*InputPath == AML_ROOT_PREFIX) && (InputPath[1]))
794322877Sjkim    {
795322877Sjkim        if (!memmove(InputPath, InputPath+1, strlen(InputPath)))
796322877Sjkim        {
797322877Sjkim            return (AE_ERROR);
798322877Sjkim        }
799322877Sjkim
800322877Sjkim        *Path = InputPath;
801322877Sjkim    }
802322877Sjkim
803322877Sjkim    return (AE_OK);
804322877Sjkim}
805322877Sjkim
806322877Sjkim
807322877Sjkim/*******************************************************************************
808322877Sjkim *
809272444Sjkim * FUNCTION:    AcpiDmAddNodeToExternalList
810254745Sjkim *
811272444Sjkim * PARAMETERS:  Node                - Namespace node for object to be added
812272444Sjkim *              Type                - ACPI object type to be added
813272444Sjkim *              Value               - Arg count if adding a Method object
814272444Sjkim *              Flags               - To be passed to the external object
815254745Sjkim *
816254745Sjkim * RETURN:      None
817254745Sjkim *
818272444Sjkim * DESCRIPTION: Insert a new name into the global list of Externals which
819272444Sjkim *              will in turn be later emitted as an External() declaration
820272444Sjkim *              in the disassembled output.
821254745Sjkim *
822272444Sjkim *              This function handles the case where the referenced name has
823272444Sjkim *              been found in the namespace, but the name originated in a
824272444Sjkim *              table other than the one that is being disassembled (such
825272444Sjkim *              as a table that is added via the iASL -e option).
826254745Sjkim *
827254745Sjkim ******************************************************************************/
828254745Sjkim
829254745Sjkimvoid
830272444SjkimAcpiDmAddNodeToExternalList (
831272444Sjkim    ACPI_NAMESPACE_NODE     *Node,
832272444Sjkim    UINT8                   Type,
833272444Sjkim    UINT32                  Value,
834272444Sjkim    UINT16                  Flags)
835254745Sjkim{
836272444Sjkim    char                    *ExternalPath;
837272444Sjkim    char                    *InternalPath;
838272444Sjkim    ACPI_STATUS             Status;
839254745Sjkim
840254745Sjkim
841272444Sjkim    ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
842272444Sjkim
843272444Sjkim    /* Get the full external and internal pathnames to the node */
844254745Sjkim
845322877Sjkim    Status = AcpiDmGetExternalAndInternalPath (Node, &ExternalPath, &InternalPath);
846272444Sjkim    if (ACPI_FAILURE (Status))
847254745Sjkim    {
848272444Sjkim        return_VOID;
849272444Sjkim    }
850254745Sjkim
851272444Sjkim    /* Remove the root backslash */
852254745Sjkim
853322877Sjkim    Status = AcpiDmRemoveRootPrefix (&ExternalPath);
854322877Sjkim    if (ACPI_FAILURE (Status))
855272444Sjkim    {
856272444Sjkim        ACPI_FREE (ExternalPath);
857322877Sjkim        ACPI_FREE (InternalPath);
858322877Sjkim        return_VOID;
859272444Sjkim    }
860254745Sjkim
861272444Sjkim    /* Create the new External() declaration node */
862254745Sjkim
863272444Sjkim    Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
864272444Sjkim        Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
865272444Sjkim    if (ACPI_FAILURE (Status))
866254745Sjkim    {
867272444Sjkim        ACPI_FREE (ExternalPath);
868272444Sjkim        ACPI_FREE (InternalPath);
869254745Sjkim    }
870254745Sjkim
871272444Sjkim    return_VOID;
872254745Sjkim}
873254745Sjkim
874254745Sjkim
875254745Sjkim/*******************************************************************************
876254745Sjkim *
877272444Sjkim * FUNCTION:    AcpiDmAddPathToExternalList
878254745Sjkim *
879272444Sjkim * PARAMETERS:  Path                - External name of the object to be added
880254745Sjkim *              Type                - ACPI object type to be added
881254745Sjkim *              Value               - Arg count if adding a Method object
882272444Sjkim *              Flags               - To be passed to the external object
883254745Sjkim *
884254745Sjkim * RETURN:      None
885254745Sjkim *
886254745Sjkim * DESCRIPTION: Insert a new name into the global list of Externals which
887254745Sjkim *              will in turn be later emitted as an External() declaration
888254745Sjkim *              in the disassembled output.
889254745Sjkim *
890272444Sjkim *              This function currently is used to add externals via a
891272444Sjkim *              reference file (via the -fe iASL option).
892272444Sjkim *
893254745Sjkim ******************************************************************************/
894254745Sjkim
895254745Sjkimstatic void
896272444SjkimAcpiDmAddPathToExternalList (
897254745Sjkim    char                    *Path,
898254745Sjkim    UINT8                   Type,
899272444Sjkim    UINT32                  Value,
900272444Sjkim    UINT16                  Flags)
901254745Sjkim{
902254745Sjkim    char                    *InternalPath;
903254745Sjkim    char                    *ExternalPath;
904254745Sjkim    ACPI_STATUS             Status;
905254745Sjkim
906254745Sjkim
907272444Sjkim    ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
908272444Sjkim
909272444Sjkim
910254745Sjkim    if (!Path)
911254745Sjkim    {
912272444Sjkim        return_VOID;
913254745Sjkim    }
914254745Sjkim
915272444Sjkim    /* Remove a root backslash if present */
916254745Sjkim
917272444Sjkim    if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
918254745Sjkim    {
919272444Sjkim        Path++;
920254745Sjkim    }
921254745Sjkim
922272444Sjkim    /* Create the internal and external pathnames */
923272444Sjkim
924272444Sjkim    Status = AcpiNsInternalizeName (Path, &InternalPath);
925272444Sjkim    if (ACPI_FAILURE (Status))
926254745Sjkim    {
927272444Sjkim        return_VOID;
928254745Sjkim    }
929254745Sjkim
930272444Sjkim    Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
931272444Sjkim        NULL, &ExternalPath);
932272444Sjkim    if (ACPI_FAILURE (Status))
933272444Sjkim    {
934272444Sjkim        ACPI_FREE (InternalPath);
935272444Sjkim        return_VOID;
936272444Sjkim    }
937272444Sjkim
938272444Sjkim    /* Create the new External() declaration node */
939272444Sjkim
940272444Sjkim    Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
941272444Sjkim        Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
942272444Sjkim    if (ACPI_FAILURE (Status))
943272444Sjkim    {
944272444Sjkim        ACPI_FREE (ExternalPath);
945272444Sjkim        ACPI_FREE (InternalPath);
946272444Sjkim    }
947272444Sjkim
948272444Sjkim    return_VOID;
949272444Sjkim}
950272444Sjkim
951272444Sjkim
952272444Sjkim/*******************************************************************************
953272444Sjkim *
954272444Sjkim * FUNCTION:    AcpiDmCreateNewExternal
955272444Sjkim *
956272444Sjkim * PARAMETERS:  ExternalPath        - External path to the object
957272444Sjkim *              InternalPath        - Internal (AML) path to the object
958272444Sjkim *              Type                - ACPI object type to be added
959272444Sjkim *              Value               - Arg count if adding a Method object
960272444Sjkim *              Flags               - To be passed to the external object
961272444Sjkim *
962272444Sjkim * RETURN:      Status
963272444Sjkim *
964272444Sjkim * DESCRIPTION: Common low-level function to insert a new name into the global
965272444Sjkim *              list of Externals which will in turn be later emitted as
966272444Sjkim *              External() declarations in the disassembled output.
967272444Sjkim *
968272444Sjkim *              Note: The external name should not include a root prefix
969272444Sjkim *              (backslash). We do not want External() statements to contain
970272444Sjkim *              a leading '\', as this prevents duplicate external statements
971272444Sjkim *              of the form:
972272444Sjkim *
973272444Sjkim *                  External (\ABCD)
974272444Sjkim *                  External (ABCD)
975272444Sjkim *
976272444Sjkim *              This would cause a compile time error when the disassembled
977272444Sjkim *              output file is recompiled.
978272444Sjkim *
979272444Sjkim *              There are two cases that are handled here. For both, we emit
980272444Sjkim *              an External() statement:
981272444Sjkim *              1) The name was simply not found in the namespace.
982272444Sjkim *              2) The name was found, but it originated in a table other than
983272444Sjkim *              the table that is being disassembled.
984272444Sjkim *
985272444Sjkim ******************************************************************************/
986272444Sjkim
987272444Sjkimstatic ACPI_STATUS
988272444SjkimAcpiDmCreateNewExternal (
989272444Sjkim    char                    *ExternalPath,
990272444Sjkim    char                    *InternalPath,
991272444Sjkim    UINT8                   Type,
992272444Sjkim    UINT32                  Value,
993272444Sjkim    UINT16                  Flags)
994272444Sjkim{
995272444Sjkim    ACPI_EXTERNAL_LIST      *NewExternal;
996272444Sjkim    ACPI_EXTERNAL_LIST      *NextExternal;
997272444Sjkim    ACPI_EXTERNAL_LIST      *PrevExternal = NULL;
998272444Sjkim
999272444Sjkim
1000272444Sjkim    ACPI_FUNCTION_TRACE (DmCreateNewExternal);
1001272444Sjkim
1002272444Sjkim
1003254745Sjkim    /* Check all existing externals to ensure no duplicates */
1004254745Sjkim
1005254745Sjkim    NextExternal = AcpiGbl_ExternalList;
1006254745Sjkim    while (NextExternal)
1007254745Sjkim    {
1008298714Sjkim        /* Check for duplicates */
1009298714Sjkim
1010284583Sjkim        if (!strcmp (ExternalPath, NextExternal->Path))
1011254745Sjkim        {
1012298714Sjkim            /*
1013298714Sjkim             * If this external came from an External() opcode, we are
1014298714Sjkim             * finished with this one. (No need to check any further).
1015298714Sjkim             */
1016298714Sjkim            if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)
1017254745Sjkim            {
1018298714Sjkim                return_ACPI_STATUS (AE_ALREADY_EXISTS);
1019254745Sjkim            }
1020254745Sjkim
1021254745Sjkim            /* Allow upgrade of type from ANY */
1022254745Sjkim
1023298714Sjkim            else if ((NextExternal->Type == ACPI_TYPE_ANY) &&
1024298714Sjkim                (Type != ACPI_TYPE_ANY))
1025254745Sjkim            {
1026254745Sjkim                NextExternal->Type = Type;
1027298714Sjkim            }
1028298714Sjkim
1029298714Sjkim            /* Update the argument count as necessary */
1030298714Sjkim
1031298714Sjkim            if (Value < NextExternal->Value)
1032298714Sjkim            {
1033254745Sjkim                NextExternal->Value = Value;
1034254745Sjkim            }
1035254745Sjkim
1036298714Sjkim            /* Update flags. */
1037298714Sjkim
1038298714Sjkim            NextExternal->Flags |= Flags;
1039298714Sjkim            NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED;
1040298714Sjkim
1041272444Sjkim            return_ACPI_STATUS (AE_ALREADY_EXISTS);
1042254745Sjkim        }
1043254745Sjkim
1044254745Sjkim        NextExternal = NextExternal->Next;
1045254745Sjkim    }
1046254745Sjkim
1047254745Sjkim    /* Allocate and init a new External() descriptor */
1048254745Sjkim
1049254745Sjkim    NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
1050254745Sjkim    if (!NewExternal)
1051254745Sjkim    {
1052272444Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
1053254745Sjkim    }
1054254745Sjkim
1055272444Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
1056272444Sjkim        "Adding external reference node (%s) type [%s]\n",
1057272444Sjkim        ExternalPath, AcpiUtGetTypeName (Type)));
1058254745Sjkim
1059272444Sjkim    NewExternal->Flags = Flags;
1060272444Sjkim    NewExternal->Value = Value;
1061254745Sjkim    NewExternal->Path = ExternalPath;
1062254745Sjkim    NewExternal->Type = Type;
1063284583Sjkim    NewExternal->Length = (UINT16) strlen (ExternalPath);
1064254745Sjkim    NewExternal->InternalPath = InternalPath;
1065254745Sjkim
1066254745Sjkim    /* Link the new descriptor into the global list, alphabetically ordered */
1067254745Sjkim
1068254745Sjkim    NextExternal = AcpiGbl_ExternalList;
1069254745Sjkim    while (NextExternal)
1070254745Sjkim    {
1071254745Sjkim        if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
1072254745Sjkim        {
1073254745Sjkim            if (PrevExternal)
1074254745Sjkim            {
1075254745Sjkim                PrevExternal->Next = NewExternal;
1076254745Sjkim            }
1077254745Sjkim            else
1078254745Sjkim            {
1079254745Sjkim                AcpiGbl_ExternalList = NewExternal;
1080254745Sjkim            }
1081254745Sjkim
1082254745Sjkim            NewExternal->Next = NextExternal;
1083272444Sjkim            return_ACPI_STATUS (AE_OK);
1084254745Sjkim        }
1085254745Sjkim
1086254745Sjkim        PrevExternal = NextExternal;
1087254745Sjkim        NextExternal = NextExternal->Next;
1088254745Sjkim    }
1089254745Sjkim
1090254745Sjkim    if (PrevExternal)
1091254745Sjkim    {
1092254745Sjkim        PrevExternal->Next = NewExternal;
1093254745Sjkim    }
1094254745Sjkim    else
1095254745Sjkim    {
1096254745Sjkim        AcpiGbl_ExternalList = NewExternal;
1097254745Sjkim    }
1098272444Sjkim
1099272444Sjkim    return_ACPI_STATUS (AE_OK);
1100254745Sjkim}
1101254745Sjkim
1102254745Sjkim
1103254745Sjkim/*******************************************************************************
1104254745Sjkim *
1105322877Sjkim * FUNCTION:    AcpiDmResolveExternal
1106198054Sjkim *
1107322877Sjkim * PARAMETERS:  Path               - Path of the external
1108322877Sjkim *              Type               - Type of the external
1109322877Sjkim *              Node               - Input node for AcpiNsLookup
1110198054Sjkim *
1111322877Sjkim * RETURN:      Status
1112322877Sjkim *
1113322877Sjkim * DESCRIPTION: Resolve the external within the namespace by AcpiNsLookup.
1114322877Sjkim *              If the returned node is an external and has the same type
1115322877Sjkim *              we assume that it was either an existing external or a
1116322877Sjkim *
1117322877Sjkim ******************************************************************************/
1118322877Sjkim
1119322877Sjkimstatic ACPI_STATUS
1120322877SjkimAcpiDmResolveExternal (
1121322877Sjkim    char                    *Path,
1122322877Sjkim    UINT8                   Type,
1123322877Sjkim    ACPI_NAMESPACE_NODE     **Node)
1124322877Sjkim{
1125322877Sjkim    ACPI_STATUS             Status;
1126322877Sjkim
1127322877Sjkim
1128322877Sjkim    Status = AcpiNsLookup (NULL, Path, Type,
1129322877Sjkim        ACPI_IMODE_LOAD_PASS1,
1130322877Sjkim        ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
1131322877Sjkim        NULL, Node);
1132322877Sjkim
1133322877Sjkim    if (!Node)
1134322877Sjkim    {
1135322877Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
1136322877Sjkim            "while adding external to namespace [%s]", Path));
1137322877Sjkim    }
1138322877Sjkim
1139322877Sjkim    /* Note the asl code "external(a) external(a)" is acceptable ASL */
1140322877Sjkim
1141322877Sjkim    else if ((*Node)->Type == Type &&
1142322877Sjkim        (*Node)->Flags & ANOBJ_IS_EXTERNAL)
1143322877Sjkim    {
1144322877Sjkim        return (AE_OK);
1145322877Sjkim    }
1146322877Sjkim    else
1147322877Sjkim    {
1148322877Sjkim        ACPI_EXCEPTION ((AE_INFO, AE_ERROR,
1149322877Sjkim            "[%s] has conflicting declarations", Path));
1150322877Sjkim    }
1151322877Sjkim
1152322877Sjkim    return (AE_ERROR);
1153322877Sjkim}
1154322877Sjkim
1155322877Sjkim
1156322877Sjkim/*******************************************************************************
1157322877Sjkim *
1158322877Sjkim * FUNCTION:    AcpiDmCreateSubobjectForExternal
1159322877Sjkim *
1160322877Sjkim * PARAMETERS:  Type                  - Type of the external
1161322877Sjkim *              Node                  - Namespace node from AcpiNsLookup
1162322877Sjkim *              ParamCount            - Value to be used for Method
1163322877Sjkim *
1164198054Sjkim * RETURN:      None
1165198054Sjkim *
1166322877Sjkim * DESCRIPTION: Add one external to the namespace. Allows external to be
1167198054Sjkim *              "resolved".
1168198054Sjkim *
1169198054Sjkim ******************************************************************************/
1170198054Sjkim
1171198054Sjkimvoid
1172322877SjkimAcpiDmCreateSubobjectForExternal (
1173322877Sjkim    UINT8                   Type,
1174322877Sjkim    ACPI_NAMESPACE_NODE     **Node,
1175322877Sjkim    UINT32                  ParamCount)
1176198054Sjkim{
1177235945Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
1178198054Sjkim
1179198054Sjkim
1180322877Sjkim    switch (Type)
1181198054Sjkim    {
1182322877Sjkim    case ACPI_TYPE_METHOD:
1183198054Sjkim
1184322877Sjkim        /* For methods, we need to save the argument count */
1185198054Sjkim
1186322877Sjkim        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
1187322877Sjkim        ObjDesc->Method.ParamCount = (UINT8) ParamCount;
1188322877Sjkim        (*Node)->Object = ObjDesc;
1189322877Sjkim        break;
1190235945Sjkim
1191322877Sjkim    case ACPI_TYPE_REGION:
1192235945Sjkim
1193322877Sjkim        /* Regions require a region sub-object */
1194198054Sjkim
1195322877Sjkim        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
1196322877Sjkim        ObjDesc->Region.Node = *Node;
1197322877Sjkim        (*Node)->Object = ObjDesc;
1198322877Sjkim        break;
1199235945Sjkim
1200322877Sjkim    default:
1201235945Sjkim
1202322877Sjkim        break;
1203322877Sjkim    }
1204322877Sjkim}
1205235945Sjkim
1206235945Sjkim
1207322877Sjkim/*******************************************************************************
1208322877Sjkim *
1209322877Sjkim * FUNCTION:    AcpiDmAddOneExternalToNamespace
1210322877Sjkim *
1211322877Sjkim * PARAMETERS:  Path                   - External parse object
1212322877Sjkim *              Type                   - Type of parse object
1213322877Sjkim *              ParamCount             - External method parameter count
1214322877Sjkim *
1215322877Sjkim * RETURN:      None
1216322877Sjkim *
1217322877Sjkim * DESCRIPTION: Add one external to the namespace by resolvign the external
1218322877Sjkim *              (by performing a namespace lookup) and annotating the resulting
1219322877Sjkim *              namespace node with the approperiate information if the type
1220322877Sjkim *              is ACPI_TYPE_REGION or ACPI_TYPE_METHOD.
1221322877Sjkim *
1222322877Sjkim ******************************************************************************/
1223250838Sjkim
1224322877Sjkimvoid
1225322877SjkimAcpiDmAddOneExternalToNamespace (
1226322877Sjkim    char                    *Path,
1227322877Sjkim    UINT8                   Type,
1228322877Sjkim    UINT32                  ParamCount)
1229322877Sjkim{
1230322877Sjkim    ACPI_STATUS             Status;
1231322877Sjkim    ACPI_NAMESPACE_NODE     *Node;
1232198054Sjkim
1233322877Sjkim
1234322877Sjkim    Status = AcpiDmResolveExternal (Path, Type, &Node);
1235322877Sjkim
1236322877Sjkim    if (ACPI_FAILURE (Status))
1237322877Sjkim    {
1238322877Sjkim        return;
1239322877Sjkim    }
1240322877Sjkim
1241322877Sjkim    AcpiDmCreateSubobjectForExternal (Type, &Node, ParamCount);
1242322877Sjkim
1243322877Sjkim}
1244322877Sjkim
1245322877Sjkim
1246322877Sjkim/*******************************************************************************
1247322877Sjkim *
1248322877Sjkim * FUNCTION:    AcpiDmAddExternalListToNamespace
1249322877Sjkim *
1250322877Sjkim * PARAMETERS:  None
1251322877Sjkim *
1252322877Sjkim * RETURN:      None
1253322877Sjkim *
1254322877Sjkim * DESCRIPTION: Add all externals within AcpiGbl_ExternalList to the namespace.
1255322877Sjkim *              Allows externals to be "resolved".
1256322877Sjkim *
1257322877Sjkim ******************************************************************************/
1258322877Sjkim
1259322877Sjkimvoid
1260322877SjkimAcpiDmAddExternalListToNamespace (
1261322877Sjkim    void)
1262322877Sjkim{
1263322877Sjkim    ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
1264322877Sjkim
1265322877Sjkim
1266322877Sjkim    while (External)
1267322877Sjkim    {
1268322877Sjkim        AcpiDmAddOneExternalToNamespace (External->InternalPath,
1269322877Sjkim            External->Type, External->Value);
1270198054Sjkim        External = External->Next;
1271198054Sjkim    }
1272198054Sjkim}
1273198054Sjkim
1274198054Sjkim
1275198054Sjkim/*******************************************************************************
1276198054Sjkim *
1277322877Sjkim * FUNCTION:    AcpiDmGetUnresolvedExternalMethodCount
1278198054Sjkim *
1279198054Sjkim * PARAMETERS:  None
1280198054Sjkim *
1281322877Sjkim * RETURN:      The number of unresolved control method externals in the
1282322877Sjkim *              external list
1283198054Sjkim *
1284322877Sjkim * DESCRIPTION: Return the number of unresolved external methods that have been
1285322877Sjkim *              generated. If any unresolved control method externals have been
1286322877Sjkim *              found, we must re-parse the entire definition block with the new
1287322877Sjkim *              information (number of arguments for the methods.)
1288322877Sjkim *              This is limitation of AML, we don't know the number of arguments
1289322877Sjkim *              from the control method invocation itself.
1290198054Sjkim *
1291322877Sjkim *              Note: resolved external control methods are external control
1292322877Sjkim *              methods encoded with the AML_EXTERNAL_OP bytecode within the
1293322877Sjkim *              AML being disassembled.
1294322877Sjkim *
1295198054Sjkim ******************************************************************************/
1296198054Sjkim
1297198054SjkimUINT32
1298322877SjkimAcpiDmGetUnresolvedExternalMethodCount (
1299198054Sjkim    void)
1300198054Sjkim{
1301198054Sjkim    ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
1302198054Sjkim    UINT32                  Count = 0;
1303198054Sjkim
1304198054Sjkim
1305198054Sjkim    while (External)
1306198054Sjkim    {
1307322877Sjkim        if (External->Type == ACPI_TYPE_METHOD &&
1308322877Sjkim            !(External->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE))
1309198054Sjkim        {
1310198054Sjkim            Count++;
1311198054Sjkim        }
1312198054Sjkim
1313198054Sjkim        External = External->Next;
1314198054Sjkim    }
1315198054Sjkim
1316198054Sjkim    return (Count);
1317198054Sjkim}
1318198054Sjkim
1319198054Sjkim
1320198054Sjkim/*******************************************************************************
1321198054Sjkim *
1322198054Sjkim * FUNCTION:    AcpiDmClearExternalList
1323198054Sjkim *
1324198054Sjkim * PARAMETERS:  None
1325198054Sjkim *
1326198054Sjkim * RETURN:      None
1327198054Sjkim *
1328198054Sjkim * DESCRIPTION: Free the entire External info list
1329198054Sjkim *
1330198054Sjkim ******************************************************************************/
1331198054Sjkim
1332198054Sjkimvoid
1333198054SjkimAcpiDmClearExternalList (
1334198054Sjkim    void)
1335198054Sjkim{
1336198054Sjkim    ACPI_EXTERNAL_LIST      *NextExternal;
1337198054Sjkim
1338198054Sjkim
1339198054Sjkim    while (AcpiGbl_ExternalList)
1340198054Sjkim    {
1341198054Sjkim        NextExternal = AcpiGbl_ExternalList->Next;
1342198054Sjkim        ACPI_FREE (AcpiGbl_ExternalList->Path);
1343198054Sjkim        ACPI_FREE (AcpiGbl_ExternalList);
1344198054Sjkim        AcpiGbl_ExternalList = NextExternal;
1345198054Sjkim    }
1346198054Sjkim}
1347198054Sjkim
1348198054Sjkim
1349198054Sjkim/*******************************************************************************
1350198054Sjkim *
1351198054Sjkim * FUNCTION:    AcpiDmEmitExternals
1352198054Sjkim *
1353198054Sjkim * PARAMETERS:  None
1354198054Sjkim *
1355198054Sjkim * RETURN:      None
1356198054Sjkim *
1357198054Sjkim * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1358198054Sjkim *              the global external info list.
1359198054Sjkim *
1360198054Sjkim ******************************************************************************/
1361198054Sjkim
1362198054Sjkimvoid
1363198054SjkimAcpiDmEmitExternals (
1364198054Sjkim    void)
1365198054Sjkim{
1366198054Sjkim    ACPI_EXTERNAL_LIST      *NextExternal;
1367198054Sjkim
1368198054Sjkim
1369198054Sjkim    if (!AcpiGbl_ExternalList)
1370198054Sjkim    {
1371198054Sjkim        return;
1372198054Sjkim    }
1373198054Sjkim
1374198054Sjkim    /*
1375246849Sjkim     * Determine the number of control methods in the external list, and
1376246849Sjkim     * also how many of those externals were resolved via the namespace.
1377246849Sjkim     */
1378246849Sjkim    NextExternal = AcpiGbl_ExternalList;
1379246849Sjkim    while (NextExternal)
1380246849Sjkim    {
1381246849Sjkim        if (NextExternal->Type == ACPI_TYPE_METHOD)
1382246849Sjkim        {
1383246849Sjkim            AcpiGbl_NumExternalMethods++;
1384272444Sjkim            if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1385246849Sjkim            {
1386246849Sjkim                AcpiGbl_ResolvedExternalMethods++;
1387246849Sjkim            }
1388246849Sjkim        }
1389246849Sjkim
1390246849Sjkim        NextExternal = NextExternal->Next;
1391246849Sjkim    }
1392246849Sjkim
1393246849Sjkim    /* Check if any control methods were unresolved */
1394246849Sjkim
1395246849Sjkim    AcpiDmUnresolvedWarning (1);
1396246849Sjkim
1397254745Sjkim    if (Gbl_ExternalRefFilename)
1398254745Sjkim    {
1399254745Sjkim        AcpiOsPrintf (
1400298714Sjkim            "    /*\n     * External declarations were imported from\n"
1401298714Sjkim            "     * a reference file -- %s\n     */\n\n",
1402254745Sjkim            Gbl_ExternalRefFilename);
1403254745Sjkim    }
1404254745Sjkim
1405246849Sjkim    /*
1406298714Sjkim     * Walk and emit the list of externals found during the AML parsing
1407198054Sjkim     */
1408198054Sjkim    while (AcpiGbl_ExternalList)
1409198054Sjkim    {
1410272444Sjkim        if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1411253690Sjkim        {
1412298714Sjkim            AcpiOsPrintf ("    External (%s%s)",
1413253690Sjkim                AcpiGbl_ExternalList->Path,
1414253690Sjkim                AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1415198054Sjkim
1416298714Sjkim            /* Check for "unresolved" method reference */
1417253690Sjkim
1418298714Sjkim            if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) &&
1419298714Sjkim                (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1420246849Sjkim            {
1421298714Sjkim                AcpiOsPrintf ("    // Warning: Unknown method, "
1422298714Sjkim                    "guessing %u arguments",
1423246849Sjkim                    AcpiGbl_ExternalList->Value);
1424246849Sjkim            }
1425298714Sjkim
1426298714Sjkim            /* Check for external from a external references file */
1427298714Sjkim
1428298714Sjkim            else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE)
1429298714Sjkim            {
1430298714Sjkim                if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1431298714Sjkim                {
1432298714Sjkim                    AcpiOsPrintf ("    // %u Arguments",
1433298714Sjkim                        AcpiGbl_ExternalList->Value);
1434298714Sjkim                }
1435298714Sjkim
1436298714Sjkim                AcpiOsPrintf ("    // From external reference file");
1437298714Sjkim            }
1438298714Sjkim
1439298714Sjkim            /* This is the normal external case */
1440298714Sjkim
1441246849Sjkim            else
1442246849Sjkim            {
1443298714Sjkim                /* For methods, add a comment with the number of arguments */
1444298714Sjkim
1445298714Sjkim                if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1446298714Sjkim                {
1447298714Sjkim                    AcpiOsPrintf ("    // %u Arguments",
1448298714Sjkim                        AcpiGbl_ExternalList->Value);
1449298714Sjkim                }
1450246849Sjkim            }
1451298714Sjkim
1452322877Sjkim            if (AcpiGbl_ExternalList->Flags &= ACPI_EXT_CONFLICTING_DECLARATION)
1453322877Sjkim            {
1454322877Sjkim                AcpiOsPrintf ("%s", ExternalConflictMessage);
1455322877Sjkim                AcpiDmConflictingDeclaration (AcpiGbl_ExternalList->Path);
1456322877Sjkim            }
1457298714Sjkim            AcpiOsPrintf ("\n");
1458198054Sjkim        }
1459198054Sjkim
1460198054Sjkim        /* Free this external info block and move on to next external */
1461198054Sjkim
1462198054Sjkim        NextExternal = AcpiGbl_ExternalList->Next;
1463272444Sjkim        if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1464198054Sjkim        {
1465198054Sjkim            ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1466198054Sjkim        }
1467198054Sjkim
1468198054Sjkim        ACPI_FREE (AcpiGbl_ExternalList->Path);
1469198054Sjkim        ACPI_FREE (AcpiGbl_ExternalList);
1470198054Sjkim        AcpiGbl_ExternalList = NextExternal;
1471198054Sjkim    }
1472198054Sjkim
1473198054Sjkim    AcpiOsPrintf ("\n");
1474198054Sjkim}
1475246849Sjkim
1476246849Sjkim
1477246849Sjkim/*******************************************************************************
1478246849Sjkim *
1479322877Sjkim * FUNCTION:    AcpiDmMarkExternalConflict
1480322877Sjkim *
1481322877Sjkim * PARAMETERS:  Path          - Namepath to search
1482322877Sjkim *
1483322877Sjkim * RETURN:      ExternalList
1484322877Sjkim *
1485322877Sjkim * DESCRIPTION: Search the AcpiGbl_ExternalList for a matching path
1486322877Sjkim *
1487322877Sjkim ******************************************************************************/
1488322877Sjkim
1489322877Sjkimvoid
1490322877SjkimAcpiDmMarkExternalConflict (
1491322877Sjkim    ACPI_NAMESPACE_NODE     *Node)
1492322877Sjkim{
1493322877Sjkim    ACPI_EXTERNAL_LIST      *ExternalList = AcpiGbl_ExternalList;
1494322877Sjkim    char                    *ExternalPath;
1495322877Sjkim    char                    *InternalPath;
1496322877Sjkim    char                    *Temp;
1497322877Sjkim    ACPI_STATUS             Status;
1498322877Sjkim
1499322877Sjkim
1500322877Sjkim    ACPI_FUNCTION_TRACE (DmMarkExternalConflict);
1501322877Sjkim
1502322877Sjkim
1503322877Sjkim    if (Node->Flags & ANOBJ_IS_EXTERNAL)
1504322877Sjkim    {
1505322877Sjkim        return_VOID;
1506322877Sjkim    }
1507322877Sjkim
1508322877Sjkim    /* Get the full external and internal pathnames to the node */
1509322877Sjkim
1510322877Sjkim    Status = AcpiDmGetExternalAndInternalPath (Node,
1511322877Sjkim        &ExternalPath, &InternalPath);
1512322877Sjkim    if (ACPI_FAILURE (Status))
1513322877Sjkim    {
1514322877Sjkim        return_VOID;
1515322877Sjkim    }
1516322877Sjkim
1517322877Sjkim    /* Remove the root backslash */
1518322877Sjkim
1519322877Sjkim    Status = AcpiDmRemoveRootPrefix (&InternalPath);
1520322877Sjkim    if (ACPI_FAILURE (Status))
1521322877Sjkim    {
1522322877Sjkim        ACPI_FREE (InternalPath);
1523322877Sjkim        ACPI_FREE (ExternalPath);
1524322877Sjkim        return_VOID;
1525322877Sjkim    }
1526322877Sjkim
1527322877Sjkim    while (ExternalList)
1528322877Sjkim    {
1529322877Sjkim        Temp = ExternalList->InternalPath;
1530322877Sjkim        if ((*ExternalList->InternalPath == AML_ROOT_PREFIX) &&
1531322877Sjkim            (ExternalList->InternalPath[1]))
1532322877Sjkim        {
1533322877Sjkim            Temp++;
1534322877Sjkim        }
1535322877Sjkim
1536322877Sjkim        if (!strcmp (ExternalList->InternalPath, InternalPath))
1537322877Sjkim        {
1538322877Sjkim            ExternalList->Flags |= ACPI_EXT_CONFLICTING_DECLARATION;
1539322877Sjkim        }
1540322877Sjkim        ExternalList = ExternalList->Next;
1541322877Sjkim    }
1542322877Sjkim
1543322877Sjkim    ACPI_FREE (InternalPath);
1544322877Sjkim    ACPI_FREE (ExternalPath);
1545322877Sjkim
1546322877Sjkim    return_VOID;
1547322877Sjkim}
1548322877Sjkim
1549322877Sjkim
1550322877Sjkim/*******************************************************************************
1551322877Sjkim *
1552322877Sjkim * FUNCTION:    AcpiDmConflictingDeclaration
1553322877Sjkim *
1554322877Sjkim * PARAMETERS:  Path                - Path with conflicting declaration
1555322877Sjkim *
1556322877Sjkim * RETURN:      None
1557322877Sjkim *
1558322877Sjkim * DESCRIPTION: Emit a warning when printing conflicting ASL external
1559322877Sjkim *              declarations.
1560322877Sjkim *
1561322877Sjkim ******************************************************************************/
1562322877Sjkim
1563322877Sjkimstatic void
1564322877SjkimAcpiDmConflictingDeclaration (
1565322877Sjkim    char                    *Path)
1566322877Sjkim{
1567322877Sjkim    fprintf (stderr,
1568322877Sjkim        " Warning - Emitting ASL code \"External (%s)\"\n"
1569322877Sjkim        "           This is a conflicting declaration with some "
1570322877Sjkim        "other declaration within the ASL code.\n"
1571322877Sjkim        "           This external declaration may need to be "
1572322877Sjkim        "deleted in order to recompile the dsl file.\n\n",
1573322877Sjkim        Path);
1574322877Sjkim}
1575322877Sjkim
1576322877Sjkim
1577322877Sjkim/*******************************************************************************
1578322877Sjkim *
1579316303Sjkim * FUNCTION:    AcpiDmEmitExternal
1580316303Sjkim *
1581316303Sjkim * PARAMETERS:  Op                  External Parse Object
1582316303Sjkim *
1583316303Sjkim * RETURN:      None
1584316303Sjkim *
1585316303Sjkim * DESCRIPTION: Emit an External() ASL statement for the current External
1586322877Sjkim *              parse object. Note: External Ops are named types so the
1587322877Sjkim *              namepath is contained within NameOp->Name.Path.
1588316303Sjkim *
1589316303Sjkim ******************************************************************************/
1590316303Sjkim
1591316303Sjkimvoid
1592316303SjkimAcpiDmEmitExternal (
1593316303Sjkim    ACPI_PARSE_OBJECT       *NameOp,
1594316303Sjkim    ACPI_PARSE_OBJECT       *TypeOp)
1595316303Sjkim{
1596316303Sjkim    AcpiOsPrintf ("External (");
1597322877Sjkim    AcpiDmNamestring (NameOp->Named.Path);
1598322877Sjkim    AcpiOsPrintf ("%s)",
1599316303Sjkim        AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer));
1600322877Sjkim    AcpiDmCheckForExternalConflict (NameOp->Named.Path);
1601322877Sjkim    AcpiOsPrintf ("\n");
1602316303Sjkim}
1603316303Sjkim
1604316303Sjkim
1605316303Sjkim/*******************************************************************************
1606316303Sjkim *
1607322877Sjkim * FUNCTION:    AcpiDmCheckForExternalConflict
1608322877Sjkim *
1609322877Sjkim * PARAMETERS:  Path                - Path to check
1610322877Sjkim *
1611322877Sjkim * RETURN:      None
1612322877Sjkim *
1613322877Sjkim * DESCRIPTION: Search the External List to see if the input Path has a
1614322877Sjkim *              conflicting declaration.
1615322877Sjkim *
1616322877Sjkim ******************************************************************************/
1617322877Sjkim
1618322877Sjkimstatic void
1619322877SjkimAcpiDmCheckForExternalConflict (
1620322877Sjkim    char                    *Path)
1621322877Sjkim{
1622322877Sjkim    ACPI_EXTERNAL_LIST      *ExternalList = AcpiGbl_ExternalList;
1623322877Sjkim    char                    *ListItemPath;
1624322877Sjkim    char                    *InputPath;
1625322877Sjkim
1626322877Sjkim
1627322877Sjkim    if (!Path)
1628322877Sjkim    {
1629322877Sjkim        return;
1630322877Sjkim    }
1631322877Sjkim
1632322877Sjkim    /* Move past the root prefix '\' */
1633322877Sjkim
1634322877Sjkim    InputPath = Path;
1635322877Sjkim    if ((*InputPath == AML_ROOT_PREFIX) && InputPath[1])
1636322877Sjkim    {
1637322877Sjkim        InputPath++;
1638322877Sjkim    }
1639322877Sjkim
1640322877Sjkim    while (ExternalList)
1641322877Sjkim    {
1642322877Sjkim        ListItemPath = ExternalList->Path;
1643322877Sjkim        if (ListItemPath)
1644322877Sjkim        {
1645322877Sjkim            /* Move past the root prefix '\' */
1646322877Sjkim
1647322877Sjkim            if ((*ListItemPath == AML_ROOT_PREFIX) &&
1648322877Sjkim                ListItemPath[1])
1649322877Sjkim            {
1650322877Sjkim                ListItemPath++;
1651322877Sjkim            }
1652322877Sjkim
1653322877Sjkim            if (!strcmp (ListItemPath, InputPath) &&
1654322877Sjkim                (ExternalList->Flags & ACPI_EXT_CONFLICTING_DECLARATION))
1655322877Sjkim            {
1656322877Sjkim                AcpiOsPrintf ("%s", ExternalConflictMessage);
1657322877Sjkim                AcpiDmConflictingDeclaration (Path);
1658322877Sjkim
1659322877Sjkim                return;
1660322877Sjkim            }
1661322877Sjkim        }
1662322877Sjkim        ExternalList = ExternalList->Next;
1663322877Sjkim    }
1664322877Sjkim}
1665322877Sjkim/*******************************************************************************
1666322877Sjkim *
1667246849Sjkim * FUNCTION:    AcpiDmUnresolvedWarning
1668246849Sjkim *
1669246849Sjkim * PARAMETERS:  Type                - Where to output the warning.
1670246849Sjkim *                                    0 means write to stderr
1671246849Sjkim *                                    1 means write to AcpiOsPrintf
1672246849Sjkim *
1673246849Sjkim * RETURN:      None
1674246849Sjkim *
1675246849Sjkim * DESCRIPTION: Issue warning message if there are unresolved external control
1676246849Sjkim *              methods within the disassembly.
1677246849Sjkim *
1678246849Sjkim ******************************************************************************/
1679246849Sjkim
1680322877Sjkim/*
1681246849SjkimSummary of the external control method problem:
1682246849Sjkim
1683246849SjkimWhen the -e option is used with disassembly, the various SSDTs are simply
1684246849Sjkimloaded into a global namespace for the disassembler to use in order to
1685246849Sjkimresolve control method references (invocations).
1686246849Sjkim
1687246849SjkimThe disassembler tracks any such references, and will emit an External()
1688246849Sjkimstatement for these types of methods, with the proper number of arguments .
1689246849Sjkim
1690246849SjkimWithout the SSDTs, the AML does not contain enough information to properly
1691246849Sjkimdisassemble the control method invocation -- because the disassembler does
1692246849Sjkimnot know how many arguments to parse.
1693246849Sjkim
1694246849SjkimAn example: Assume we have two control methods. ABCD has one argument, and
1695246849SjkimEFGH has zero arguments. Further, we have two additional control methods
1696246849Sjkimthat invoke ABCD and EFGH, named T1 and T2:
1697246849Sjkim
1698246849Sjkim    Method (ABCD, 1)
1699246849Sjkim    {
1700246849Sjkim    }
1701246849Sjkim    Method (EFGH, 0)
1702246849Sjkim    {
1703246849Sjkim    }
1704246849Sjkim    Method (T1)
1705246849Sjkim    {
1706246849Sjkim        ABCD (Add (2, 7, Local0))
1707246849Sjkim    }
1708246849Sjkim    Method (T2)
1709246849Sjkim    {
1710246849Sjkim        EFGH ()
1711246849Sjkim        Add (2, 7, Local0)
1712246849Sjkim    }
1713246849Sjkim
1714246849SjkimHere is the AML code that is generated for T1 and T2:
1715246849Sjkim
1716246849Sjkim     185:      Method (T1)
1717246849Sjkim
1718246849Sjkim0000034C:  14 10 54 31 5F 5F 00 ...    "..T1__."
1719246849Sjkim
1720246849Sjkim     186:      {
1721246849Sjkim     187:          ABCD (Add (2, 7, Local0))
1722246849Sjkim
1723246849Sjkim00000353:  41 42 43 44 ............    "ABCD"
1724246849Sjkim00000357:  72 0A 02 0A 07 60 ......    "r....`"
1725246849Sjkim
1726246849Sjkim     188:      }
1727246849Sjkim
1728246849Sjkim     190:      Method (T2)
1729246849Sjkim
1730246849Sjkim0000035D:  14 10 54 32 5F 5F 00 ...    "..T2__."
1731246849Sjkim
1732246849Sjkim     191:      {
1733246849Sjkim     192:          EFGH ()
1734246849Sjkim
1735246849Sjkim00000364:  45 46 47 48 ............    "EFGH"
1736246849Sjkim
1737246849Sjkim     193:          Add (2, 7, Local0)
1738246849Sjkim
1739246849Sjkim00000368:  72 0A 02 0A 07 60 ......    "r....`"
1740246849Sjkim     194:      }
1741246849Sjkim
1742246849SjkimNote that the AML code for T1 and T2 is essentially identical. When
1743246849Sjkimdisassembling this code, the methods ABCD and EFGH must be known to the
1744246849Sjkimdisassembler, otherwise it does not know how to handle the method invocations.
1745246849Sjkim
1746246849SjkimIn other words, if ABCD and EFGH are actually external control methods
1747246849Sjkimappearing in an SSDT, the disassembler does not know what to do unless
1748246849Sjkimthe owning SSDT has been loaded via the -e option.
1749322877Sjkim*/
1750246849Sjkim
1751298714Sjkimstatic char             ExternalWarningPart1[600];
1752298714Sjkimstatic char             ExternalWarningPart2[400];
1753298714Sjkimstatic char             ExternalWarningPart3[400];
1754298714Sjkimstatic char             ExternalWarningPart4[200];
1755298714Sjkim
1756246849Sjkimvoid
1757246849SjkimAcpiDmUnresolvedWarning (
1758246849Sjkim    UINT8                   Type)
1759246849Sjkim{
1760298714Sjkim    char                    *Format;
1761298714Sjkim    char                    Pad[] = "     *";
1762298714Sjkim    char                    NoPad[] = "";
1763246849Sjkim
1764298714Sjkim
1765246849Sjkim    if (!AcpiGbl_NumExternalMethods)
1766246849Sjkim    {
1767246849Sjkim        return;
1768246849Sjkim    }
1769246849Sjkim
1770298714Sjkim    if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
1771298714Sjkim    {
1772298714Sjkim        return;
1773298714Sjkim    }
1774298714Sjkim
1775298714Sjkim    Format = Type ? Pad : NoPad;
1776298714Sjkim
1777298714Sjkim    sprintf (ExternalWarningPart1,
1778298714Sjkim        "%s iASL Warning: There %s %u external control method%s found during\n"
1779298714Sjkim        "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1780298714Sjkim        "%s ACPI tables may be required to properly disassemble the code. This\n"
1781298714Sjkim        "%s resulting disassembler output file may not compile because the\n"
1782298714Sjkim        "%s disassembler did not know how many arguments to assign to the\n"
1783298714Sjkim        "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1784298714Sjkim        "%s runtime and may or may not be available via the host OS.\n",
1785298714Sjkim        Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
1786298714Sjkim        AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
1787298714Sjkim        Format, AcpiGbl_ResolvedExternalMethods,
1788298714Sjkim        (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
1789298714Sjkim        (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
1790298714Sjkim        Format, Format, Format, Format, Format);
1791298714Sjkim
1792298714Sjkim    sprintf (ExternalWarningPart2,
1793298714Sjkim        "%s To specify the tables needed to resolve external control method\n"
1794298714Sjkim        "%s references, the -e option can be used to specify the filenames.\n"
1795298714Sjkim        "%s Example iASL invocations:\n"
1796298714Sjkim        "%s     iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1797298714Sjkim        "%s     iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1798298714Sjkim        "%s     iasl -e ssdt*.aml -d dsdt.aml\n",
1799298714Sjkim        Format, Format, Format, Format, Format, Format);
1800298714Sjkim
1801298714Sjkim    sprintf (ExternalWarningPart3,
1802298714Sjkim        "%s In addition, the -fe option can be used to specify a file containing\n"
1803298714Sjkim        "%s control method external declarations with the associated method\n"
1804298714Sjkim        "%s argument counts. Each line of the file must be of the form:\n"
1805298714Sjkim        "%s     External (<method pathname>, MethodObj, <argument count>)\n"
1806298714Sjkim        "%s Invocation:\n"
1807298714Sjkim        "%s     iasl -fe refs.txt -d dsdt.aml\n",
1808298714Sjkim        Format, Format, Format, Format, Format, Format);
1809298714Sjkim
1810298714Sjkim    sprintf (ExternalWarningPart4,
1811298714Sjkim        "%s The following methods were unresolved and many not compile properly\n"
1812298714Sjkim        "%s because the disassembler had to guess at the number of arguments\n"
1813298714Sjkim        "%s required for each:\n",
1814298714Sjkim        Format, Format, Format);
1815298714Sjkim
1816246849Sjkim    if (Type)
1817246849Sjkim    {
1818246849Sjkim        if (!AcpiGbl_ExternalFileList)
1819246849Sjkim        {
1820246849Sjkim            /* The -e option was not specified */
1821246849Sjkim
1822298714Sjkim           AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     *\n%s     */\n",
1823298714Sjkim               ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
1824298714Sjkim               ExternalWarningPart4);
1825246849Sjkim        }
1826298714Sjkim        else
1827246849Sjkim        {
1828246849Sjkim            /* The -e option was specified, but there are still some unresolved externals */
1829246849Sjkim
1830298714Sjkim            AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     */\n",
1831298714Sjkim               ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
1832246849Sjkim        }
1833246849Sjkim    }
1834246849Sjkim    else
1835246849Sjkim    {
1836246849Sjkim        if (!AcpiGbl_ExternalFileList)
1837246849Sjkim        {
1838246849Sjkim            /* The -e option was not specified */
1839246849Sjkim
1840298714Sjkim            fprintf (stderr, "\n%s\n%s\n%s\n",
1841298714Sjkim               ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
1842246849Sjkim        }
1843298714Sjkim        else
1844246849Sjkim        {
1845246849Sjkim            /* The -e option was specified, but there are still some unresolved externals */
1846246849Sjkim
1847298714Sjkim            fprintf (stderr, "\n%s\n%s\n",
1848298714Sjkim               ExternalWarningPart1, ExternalWarningPart3);
1849246849Sjkim        }
1850246849Sjkim    }
1851246849Sjkim}
1852