Home | History | Annotate | Line # | Download | only in acpixtract
acpixtract.c revision 1.9
      1 /******************************************************************************
      2  *
      3  * Module Name: acpixtract - Top level functions to convert ascii/hex
      4  *                           ACPI tables to the original binary tables
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2017, Intel Corp.
     10  * All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions, and the following disclaimer,
     17  *    without modification.
     18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     19  *    substantially similar to the "NO WARRANTY" disclaimer below
     20  *    ("Disclaimer") and any redistribution must be conditioned upon
     21  *    including a substantially similar Disclaimer requirement for further
     22  *    binary redistribution.
     23  * 3. Neither the names of the above-listed copyright holders nor the names
     24  *    of any contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * Alternatively, this software may be distributed under the terms of the
     28  * GNU General Public License ("GPL") version 2 as published by the Free
     29  * Software Foundation.
     30  *
     31  * NO WARRANTY
     32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     42  * POSSIBILITY OF SUCH DAMAGES.
     43  */
     44 
     45 #include "acpixtract.h"
     46 
     47 
     48 /******************************************************************************
     49  *
     50  * FUNCTION:    AxExtractTables
     51  *
     52  * PARAMETERS:  InputPathname       - Filename for input acpidump file
     53  *              Signature           - Requested ACPI signature to extract.
     54  *                                    NULL means extract ALL tables.
     55  *              MinimumInstances    - Min instances that are acceptable
     56  *
     57  * RETURN:      Status
     58  *
     59  * DESCRIPTION: Convert text ACPI tables to binary
     60  *
     61  ******************************************************************************/
     62 
     63 int
     64 AxExtractTables (
     65     char                    *InputPathname,
     66     char                    *Signature,
     67     unsigned int            MinimumInstances)
     68 {
     69     FILE                    *InputFile;
     70     FILE                    *OutputFile = NULL;
     71     unsigned int            BytesConverted;
     72     unsigned int            ThisTableBytesWritten = 0;
     73     unsigned int            FoundTable = 0;
     74     unsigned int            Instances = 0;
     75     unsigned int            ThisInstance;
     76     char                    ThisSignature[5];
     77     char                    UpperSignature[5];
     78     int                     Status = 0;
     79     unsigned int            State = AX_STATE_FIND_HEADER;
     80 
     81 
     82     /* Open input in text mode, output is in binary mode */
     83 
     84     InputFile = fopen (InputPathname, "r");
     85     if (!InputFile)
     86     {
     87         printf ("Could not open input file %s\n", InputPathname);
     88         return (-1);
     89     }
     90 
     91     if (!AxIsFileAscii (InputFile))
     92     {
     93         fclose (InputFile);
     94         return (-1);
     95     }
     96 
     97     if (Signature)
     98     {
     99         strncpy (UpperSignature, Signature, 4);
    100         UpperSignature[4] = 0;
    101         AcpiUtStrupr (UpperSignature);
    102 
    103         /* Are there enough instances of the table to continue? */
    104 
    105         AxNormalizeSignature (UpperSignature);
    106         Instances = AxCountTableInstances (InputPathname, UpperSignature);
    107 
    108         if (Instances < MinimumInstances)
    109         {
    110             printf ("Table [%s] was not found in %s\n",
    111                 UpperSignature, InputPathname);
    112             fclose (InputFile);
    113             return (0);             /* Don't abort */
    114         }
    115 
    116         if (Instances == 0)
    117         {
    118             fclose (InputFile);
    119             return (-1);
    120         }
    121     }
    122 
    123     /* Convert all instances of the table to binary */
    124 
    125     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    126     {
    127         /*
    128          * Check up front if we have a header line of the form:
    129          * DSDT @ 0xdfffd0c0 (10999 bytes)
    130          */
    131         if (AX_IS_TABLE_BLOCK_HEADER &&
    132             (State == AX_STATE_EXTRACT_DATA))
    133         {
    134             /* End of previous table, start of new table */
    135 
    136             if (ThisTableBytesWritten)
    137             {
    138                 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
    139                     ThisTableBytesWritten, Gbl_OutputFilename);
    140             }
    141             else
    142             {
    143                 Gbl_TableCount--;
    144             }
    145 
    146             State = AX_STATE_FIND_HEADER;
    147         }
    148 
    149         switch (State)
    150         {
    151         case AX_STATE_FIND_HEADER:
    152 
    153             if (!AxIsDataBlockHeader ())
    154             {
    155                 continue;
    156             }
    157 
    158             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
    159             if (Signature)
    160             {
    161                 /* Ignore signatures that don't match */
    162 
    163                 if (!ACPI_COMPARE_NAME (ThisSignature, UpperSignature))
    164                 {
    165                     continue;
    166                 }
    167             }
    168 
    169             /*
    170              * Get the instance number for this signature. Only the
    171              * SSDT and PSDT tables can have multiple instances.
    172              */
    173             ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
    174 
    175             /* Build an output filename and create/open the output file */
    176 
    177             if (ThisInstance > 0)
    178             {
    179                 /* Add instance number to the output filename */
    180 
    181                 sprintf (Gbl_OutputFilename, "%4.4s%u.dat",
    182                     ThisSignature, ThisInstance);
    183             }
    184             else
    185             {
    186                 sprintf (Gbl_OutputFilename, "%4.4s.dat",
    187                     ThisSignature);
    188             }
    189 
    190             AcpiUtStrlwr (Gbl_OutputFilename);
    191             OutputFile = fopen (Gbl_OutputFilename, "w+b");
    192             if (!OutputFile)
    193             {
    194                 printf ("Could not open output file %s\n",
    195                     Gbl_OutputFilename);
    196                 fclose (InputFile);
    197                 return (-1);
    198             }
    199 
    200             /*
    201              * Toss this block header of the form "<sig> @ <addr>" line
    202              * and move on to the actual data block
    203              */
    204             Gbl_TableCount++;
    205             FoundTable = 1;
    206             ThisTableBytesWritten = 0;
    207             State = AX_STATE_EXTRACT_DATA;
    208             continue;
    209 
    210         case AX_STATE_EXTRACT_DATA:
    211 
    212             if (!AxIsHexDataLine ())
    213             {
    214                 continue;   /* Toss any lines that are not raw hex data */
    215             }
    216 
    217             /* Empty line or non-data line terminates the data block */
    218 
    219             BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature,
    220                 ThisTableBytesWritten);
    221             switch (BytesConverted)
    222             {
    223             case 0:
    224 
    225                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
    226                 continue;
    227 
    228             case -1:
    229 
    230                 goto CleanupAndExit; /* There was a write error */
    231 
    232             default: /* Normal case, get next line */
    233 
    234                 ThisTableBytesWritten += BytesConverted;
    235                 continue;
    236             }
    237 
    238         default:
    239 
    240             Status = -1;
    241             goto CleanupAndExit;
    242         }
    243     }
    244 
    245     if (!FoundTable)
    246     {
    247         printf ("No ACPI tables were found in %s\n", InputPathname);
    248     }
    249 
    250 
    251 CleanupAndExit:
    252 
    253     if (State == AX_STATE_EXTRACT_DATA)
    254     {
    255         /* Received an input file EOF while extracting data */
    256 
    257         printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
    258             ThisTableBytesWritten, Gbl_OutputFilename);
    259     }
    260 
    261     if (OutputFile)
    262     {
    263         fclose (OutputFile);
    264     }
    265 
    266     fclose (InputFile);
    267     return (Status);
    268 }
    269 
    270 
    271 /******************************************************************************
    272  *
    273  * FUNCTION:    AxExtractToMultiAmlFile
    274  *
    275  * PARAMETERS:  InputPathname       - Filename for input acpidump file
    276  *
    277  * RETURN:      Status
    278  *
    279  * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all
    280  *              into a single output file. Used to simplify the loading of
    281  *              multiple/many SSDTs into a utility like acpiexec -- instead
    282  *              of creating many separate output files.
    283  *
    284  ******************************************************************************/
    285 
    286 int
    287 AxExtractToMultiAmlFile (
    288     char                    *InputPathname)
    289 {
    290     FILE                    *InputFile;
    291     FILE                    *OutputFile;
    292     int                     Status = 0;
    293     unsigned int            TotalBytesWritten = 0;
    294     unsigned int            ThisTableBytesWritten = 0;
    295     unsigned int            BytesConverted;
    296     char                    ThisSignature[4];
    297     unsigned int            State = AX_STATE_FIND_HEADER;
    298 
    299 
    300     strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME);
    301 
    302     /* Open the input file in text mode */
    303 
    304     InputFile = fopen (InputPathname, "r");
    305     if (!InputFile)
    306     {
    307         printf ("Could not open input file %s\n", InputPathname);
    308         return (-1);
    309     }
    310 
    311     if (!AxIsFileAscii (InputFile))
    312     {
    313         fclose (InputFile);
    314         return (-1);
    315     }
    316 
    317     /* Open the output file in binary mode */
    318 
    319     OutputFile = fopen (Gbl_OutputFilename, "w+b");
    320     if (!OutputFile)
    321     {
    322         printf ("Could not open output file %s\n", Gbl_OutputFilename);
    323         fclose (InputFile);
    324         return (-1);
    325     }
    326 
    327     /* Convert the DSDT and all SSDTs to binary */
    328 
    329     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    330     {
    331         /*
    332          * Check up front if we have a header line of the form:
    333          * DSDT @ 0xdfffd0c0 (10999 bytes)
    334          */
    335         if (AX_IS_TABLE_BLOCK_HEADER &&
    336             (State == AX_STATE_EXTRACT_DATA))
    337         {
    338             /* End of previous table, start of new table */
    339 
    340             if (ThisTableBytesWritten)
    341             {
    342                 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
    343                     ThisTableBytesWritten, Gbl_OutputFilename);
    344             }
    345             else
    346             {
    347                 Gbl_TableCount--;
    348             }
    349 
    350             State = AX_STATE_FIND_HEADER;
    351         }
    352 
    353         switch (State)
    354         {
    355         case AX_STATE_FIND_HEADER:
    356 
    357             if (!AxIsDataBlockHeader ())
    358             {
    359                 continue;
    360             }
    361 
    362             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
    363 
    364             /* Only want DSDT and SSDTs */
    365 
    366             if (!ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_DSDT) &&
    367                 !ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_SSDT))
    368             {
    369                 continue;
    370             }
    371 
    372             /*
    373              * Toss this block header of the form "<sig> @ <addr>" line
    374              * and move on to the actual data block
    375              */
    376             Gbl_TableCount++;
    377             ThisTableBytesWritten = 0;
    378             State = AX_STATE_EXTRACT_DATA;
    379             continue;
    380 
    381         case AX_STATE_EXTRACT_DATA:
    382 
    383             if (!AxIsHexDataLine ())
    384             {
    385                 continue;   /* Toss any lines that are not raw hex data */
    386             }
    387 
    388             /* Empty line or non-data line terminates the data block */
    389 
    390             BytesConverted = AxConvertAndWrite (
    391                 OutputFile, ThisSignature, ThisTableBytesWritten);
    392             switch (BytesConverted)
    393             {
    394             case 0:
    395 
    396                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
    397                 continue;
    398 
    399             case -1:
    400 
    401                 goto CleanupAndExit; /* There was a write error */
    402 
    403             default: /* Normal case, get next line */
    404 
    405                 ThisTableBytesWritten += BytesConverted;
    406                 TotalBytesWritten += BytesConverted;
    407                 continue;
    408             }
    409 
    410         default:
    411 
    412             Status = -1;
    413             goto CleanupAndExit;
    414         }
    415     }
    416 
    417 
    418 CleanupAndExit:
    419 
    420     if (State == AX_STATE_EXTRACT_DATA)
    421     {
    422         /* Received an input file EOF or error while writing data */
    423 
    424         printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
    425             ThisTableBytesWritten, Gbl_OutputFilename);
    426     }
    427 
    428     printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n",
    429         Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten);
    430 
    431     fclose (InputFile);
    432     fclose (OutputFile);
    433     return (Status);
    434 }
    435 
    436 
    437 /******************************************************************************
    438  *
    439  * FUNCTION:    AxListAllTables
    440  *
    441  * PARAMETERS:  InputPathname       - Filename for acpidump file
    442  *
    443  * RETURN:      Status
    444  *
    445  * DESCRIPTION: Display info for all ACPI tables found in input. Does not
    446  *              perform an actual extraction of the tables.
    447  *
    448  ******************************************************************************/
    449 
    450 int
    451 AxListAllTables (
    452     char                    *InputPathname)
    453 {
    454     FILE                    *InputFile;
    455     unsigned char           Header[48];
    456     UINT32                  ByteCount = 0;
    457     unsigned int            State = AX_STATE_FIND_HEADER;
    458 
    459 
    460     /* Open input in text mode, output is in binary mode */
    461 
    462     InputFile = fopen (InputPathname, "r");
    463     if (!InputFile)
    464     {
    465         printf ("Could not open input file %s\n", InputPathname);
    466         return (-1);
    467     }
    468 
    469     if (!AxIsFileAscii (InputFile))
    470     {
    471         fclose (InputFile);
    472         return (-1);
    473     }
    474 
    475     /* Info header */
    476 
    477     printf ("\n Signature  Length    Version Oem       Oem         "
    478         "Oem         Compiler Compiler\n");
    479     printf (  "                              Id        TableId     "
    480         "RevisionId  Name     Revision\n");
    481     printf (  " _________  __________  ____  ________  __________  "
    482         "__________  _______  __________\n\n");
    483 
    484     /* Dump the headers for all tables found in the input file */
    485 
    486     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    487     {
    488         /* Ignore empty lines */
    489 
    490         if (AxIsEmptyLine (Gbl_LineBuffer))
    491         {
    492             continue;
    493         }
    494 
    495         /*
    496          * Check up front if we have a header line of the form:
    497          * DSDT @ 0xdfffd0c0 (10999 bytes)
    498          */
    499         if (AX_IS_TABLE_BLOCK_HEADER &&
    500             (State == AX_STATE_EXTRACT_DATA))
    501         {
    502             State = AX_STATE_FIND_HEADER;
    503         }
    504 
    505         switch (State)
    506         {
    507         case AX_STATE_FIND_HEADER:
    508 
    509             ByteCount = 0;
    510             if (!AxIsDataBlockHeader ())
    511             {
    512                 continue;
    513             }
    514 
    515             State = AX_STATE_EXTRACT_DATA;
    516             continue;
    517 
    518         case AX_STATE_EXTRACT_DATA:
    519 
    520             /* Ignore any lines that don't look like a data line */
    521 
    522             if (!AxIsHexDataLine ())
    523             {
    524                 continue;   /* Toss any lines that are not raw hex data */
    525             }
    526 
    527             /* Convert header to hex and display it */
    528 
    529             ByteCount += AxConvertToBinary (Gbl_LineBuffer, &Header[ByteCount]);
    530             if (ByteCount >= sizeof (ACPI_TABLE_HEADER))
    531             {
    532                 AxDumpTableHeader (Header);
    533                 State = AX_STATE_FIND_HEADER;
    534             }
    535             continue;
    536 
    537         default:
    538             break;
    539         }
    540     }
    541 
    542     printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
    543     fclose (InputFile);
    544     return (0);
    545 }
    546