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