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