The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/acpica/common/dmextern.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 - 2022, Intel Corp.
   12  * All rights reserved.
   13  *
   14  * 2. License
   15  *
   16  * 2.1. This is your license from Intel Corp. under its intellectual property
   17  * rights. You may have additional license terms from the party that provided
   18  * you this software, covering your right to use that party's intellectual
   19  * property rights.
   20  *
   21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
   22  * copy of the source code appearing in this file ("Covered Code") an
   23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
   24  * base code distributed originally by Intel ("Original Intel Code") to copy,
   25  * make derivatives, distribute, use and display any portion of the Covered
   26  * Code in any form, with the right to sublicense such rights; and
   27  *
   28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
   29  * license (with the right to sublicense), under only those claims of Intel
   30  * patents that are infringed by the Original Intel Code, to make, use, sell,
   31  * offer to sell, and import the Covered Code and derivative works thereof
   32  * solely to the minimum extent necessary to exercise the above copyright
   33  * license, and in no event shall the patent license extend to any additions
   34  * to or modifications of the Original Intel Code. No other license or right
   35  * is granted directly or by implication, estoppel or otherwise;
   36  *
   37  * The above copyright and patent license is granted only if the following
   38  * conditions are met:
   39  *
   40  * 3. Conditions
   41  *
   42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
   43  * Redistribution of source code of any substantial portion of the Covered
   44  * Code or modification with rights to further distribute source must include
   45  * the above Copyright Notice, the above License, this list of Conditions,
   46  * and the following Disclaimer and Export Compliance provision. In addition,
   47  * Licensee must cause all Covered Code to which Licensee contributes to
   48  * contain a file documenting the changes Licensee made to create that Covered
   49  * Code and the date of any change. Licensee must include in that file the
   50  * documentation of any changes made by any predecessor Licensee. Licensee
   51  * must include a prominent statement that the modification is derived,
   52  * directly or indirectly, from Original Intel Code.
   53  *
   54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
   55  * Redistribution of source code of any substantial portion of the Covered
   56  * Code or modification without rights to further distribute source must
   57  * include the following Disclaimer and Export Compliance provision in the
   58  * documentation and/or other materials provided with distribution. In
   59  * addition, Licensee may not authorize further sublicense of source of any
   60  * portion of the Covered Code, and must include terms to the effect that the
   61  * license from Licensee to its licensee is limited to the intellectual
   62  * property embodied in the software Licensee provides to its licensee, and
   63  * not to intellectual property embodied in modifications its licensee may
   64  * make.
   65  *
   66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
   67  * substantial portion of the Covered Code or modification must reproduce the
   68  * above Copyright Notice, and the following Disclaimer and Export Compliance
   69  * provision in the documentation and/or other materials provided with the
   70  * distribution.
   71  *
   72  * 3.4. Intel retains all right, title, and interest in and to the Original
   73  * Intel Code.
   74  *
   75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
   76  * Intel shall be used in advertising or otherwise to promote the sale, use or
   77  * other dealings in products derived from or relating to the Covered Code
   78  * without prior written authorization from Intel.
   79  *
   80  * 4. Disclaimer and Export Compliance
   81  *
   82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
   83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
   84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
   85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
   86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
   87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
   88  * PARTICULAR PURPOSE.
   89  *
   90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
   91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
   92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
   93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
   94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
   95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
   96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
   97  * LIMITED REMEDY.
   98  *
   99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
  100  * software or system incorporating such software without first obtaining any
  101  * required license or other approval from the U. S. Department of Commerce or
  102  * any other agency or department of the United States Government. In the
  103  * event Licensee exports any such software from the United States or
  104  * re-exports any such software from a foreign destination, Licensee shall
  105  * ensure that the distribution and export/re-export of the software is in
  106  * compliance with all laws, regulations, orders, or other restrictions of the
  107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
  108  * any of its subsidiaries will export/re-export any technical data, process,
  109  * software, or service, directly or indirectly, to any country for which the
  110  * United States government or any agency thereof requires an export license,
  111  * other governmental approval, or letter of assurance, without first obtaining
  112  * such license, approval or letter.
  113  *
  114  *****************************************************************************
  115  *
  116  * Alternatively, you may choose to be licensed under the terms of the
  117  * following license:
  118  *
  119  * Redistribution and use in source and binary forms, with or without
  120  * modification, are permitted provided that the following conditions
  121  * are met:
  122  * 1. Redistributions of source code must retain the above copyright
  123  *    notice, this list of conditions, and the following disclaimer,
  124  *    without modification.
  125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  126  *    substantially similar to the "NO WARRANTY" disclaimer below
  127  *    ("Disclaimer") and any redistribution must be conditioned upon
  128  *    including a substantially similar Disclaimer requirement for further
  129  *    binary redistribution.
  130  * 3. Neither the names of the above-listed copyright holders nor the names
  131  *    of any contributors may be used to endorse or promote products derived
  132  *    from this software without specific prior written permission.
  133  *
  134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  145  *
  146  * Alternatively, you may choose to be licensed under the terms of the
  147  * GNU General Public License ("GPL") version 2 as published by the Free
  148  * Software Foundation.
  149  *
  150  *****************************************************************************/
  151 
  152 #include <contrib/dev/acpica/include/acpi.h>
  153 #include <contrib/dev/acpica/include/accommon.h>
  154 #include <contrib/dev/acpica/include/amlcode.h>
  155 #include <contrib/dev/acpica/include/acnamesp.h>
  156 #include <contrib/dev/acpica/include/acdisasm.h>
  157 #include <contrib/dev/acpica/compiler/aslcompiler.h>
  158 #include <stdio.h>
  159 #include <errno.h>
  160 
  161 
  162 /*
  163  * This module is used for application-level code (iASL disassembler) only.
  164  *
  165  * It contains the code to create and emit any necessary External() ASL
  166  * statements for the module being disassembled.
  167  */
  168 #define _COMPONENT          ACPI_CA_DISASSEMBLER
  169         ACPI_MODULE_NAME    ("dmextern")
  170 
  171 
  172 /*
  173  * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
  174  * ObjectTypeKeyword. Used to generate typed external declarations
  175  */
  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     char                    *Temp;
 1497     ACPI_STATUS             Status;
 1498 
 1499 
 1500     ACPI_FUNCTION_TRACE (DmMarkExternalConflict);
 1501 
 1502 
 1503     if (Node->Flags & ANOBJ_IS_EXTERNAL)
 1504     {
 1505         return_VOID;
 1506     }
 1507 
 1508     /* Get the full external and internal pathnames to the node */
 1509 
 1510     Status = AcpiDmGetExternalAndInternalPath (Node,
 1511         &ExternalPath, &InternalPath);
 1512     if (ACPI_FAILURE (Status))
 1513     {
 1514         return_VOID;
 1515     }
 1516 
 1517     /* Remove the root backslash */
 1518 
 1519     Status = AcpiDmRemoveRootPrefix (&InternalPath);
 1520     if (ACPI_FAILURE (Status))
 1521     {
 1522         ACPI_FREE (InternalPath);
 1523         ACPI_FREE (ExternalPath);
 1524         return_VOID;
 1525     }
 1526 
 1527     while (ExternalList)
 1528     {
 1529         Temp = ExternalList->InternalPath;
 1530         if ((*ExternalList->InternalPath == AML_ROOT_PREFIX) &&
 1531             (ExternalList->InternalPath[1]))
 1532         {
 1533             Temp++;
 1534         }
 1535 
 1536         if (!strcmp (ExternalList->InternalPath, InternalPath))
 1537         {
 1538             ExternalList->Flags |= ACPI_EXT_CONFLICTING_DECLARATION;
 1539         }
 1540         ExternalList = ExternalList->Next;
 1541     }
 1542 
 1543     ACPI_FREE (InternalPath);
 1544     ACPI_FREE (ExternalPath);
 1545 
 1546     return_VOID;
 1547 }
 1548 
 1549 
 1550 /*******************************************************************************
 1551  *
 1552  * FUNCTION:    AcpiDmConflictingDeclaration
 1553  *
 1554  * PARAMETERS:  Path                - Path with conflicting declaration
 1555  *
 1556  * RETURN:      None
 1557  *
 1558  * DESCRIPTION: Emit a warning when printing conflicting ASL external
 1559  *              declarations.
 1560  *
 1561  ******************************************************************************/
 1562 
 1563 static void
 1564 AcpiDmConflictingDeclaration (
 1565     char                    *Path)
 1566 {
 1567     fprintf (stderr,
 1568         " Warning - Emitting ASL code \"External (%s)\"\n"
 1569         "           This is a conflicting declaration with some "
 1570         "other declaration within the ASL code.\n"
 1571         "           This external declaration may need to be "
 1572         "deleted in order to recompile the dsl file.\n\n",
 1573         Path);
 1574 }
 1575 
 1576 
 1577 /*******************************************************************************
 1578  *
 1579  * FUNCTION:    AcpiDmEmitExternal
 1580  *
 1581  * PARAMETERS:  Op                  External Parse Object
 1582  *
 1583  * RETURN:      None
 1584  *
 1585  * DESCRIPTION: Emit an External() ASL statement for the current External
 1586  *              parse object. Note: External Ops are named types so the
 1587  *              namepath is contained within NameOp->Name.Path.
 1588  *
 1589  ******************************************************************************/
 1590 
 1591 void
 1592 AcpiDmEmitExternal (
 1593     ACPI_PARSE_OBJECT       *NameOp,
 1594     ACPI_PARSE_OBJECT       *TypeOp)
 1595 {
 1596     AcpiOsPrintf ("External (");
 1597     AcpiDmNamestring (NameOp->Named.Path);
 1598     AcpiOsPrintf ("%s)",
 1599         AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer));
 1600     AcpiDmCheckForExternalConflict (NameOp->Named.Path);
 1601     AcpiOsPrintf ("\n");
 1602 }
 1603 
 1604 
 1605 /*******************************************************************************
 1606  *
 1607  * FUNCTION:    AcpiDmCheckForExternalConflict
 1608  *
 1609  * PARAMETERS:  Path                - Path to check
 1610  *
 1611  * RETURN:      None
 1612  *
 1613  * DESCRIPTION: Search the External List to see if the input Path has a
 1614  *              conflicting declaration.
 1615  *
 1616  ******************************************************************************/
 1617 
 1618 static void
 1619 AcpiDmCheckForExternalConflict (
 1620     char                    *Path)
 1621 {
 1622     ACPI_EXTERNAL_LIST      *ExternalList = AcpiGbl_ExternalList;
 1623     char                    *ListItemPath;
 1624     char                    *InputPath;
 1625 
 1626 
 1627     if (!Path)
 1628     {
 1629         return;
 1630     }
 1631 
 1632     /* Move past the root prefix '\' */
 1633 
 1634     InputPath = Path;
 1635     if ((*InputPath == AML_ROOT_PREFIX) && InputPath[1])
 1636     {
 1637         InputPath++;
 1638     }
 1639 
 1640     while (ExternalList)
 1641     {
 1642         ListItemPath = ExternalList->Path;
 1643         if (ListItemPath)
 1644         {
 1645             /* Move past the root prefix '\' */
 1646 
 1647             if ((*ListItemPath == AML_ROOT_PREFIX) &&
 1648                 ListItemPath[1])
 1649             {
 1650                 ListItemPath++;
 1651             }
 1652 
 1653             if (!strcmp (ListItemPath, InputPath) &&
 1654                 (ExternalList->Flags & ACPI_EXT_CONFLICTING_DECLARATION))
 1655             {
 1656                 AcpiOsPrintf ("%s", ExternalConflictMessage);
 1657                 AcpiDmConflictingDeclaration (Path);
 1658 
 1659                 return;
 1660             }
 1661         }
 1662         ExternalList = ExternalList->Next;
 1663     }
 1664 }
 1665 /*******************************************************************************
 1666  *
 1667  * FUNCTION:    AcpiDmUnresolvedWarning
 1668  *
 1669  * PARAMETERS:  Type                - Where to output the warning.
 1670  *                                    0 means write to stderr
 1671  *                                    1 means write to AcpiOsPrintf
 1672  *
 1673  * RETURN:      None
 1674  *
 1675  * DESCRIPTION: Issue warning message if there are unresolved external control
 1676  *              methods within the disassembly.
 1677  *
 1678  ******************************************************************************/
 1679 
 1680 /*
 1681 Summary of the external control method problem:
 1682 
 1683 When the -e option is used with disassembly, the various SSDTs are simply
 1684 loaded into a global namespace for the disassembler to use in order to
 1685 resolve control method references (invocations).
 1686 
 1687 The disassembler tracks any such references, and will emit an External()
 1688 statement for these types of methods, with the proper number of arguments .
 1689 
 1690 Without the SSDTs, the AML does not contain enough information to properly
 1691 disassemble the control method invocation -- because the disassembler does
 1692 not know how many arguments to parse.
 1693 
 1694 An example: Assume we have two control methods. ABCD has one argument, and
 1695 EFGH has zero arguments. Further, we have two additional control methods
 1696 that invoke ABCD and EFGH, named T1 and T2:
 1697 
 1698     Method (ABCD, 1)
 1699     {
 1700     }
 1701     Method (EFGH, 0)
 1702     {
 1703     }
 1704     Method (T1)
 1705     {
 1706         ABCD (Add (2, 7, Local0))
 1707     }
 1708     Method (T2)
 1709     {
 1710         EFGH ()
 1711         Add (2, 7, Local0)
 1712     }
 1713 
 1714 Here is the AML code that is generated for T1 and T2:
 1715 
 1716      185:      Method (T1)
 1717 
 1718 0000034C:  14 10 54 31 5F 5F 00 ...    "..T1__."
 1719 
 1720      186:      {
 1721      187:          ABCD (Add (2, 7, Local0))
 1722 
 1723 00000353:  41 42 43 44 ............    "ABCD"
 1724 00000357:  72 0A 02 0A 07 60 ......    "r....`"
 1725 
 1726      188:      }
 1727 
 1728      190:      Method (T2)
 1729 
 1730 0000035D:  14 10 54 32 5F 5F 00 ...    "..T2__."
 1731 
 1732      191:      {
 1733      192:          EFGH ()
 1734 
 1735 00000364:  45 46 47 48 ............    "EFGH"
 1736 
 1737      193:          Add (2, 7, Local0)
 1738 
 1739 00000368:  72 0A 02 0A 07 60 ......    "r....`"
 1740      194:      }
 1741 
 1742 Note that the AML code for T1 and T2 is essentially identical. When
 1743 disassembling this code, the methods ABCD and EFGH must be known to the
 1744 disassembler, otherwise it does not know how to handle the method invocations.
 1745 
 1746 In other words, if ABCD and EFGH are actually external control methods
 1747 appearing in an SSDT, the disassembler does not know what to do unless
 1748 the owning SSDT has been loaded via the -e option.
 1749 */
 1750 
 1751 static char             ExternalWarningPart1[600];
 1752 static char             ExternalWarningPart2[400];
 1753 static char             ExternalWarningPart3[400];
 1754 static char             ExternalWarningPart4[200];
 1755 
 1756 void
 1757 AcpiDmUnresolvedWarning (
 1758     UINT8                   Type)
 1759 {
 1760     char                    *Format;
 1761     char                    Pad[] = "     *";
 1762     char                    NoPad[] = "";
 1763 
 1764 
 1765     if (!AcpiGbl_NumExternalMethods)
 1766     {
 1767         return;
 1768     }
 1769 
 1770     if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
 1771     {
 1772         return;
 1773     }
 1774 
 1775     Format = Type ? Pad : NoPad;
 1776 
 1777     sprintf (ExternalWarningPart1,
 1778         "%s iASL Warning: There %s %u external control method%s found during\n"
 1779         "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
 1780         "%s ACPI tables may be required to properly disassemble the code. This\n"
 1781         "%s resulting disassembler output file may not compile because the\n"
 1782         "%s disassembler did not know how many arguments to assign to the\n"
 1783         "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
 1784         "%s runtime and may or may not be available via the host OS.\n",
 1785         Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
 1786         AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
 1787         Format, AcpiGbl_ResolvedExternalMethods,
 1788         (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
 1789         (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
 1790         Format, Format, Format, Format, Format);
 1791 
 1792     sprintf (ExternalWarningPart2,
 1793         "%s To specify the tables needed to resolve external control method\n"
 1794         "%s references, the -e option can be used to specify the filenames.\n"
 1795         "%s Example iASL invocations:\n"
 1796         "%s     iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
 1797         "%s     iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
 1798         "%s     iasl -e ssdt*.aml -d dsdt.aml\n",
 1799         Format, Format, Format, Format, Format, Format);
 1800 
 1801     sprintf (ExternalWarningPart3,
 1802         "%s In addition, the -fe option can be used to specify a file containing\n"
 1803         "%s control method external declarations with the associated method\n"
 1804         "%s argument counts. Each line of the file must be of the form:\n"
 1805         "%s     External (<method pathname>, MethodObj, <argument count>)\n"
 1806         "%s Invocation:\n"
 1807         "%s     iasl -fe refs.txt -d dsdt.aml\n",
 1808         Format, Format, Format, Format, Format, Format);
 1809 
 1810     sprintf (ExternalWarningPart4,
 1811         "%s The following methods were unresolved and many not compile properly\n"
 1812         "%s because the disassembler had to guess at the number of arguments\n"
 1813         "%s required for each:\n",
 1814         Format, Format, Format);
 1815 
 1816     if (Type)
 1817     {
 1818         if (!AcpiGbl_ExternalFileList)
 1819         {
 1820             /* The -e option was not specified */
 1821 
 1822            AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     *\n%s     */\n",
 1823                ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
 1824                ExternalWarningPart4);
 1825         }
 1826         else
 1827         {
 1828             /* The -e option was specified, but there are still some unresolved externals */
 1829 
 1830             AcpiOsPrintf ("    /*\n%s     *\n%s     *\n%s     */\n",
 1831                ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
 1832         }
 1833     }
 1834     else
 1835     {
 1836         if (!AcpiGbl_ExternalFileList)
 1837         {
 1838             /* The -e option was not specified */
 1839 
 1840             fprintf (stderr, "\n%s\n%s\n%s\n",
 1841                ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
 1842         }
 1843         else
 1844         {
 1845             /* The -e option was specified, but there are still some unresolved externals */
 1846 
 1847             fprintf (stderr, "\n%s\n%s\n",
 1848                ExternalWarningPart1, ExternalWarningPart3);
 1849         }
 1850     }
 1851 }

Cache object: 518f83d05e15e262e920b471093beddf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.