Home | History | Annotate | Line # | Download | only in acpixtract
acpixtract.c revision 1.11
      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     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 
     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             switch (BytesConverted)
    220             {
    221             case 0:
    222 
    223                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
    224                 continue;
    225 
    226             case -1:
    227 
    228                 Status = -1;
    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     int                     TotalBytesWritten = 0;
    293     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 (OutputFile, ThisSignature);
    390             switch (BytesConverted)
    391             {
    392             case 0:
    393 
    394                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
    395                 continue;
    396 
    397             case -1:
    398 
    399                 Status = -1;
    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     UINT32                  ThisLineByteCount;
    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             ThisLineByteCount = AxConvertToBinary (Gbl_LineBuffer,
    530                 &Header[ByteCount]);
    531             if (ThisLineByteCount == EOF)
    532             {
    533                 fclose (InputFile);
    534                 return (-1);
    535             }
    536 
    537             ByteCount += ThisLineByteCount;
    538             if (ByteCount >= sizeof (ACPI_TABLE_HEADER))
    539             {
    540                 AxDumpTableHeader (Header);
    541                 State = AX_STATE_FIND_HEADER;
    542             }
    543             continue;
    544 
    545         default:
    546             break;
    547         }
    548     }
    549 
    550     printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
    551     fclose (InputFile);
    552     return (0);
    553 }
    554