Home | History | Annotate | Line # | Download | only in common
adisasm.c revision 1.1.1.10
      1 /******************************************************************************
      2  *
      3  * Module Name: adisasm - Application-level disassembler routines
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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     if (File)
    304     {
    305         fclose (File);
    306         AcpiOsRedirectOutput (stdout);
    307     }
    308 
    309     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
    310     AcpiGbl_ParseOpRoot = NULL;
    311     return (Status);
    312 }
    313 
    314 
    315 /******************************************************************************
    316  *
    317  * FUNCTION:    AdDisassembleOneTable
    318  *
    319  * PARAMETERS:  Table               - Raw AML table
    320  *              File                - Pointer for the input file
    321  *              Filename            - AML input filename
    322  *              DisasmFilename      - Output filename
    323  *
    324  * RETURN:      Status
    325  *
    326  * DESCRIPTION: Disassemble a single ACPI table. AML or data table.
    327  *
    328  *****************************************************************************/
    329 
    330 static ACPI_STATUS
    331 AdDisassembleOneTable (
    332     ACPI_TABLE_HEADER       *Table,
    333     FILE                    *File,
    334     char                    *Filename,
    335     char                    *DisasmFilename)
    336 {
    337     ACPI_STATUS             Status;
    338     ACPI_OWNER_ID           OwnerId;
    339 
    340 
    341 #ifdef ACPI_ASL_COMPILER
    342 
    343     /*
    344      * For ASL-/ASL+ converter: replace the temporary "XXXX"
    345      * table signature with the original. This "XXXX" makes
    346      * it harder for the AML interpreter to run the badaml
    347      * (.xxx) file produced from the converter in case if
    348      * it fails to get deleted.
    349      */
    350     if (Gbl_CaptureComments)
    351     {
    352         strncpy (Table->Signature, AcpiGbl_TableSig, 4);
    353     }
    354 #endif
    355 
    356     /* ForceAmlDisassembly means to assume the table contains valid AML */
    357 
    358     if (!AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table))
    359     {
    360         AdDisassemblerHeader (Filename, ACPI_IS_DATA_TABLE);
    361 
    362         /* This is a "Data Table" (non-AML table) */
    363 
    364         AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
    365             Table->Signature);
    366         AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]  "
    367             "FieldName : FieldValue\n */\n\n");
    368 
    369         AcpiDmDumpDataTable (Table);
    370         fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n",
    371             Table->Signature);
    372 
    373         if (File)
    374         {
    375             fprintf (stderr, "Formatted output:  %s - %u bytes\n",
    376                 DisasmFilename, CmGetFileSize (File));
    377         }
    378 
    379         return (AE_OK);
    380     }
    381 
    382     /*
    383      * This is an AML table (DSDT or SSDT).
    384      * Always parse the tables, only option is what to display
    385      */
    386     Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
    387     if (ACPI_FAILURE (Status))
    388     {
    389         AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
    390             AcpiFormatException (Status));
    391         return (Status);
    392     }
    393 
    394     /* Debug output, namespace and parse tree */
    395 
    396     if (AslCompilerdebug && File)
    397     {
    398         AcpiOsPrintf ("/**** Before second load\n");
    399 
    400         NsSetupNamespaceListing (File);
    401         NsDisplayNamespace ();
    402 
    403         AcpiOsPrintf ("*****/\n");
    404     }
    405 
    406     /* Load namespace from names created within control methods */
    407 
    408     AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
    409         AcpiGbl_RootNode, OwnerId);
    410 
    411     /*
    412      * Cross reference the namespace here, in order to
    413      * generate External() statements
    414      */
    415     AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
    416         AcpiGbl_RootNode, OwnerId);
    417 
    418     if (AslCompilerdebug)
    419     {
    420         AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
    421     }
    422 
    423     /* Find possible calls to external control methods */
    424 
    425     AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
    426 
    427     /*
    428      * If we found any external control methods, we must reparse
    429      * the entire tree with the new information (namely, the
    430      * number of arguments per method)
    431      */
    432     if (AcpiDmGetExternalMethodCount ())
    433     {
    434         Status = AdReparseOneTable (Table, File, OwnerId);
    435         if (ACPI_FAILURE (Status))
    436         {
    437             return (Status);
    438         }
    439     }
    440 
    441     /*
    442      * Now that the namespace is finalized, we can perform namespace
    443      * transforms.
    444      *
    445      * 1) Convert fixed-offset references to resource descriptors
    446      *    to symbolic references (Note: modifies namespace)
    447      */
    448     AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
    449 
    450     /* Optional displays */
    451 
    452     if (AcpiGbl_DmOpt_Disasm)
    453     {
    454         /* This is the real disassembly */
    455 
    456         AdDisplayTables (Filename, Table);
    457 
    458         /* Dump hex table if requested (-vt) */
    459 
    460         AcpiDmDumpDataTable (Table);
    461 
    462         fprintf (stderr, "Disassembly completed\n");
    463         if (File)
    464         {
    465             fprintf (stderr, "ASL Output:    %s - %u bytes\n",
    466                 DisasmFilename, CmGetFileSize (File));
    467         }
    468 
    469         if (Gbl_MapfileFlag)
    470         {
    471             fprintf (stderr, "%14s %s - %u bytes\n",
    472                 Gbl_Files[ASL_FILE_MAP_OUTPUT].ShortDescription,
    473                 Gbl_Files[ASL_FILE_MAP_OUTPUT].Filename,
    474                 FlGetFileSize (ASL_FILE_MAP_OUTPUT));
    475         }
    476     }
    477 
    478     return (AE_OK);
    479 }
    480 
    481 
    482 /******************************************************************************
    483  *
    484  * FUNCTION:    AdReparseOneTable
    485  *
    486  * PARAMETERS:  Table               - Raw AML table
    487  *              File                - Pointer for the input file
    488  *              OwnerId             - ID for this table
    489  *
    490  * RETURN:      Status
    491  *
    492  * DESCRIPTION: Reparse a table that has already been loaded. Used to
    493  *              integrate information about external control methods.
    494  *              These methods may have been previously parsed incorrectly.
    495  *
    496  *****************************************************************************/
    497 
    498 static ACPI_STATUS
    499 AdReparseOneTable (
    500     ACPI_TABLE_HEADER       *Table,
    501     FILE                    *File,
    502     ACPI_OWNER_ID           OwnerId)
    503 {
    504     ACPI_STATUS             Status;
    505     ACPI_COMMENT_ADDR_NODE  *AddrListHead;
    506 
    507 
    508     fprintf (stderr,
    509         "\nFound %u external control methods, "
    510         "reparsing with new information\n",
    511         AcpiDmGetExternalMethodCount ());
    512 
    513     /* Reparse, rebuild namespace */
    514 
    515     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
    516     AcpiGbl_ParseOpRoot = NULL;
    517     AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
    518 
    519     AcpiGbl_RootNode                    = NULL;
    520     AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
    521     AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
    522     AcpiGbl_RootNodeStruct.Type         = ACPI_TYPE_DEVICE;
    523     AcpiGbl_RootNodeStruct.Parent       = NULL;
    524     AcpiGbl_RootNodeStruct.Child        = NULL;
    525     AcpiGbl_RootNodeStruct.Peer         = NULL;
    526     AcpiGbl_RootNodeStruct.Object       = NULL;
    527     AcpiGbl_RootNodeStruct.Flags        = 0;
    528 
    529     Status = AcpiNsRootInitialize ();
    530     if (ACPI_FAILURE (Status))
    531     {
    532         return (Status);
    533     }
    534 
    535     /* New namespace, add the external definitions first */
    536 
    537     AcpiDmAddExternalsToNamespace ();
    538 
    539     /* For -ca option: clear the list of comment addresses. */
    540 
    541     while (AcpiGbl_CommentAddrListHead)
    542     {
    543         AddrListHead= AcpiGbl_CommentAddrListHead;
    544         AcpiGbl_CommentAddrListHead = AcpiGbl_CommentAddrListHead->Next;
    545         AcpiOsFree(AddrListHead);
    546     }
    547 
    548     /* Parse the table again. No need to reload it, however */
    549 
    550     Status = AdParseTable (Table, NULL, FALSE, FALSE);
    551     if (ACPI_FAILURE (Status))
    552     {
    553         AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
    554             AcpiFormatException (Status));
    555         return (Status);
    556     }
    557 
    558     /* Cross reference the namespace again */
    559 
    560     AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
    561         AcpiGbl_RootNode, OwnerId);
    562 
    563     AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
    564         AcpiGbl_RootNode, OwnerId);
    565 
    566     /* Debug output - namespace and parse tree */
    567 
    568     if (AslCompilerdebug)
    569     {
    570         AcpiOsPrintf ("/**** After second load and resource conversion\n");
    571         if (File)
    572         {
    573             NsSetupNamespaceListing (File);
    574             NsDisplayNamespace ();
    575         }
    576 
    577         AcpiOsPrintf ("*****/\n");
    578         AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
    579     }
    580 
    581     return (AE_OK);
    582 }
    583 
    584 
    585 /******************************************************************************
    586  *
    587  * FUNCTION:    AdDoExternalFileList
    588  *
    589  * PARAMETERS:  Filename            - Input file for the table
    590  *
    591  * RETURN:      Status
    592  *
    593  * DESCRIPTION: Process all tables found in the -e external files list
    594  *
    595  *****************************************************************************/
    596 
    597 static ACPI_STATUS
    598 AdDoExternalFileList (
    599     char                    *Filename)
    600 {
    601     ACPI_EXTERNAL_FILE      *ExternalFileList;
    602     char                    *ExternalFilename;
    603     ACPI_NEW_TABLE_DESC     *ExternalListHead = NULL;
    604     ACPI_STATUS             Status;
    605     ACPI_STATUS             GlobalStatus = AE_OK;
    606     ACPI_OWNER_ID           OwnerId;
    607 
    608 
    609     /*
    610      * External filenames are specified on the command line like this:
    611      * Example: iasl -e file1,file2,file3 -d xxx.aml
    612      */
    613     ExternalFileList = AcpiGbl_ExternalFileList;
    614 
    615     /* Process each external file */
    616 
    617     while (ExternalFileList)
    618     {
    619         ExternalFilename = ExternalFileList->Path;
    620         if (!strcmp (ExternalFilename, Filename))
    621         {
    622             /* Next external file */
    623 
    624             ExternalFileList = ExternalFileList->Next;
    625             continue;
    626         }
    627 
    628         AcpiOsPrintf ("External object resolution file %16s\n",
    629             ExternalFilename);
    630 
    631         Status = AcGetAllTablesFromFile (
    632             ExternalFilename, ACPI_GET_ONLY_AML_TABLES, &ExternalListHead);
    633         if (ACPI_FAILURE (Status))
    634         {
    635             if (Status == AE_TYPE)
    636             {
    637                 ExternalFileList = ExternalFileList->Next;
    638                 GlobalStatus = AE_TYPE;
    639                 Status = AE_OK;
    640                 continue;
    641             }
    642 
    643             return (Status);
    644         }
    645 
    646         /* Load external tables for symbol resolution */
    647 
    648         while (ExternalListHead)
    649         {
    650             Status = AdParseTable (
    651                 ExternalListHead->Table, &OwnerId, TRUE, TRUE);
    652             if (ACPI_FAILURE (Status))
    653             {
    654                 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
    655                     AcpiFormatException (Status));
    656                 return (Status);
    657             }
    658 
    659             /*
    660              * Load namespace from names created within control methods
    661              * Set owner id of nodes in external table
    662              */
    663             AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
    664                 AcpiGbl_RootNode, OwnerId);
    665             AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
    666 
    667             ExternalListHead = ExternalListHead->Next;
    668         }
    669 
    670         /* Next external file */
    671 
    672         ExternalFileList = ExternalFileList->Next;
    673     }
    674 
    675     if (ACPI_FAILURE (GlobalStatus))
    676     {
    677         return (GlobalStatus);
    678     }
    679 
    680     /* Clear external list generated by Scope in external tables */
    681 
    682     if (AcpiGbl_ExternalFileList)
    683     {
    684         AcpiDmClearExternalList ();
    685     }
    686 
    687     /* Load any externals defined in the optional external ref file */
    688 
    689     AcpiDmGetExternalsFromFile ();
    690     return (AE_OK);
    691 }
    692