Home | History | Annotate | Line # | Download | only in acpixtract
acpixtract.c revision 1.18
      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 - 2023, 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 MERCHANTABILITY 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     int                     BytesConverted;
     72     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     memset (UpperSignature, 0, sizeof(UpperSignature));
     82 
     83     /* Open input in text mode, output is in binary mode */
     84 
     85     InputFile = fopen (InputPathname, "r");
     86     if (!InputFile)
     87     {
     88         printf ("Could not open input file %s\n", InputPathname);
     89         return (-1);
     90     }
     91 
     92     if (!AxIsFileAscii (InputFile))
     93     {
     94         fclose (InputFile);
     95         return (-1);
     96     }
     97 
     98     if (Signature)
     99     {
    100         strncpy (UpperSignature, Signature, ACPI_NAMESEG_SIZE);
    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 || MinimumInstances == AX_OPTIONAL_TABLES)
    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_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer);
    159             if (Signature)
    160             {
    161                 /* Ignore signatures that don't match */
    162 
    163                 if (!ACPI_COMPARE_NAMESEG (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             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                 Status = -1;
    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     int                     TotalBytesWritten = 0;
    294     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_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer);
    363 
    364             /* Only want DSDT and SSDTs */
    365 
    366             if (!ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_DSDT) &&
    367                 !ACPI_COMPARE_NAMESEG (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 (OutputFile, ThisSignature);
    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                 Status = -1;
    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     INT32                   ThisLineByteCount;
    458     unsigned int            State = AX_STATE_FIND_HEADER;
    459 
    460 
    461     /* Open input in text mode, output is in binary mode */
    462 
    463     InputFile = fopen (InputPathname, "r");
    464     if (!InputFile)
    465     {
    466         printf ("Could not open input file %s\n", InputPathname);
    467         return (-1);
    468     }
    469 
    470     if (!AxIsFileAscii (InputFile))
    471     {
    472         fclose (InputFile);
    473         return (-1);
    474     }
    475 
    476     /* Info header */
    477 
    478     printf ("\n Signature  Length    Version Oem       Oem         "
    479         "Oem         Compiler Compiler\n");
    480     printf (  "                              Id        TableId     "
    481         "RevisionId  Name     Revision\n");
    482     printf (  " _________  __________  ____  ________  __________  "
    483         "__________  _______  __________\n\n");
    484 
    485     /* Dump the headers for all tables found in the input file */
    486 
    487     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    488     {
    489         /* Ignore empty lines */
    490 
    491         if (AxIsEmptyLine (Gbl_LineBuffer))
    492         {
    493             continue;
    494         }
    495 
    496         /*
    497          * Check up front if we have a header line of the form:
    498          * DSDT @ 0xdfffd0c0 (10999 bytes)
    499          */
    500         if (AX_IS_TABLE_BLOCK_HEADER &&
    501             (State == AX_STATE_EXTRACT_DATA))
    502         {
    503             State = AX_STATE_FIND_HEADER;
    504         }
    505 
    506         switch (State)
    507         {
    508         case AX_STATE_FIND_HEADER:
    509 
    510             ByteCount = 0;
    511             if (!AxIsDataBlockHeader ())
    512             {
    513                 continue;
    514             }
    515 
    516             State = AX_STATE_EXTRACT_DATA;
    517             continue;
    518 
    519         case AX_STATE_EXTRACT_DATA:
    520 
    521             /* Ignore any lines that don't look like a data line */
    522 
    523             if (!AxIsHexDataLine ())
    524             {
    525                 continue;   /* Toss any lines that are not raw hex data */
    526             }
    527 
    528             /* Convert header to hex and display it */
    529 
    530             ThisLineByteCount = AxConvertToBinary (Gbl_LineBuffer,
    531                 &Header[ByteCount]);
    532             if (ThisLineByteCount == EOF)
    533             {
    534                 fclose (InputFile);
    535                 return (-1);
    536             }
    537 
    538             ByteCount += ThisLineByteCount;
    539             if (ByteCount >= sizeof (ACPI_TABLE_HEADER))
    540             {
    541                 AxDumpTableHeader (Header);
    542                 State = AX_STATE_FIND_HEADER;
    543             }
    544             continue;
    545 
    546         default:
    547             break;
    548         }
    549     }
    550 
    551     printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
    552     fclose (InputFile);
    553     return (0);
    554 }
    555