Home | History | Annotate | Line # | Download | only in common
      1 /******************************************************************************
      2  *
      3  * Module Name: dmextern - Support for External() ASL statements
      4  *
      5  *****************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights. You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code. No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision. In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change. Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee. Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution. In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government. In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************
    115  *
    116  * Alternatively, you may choose to be licensed under the terms of the
    117  * following license:
    118  *
    119  * Redistribution and use in source and binary forms, with or without
    120  * modification, are permitted provided that the following conditions
    121  * are met:
    122  * 1. Redistributions of source code must retain the above copyright
    123  *    notice, this list of conditions, and the following disclaimer,
    124  *    without modification.
    125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    126  *    substantially similar to the "NO WARRANTY" disclaimer below
    127  *    ("Disclaimer") and any redistribution must be conditioned upon
    128  *    including a substantially similar Disclaimer requirement for further
    129  *    binary redistribution.
    130  * 3. Neither the names of the above-listed copyright holders nor the names
    131  *    of any contributors may be used to endorse or promote products derived
    132  *    from this software without specific prior written permission.
    133  *
    134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    145  *
    146  * Alternatively, you may choose to be licensed under the terms of the
    147  * GNU General Public License ("GPL") version 2 as published by the Free
    148  * Software Foundation.
    149  *
    150  *****************************************************************************/
    151 
    152 #include "acpi.h"
    153 #include "accommon.h"
    154 #include "amlcode.h"
    155 #include "acnamesp.h"
    156 #include "acdisasm.h"
    157 #include "aslcompiler.h"
    158 #include <stdio.h>
    159 #include <errno.h>
    160 
    161 
    162 /*
    163  * This module is used for application-level code (iASL disassembler) only.
    164  *
    165  * It contains the code to create and emit any necessary External() ASL
    166  * statements for the module being disassembled.
    167  */
    168 #define _COMPONENT          ACPI_CA_DISASSEMBLER
    169         ACPI_MODULE_NAME    ("dmextern")
    170 
    171 
    172 /*
    173  * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
    174  * ObjectTypeKeyword. Used to generate typed external declarations
    175  */
    176 static const char           *AcpiGbl_DmTypeNames[] =
    177 {
    178     /* 00 */ ", UnknownObj",        /* Type ANY */
    179     /* 01 */ ", IntObj",
    180     /* 02 */ ", StrObj",
    181     /* 03 */ ", BuffObj",
    182     /* 04 */ ", PkgObj",
    183     /* 05 */ ", FieldUnitObj",
    184     /* 06 */ ", DeviceObj",
    185     /* 07 */ ", EventObj",
    186     /* 08 */ ", MethodObj",
    187     /* 09 */ ", MutexObj",
    188     /* 10 */ ", OpRegionObj",
    189     /* 11 */ ", PowerResObj",
    190     /* 12 */ ", ProcessorObj",
    191     /* 13 */ ", ThermalZoneObj",
    192     /* 14 */ ", BuffFieldObj",
    193     /* 15 */ ", DDBHandleObj",
    194     /* 16 */ "",                    /* Debug object */
    195     /* 17 */ ", FieldUnitObj",
    196     /* 18 */ ", FieldUnitObj",
    197     /* 19 */ ", FieldUnitObj"
    198 };
    199 
    200 #define METHOD_SEPARATORS           " \t,()\n"
    201 
    202 static const char          *ExternalConflictMessage =
    203     "    // Conflicts with a later declaration";
    204 
    205 
    206 /* Local prototypes */
    207 
    208 static const char *
    209 AcpiDmGetObjectTypeName (
    210     ACPI_OBJECT_TYPE        Type);
    211 
    212 static char *
    213 AcpiDmNormalizeParentPrefix (
    214     ACPI_PARSE_OBJECT       *Op,
    215     char                    *Path);
    216 
    217 static ACPI_STATUS
    218 AcpiDmGetExternalAndInternalPath (
    219     ACPI_NAMESPACE_NODE     *Node,
    220     char                    **ExternalPath,
    221     char                    **InternalPath);
    222 
    223 static ACPI_STATUS
    224 AcpiDmRemoveRootPrefix (
    225     char                    **Path);
    226 
    227 static void
    228 AcpiDmAddPathToExternalList (
    229     char                    *Path,
    230     UINT8                   Type,
    231     UINT32                  Value,
    232     UINT16                  Flags);
    233 
    234 static ACPI_STATUS
    235 AcpiDmCreateNewExternal (
    236     char                    *ExternalPath,
    237     char                    *InternalPath,
    238     UINT8                   Type,
    239     UINT32                  Value,
    240     UINT16                  Flags);
    241 
    242 static void
    243 AcpiDmCheckForExternalConflict (
    244     char                    *Path);
    245 
    246 static ACPI_STATUS
    247 AcpiDmResolveExternal (
    248     char                    *Path,
    249     UINT8                   Type,
    250     ACPI_NAMESPACE_NODE     **Node);
    251 
    252 
    253 static void
    254 AcpiDmConflictingDeclaration (
    255     char                    *Path);
    256 
    257 
    258 /*******************************************************************************
    259  *
    260  * FUNCTION:    AcpiDmGetObjectTypeName
    261  *
    262  * PARAMETERS:  Type                - An ACPI_OBJECT_TYPE
    263  *
    264  * RETURN:      Pointer to a string
    265  *
    266  * DESCRIPTION: Map an object type to the ASL object type string.
    267  *
    268  ******************************************************************************/
    269 
    270 static const char *
    271 AcpiDmGetObjectTypeName (
    272     ACPI_OBJECT_TYPE        Type)
    273 {
    274 
    275     if (Type == ACPI_TYPE_LOCAL_SCOPE)
    276     {
    277         Type = ACPI_TYPE_DEVICE;
    278     }
    279     else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
    280     {
    281         return ("");
    282     }
    283 
    284     return (AcpiGbl_DmTypeNames[Type]);
    285 }
    286 
    287 
    288 /*******************************************************************************
    289  *
    290  * FUNCTION:    AcpiDmNormalizeParentPrefix
    291  *
    292  * PARAMETERS:  Op                  - Parse op
    293  *              Path                - Path with parent prefix
    294  *
    295  * RETURN:      The full pathname to the object (from the namespace root)
    296  *
    297  * DESCRIPTION: Returns the full pathname of a path with parent prefix
    298  *              The caller must free the fullpath returned.
    299  *
    300  ******************************************************************************/
    301 
    302 static char *
    303 AcpiDmNormalizeParentPrefix (
    304     ACPI_PARSE_OBJECT       *Op,
    305     char                    *Path)
    306 {
    307     ACPI_NAMESPACE_NODE     *Node;
    308     char                    *Fullpath;
    309     char                    *ParentPath;
    310     ACPI_SIZE               Length;
    311     UINT32                  Index = 0;
    312 
    313 
    314     if (!Op)
    315     {
    316         return (NULL);
    317     }
    318 
    319     /* Search upwards in the parse tree until we reach the next namespace node */
    320 
    321     Op = Op->Common.Parent;
    322     while (Op)
    323     {
    324         if (Op->Common.Node)
    325         {
    326             break;
    327         }
    328 
    329         Op = Op->Common.Parent;
    330     }
    331 
    332     if (!Op)
    333     {
    334         return (NULL);
    335     }
    336 
    337     /*
    338      * Find the actual parent node for the reference:
    339      * Remove all carat prefixes from the input path.
    340      * There may be multiple parent prefixes (For example, ^^^M000)
    341      */
    342     Node = Op->Common.Node;
    343     while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
    344     {
    345         Node = Node->Parent;
    346         Path++;
    347     }
    348 
    349     if (!Node)
    350     {
    351         return (NULL);
    352     }
    353 
    354     /* Get the full pathname for the parent node */
    355 
    356     ParentPath = AcpiNsGetExternalPathname (Node);
    357     if (!ParentPath)
    358     {
    359         return (NULL);
    360     }
    361 
    362     Length = (strlen (ParentPath) + strlen (Path) + 1);
    363     if (ParentPath[1])
    364     {
    365         /*
    366          * If ParentPath is not just a simple '\', increment the length
    367          * for the required dot separator (ParentPath.Path)
    368          */
    369         Length++;
    370 
    371         /* For External() statements, we do not want a leading '\' */
    372 
    373         if (*ParentPath == AML_ROOT_PREFIX)
    374         {
    375             Index = 1;
    376         }
    377     }
    378 
    379     Fullpath = ACPI_ALLOCATE_ZEROED (Length);
    380     if (!Fullpath)
    381     {
    382         goto Cleanup;
    383     }
    384 
    385     /*
    386      * Concatenate parent fullpath and path. For example,
    387      * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
    388      *
    389      * Copy the parent path
    390      */
    391     strcpy (Fullpath, &ParentPath[Index]);
    392 
    393     /*
    394      * Add dot separator
    395      * (don't need dot if parent fullpath is a single backslash)
    396      */
    397     if (ParentPath[1])
    398     {
    399         strcat (Fullpath, ".");
    400     }
    401 
    402     /* Copy child path (carat parent prefix(es) were skipped above) */
    403 
    404     strcat (Fullpath, Path);
    405 
    406 Cleanup:
    407     ACPI_FREE (ParentPath);
    408     return (Fullpath);
    409 }
    410 
    411 
    412 /*******************************************************************************
    413  *
    414  * FUNCTION:    AcpiDmAddToExternalFileList
    415  *
    416  * PARAMETERS:  PathList            - Single path or list separated by comma
    417  *
    418  * RETURN:      None
    419  *
    420  * DESCRIPTION: Add external files to global list
    421  *
    422  ******************************************************************************/
    423 
    424 ACPI_STATUS
    425 AcpiDmAddToExternalFileList (
    426     char                    *Pathname)
    427 {
    428     ACPI_EXTERNAL_FILE      *ExternalFile;
    429     char                    *LocalPathname;
    430 
    431 
    432     if (!Pathname)
    433     {
    434         return (AE_OK);
    435     }
    436 
    437     LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
    438     if (!LocalPathname)
    439     {
    440         return (AE_NO_MEMORY);
    441     }
    442 
    443     ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
    444     if (!ExternalFile)
    445     {
    446         ACPI_FREE (LocalPathname);
    447         return (AE_NO_MEMORY);
    448     }
    449 
    450     /* Take a copy of the file pathname */
    451 
    452     strcpy (LocalPathname, Pathname);
    453     ExternalFile->Path = LocalPathname;
    454 
    455     if (AcpiGbl_ExternalFileList)
    456     {
    457         ExternalFile->Next = AcpiGbl_ExternalFileList;
    458     }
    459 
    460     AcpiGbl_ExternalFileList = ExternalFile;
    461     return (AE_OK);
    462 }
    463 
    464 
    465 /*******************************************************************************
    466  *
    467  * FUNCTION:    AcpiDmClearExternalFileList
    468  *
    469  * PARAMETERS:  None
    470  *
    471  * RETURN:      None
    472  *
    473  * DESCRIPTION: Clear the external file list
    474  *
    475  ******************************************************************************/
    476 
    477 void
    478 AcpiDmClearExternalFileList (
    479     void)
    480 {
    481     ACPI_EXTERNAL_FILE      *NextExternal;
    482 
    483 
    484     while (AcpiGbl_ExternalFileList)
    485     {
    486         NextExternal = AcpiGbl_ExternalFileList->Next;
    487         ACPI_FREE (AcpiGbl_ExternalFileList->Path);
    488         ACPI_FREE (AcpiGbl_ExternalFileList);
    489         AcpiGbl_ExternalFileList = NextExternal;
    490     }
    491 }
    492 
    493 
    494 /*******************************************************************************
    495  *
    496  * FUNCTION:    AcpiDmGetExternalsFromFile
    497  *
    498  * PARAMETERS:  None
    499  *
    500  * RETURN:      None
    501  *
    502  * DESCRIPTION: Process the optional external reference file.
    503  *
    504  * Each line in the file should be of the form:
    505  *      External (<Method namepath>, MethodObj, <ArgCount>)
    506  *
    507  * Example:
    508  *      External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
    509  *
    510  ******************************************************************************/
    511 
    512 void
    513 AcpiDmGetExternalsFromFile (
    514     void)
    515 {
    516     FILE                    *ExternalRefFile;
    517     char                    *Token;
    518     char                    *MethodName;
    519     UINT32                  ArgCount;
    520     UINT32                  ImportCount = 0;
    521 
    522 
    523     if (!AslGbl_ExternalRefFilename)
    524     {
    525         return;
    526     }
    527 
    528     /* Open the file */
    529 
    530     ExternalRefFile = fopen (AslGbl_ExternalRefFilename, "r");
    531     if (!ExternalRefFile)
    532     {
    533         fprintf (stderr, "Could not open external reference file \"%s\"\n",
    534             AslGbl_ExternalRefFilename);
    535         AslAbort ();
    536         return;
    537     }
    538 
    539     /* Each line defines a method */
    540 
    541     while (fgets (AslGbl_StringBuffer, ASL_STRING_BUFFER_SIZE, ExternalRefFile))
    542     {
    543         Token = strtok (AslGbl_StringBuffer, METHOD_SEPARATORS);   /* "External" */
    544         if (!Token)
    545         {
    546             continue;
    547         }
    548 
    549         if (strcmp (Token, "External"))
    550         {
    551             continue;
    552         }
    553 
    554         MethodName = strtok (NULL, METHOD_SEPARATORS);      /* Method namepath */
    555         if (!MethodName)
    556         {
    557             continue;
    558         }
    559 
    560         Token = strtok (NULL, METHOD_SEPARATORS);           /* "MethodObj" */
    561         if (!Token)
    562         {
    563             continue;
    564         }
    565 
    566         if (strcmp (Token, "MethodObj"))
    567         {
    568             continue;
    569         }
    570 
    571         Token = strtok (NULL, METHOD_SEPARATORS);           /* Arg count */
    572         if (!Token)
    573         {
    574             continue;
    575         }
    576 
    577         /* Convert arg count string to an integer */
    578 
    579         errno = 0;
    580         ArgCount = strtoul (Token, NULL, 0);
    581         if (errno)
    582         {
    583             fprintf (stderr, "Invalid argument count (%s)\n", Token);
    584             continue;
    585         }
    586 
    587         if (ArgCount > 7)
    588         {
    589             fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
    590             continue;
    591         }
    592 
    593         /* Add this external to the global list */
    594 
    595         AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
    596             AslGbl_ExternalRefFilename, ArgCount, MethodName);
    597 
    598         AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
    599             ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
    600         ImportCount++;
    601     }
    602 
    603     if (!ImportCount)
    604     {
    605         fprintf (stderr,
    606             "Did not find any external methods in reference file \"%s\"\n",
    607             AslGbl_ExternalRefFilename);
    608     }
    609     else
    610     {
    611         /* Add the external(s) to the namespace */
    612 
    613         AcpiDmAddExternalListToNamespace ();
    614 
    615         AcpiOsPrintf ("%s: Imported %u external method definitions\n",
    616             AslGbl_ExternalRefFilename, ImportCount);
    617     }
    618 
    619     fclose (ExternalRefFile);
    620 }
    621 
    622 
    623 /*******************************************************************************
    624  *
    625  * FUNCTION:    AcpiDmAddOpToExternalList
    626  *
    627  * PARAMETERS:  Op                  - Current parser Op
    628  *              Path                - Internal (AML) path to the object
    629  *              Type                - ACPI object type to be added
    630  *              Value               - Arg count if adding a Method object
    631  *              Flags               - To be passed to the external object
    632  *
    633  * RETURN:      None
    634  *
    635  * DESCRIPTION: Insert a new name into the global list of Externals which
    636  *              will in turn be later emitted as an External() declaration
    637  *              in the disassembled output.
    638  *
    639  *              This function handles the most common case where the referenced
    640  *              name is simply not found in the constructed namespace.
    641  *
    642  ******************************************************************************/
    643 
    644 void
    645 AcpiDmAddOpToExternalList (
    646     ACPI_PARSE_OBJECT       *Op,
    647     char                    *Path,
    648     UINT8                   Type,
    649     UINT32                  Value,
    650     UINT16                  Flags)
    651 {
    652     char                    *ExternalPath;
    653     char                    *InternalPath = Path;
    654     char                    *Temp;
    655     ACPI_STATUS             Status;
    656 
    657 
    658     ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
    659 
    660 
    661     if (!Path)
    662     {
    663         return_VOID;
    664     }
    665 
    666     /* Remove a root backslash if present */
    667 
    668     if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
    669     {
    670         Path++;
    671     }
    672 
    673     /* Externalize the pathname */
    674 
    675     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
    676         NULL, &ExternalPath);
    677     if (ACPI_FAILURE (Status))
    678     {
    679         return_VOID;
    680     }
    681 
    682     /*
    683      * Get the full pathname from the root if "Path" has one or more
    684      * parent prefixes (^). Note: path will not contain a leading '\'.
    685      */
    686     if (*Path == (UINT8) AML_PARENT_PREFIX)
    687     {
    688         Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
    689 
    690         /* Set new external path */
    691 
    692         ACPI_FREE (ExternalPath);
    693         ExternalPath = Temp;
    694         if (!Temp)
    695         {
    696             return_VOID;
    697         }
    698 
    699         /* Create the new internal pathname */
    700 
    701         Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
    702         Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
    703         if (ACPI_FAILURE (Status))
    704         {
    705             ACPI_FREE (ExternalPath);
    706             return_VOID;
    707         }
    708     }
    709 
    710     /* Create the new External() declaration node */
    711 
    712     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
    713         Type, Value, Flags);
    714     if (ACPI_FAILURE (Status))
    715     {
    716         ACPI_FREE (ExternalPath);
    717         if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
    718         {
    719             ACPI_FREE (InternalPath);
    720         }
    721     }
    722 
    723     return_VOID;
    724 }
    725 
    726 
    727 /*******************************************************************************
    728  *
    729  * FUNCTION:    AcpiDmGetExternalAndInternalPath
    730  *
    731  * PARAMETERS:  Node                - Namespace node for object to be added
    732  *              ExternalPath        - Will contain the external path of the node
    733  *              InternalPath        - Will contain the internal path of the node
    734  *
    735  * RETURN:      None
    736  *
    737  * DESCRIPTION: Get the External and Internal path from the given node.
    738  *
    739  ******************************************************************************/
    740 
    741 static ACPI_STATUS
    742 AcpiDmGetExternalAndInternalPath (
    743     ACPI_NAMESPACE_NODE     *Node,
    744     char                    **ExternalPath,
    745     char                    **InternalPath)
    746 {
    747     ACPI_STATUS             Status;
    748 
    749 
    750     if (!Node)
    751     {
    752         return (AE_BAD_PARAMETER);
    753     }
    754 
    755     /* Get the full external and internal pathnames to the node */
    756 
    757     *ExternalPath = AcpiNsGetExternalPathname (Node);
    758     if (!*ExternalPath)
    759     {
    760         return (AE_BAD_PATHNAME);
    761     }
    762 
    763     Status = AcpiNsInternalizeName (*ExternalPath, InternalPath);
    764     if (ACPI_FAILURE (Status))
    765     {
    766         ACPI_FREE (*ExternalPath);
    767         return (Status);
    768     }
    769 
    770     return (AE_OK);
    771 }
    772 
    773 
    774 /*******************************************************************************
    775  *
    776  * FUNCTION:    AcpiDmRemoveRootPrefix
    777  *
    778  * PARAMETERS:  Path                - Remove Root prefix from this Path
    779  *
    780  * RETURN:      None
    781  *
    782  * DESCRIPTION: Remove the root prefix character '\' from Path.
    783  *
    784  ******************************************************************************/
    785 
    786 static ACPI_STATUS
    787 AcpiDmRemoveRootPrefix (
    788     char                    **Path)
    789 {
    790     char                    *InputPath = *Path;
    791 
    792 
    793     if ((*InputPath == AML_ROOT_PREFIX) && (InputPath[1]))
    794     {
    795         if (!memmove(InputPath, InputPath+1, strlen(InputPath)))
    796         {
    797             return (AE_ERROR);
    798         }
    799 
    800         *Path = InputPath;
    801     }
    802 
    803     return (AE_OK);
    804 }
    805 
    806 
    807 /*******************************************************************************
    808  *
    809  * FUNCTION:    AcpiDmAddNodeToExternalList
    810  *
    811  * PARAMETERS:  Node                - Namespace node for object to be added
    812  *              Type                - ACPI object type to be added
    813  *              Value               - Arg count if adding a Method object
    814  *              Flags               - To be passed to the external object
    815  *
    816  * RETURN:      None
    817  *
    818  * DESCRIPTION: Insert a new name into the global list of Externals which
    819  *              will in turn be later emitted as an External() declaration
    820  *              in the disassembled output.
    821  *
    822  *              This function handles the case where the referenced name has
    823  *              been found in the namespace, but the name originated in a
    824  *              table other than the one that is being disassembled (such
    825  *              as a table that is added via the iASL -e option).
    826  *
    827  ******************************************************************************/
    828 
    829 void
    830 AcpiDmAddNodeToExternalList (
    831     ACPI_NAMESPACE_NODE     *Node,
    832     UINT8                   Type,
    833     UINT32                  Value,
    834     UINT16                  Flags)
    835 {
    836     char                    *ExternalPath;
    837     char                    *InternalPath;
    838     ACPI_STATUS             Status;
    839 
    840 
    841     ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
    842 
    843     /* Get the full external and internal pathnames to the node */
    844 
    845     Status = AcpiDmGetExternalAndInternalPath (Node, &ExternalPath, &InternalPath);
    846     if (ACPI_FAILURE (Status))
    847     {
    848         return_VOID;
    849     }
    850 
    851     /* Remove the root backslash */
    852 
    853     Status = AcpiDmRemoveRootPrefix (&ExternalPath);
    854     if (ACPI_FAILURE (Status))
    855     {
    856         ACPI_FREE (ExternalPath);
    857         ACPI_FREE (InternalPath);
    858         return_VOID;
    859     }
    860 
    861     /* Create the new External() declaration node */
    862 
    863     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
    864         Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
    865     if (ACPI_FAILURE (Status))
    866     {
    867         ACPI_FREE (ExternalPath);
    868         ACPI_FREE (InternalPath);
    869     }
    870 
    871     return_VOID;
    872 }
    873 
    874 
    875 /*******************************************************************************
    876  *
    877  * FUNCTION:    AcpiDmAddPathToExternalList
    878  *
    879  * PARAMETERS:  Path                - External name of the object to be added
    880  *              Type                - ACPI object type to be added
    881  *              Value               - Arg count if adding a Method object
    882  *              Flags               - To be passed to the external object
    883  *
    884  * RETURN:      None
    885  *
    886  * DESCRIPTION: Insert a new name into the global list of Externals which
    887  *              will in turn be later emitted as an External() declaration
    888  *              in the disassembled output.
    889  *
    890  *              This function currently is used to add externals via a
    891  *              reference file (via the -fe iASL option).
    892  *
    893  ******************************************************************************/
    894 
    895 static void
    896 AcpiDmAddPathToExternalList (
    897     char                    *Path,
    898     UINT8                   Type,
    899     UINT32                  Value,
    900     UINT16                  Flags)
    901 {
    902     char                    *InternalPath;
    903     char                    *ExternalPath;
    904     ACPI_STATUS             Status;
    905 
    906 
    907     ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
    908 
    909 
    910     if (!Path)
    911     {
    912         return_VOID;
    913     }
    914 
    915     /* Remove a root backslash if present */
    916 
    917     if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
    918     {
    919         Path++;
    920     }
    921 
    922     /* Create the internal and external pathnames */
    923 
    924     Status = AcpiNsInternalizeName (Path, &InternalPath);
    925     if (ACPI_FAILURE (Status))
    926     {
    927         return_VOID;
    928     }
    929 
    930     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
    931         NULL, &ExternalPath);
    932     if (ACPI_FAILURE (Status))
    933     {
    934         ACPI_FREE (InternalPath);
    935         return_VOID;
    936     }
    937 
    938     /* Create the new External() declaration node */
    939 
    940     Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
    941         Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
    942     if (ACPI_FAILURE (Status))
    943     {
    944         ACPI_FREE (ExternalPath);
    945         ACPI_FREE (InternalPath);
    946     }
    947 
    948     return_VOID;
    949 }
    950 
    951 
    952 /*******************************************************************************
    953  *
    954  * FUNCTION:    AcpiDmCreateNewExternal
    955  *
    956  * PARAMETERS:  ExternalPath        - External path to the object
    957  *              InternalPath        - Internal (AML) path to the object
    958  *              Type                - ACPI object type to be added
    959  *              Value               - Arg count if adding a Method object
    960  *              Flags               - To be passed to the external object
    961  *
    962  * RETURN:      Status
    963  *
    964  * DESCRIPTION: Common low-level function to insert a new name into the global
    965  *              list of Externals which will in turn be later emitted as
    966  *              External() declarations in the disassembled output.
    967  *
    968  *              Note: The external name should not include a root prefix
    969  *              (backslash). We do not want External() statements to contain
    970  *              a leading '\', as this prevents duplicate external statements
    971  *              of the form:
    972  *
    973  *                  External (\ABCD)
    974  *                  External (ABCD)
    975  *
    976  *              This would cause a compile time error when the disassembled
    977  *              output file is recompiled.
    978  *
    979  *              There are two cases that are handled here. For both, we emit
    980  *              an External() statement:
    981  *              1) The name was simply not found in the namespace.
    982  *              2) The name was found, but it originated in a table other than
    983  *              the table that is being disassembled.
    984  *
    985  ******************************************************************************/
    986 
    987 static ACPI_STATUS
    988 AcpiDmCreateNewExternal (
    989     char                    *ExternalPath,
    990     char                    *InternalPath,
    991     UINT8                   Type,
    992     UINT32                  Value,
    993     UINT16                  Flags)
    994 {
    995     ACPI_EXTERNAL_LIST      *NewExternal;
    996     ACPI_EXTERNAL_LIST      *NextExternal;
    997     ACPI_EXTERNAL_LIST      *PrevExternal = NULL;
    998 
    999 
   1000     ACPI_FUNCTION_TRACE (DmCreateNewExternal);
   1001 
   1002 
   1003     /* Check all existing externals to ensure no duplicates */
   1004 
   1005     NextExternal = AcpiGbl_ExternalList;
   1006     while (NextExternal)
   1007     {
   1008         /* Check for duplicates */
   1009 
   1010         if (!strcmp (ExternalPath, NextExternal->Path))
   1011         {
   1012             /*
   1013              * If this external came from an External() opcode, we are
   1014              * finished with this one. (No need to check any further).
   1015              */
   1016             if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)
   1017             {
   1018                 return_ACPI_STATUS (AE_ALREADY_EXISTS);
   1019             }
   1020 
   1021             /* Allow upgrade of type from ANY */
   1022 
   1023             else if ((NextExternal->Type == ACPI_TYPE_ANY) &&
   1024                 (Type != ACPI_TYPE_ANY))
   1025             {
   1026                 NextExternal->Type = Type;
   1027             }
   1028 
   1029             /* Update the argument count as necessary */
   1030 
   1031             if (Value < NextExternal->Value)
   1032             {
   1033                 NextExternal->Value = Value;
   1034             }
   1035 
   1036             /* Update flags. */
   1037 
   1038             NextExternal->Flags |= Flags;
   1039             NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED;
   1040 
   1041             return_ACPI_STATUS (AE_ALREADY_EXISTS);
   1042         }
   1043 
   1044         NextExternal = NextExternal->Next;
   1045     }
   1046 
   1047     /* Allocate and init a new External() descriptor */
   1048 
   1049     NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
   1050     if (!NewExternal)
   1051     {
   1052         return_ACPI_STATUS (AE_NO_MEMORY);
   1053     }
   1054 
   1055     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
   1056         "Adding external reference node (%s) type [%s]\n",
   1057         ExternalPath, AcpiUtGetTypeName (Type)));
   1058 
   1059     NewExternal->Flags = Flags;
   1060     NewExternal->Value = Value;
   1061     NewExternal->Path = ExternalPath;
   1062     NewExternal->Type = Type;
   1063     NewExternal->Length = (UINT16) strlen (ExternalPath);
   1064     NewExternal->InternalPath = InternalPath;
   1065 
   1066     /* Link the new descriptor into the global list, alphabetically ordered */
   1067 
   1068     NextExternal = AcpiGbl_ExternalList;
   1069     while (NextExternal)
   1070     {
   1071         if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
   1072         {
   1073             if (PrevExternal)
   1074             {
   1075                 PrevExternal->Next = NewExternal;
   1076             }
   1077             else
   1078             {
   1079                 AcpiGbl_ExternalList = NewExternal;
   1080             }
   1081 
   1082             NewExternal->Next = NextExternal;
   1083             return_ACPI_STATUS (AE_OK);
   1084         }
   1085 
   1086         PrevExternal = NextExternal;
   1087         NextExternal = NextExternal->Next;
   1088     }
   1089 
   1090     if (PrevExternal)
   1091     {
   1092         PrevExternal->Next = NewExternal;
   1093     }
   1094     else
   1095     {
   1096         AcpiGbl_ExternalList = NewExternal;
   1097     }
   1098 
   1099     return_ACPI_STATUS (AE_OK);
   1100 }
   1101 
   1102 
   1103 /*******************************************************************************
   1104  *
   1105  * FUNCTION:    AcpiDmResolveExternal
   1106  *
   1107  * PARAMETERS:  Path               - Path of the external
   1108  *              Type               - Type of the external
   1109  *              Node               - Input node for AcpiNsLookup
   1110  *
   1111  * RETURN:      Status
   1112  *
   1113  * DESCRIPTION: Resolve the external within the namespace by AcpiNsLookup.
   1114  *              If the returned node is an external and has the same type
   1115  *              we assume that it was either an existing external or a
   1116  *
   1117  ******************************************************************************/
   1118 
   1119 static ACPI_STATUS
   1120 AcpiDmResolveExternal (
   1121     char                    *Path,
   1122     UINT8                   Type,
   1123     ACPI_NAMESPACE_NODE     **Node)
   1124 {
   1125     ACPI_STATUS             Status;
   1126 
   1127 
   1128     Status = AcpiNsLookup (NULL, Path, Type,
   1129         ACPI_IMODE_LOAD_PASS1,
   1130         ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
   1131         NULL, Node);
   1132 
   1133     if (!Node)
   1134     {
   1135         ACPI_EXCEPTION ((AE_INFO, Status,
   1136             "while adding external to namespace [%s]", Path));
   1137     }
   1138 
   1139     /* Note the asl code "external(a) external(a)" is acceptable ASL */
   1140 
   1141     else if ((*Node)->Type == Type &&
   1142         (*Node)->Flags & ANOBJ_IS_EXTERNAL)
   1143     {
   1144         return (AE_OK);
   1145     }
   1146     else
   1147     {
   1148         ACPI_EXCEPTION ((AE_INFO, AE_ERROR,
   1149             "[%s] has conflicting declarations", Path));
   1150     }
   1151 
   1152     return (AE_ERROR);
   1153 }
   1154 
   1155 
   1156 /*******************************************************************************
   1157  *
   1158  * FUNCTION:    AcpiDmCreateSubobjectForExternal
   1159  *
   1160  * PARAMETERS:  Type                  - Type of the external
   1161  *              Node                  - Namespace node from AcpiNsLookup
   1162  *              ParamCount            - Value to be used for Method
   1163  *
   1164  * RETURN:      None
   1165  *
   1166  * DESCRIPTION: Add one external to the namespace. Allows external to be
   1167  *              "resolved".
   1168  *
   1169  ******************************************************************************/
   1170 
   1171 void
   1172 AcpiDmCreateSubobjectForExternal (
   1173     UINT8                   Type,
   1174     ACPI_NAMESPACE_NODE     **Node,
   1175     UINT32                  ParamCount)
   1176 {
   1177     ACPI_OPERAND_OBJECT     *ObjDesc;
   1178 
   1179 
   1180     switch (Type)
   1181     {
   1182     case ACPI_TYPE_METHOD:
   1183 
   1184         /* For methods, we need to save the argument count */
   1185 
   1186         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
   1187         ObjDesc->Method.ParamCount = (UINT8) ParamCount;
   1188         (*Node)->Object = ObjDesc;
   1189         break;
   1190 
   1191     case ACPI_TYPE_REGION:
   1192 
   1193         /* Regions require a region sub-object */
   1194 
   1195         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
   1196         ObjDesc->Region.Node = *Node;
   1197         (*Node)->Object = ObjDesc;
   1198         break;
   1199 
   1200     default:
   1201 
   1202         break;
   1203     }
   1204 }
   1205 
   1206 
   1207 /*******************************************************************************
   1208  *
   1209  * FUNCTION:    AcpiDmAddOneExternalToNamespace
   1210  *
   1211  * PARAMETERS:  Path                   - External parse object
   1212  *              Type                   - Type of parse object
   1213  *              ParamCount             - External method parameter count
   1214  *
   1215  * RETURN:      None
   1216  *
   1217  * DESCRIPTION: Add one external to the namespace by resolvign the external
   1218  *              (by performing a namespace lookup) and annotating the resulting
   1219  *              namespace node with the appropriate information if the type
   1220  *              is ACPI_TYPE_REGION or ACPI_TYPE_METHOD.
   1221  *
   1222  ******************************************************************************/
   1223 
   1224 void
   1225 AcpiDmAddOneExternalToNamespace (
   1226     char                    *Path,
   1227     UINT8                   Type,
   1228     UINT32                  ParamCount)
   1229 {
   1230     ACPI_STATUS             Status;
   1231     ACPI_NAMESPACE_NODE     *Node;
   1232 
   1233 
   1234     Status = AcpiDmResolveExternal (Path, Type, &Node);
   1235 
   1236     if (ACPI_FAILURE (Status))
   1237     {
   1238         return;
   1239     }
   1240 
   1241     AcpiDmCreateSubobjectForExternal (Type, &Node, ParamCount);
   1242 
   1243 }
   1244 
   1245 
   1246 /*******************************************************************************
   1247  *
   1248  * FUNCTION:    AcpiDmAddExternalListToNamespace
   1249  *
   1250  * PARAMETERS:  None
   1251  *
   1252  * RETURN:      None
   1253  *
   1254  * DESCRIPTION: Add all externals within AcpiGbl_ExternalList to the namespace.
   1255  *              Allows externals to be "resolved".
   1256  *
   1257  ******************************************************************************/
   1258 
   1259 void
   1260 AcpiDmAddExternalListToNamespace (
   1261     void)
   1262 {
   1263     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
   1264 
   1265 
   1266     while (External)
   1267     {
   1268         AcpiDmAddOneExternalToNamespace (External->InternalPath,
   1269             External->Type, External->Value);
   1270         External = External->Next;
   1271     }
   1272 }
   1273 
   1274 
   1275 /*******************************************************************************
   1276  *
   1277  * FUNCTION:    AcpiDmGetUnresolvedExternalMethodCount
   1278  *
   1279  * PARAMETERS:  None
   1280  *
   1281  * RETURN:      The number of unresolved control method externals in the
   1282  *              external list
   1283  *
   1284  * DESCRIPTION: Return the number of unresolved external methods that have been
   1285  *              generated. If any unresolved control method externals have been
   1286  *              found, we must re-parse the entire definition block with the new
   1287  *              information (number of arguments for the methods.)
   1288  *              This is limitation of AML, we don't know the number of arguments
   1289  *              from the control method invocation itself.
   1290  *
   1291  *              Note: resolved external control methods are external control
   1292  *              methods encoded with the AML_EXTERNAL_OP bytecode within the
   1293  *              AML being disassembled.
   1294  *
   1295  ******************************************************************************/
   1296 
   1297 UINT32
   1298 AcpiDmGetUnresolvedExternalMethodCount (
   1299     void)
   1300 {
   1301     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
   1302     UINT32                  Count = 0;
   1303 
   1304 
   1305     while (External)
   1306     {
   1307         if (External->Type == ACPI_TYPE_METHOD &&
   1308             !(External->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE))
   1309         {
   1310             Count++;
   1311         }
   1312 
   1313         External = External->Next;
   1314     }
   1315 
   1316     return (Count);
   1317 }
   1318 
   1319 
   1320 /*******************************************************************************
   1321  *
   1322  * FUNCTION:    AcpiDmClearExternalList
   1323  *
   1324  * PARAMETERS:  None
   1325  *
   1326  * RETURN:      None
   1327  *
   1328  * DESCRIPTION: Free the entire External info list
   1329  *
   1330  ******************************************************************************/
   1331 
   1332 void
   1333 AcpiDmClearExternalList (
   1334     void)
   1335 {
   1336     ACPI_EXTERNAL_LIST      *NextExternal;
   1337 
   1338 
   1339     while (AcpiGbl_ExternalList)
   1340     {
   1341         NextExternal = AcpiGbl_ExternalList->Next;
   1342         ACPI_FREE (AcpiGbl_ExternalList->Path);
   1343         ACPI_FREE (AcpiGbl_ExternalList);
   1344         AcpiGbl_ExternalList = NextExternal;
   1345     }
   1346 }
   1347 
   1348 
   1349 /*******************************************************************************
   1350  *
   1351  * FUNCTION:    AcpiDmEmitExternals
   1352  *
   1353  * PARAMETERS:  None
   1354  *
   1355  * RETURN:      None
   1356  *
   1357  * DESCRIPTION: Emit an External() ASL statement for each of the externals in
   1358  *              the global external info list.
   1359  *
   1360  ******************************************************************************/
   1361 
   1362 void
   1363 AcpiDmEmitExternals (
   1364     void)
   1365 {
   1366     ACPI_EXTERNAL_LIST      *NextExternal;
   1367 
   1368 
   1369     if (!AcpiGbl_ExternalList)
   1370     {
   1371         return;
   1372     }
   1373 
   1374     /*
   1375      * Determine the number of control methods in the external list, and
   1376      * also how many of those externals were resolved via the namespace.
   1377      */
   1378     NextExternal = AcpiGbl_ExternalList;
   1379     while (NextExternal)
   1380     {
   1381         if (NextExternal->Type == ACPI_TYPE_METHOD)
   1382         {
   1383             AcpiGbl_NumExternalMethods++;
   1384             if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
   1385             {
   1386                 AcpiGbl_ResolvedExternalMethods++;
   1387             }
   1388         }
   1389 
   1390         NextExternal = NextExternal->Next;
   1391     }
   1392 
   1393     /* Check if any control methods were unresolved */
   1394 
   1395     AcpiDmUnresolvedWarning (1);
   1396 
   1397     if (AslGbl_ExternalRefFilename)
   1398     {
   1399         AcpiOsPrintf (
   1400             "    /*\n     * External declarations were imported from\n"
   1401             "     * a reference file -- %s\n     */\n\n",
   1402             AslGbl_ExternalRefFilename);
   1403     }
   1404 
   1405     /*
   1406      * Walk and emit the list of externals found during the AML parsing
   1407      */
   1408     while (AcpiGbl_ExternalList)
   1409     {
   1410         if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
   1411         {
   1412             AcpiOsPrintf ("    External (%s%s)",
   1413                 AcpiGbl_ExternalList->Path,
   1414                 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
   1415 
   1416             /* Check for "unresolved" method reference */
   1417 
   1418             if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) &&
   1419                 (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
   1420             {
   1421                 AcpiOsPrintf ("    // Warning: Unknown method, "
   1422                     "guessing %u arguments",
   1423                     AcpiGbl_ExternalList->Value);
   1424             }
   1425 
   1426             /* Check for external from a external references file */
   1427 
   1428             else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE)
   1429             {
   1430                 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
   1431                 {
   1432                     AcpiOsPrintf ("    // %u Arguments",
   1433                         AcpiGbl_ExternalList->Value);
   1434                 }
   1435 
   1436                 AcpiOsPrintf ("    // From external reference file");
   1437             }
   1438 
   1439             /* This is the normal external case */
   1440 
   1441             else
   1442             {
   1443                 /* For methods, add a comment with the number of arguments */
   1444 
   1445                 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
   1446                 {
   1447                     AcpiOsPrintf ("    // %u Arguments",
   1448                         AcpiGbl_ExternalList->Value);
   1449                 }
   1450             }
   1451 
   1452             if (AcpiGbl_ExternalList->Flags &= ACPI_EXT_CONFLICTING_DECLARATION)
   1453             {
   1454                 AcpiOsPrintf ("%s", ExternalConflictMessage);
   1455                 AcpiDmConflictingDeclaration (AcpiGbl_ExternalList->Path);
   1456             }
   1457             AcpiOsPrintf ("\n");
   1458         }
   1459 
   1460         /* Free this external info block and move on to next external */
   1461 
   1462         NextExternal = AcpiGbl_ExternalList->Next;
   1463         if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
   1464         {
   1465             ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
   1466         }
   1467 
   1468         ACPI_FREE (AcpiGbl_ExternalList->Path);
   1469         ACPI_FREE (AcpiGbl_ExternalList);
   1470         AcpiGbl_ExternalList = NextExternal;
   1471     }
   1472 
   1473     AcpiOsPrintf ("\n");
   1474 }
   1475 
   1476 
   1477 /*******************************************************************************
   1478  *
   1479  * FUNCTION:    AcpiDmMarkExternalConflict
   1480  *
   1481  * PARAMETERS:  Path          - Namepath to search
   1482  *
   1483  * RETURN:      ExternalList
   1484  *
   1485  * DESCRIPTION: Search the AcpiGbl_ExternalList for a matching path
   1486  *
   1487  ******************************************************************************/
   1488 
   1489 void
   1490 AcpiDmMarkExternalConflict (
   1491     ACPI_NAMESPACE_NODE     *Node)
   1492 {
   1493     ACPI_EXTERNAL_LIST      *ExternalList = AcpiGbl_ExternalList;
   1494     char                    *ExternalPath;
   1495     char                    *InternalPath;
   1496     ACPI_STATUS             Status;
   1497 
   1498 
   1499     ACPI_FUNCTION_TRACE (DmMarkExternalConflict);
   1500 
   1501 
   1502     if (Node->Flags & ANOBJ_IS_EXTERNAL)
   1503     {
   1504         return_VOID;
   1505     }
   1506 
   1507     /* Get the full external and internal pathnames to the node */
   1508 
   1509     Status = AcpiDmGetExternalAndInternalPath (Node,
   1510         &ExternalPath, &InternalPath);
   1511     if (ACPI_FAILURE (Status))
   1512     {
   1513         return_VOID;
   1514     }
   1515 
   1516     /* Remove the root backslash */
   1517 
   1518     Status = AcpiDmRemoveRootPrefix (&InternalPath);
   1519     if (ACPI_FAILURE (Status))
   1520     {
   1521         ACPI_FREE (InternalPath);
   1522         ACPI_FREE (ExternalPath);
   1523         return_VOID;
   1524     }
   1525 
   1526     while (ExternalList)
   1527     {
   1528         if (!strcmp (ExternalList->InternalPath, InternalPath))
   1529         {
   1530             ExternalList->Flags |= ACPI_EXT_CONFLICTING_DECLARATION;
   1531         }
   1532         ExternalList = ExternalList->Next;
   1533     }
   1534 
   1535     ACPI_FREE (InternalPath);
   1536     ACPI_FREE (ExternalPath);
   1537 
   1538     return_VOID;
   1539 }
   1540 
   1541 
   1542 /*******************************************************************************
   1543  *
   1544  * FUNCTION:    AcpiDmConflictingDeclaration
   1545  *
   1546  * PARAMETERS:  Path                - Path with conflicting declaration
   1547  *
   1548  * RETURN:      None
   1549  *
   1550  * DESCRIPTION: Emit a warning when printing conflicting ASL external
   1551  *              declarations.
   1552  *
   1553  ******************************************************************************/
   1554 
   1555 static void
   1556 AcpiDmConflictingDeclaration (
   1557     char                    *Path)
   1558 {
   1559     fprintf (stderr,
   1560         " Warning - Emitting ASL code \"External (%s)\"\n"
   1561         "           This is a conflicting declaration with some "
   1562         "other declaration within the ASL code.\n"
   1563         "           This external declaration may need to be "
   1564         "deleted in order to recompile the dsl file.\n\n",
   1565         Path);
   1566 }
   1567 
   1568 
   1569 /*******************************************************************************
   1570  *
   1571  * FUNCTION:    AcpiDmEmitExternal
   1572  *
   1573  * PARAMETERS:  Op                  External Parse Object
   1574  *
   1575  * RETURN:      None
   1576  *
   1577  * DESCRIPTION: Emit an External() ASL statement for the current External
   1578  *              parse object. Note: External Ops are named types so the
   1579  *              namepath is contained within NameOp->Name.Path.
   1580  *
   1581  ******************************************************************************/
   1582 
   1583 void
   1584 AcpiDmEmitExternal (
   1585     ACPI_PARSE_OBJECT       *NameOp,
   1586     ACPI_PARSE_OBJECT       *TypeOp)
   1587 {
   1588     AcpiOsPrintf ("External (");
   1589     AcpiDmNamestring (NameOp->Named.Path);
   1590     AcpiOsPrintf ("%s)",
   1591         AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer));
   1592     AcpiDmCheckForExternalConflict (NameOp->Named.Path);
   1593     AcpiOsPrintf ("\n");
   1594 }
   1595 
   1596 
   1597 /*******************************************************************************
   1598  *
   1599  * FUNCTION:    AcpiDmCheckForExternalConflict
   1600  *
   1601  * PARAMETERS:  Path                - Path to check
   1602  *
   1603  * RETURN:      None
   1604  *
   1605  * DESCRIPTION: Search the External List to see if the input Path has a
   1606  *              conflicting declaration.
   1607  *
   1608  ******************************************************************************/
   1609 
   1610 static void
   1611 AcpiDmCheckForExternalConflict (
   1612     char                    *Path)
   1613 {
   1614     ACPI_EXTERNAL_LIST      *ExternalList = AcpiGbl_ExternalList;
   1615     char                    *ListItemPath;
   1616     char                    *InputPath;
   1617 
   1618 
   1619     if (!Path)
   1620     {
   1621         return;
   1622     }
   1623 
   1624     /* Move past the root prefix '\' */
   1625 
   1626     InputPath = Path;
   1627     if ((*InputPath == AML_ROOT_PREFIX) && InputPath[1])
   1628     {
   1629         InputPath++;
   1630     }
   1631 
   1632     while (ExternalList)
   1633     {
   1634         ListItemPath = ExternalList->Path;
   1635         if (ListItemPath)
   1636         {
   1637             /* Move past the root prefix '\' */
   1638 
   1639             if ((*ListItemPath == AML_ROOT_PREFIX) &&
   1640                 ListItemPath[1])
   1641             {
   1642                 ListItemPath++;
   1643             }
   1644 
   1645             if (!strcmp (ListItemPath, InputPath) &&
   1646                 (ExternalList->Flags & ACPI_EXT_CONFLICTING_DECLARATION))
   1647             {
   1648                 AcpiOsPrintf ("%s", ExternalConflictMessage);
   1649                 AcpiDmConflictingDeclaration (Path);
   1650 
   1651                 return;
   1652             }
   1653         }
   1654         ExternalList = ExternalList->Next;
   1655     }
   1656 }
   1657 /*******************************************************************************
   1658  *
   1659  * FUNCTION:    AcpiDmUnresolvedWarning
   1660  *
   1661  * PARAMETERS:  Type                - Where to output the warning.
   1662  *                                    0 means write to stderr
   1663  *                                    1 means write to AcpiOsPrintf
   1664  *
   1665  * RETURN:      None
   1666  *
   1667  * DESCRIPTION: Issue warning message if there are unresolved external control
   1668  *              methods within the disassembly.
   1669  *
   1670  ******************************************************************************/
   1671 
   1672 /*
   1673 Summary of the external control method problem:
   1674 
   1675 When the -e option is used with disassembly, the various SSDTs are simply
   1676 loaded into a global namespace for the disassembler to use in order to
   1677 resolve control method references (invocations).
   1678 
   1679 The disassembler tracks any such references, and will emit an External()
   1680 statement for these types of methods, with the proper number of arguments .
   1681 
   1682 Without the SSDTs, the AML does not contain enough information to properly
   1683 disassemble the control method invocation -- because the disassembler does
   1684 not know how many arguments to parse.
   1685 
   1686 An example: Assume we have two control methods. ABCD has one argument, and
   1687 EFGH has zero arguments. Further, we have two additional control methods
   1688 that invoke ABCD and EFGH, named T1 and T2:
   1689 
   1690     Method (ABCD, 1)
   1691     {
   1692     }
   1693     Method (EFGH, 0)
   1694     {
   1695     }
   1696     Method (T1)
   1697     {
   1698         ABCD (Add (2, 7, Local0))
   1699     }
   1700     Method (T2)
   1701     {
   1702         EFGH ()
   1703         Add (2, 7, Local0)
   1704     }
   1705 
   1706 Here is the AML code that is generated for T1 and T2:
   1707 
   1708      185:      Method (T1)
   1709 
   1710 0000034C:  14 10 54 31 5F 5F 00 ...    "..T1__."
   1711 
   1712      186:      {
   1713      187:          ABCD (Add (2, 7, Local0))
   1714 
   1715 00000353:  41 42 43 44 ............    "ABCD"
   1716 00000357:  72 0A 02 0A 07 60 ......    "r....`"
   1717 
   1718      188:      }
   1719 
   1720      190:      Method (T2)
   1721 
   1722 0000035D:  14 10 54 32 5F 5F 00 ...    "..T2__."
   1723 
   1724      191:      {
   1725      192:          EFGH ()
   1726 
   1727 00000364:  45 46 47 48 ............    "EFGH"
   1728 
   1729      193:          Add (2, 7, Local0)
   1730 
   1731 00000368:  72 0A 02 0A 07 60 ......    "r....`"
   1732      194:      }
   1733 
   1734 Note that the AML code for T1 and T2 is essentially identical. When
   1735 disassembling this code, the methods ABCD and EFGH must be known to the
   1736 disassembler, otherwise it does not know how to handle the method invocations.
   1737 
   1738 In other words, if ABCD and EFGH are actually external control methods
   1739 appearing in an SSDT, the disassembler does not know what to do unless
   1740 the owning SSDT has been loaded via the -e option.
   1741 */
   1742 
   1743 static char             ExternalWarningPart1[600];
   1744 static char             ExternalWarningPart2[400];
   1745 static char             ExternalWarningPart3[400];
   1746 static char             ExternalWarningPart4[200];
   1747 
   1748 void
   1749 AcpiDmUnresolvedWarning (
   1750     UINT8                   Type)
   1751 {
   1752     char                    *Format;
   1753     char                    Pad[] = "     *";
   1754     char                    NoPad[] = "";
   1755 
   1756 
   1757     if (!AcpiGbl_NumExternalMethods)
   1758     {
   1759         return;
   1760     }
   1761 
   1762     if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
   1763     {
   1764         return;
   1765     }
   1766 
   1767     Format = Type ? Pad : NoPad;
   1768 
   1769     sprintf (ExternalWarningPart1,
   1770         "%s iASL Warning: There %s %u external control method%s found during\n"
   1771         "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
   1772         "%s ACPI tables may be required to properly disassemble the code. This\n"
   1773         "%s resulting disassembler output file may not compile because the\n"
   1774         "%s disassembler did not know how many arguments to assign to the\n"
   1775         "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
   1776         "%s runtime and may or may not be available via the host OS.\n",
   1777         Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
   1778         AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
   1779         Format, AcpiGbl_ResolvedExternalMethods,
   1780         (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
   1781         (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
   1782         Format, Format, Format, Format, Format);
   1783 
   1784     sprintf (ExternalWarningPart2,
   1785         "%s To specify the tables needed to resolve external control method\n"
   1786         "%s references, the -e option can be used to specify the filenames.\n"
   1787         "%s Example iASL invocations:\n"
   1788         "%s     iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
   1789         "%s     iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
   1790         "%s     iasl -e ssdt*.aml -d dsdt.aml\n",
   1791         Format, Format, Format, Format, Format, Format);
   1792 
   1793     sprintf (ExternalWarningPart3,
   1794         "%s In addition, the -fe option can be used to specify a file containing\n"
   1795         "%s control method external declarations with the associated method\n"
   1796         "%s argument counts. Each line of the file must be of the form:\n"
   1797         "%s     External (<method pathname>, MethodObj, <argument count>)\n"
   1798         "%s Invocation:\n"
   1799         "%s     iasl -fe refs.txt -d dsdt.aml\n",
   1800         Format, Format, Format, Format, Format, Format);
   1801 
   1802     sprintf (ExternalWarningPart4,
   1803         "%s The following methods were unresolved and many not compile properly\n"
   1804         "%s because the disassembler had to guess at the number of arguments\n"
   1805         "%s required for each:\n",
   1806         Format, Format, Format);
   1807 
   1808     if (Type)
   1809     {
   1810         if (!AcpiGbl_ExternalFileList)
   1811         {
   1812             /* The -e option was not specified */
   1813 
   1814            AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     *\n%s     */\n",
   1815                ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
   1816                ExternalWarningPart4);
   1817         }
   1818         else
   1819         {
   1820             /* The -e option was specified, but there are still some unresolved externals */
   1821 
   1822             AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     */\n",
   1823                ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
   1824         }
   1825     }
   1826     else
   1827     {
   1828         if (!AcpiGbl_ExternalFileList)
   1829         {
   1830             /* The -e option was not specified */
   1831 
   1832             fprintf (stderr, "\n%s\n%s\n%s\n",
   1833                ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
   1834         }
   1835         else
   1836         {
   1837             /* The -e option was specified, but there are still some unresolved externals */
   1838 
   1839             fprintf (stderr, "\n%s\n%s\n",
   1840                ExternalWarningPart1, ExternalWarningPart3);
   1841         }
   1842     }
   1843 }
   1844