Home | History | Annotate | Line # | Download | only in common
adisasm.c revision 1.1.1.4.2.4
      1 /******************************************************************************
      2  *
      3  * Module Name: adisasm - Application-level disassembler routines
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, 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 "aslcompiler.h"
     45 #include "amlcode.h"
     46 #include "acdisasm.h"
     47 #include "acdispat.h"
     48 #include "acnamesp.h"
     49 #include "acparser.h"
     50 #include "acapps.h"
     51 
     52 
     53 #define _COMPONENT          ACPI_TOOLS
     54         ACPI_MODULE_NAME    ("adisasm")
     55 
     56 /* Local prototypes */
     57 
     58 static ACPI_STATUS
     59 AdDoExternalFileList (
     60     char                    *Filename);
     61 
     62 static ACPI_STATUS
     63 AdDisassembleOneTable (
     64     ACPI_TABLE_HEADER       *Table,
     65     FILE                    *File,
     66     char                    *Filename,
     67     char                    *DisasmFilename);
     68 
     69 static ACPI_STATUS
     70 AdReparseOneTable (
     71     ACPI_TABLE_HEADER       *Table,
     72     FILE                    *File,
     73     ACPI_OWNER_ID           OwnerId);
     74 
     75 
     76 ACPI_TABLE_DESC             LocalTables[1];
     77 ACPI_PARSE_OBJECT           *AcpiGbl_ParseOpRoot;
     78 
     79 
     80 /* Stubs for everything except ASL compiler */
     81 
     82 #ifndef ACPI_ASL_COMPILER
     83 BOOLEAN
     84 AcpiDsIsResultUsed (
     85     ACPI_PARSE_OBJECT       *Op,
     86     ACPI_WALK_STATE         *WalkState)
     87 {
     88     return (TRUE);
     89 }
     90 
     91 ACPI_STATUS
     92 AcpiDsMethodError (
     93     ACPI_STATUS             Status,
     94     ACPI_WALK_STATE         *WalkState)
     95 {
     96     return (Status);
     97 }
     98 #endif
     99 
    100 
    101 /*******************************************************************************
    102  *
    103  * FUNCTION:    AdInitialize
    104  *
    105  * PARAMETERS:  None
    106  *
    107  * RETURN:      Status
    108  *
    109  * DESCRIPTION: ACPICA and local initialization
    110  *
    111  ******************************************************************************/
    112 
    113 ACPI_STATUS
    114 AdInitialize (
    115     void)
    116 {
    117     ACPI_STATUS             Status;
    118 
    119 
    120     /* ACPICA subsystem initialization */
    121 
    122     Status = AcpiOsInitialize ();
    123     if (ACPI_FAILURE (Status))
    124     {
    125         return (Status);
    126     }
    127 
    128     Status = AcpiUtInitGlobals ();
    129     if (ACPI_FAILURE (Status))
    130     {
    131         return (Status);
    132     }
    133 
    134     Status = AcpiUtMutexInitialize ();
    135     if (ACPI_FAILURE (Status))
    136     {
    137         return (Status);
    138     }
    139 
    140     Status = AcpiNsRootInitialize ();
    141     if (ACPI_FAILURE (Status))
    142     {
    143         return (Status);
    144     }
    145 
    146     /* Setup the Table Manager (cheat - there is no RSDT) */
    147 
    148     AcpiGbl_RootTableList.MaxTableCount = 1;
    149     AcpiGbl_RootTableList.CurrentTableCount = 0;
    150     AcpiGbl_RootTableList.Tables = LocalTables;
    151 
    152     return (Status);
    153 }
    154 
    155 
    156 /******************************************************************************
    157  *
    158  * FUNCTION:    AdAmlDisassemble
    159  *
    160  * PARAMETERS:  Filename            - AML input filename
    161  *              OutToFile           - TRUE if output should go to a file
    162  *              Prefix              - Path prefix for output
    163  *              OutFilename         - where the filename is returned
    164  *
    165  * RETURN:      Status
    166  *
    167  * DESCRIPTION: Disassembler entry point. Disassemble an entire ACPI table.
    168  *
    169  *****************************************************************************/
    170 
    171 ACPI_STATUS
    172 AdAmlDisassemble (
    173     BOOLEAN                 OutToFile,
    174     char                    *Filename,
    175     char                    *Prefix,
    176     char                    **OutFilename)
    177 {
    178     ACPI_STATUS             Status;
    179     char                    *DisasmFilename = NULL;
    180     FILE                    *File = NULL;
    181     ACPI_TABLE_HEADER       *Table = NULL;
    182     ACPI_NEW_TABLE_DESC     *ListHead = NULL;
    183 
    184 
    185     /*
    186      * Input: AML code from either a file or via GetTables (memory or
    187      * registry)
    188      */
    189     if (Filename)
    190     {
    191         /* Get the list of all AML tables in the file */
    192 
    193         Status = AcGetAllTablesFromFile (Filename,
    194             ACPI_GET_ALL_TABLES, &ListHead);
    195         if (ACPI_FAILURE (Status))
    196         {
    197             AcpiOsPrintf ("Could not get ACPI tables from %s, %s\n",
    198                 Filename, AcpiFormatException (Status));
    199             return (Status);
    200         }
    201 
    202         /* Process any user-specified files for external objects */
    203 
    204         Status = AdDoExternalFileList (Filename);
    205         if (ACPI_FAILURE (Status))
    206         {
    207             return (Status);
    208         }
    209     }
    210     else
    211     {
    212         Status = AdGetLocalTables ();
    213         if (ACPI_FAILURE (Status))
    214         {
    215             AcpiOsPrintf ("Could not get ACPI tables, %s\n",
    216                 AcpiFormatException (Status));
    217             return (Status);
    218         }
    219 
    220         if (!AcpiGbl_DmOpt_Disasm)
    221         {
    222             return (AE_OK);
    223         }
    224 
    225         /* Obtained the local tables, just disassemble the DSDT */
    226 
    227         Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
    228         if (ACPI_FAILURE (Status))
    229         {
    230             AcpiOsPrintf ("Could not get DSDT, %s\n",
    231                 AcpiFormatException (Status));
    232             return (Status);
    233         }
    234 
    235         AcpiOsPrintf ("\nDisassembly of DSDT\n");
    236         Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
    237     }
    238 
    239     /*
    240      * Output: ASL code. Redirect to a file if requested
    241      */
    242     if (OutToFile)
    243     {
    244         /* Create/Open a disassembly output file */
    245 
    246         DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
    247         if (!DisasmFilename)
    248         {
    249             fprintf (stderr, "Could not generate output filename\n");
    250             Status = AE_ERROR;
    251             goto Cleanup;
    252         }
    253 
    254         File = fopen (DisasmFilename, "w+");
    255         if (!File)
    256         {
    257             fprintf (stderr, "Could not open output file %s\n",
    258                 DisasmFilename);
    259             Status = AE_ERROR;
    260             goto Cleanup;
    261         }
    262 
    263         AcpiOsRedirectOutput (File);
    264     }
    265 
    266     *OutFilename = DisasmFilename;
    267 
    268     /* Disassemble all AML tables within the file */
    269 
    270     while (ListHead)
    271     {
    272         Status = AdDisassembleOneTable (ListHead->Table,
    273             File, Filename, DisasmFilename);
    274         if (ACPI_FAILURE (Status))
    275         {
    276             break;
    277         }
    278 
    279         ListHead = ListHead->Next;
    280     }
    281 
    282 Cleanup:
    283 
    284     if (Table &&
    285         !AcpiGbl_ForceAmlDisassembly &&
    286         !AcpiUtIsAmlTable (Table))
    287     {
    288         ACPI_FREE (Table);
    289     }
    290 
    291     if (File)
    292     {
    293         fclose (File);
    294         AcpiOsRedirectOutput (stdout);
    295     }
    296 
    297     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
    298     AcpiGbl_ParseOpRoot = NULL;
    299     return (Status);
    300 }
    301 
    302 
    303 /******************************************************************************
    304  *
    305  * FUNCTION:    AdDisassembleOneTable
    306  *
    307  * PARAMETERS:  Table               - Raw AML table
    308  *              File                - Pointer for the input file
    309  *              Filename            - AML input filename
    310  *              DisasmFilename      - Output filename
    311  *
    312  * RETURN:      Status
    313  *
    314  * DESCRIPTION: Disassemble a single ACPI table. AML or data table.
    315  *
    316  *****************************************************************************/
    317 
    318 static ACPI_STATUS
    319 AdDisassembleOneTable (
    320     ACPI_TABLE_HEADER       *Table,
    321     FILE                    *File,
    322     char                    *Filename,
    323     char                    *DisasmFilename)
    324 {
    325     ACPI_STATUS             Status;
    326     ACPI_OWNER_ID           OwnerId;
    327 
    328 
    329     /* ForceAmlDisassembly means to assume the table contains valid AML */
    330 
    331     if (!AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table))
    332     {
    333         AdDisassemblerHeader (Filename, ACPI_IS_DATA_TABLE);
    334 
    335         /* This is a "Data Table" (non-AML table) */
    336 
    337         AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
    338             Table->Signature);
    339         AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]  "
    340             "FieldName : FieldValue\n */\n\n");
    341 
    342         AcpiDmDumpDataTable (Table);
    343         fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n",
    344             Table->Signature);
    345 
    346         if (File)
    347         {
    348             fprintf (stderr, "Formatted output:  %s - %u bytes\n",
    349                 DisasmFilename, CmGetFileSize (File));
    350         }
    351 
    352         return (AE_OK);
    353     }
    354 
    355     /*
    356      * This is an AML table (DSDT or SSDT).
    357      * Always parse the tables, only option is what to display
    358      */
    359     Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
    360     if (ACPI_FAILURE (Status))
    361     {
    362         AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
    363             AcpiFormatException (Status));
    364         return (Status);
    365     }
    366 
    367     /* Debug output, namespace and parse tree */
    368 
    369     if (AslCompilerdebug && File)
    370     {
    371         AcpiOsPrintf ("/**** Before second load\n");
    372 
    373         NsSetupNamespaceListing (File);
    374         NsDisplayNamespace ();
    375 
    376         AcpiOsPrintf ("*****/\n");
    377     }
    378 
    379     /* Load namespace from names created within control methods */
    380 
    381     AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
    382         AcpiGbl_RootNode, OwnerId);
    383 
    384     /*
    385      * Cross reference the namespace here, in order to
    386      * generate External() statements
    387      */
    388     AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
    389         AcpiGbl_RootNode, OwnerId);
    390 
    391     if (AslCompilerdebug)
    392     {
    393         AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
    394     }
    395 
    396     /* Find possible calls to external control methods */
    397 
    398     AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
    399 
    400     /*
    401      * If we found any external control methods, we must reparse
    402      * the entire tree with the new information (namely, the
    403      * number of arguments per method)
    404      */
    405     if (AcpiDmGetExternalMethodCount ())
    406     {
    407         Status = AdReparseOneTable (Table, File, OwnerId);
    408         if (ACPI_FAILURE (Status))
    409         {
    410             return (Status);
    411         }
    412     }
    413 
    414     /*
    415      * Now that the namespace is finalized, we can perform namespace
    416      * transforms.
    417      *
    418      * 1) Convert fixed-offset references to resource descriptors
    419      *    to symbolic references (Note: modifies namespace)
    420      */
    421     AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
    422 
    423     /* Optional displays */
    424 
    425     if (AcpiGbl_DmOpt_Disasm)
    426     {
    427         /* This is the real disassembly */
    428 
    429         AdDisplayTables (Filename, Table);
    430 
    431         /* Dump hex table if requested (-vt) */
    432 
    433         AcpiDmDumpDataTable (Table);
    434 
    435         fprintf (stderr, "Disassembly completed\n");
    436         if (File)
    437         {
    438             fprintf (stderr, "ASL Output:    %s - %u bytes\n",
    439                 DisasmFilename, CmGetFileSize (File));
    440         }
    441 
    442         if (Gbl_MapfileFlag)
    443         {
    444             fprintf (stderr, "%14s %s - %u bytes\n",
    445                 Gbl_Files[ASL_FILE_MAP_OUTPUT].ShortDescription,
    446                 Gbl_Files[ASL_FILE_MAP_OUTPUT].Filename,
    447                 FlGetFileSize (ASL_FILE_MAP_OUTPUT));
    448         }
    449     }
    450 
    451     return (AE_OK);
    452 }
    453 
    454 
    455 /******************************************************************************
    456  *
    457  * FUNCTION:    AdReparseOneTable
    458  *
    459  * PARAMETERS:  Table               - Raw AML table
    460  *              File                - Pointer for the input file
    461  *              OwnerId             - ID for this table
    462  *
    463  * RETURN:      Status
    464  *
    465  * DESCRIPTION: Reparse a table that has already been loaded. Used to
    466  *              integrate information about external control methods.
    467  *              These methods may have been previously parsed incorrectly.
    468  *
    469  *****************************************************************************/
    470 
    471 static ACPI_STATUS
    472 AdReparseOneTable (
    473     ACPI_TABLE_HEADER       *Table,
    474     FILE                    *File,
    475     ACPI_OWNER_ID           OwnerId)
    476 {
    477     ACPI_STATUS             Status;
    478 
    479 
    480     fprintf (stderr,
    481         "\nFound %u external control methods, "
    482         "reparsing with new information\n",
    483         AcpiDmGetExternalMethodCount ());
    484 
    485     /* Reparse, rebuild namespace */
    486 
    487     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
    488     AcpiGbl_ParseOpRoot = NULL;
    489     AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
    490 
    491     AcpiGbl_RootNode                    = NULL;
    492     AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
    493     AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
    494     AcpiGbl_RootNodeStruct.Type         = ACPI_TYPE_DEVICE;
    495     AcpiGbl_RootNodeStruct.Parent       = NULL;
    496     AcpiGbl_RootNodeStruct.Child        = NULL;
    497     AcpiGbl_RootNodeStruct.Peer         = NULL;
    498     AcpiGbl_RootNodeStruct.Object       = NULL;
    499     AcpiGbl_RootNodeStruct.Flags        = 0;
    500 
    501     Status = AcpiNsRootInitialize ();
    502     if (ACPI_FAILURE (Status))
    503     {
    504         return (Status);
    505     }
    506 
    507     /* New namespace, add the external definitions first */
    508 
    509     AcpiDmAddExternalsToNamespace ();
    510 
    511     /* Parse the table again. No need to reload it, however */
    512 
    513     Status = AdParseTable (Table, NULL, FALSE, FALSE);
    514     if (ACPI_FAILURE (Status))
    515     {
    516         AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
    517             AcpiFormatException (Status));
    518         return (Status);
    519     }
    520 
    521     /* Cross reference the namespace again */
    522 
    523     AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
    524         AcpiGbl_RootNode, OwnerId);
    525 
    526     AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
    527         AcpiGbl_RootNode, OwnerId);
    528 
    529     /* Debug output - namespace and parse tree */
    530 
    531     if (AslCompilerdebug)
    532     {
    533         AcpiOsPrintf ("/**** After second load and resource conversion\n");
    534         if (File)
    535         {
    536             NsSetupNamespaceListing (File);
    537             NsDisplayNamespace ();
    538         }
    539 
    540         AcpiOsPrintf ("*****/\n");
    541         AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
    542     }
    543 
    544     return (AE_OK);
    545 }
    546 
    547 
    548 /******************************************************************************
    549  *
    550  * FUNCTION:    AdDoExternalFileList
    551  *
    552  * PARAMETERS:  Filename            - Input file for the table
    553  *
    554  * RETURN:      Status
    555  *
    556  * DESCRIPTION: Process all tables found in the -e external files list
    557  *
    558  *****************************************************************************/
    559 
    560 static ACPI_STATUS
    561 AdDoExternalFileList (
    562     char                    *Filename)
    563 {
    564     ACPI_EXTERNAL_FILE      *ExternalFileList;
    565     char                    *ExternalFilename;
    566     ACPI_NEW_TABLE_DESC     *ExternalListHead = NULL;
    567     ACPI_STATUS             Status;
    568     ACPI_STATUS             GlobalStatus = AE_OK;
    569     ACPI_OWNER_ID           OwnerId;
    570 
    571 
    572     /*
    573      * External filenames are specified on the command line like this:
    574      * Example: iasl -e file1,file2,file3 -d xxx.aml
    575      */
    576     ExternalFileList = AcpiGbl_ExternalFileList;
    577 
    578     /* Process each external file */
    579 
    580     while (ExternalFileList)
    581     {
    582         ExternalFilename = ExternalFileList->Path;
    583         if (!strcmp (ExternalFilename, Filename))
    584         {
    585             /* Next external file */
    586 
    587             ExternalFileList = ExternalFileList->Next;
    588             continue;
    589         }
    590 
    591         AcpiOsPrintf ("External object resolution file %16s\n",
    592             ExternalFilename);
    593 
    594         Status = AcGetAllTablesFromFile (
    595             ExternalFilename, ACPI_GET_ONLY_AML_TABLES, &ExternalListHead);
    596         if (ACPI_FAILURE (Status))
    597         {
    598             if (Status == AE_TYPE)
    599             {
    600                 ExternalFileList = ExternalFileList->Next;
    601                 GlobalStatus = AE_TYPE;
    602                 Status = AE_OK;
    603                 continue;
    604             }
    605 
    606             return (Status);
    607         }
    608 
    609         /* Load external tables for symbol resolution */
    610 
    611         while (ExternalListHead)
    612         {
    613             Status = AdParseTable (
    614                 ExternalListHead->Table, &OwnerId, TRUE, TRUE);
    615             if (ACPI_FAILURE (Status))
    616             {
    617                 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
    618                     AcpiFormatException (Status));
    619                 return (Status);
    620             }
    621 
    622             /*
    623              * Load namespace from names created within control methods
    624              * Set owner id of nodes in external table
    625              */
    626             AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
    627                 AcpiGbl_RootNode, OwnerId);
    628             AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
    629 
    630             ExternalListHead = ExternalListHead->Next;
    631         }
    632 
    633         /* Next external file */
    634 
    635         ExternalFileList = ExternalFileList->Next;
    636     }
    637 
    638     if (ACPI_FAILURE (GlobalStatus))
    639     {
    640         return (GlobalStatus);
    641     }
    642 
    643     /* Clear external list generated by Scope in external tables */
    644 
    645     if (AcpiGbl_ExternalFileList)
    646     {
    647         AcpiDmClearExternalList ();
    648     }
    649 
    650     /* Load any externals defined in the optional external ref file */
    651 
    652     AcpiDmGetExternalsFromFile ();
    653     return (AE_OK);
    654 }
    655