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