Home | History | Annotate | Line # | Download | only in acpixtract
acpixtract.c revision 1.10
      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 - 2018, 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, ACPI_NAME_SIZE);
    100         AcpiUtStrupr (UpperSignature);
    101 
    102         /* Are there enough instances of the table to continue? */
    103 
    104         AxNormalizeSignature (UpperSignature);
    105         Instances = AxCountTableInstances (InputPathname, UpperSignature);
    106 
    107         if (Instances < MinimumInstances)
    108         {
    109             printf ("Table [%s] was not found in %s\n",
    110                 UpperSignature, InputPathname);
    111             fclose (InputFile);
    112             return (0);             /* Don't abort */
    113         }
    114 
    115         if (Instances == 0)
    116         {
    117             fclose (InputFile);
    118             return (-1);
    119         }
    120     }
    121 
    122     /* Convert all instances of the table to binary */
    123 
    124     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    125     {
    126         /*
    127          * Check up front if we have a header line of the form:
    128          * DSDT @ 0xdfffd0c0 (10999 bytes)
    129          */
    130         if (AX_IS_TABLE_BLOCK_HEADER &&
    131             (State == AX_STATE_EXTRACT_DATA))
    132         {
    133             /* End of previous table, start of new table */
    134 
    135             if (ThisTableBytesWritten)
    136             {
    137                 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
    138                     ThisTableBytesWritten, Gbl_OutputFilename);
    139             }
    140             else
    141             {
    142                 Gbl_TableCount--;
    143             }
    144 
    145             State = AX_STATE_FIND_HEADER;
    146         }
    147 
    148         switch (State)
    149         {
    150         case AX_STATE_FIND_HEADER:
    151 
    152             if (!AxIsDataBlockHeader ())
    153             {
    154                 continue;
    155             }
    156 
    157             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
    158             if (Signature)
    159             {
    160                 /* Ignore signatures that don't match */
    161 
    162                 if (!ACPI_COMPARE_NAME (ThisSignature, UpperSignature))
    163                 {
    164                     continue;
    165                 }
    166             }
    167 
    168             /*
    169              * Get the instance number for this signature. Only the
    170              * SSDT and PSDT tables can have multiple instances.
    171              */
    172             ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
    173 
    174             /* Build an output filename and create/open the output file */
    175 
    176             if (ThisInstance > 0)
    177             {
    178                 /* Add instance number to the output filename */
    179 
    180                 sprintf (Gbl_OutputFilename, "%4.4s%u.dat",
    181                     ThisSignature, ThisInstance);
    182             }
    183             else
    184             {
    185                 sprintf (Gbl_OutputFilename, "%4.4s.dat",
    186                     ThisSignature);
    187             }
    188 
    189             AcpiUtStrlwr (Gbl_OutputFilename);
    190             OutputFile = fopen (Gbl_OutputFilename, "w+b");
    191             if (!OutputFile)
    192             {
    193                 printf ("Could not open output file %s\n",
    194                     Gbl_OutputFilename);
    195                 fclose (InputFile);
    196                 return (-1);
    197             }
    198 
    199             /*
    200              * Toss this block header of the form "<sig> @ <addr>" line
    201              * and move on to the actual data block
    202              */
    203             Gbl_TableCount++;
    204             FoundTable = 1;
    205             ThisTableBytesWritten = 0;
    206             State = AX_STATE_EXTRACT_DATA;
    207             continue;
    208 
    209         case AX_STATE_EXTRACT_DATA:
    210 
    211             if (!AxIsHexDataLine ())
    212             {
    213                 continue;   /* Toss any lines that are not raw hex data */
    214             }
    215 
    216             /* Empty line or non-data line terminates the data block */
    217 
    218             BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature,
    219                 ThisTableBytesWritten);
    220             switch (BytesConverted)
    221             {
    222             case 0:
    223 
    224                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
    225                 continue;
    226 
    227             case -1:
    228 
    229                 goto CleanupAndExit; /* There was a write error */
    230 
    231             default: /* Normal case, get next line */
    232 
    233                 ThisTableBytesWritten += BytesConverted;
    234                 continue;
    235             }
    236 
    237         default:
    238 
    239             Status = -1;
    240             goto CleanupAndExit;
    241         }
    242     }
    243 
    244     if (!FoundTable)
    245     {
    246         printf ("No ACPI tables were found in %s\n", InputPathname);
    247     }
    248 
    249 
    250 CleanupAndExit:
    251 
    252     if (State == AX_STATE_EXTRACT_DATA)
    253     {
    254         /* Received an input file EOF while extracting data */
    255 
    256         printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
    257             ThisTableBytesWritten, Gbl_OutputFilename);
    258     }
    259 
    260     if (OutputFile)
    261     {
    262         fclose (OutputFile);
    263     }
    264 
    265     fclose (InputFile);
    266     return (Status);
    267 }
    268 
    269 
    270 /******************************************************************************
    271  *
    272  * FUNCTION:    AxExtractToMultiAmlFile
    273  *
    274  * PARAMETERS:  InputPathname       - Filename for input acpidump file
    275  *
    276  * RETURN:      Status
    277  *
    278  * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all
    279  *              into a single output file. Used to simplify the loading of
    280  *              multiple/many SSDTs into a utility like acpiexec -- instead
    281  *              of creating many separate output files.
    282  *
    283  ******************************************************************************/
    284 
    285 int
    286 AxExtractToMultiAmlFile (
    287     char                    *InputPathname)
    288 {
    289     FILE                    *InputFile;
    290     FILE                    *OutputFile;
    291     int                     Status = 0;
    292     unsigned int            TotalBytesWritten = 0;
    293     unsigned int            ThisTableBytesWritten = 0;
    294     unsigned int            BytesConverted;
    295     char                    ThisSignature[4];
    296     unsigned int            State = AX_STATE_FIND_HEADER;
    297 
    298 
    299     strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME);
    300 
    301     /* Open the input file in text mode */
    302 
    303     InputFile = fopen (InputPathname, "r");
    304     if (!InputFile)
    305     {
    306         printf ("Could not open input file %s\n", InputPathname);
    307         return (-1);
    308     }
    309 
    310     if (!AxIsFileAscii (InputFile))
    311     {
    312         fclose (InputFile);
    313         return (-1);
    314     }
    315 
    316     /* Open the output file in binary mode */
    317 
    318     OutputFile = fopen (Gbl_OutputFilename, "w+b");
    319     if (!OutputFile)
    320     {
    321         printf ("Could not open output file %s\n", Gbl_OutputFilename);
    322         fclose (InputFile);
    323         return (-1);
    324     }
    325 
    326     /* Convert the DSDT and all SSDTs to binary */
    327 
    328     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    329     {
    330         /*
    331          * Check up front if we have a header line of the form:
    332          * DSDT @ 0xdfffd0c0 (10999 bytes)
    333          */
    334         if (AX_IS_TABLE_BLOCK_HEADER &&
    335             (State == AX_STATE_EXTRACT_DATA))
    336         {
    337             /* End of previous table, start of new table */
    338 
    339             if (ThisTableBytesWritten)
    340             {
    341                 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
    342                     ThisTableBytesWritten, Gbl_OutputFilename);
    343             }
    344             else
    345             {
    346                 Gbl_TableCount--;
    347             }
    348 
    349             State = AX_STATE_FIND_HEADER;
    350         }
    351 
    352         switch (State)
    353         {
    354         case AX_STATE_FIND_HEADER:
    355 
    356             if (!AxIsDataBlockHeader ())
    357             {
    358                 continue;
    359             }
    360 
    361             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
    362 
    363             /* Only want DSDT and SSDTs */
    364 
    365             if (!ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_DSDT) &&
    366                 !ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_SSDT))
    367             {
    368                 continue;
    369             }
    370 
    371             /*
    372              * Toss this block header of the form "<sig> @ <addr>" line
    373              * and move on to the actual data block
    374              */
    375             Gbl_TableCount++;
    376             ThisTableBytesWritten = 0;
    377             State = AX_STATE_EXTRACT_DATA;
    378             continue;
    379 
    380         case AX_STATE_EXTRACT_DATA:
    381 
    382             if (!AxIsHexDataLine ())
    383             {
    384                 continue;   /* Toss any lines that are not raw hex data */
    385             }
    386 
    387             /* Empty line or non-data line terminates the data block */
    388 
    389             BytesConverted = AxConvertAndWrite (
    390                 OutputFile, ThisSignature, ThisTableBytesWritten);
    391             switch (BytesConverted)
    392             {
    393             case 0:
    394 
    395                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
    396                 continue;
    397 
    398             case -1:
    399 
    400                 goto CleanupAndExit; /* There was a write error */
    401 
    402             default: /* Normal case, get next line */
    403 
    404                 ThisTableBytesWritten += BytesConverted;
    405                 TotalBytesWritten += BytesConverted;
    406                 continue;
    407             }
    408 
    409         default:
    410 
    411             Status = -1;
    412             goto CleanupAndExit;
    413         }
    414     }
    415 
    416 
    417 CleanupAndExit:
    418 
    419     if (State == AX_STATE_EXTRACT_DATA)
    420     {
    421         /* Received an input file EOF or error while writing data */
    422 
    423         printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
    424             ThisTableBytesWritten, Gbl_OutputFilename);
    425     }
    426 
    427     printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n",
    428         Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten);
    429 
    430     fclose (InputFile);
    431     fclose (OutputFile);
    432     return (Status);
    433 }
    434 
    435 
    436 /******************************************************************************
    437  *
    438  * FUNCTION:    AxListAllTables
    439  *
    440  * PARAMETERS:  InputPathname       - Filename for acpidump file
    441  *
    442  * RETURN:      Status
    443  *
    444  * DESCRIPTION: Display info for all ACPI tables found in input. Does not
    445  *              perform an actual extraction of the tables.
    446  *
    447  ******************************************************************************/
    448 
    449 int
    450 AxListAllTables (
    451     char                    *InputPathname)
    452 {
    453     FILE                    *InputFile;
    454     unsigned char           Header[48];
    455     UINT32                  ByteCount = 0;
    456     unsigned int            State = AX_STATE_FIND_HEADER;
    457 
    458 
    459     /* Open input in text mode, output is in binary mode */
    460 
    461     InputFile = fopen (InputPathname, "r");
    462     if (!InputFile)
    463     {
    464         printf ("Could not open input file %s\n", InputPathname);
    465         return (-1);
    466     }
    467 
    468     if (!AxIsFileAscii (InputFile))
    469     {
    470         fclose (InputFile);
    471         return (-1);
    472     }
    473 
    474     /* Info header */
    475 
    476     printf ("\n Signature  Length    Version Oem       Oem         "
    477         "Oem         Compiler Compiler\n");
    478     printf (  "                              Id        TableId     "
    479         "RevisionId  Name     Revision\n");
    480     printf (  " _________  __________  ____  ________  __________  "
    481         "__________  _______  __________\n\n");
    482 
    483     /* Dump the headers for all tables found in the input file */
    484 
    485     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    486     {
    487         /* Ignore empty lines */
    488 
    489         if (AxIsEmptyLine (Gbl_LineBuffer))
    490         {
    491             continue;
    492         }
    493 
    494         /*
    495          * Check up front if we have a header line of the form:
    496          * DSDT @ 0xdfffd0c0 (10999 bytes)
    497          */
    498         if (AX_IS_TABLE_BLOCK_HEADER &&
    499             (State == AX_STATE_EXTRACT_DATA))
    500         {
    501             State = AX_STATE_FIND_HEADER;
    502         }
    503 
    504         switch (State)
    505         {
    506         case AX_STATE_FIND_HEADER:
    507 
    508             ByteCount = 0;
    509             if (!AxIsDataBlockHeader ())
    510             {
    511                 continue;
    512             }
    513 
    514             State = AX_STATE_EXTRACT_DATA;
    515             continue;
    516 
    517         case AX_STATE_EXTRACT_DATA:
    518 
    519             /* Ignore any lines that don't look like a data line */
    520 
    521             if (!AxIsHexDataLine ())
    522             {
    523                 continue;   /* Toss any lines that are not raw hex data */
    524             }
    525 
    526             /* Convert header to hex and display it */
    527 
    528             ByteCount += AxConvertToBinary (Gbl_LineBuffer, &Header[ByteCount]);
    529             if (ByteCount >= sizeof (ACPI_TABLE_HEADER))
    530             {
    531                 AxDumpTableHeader (Header);
    532                 State = AX_STATE_FIND_HEADER;
    533             }
    534             continue;
    535 
    536         default:
    537             break;
    538         }
    539     }
    540 
    541     printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
    542     fclose (InputFile);
    543     return (0);
    544 }
    545