Home | History | Annotate | Line # | Download | only in acpixtract
acpixtract.c revision 1.7
      1 /******************************************************************************
      2  *
      3  * Module Name: acpixtract - convert ascii ACPI tables to binary
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, 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 "acpixtract.h"
     45 
     46 
     47 /* Local prototypes */
     48 
     49 static BOOLEAN
     50 AxIsFileAscii (
     51     FILE                    *Handle);
     52 
     53 
     54 /******************************************************************************
     55  *
     56  * FUNCTION:    AxExtractTables
     57  *
     58  * PARAMETERS:  InputPathname       - Filename for input acpidump file
     59  *              Signature           - Requested ACPI signature to extract.
     60  *                                    NULL means extract ALL tables.
     61  *              MinimumInstances    - Min instances that are acceptable
     62  *
     63  * RETURN:      Status
     64  *
     65  * DESCRIPTION: Convert text ACPI tables to binary
     66  *
     67  ******************************************************************************/
     68 
     69 int
     70 AxExtractTables (
     71     char                    *InputPathname,
     72     char                    *Signature,
     73     unsigned int            MinimumInstances)
     74 {
     75     FILE                    *InputFile;
     76     FILE                    *OutputFile = NULL;
     77     unsigned int            BytesConverted;
     78     unsigned int            ThisTableBytesWritten = 0;
     79     unsigned int            FoundTable = 0;
     80     unsigned int            Instances = 0;
     81     unsigned int            ThisInstance;
     82     char                    ThisSignature[5];
     83     char                    UpperSignature[5];
     84     int                     Status = 0;
     85     unsigned int            State = AX_STATE_FIND_HEADER;
     86 
     87 
     88     /* Open input in text mode, output is in binary mode */
     89 
     90     InputFile = fopen (InputPathname, "rt");
     91     if (!InputFile)
     92     {
     93         printf ("Could not open input file %s\n", InputPathname);
     94         return (-1);
     95     }
     96 
     97     if (!AxIsFileAscii (InputFile))
     98     {
     99         fclose (InputFile);
    100         return (-1);
    101     }
    102 
    103     if (Signature)
    104     {
    105         strncpy (UpperSignature, Signature, 4);
    106         UpperSignature[4] = 0;
    107         AcpiUtStrupr (UpperSignature);
    108 
    109         /* Are there enough instances of the table to continue? */
    110 
    111         AxNormalizeSignature (UpperSignature);
    112 
    113         Instances = AxCountTableInstances (InputPathname, UpperSignature);
    114         if (Instances < MinimumInstances)
    115         {
    116             printf ("Table [%s] was not found in %s\n",
    117                 UpperSignature, InputPathname);
    118             fclose (InputFile);
    119             return (-1);
    120         }
    121 
    122         if (Instances == 0)
    123         {
    124             fclose (InputFile);
    125             return (-1);
    126         }
    127     }
    128 
    129     /* Convert all instances of the table to binary */
    130 
    131     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    132     {
    133         switch (State)
    134         {
    135         case AX_STATE_FIND_HEADER:
    136 
    137             if (!AxIsDataBlockHeader ())
    138             {
    139                 continue;
    140             }
    141 
    142             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
    143             if (Signature)
    144             {
    145                 /* Ignore signatures that don't match */
    146 
    147                 if (!ACPI_COMPARE_NAME (ThisSignature, UpperSignature))
    148                 {
    149                     continue;
    150                 }
    151             }
    152 
    153             /*
    154              * Get the instance number for this signature. Only the
    155              * SSDT and PSDT tables can have multiple instances.
    156              */
    157             ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
    158 
    159             /* Build an output filename and create/open the output file */
    160 
    161             if (ThisInstance > 0)
    162             {
    163                 /* Add instance number to the output filename */
    164 
    165                 sprintf (Gbl_OutputFilename, "%4.4s%u.dat",
    166                     ThisSignature, ThisInstance);
    167             }
    168             else
    169             {
    170                 sprintf (Gbl_OutputFilename, "%4.4s.dat",
    171                     ThisSignature);
    172             }
    173 
    174             AcpiUtStrlwr (Gbl_OutputFilename);
    175             OutputFile = fopen (Gbl_OutputFilename, "w+b");
    176             if (!OutputFile)
    177             {
    178                 printf ("Could not open output file %s\n",
    179                     Gbl_OutputFilename);
    180                 fclose (InputFile);
    181                 return (-1);
    182             }
    183 
    184             /*
    185              * Toss this block header of the form "<sig> @ <addr>" line
    186              * and move on to the actual data block
    187              */
    188             Gbl_TableCount++;
    189             FoundTable = 1;
    190             ThisTableBytesWritten = 0;
    191             State = AX_STATE_EXTRACT_DATA;
    192             continue;
    193 
    194         case AX_STATE_EXTRACT_DATA:
    195 
    196             /* Empty line or non-data line terminates the data block */
    197 
    198             BytesConverted = AxProcessOneTextLine (
    199                 OutputFile, ThisSignature, ThisTableBytesWritten);
    200             switch (BytesConverted)
    201             {
    202             case 0:
    203 
    204                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
    205                 continue;
    206 
    207             case -1:
    208 
    209                 goto CleanupAndExit; /* There was a write error */
    210 
    211             default: /* Normal case, get next line */
    212 
    213                 ThisTableBytesWritten += BytesConverted;
    214                 continue;
    215             }
    216 
    217         default:
    218 
    219             Status = -1;
    220             goto CleanupAndExit;
    221         }
    222     }
    223 
    224     if (!FoundTable)
    225     {
    226         printf ("No ACPI tables were found in %s\n", InputPathname);
    227     }
    228 
    229 
    230 CleanupAndExit:
    231 
    232     if (State == AX_STATE_EXTRACT_DATA)
    233     {
    234         /* Received an input file EOF while extracting data */
    235 
    236         printf (AX_TABLE_INFO_FORMAT,
    237             ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename);
    238     }
    239 
    240     if (Gbl_TableCount > 1)
    241     {
    242         printf ("\n%u binary ACPI tables extracted\n",
    243             Gbl_TableCount);
    244     }
    245 
    246     if (OutputFile)
    247     {
    248         fclose (OutputFile);
    249     }
    250 
    251     fclose (InputFile);
    252     return (Status);
    253 }
    254 
    255 
    256 /******************************************************************************
    257  *
    258  * FUNCTION:    AxExtractToMultiAmlFile
    259  *
    260  * PARAMETERS:  InputPathname       - Filename for input acpidump file
    261  *
    262  * RETURN:      Status
    263  *
    264  * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all
    265  *              into a single output file. Used to simplify the loading of
    266  *              multiple/many SSDTs into a utility like acpiexec -- instead
    267  *              of creating many separate output files.
    268  *
    269  ******************************************************************************/
    270 
    271 int
    272 AxExtractToMultiAmlFile (
    273     char                    *InputPathname)
    274 {
    275     FILE                    *InputFile;
    276     FILE                    *OutputFile;
    277     int                     Status = 0;
    278     unsigned int            TotalBytesWritten = 0;
    279     unsigned int            ThisTableBytesWritten = 0;
    280     unsigned int             BytesConverted;
    281     char                    ThisSignature[4];
    282     unsigned int            State = AX_STATE_FIND_HEADER;
    283 
    284 
    285     strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME);
    286 
    287     /* Open the input file in text mode */
    288 
    289     InputFile = fopen (InputPathname, "rt");
    290     if (!InputFile)
    291     {
    292         printf ("Could not open input file %s\n", InputPathname);
    293         return (-1);
    294     }
    295 
    296     if (!AxIsFileAscii (InputFile))
    297     {
    298         fclose (InputFile);
    299         return (-1);
    300     }
    301 
    302     /* Open the output file in binary mode */
    303 
    304     OutputFile = fopen (Gbl_OutputFilename, "w+b");
    305     if (!OutputFile)
    306     {
    307         printf ("Could not open output file %s\n", Gbl_OutputFilename);
    308         fclose (InputFile);
    309         return (-1);
    310     }
    311 
    312     /* Convert the DSDT and all SSDTs to binary */
    313 
    314     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    315     {
    316         switch (State)
    317         {
    318         case AX_STATE_FIND_HEADER:
    319 
    320             if (!AxIsDataBlockHeader ())
    321             {
    322                 continue;
    323             }
    324 
    325             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
    326 
    327             /* Only want DSDT and SSDTs */
    328 
    329             if (!ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_DSDT) &&
    330                 !ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_SSDT))
    331             {
    332                 continue;
    333             }
    334 
    335             /*
    336              * Toss this block header of the form "<sig> @ <addr>" line
    337              * and move on to the actual data block
    338              */
    339             Gbl_TableCount++;
    340             ThisTableBytesWritten = 0;
    341             State = AX_STATE_EXTRACT_DATA;
    342             continue;
    343 
    344         case AX_STATE_EXTRACT_DATA:
    345 
    346             /* Empty line or non-data line terminates the data block */
    347 
    348             BytesConverted = AxProcessOneTextLine (
    349                 OutputFile, ThisSignature, ThisTableBytesWritten);
    350             switch (BytesConverted)
    351             {
    352             case 0:
    353 
    354                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
    355                 continue;
    356 
    357             case -1:
    358 
    359                 goto CleanupAndExit; /* There was a write error */
    360 
    361             default: /* Normal case, get next line */
    362 
    363                 ThisTableBytesWritten += BytesConverted;
    364                 TotalBytesWritten += BytesConverted;
    365                 continue;
    366             }
    367 
    368         default:
    369 
    370             Status = -1;
    371             goto CleanupAndExit;
    372         }
    373     }
    374 
    375 
    376 CleanupAndExit:
    377 
    378     if (State == AX_STATE_EXTRACT_DATA)
    379     {
    380         /* Received an input file EOF or error while writing data */
    381 
    382         printf (AX_TABLE_INFO_FORMAT,
    383             ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename);
    384     }
    385 
    386     printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n",
    387         Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten);
    388 
    389     fclose (InputFile);
    390     fclose (OutputFile);
    391     return (Status);
    392 }
    393 
    394 
    395 /******************************************************************************
    396  *
    397  * FUNCTION:    AxListTables
    398  *
    399  * PARAMETERS:  InputPathname       - Filename for acpidump file
    400  *
    401  * RETURN:      Status
    402  *
    403  * DESCRIPTION: Display info for all ACPI tables found in input. Does not
    404  *              perform an actual extraction of the tables.
    405  *
    406  ******************************************************************************/
    407 
    408 int
    409 AxListTables (
    410     char                    *InputPathname)
    411 {
    412     FILE                    *InputFile;
    413     size_t                  HeaderSize;
    414     unsigned char           Header[48];
    415     ACPI_TABLE_HEADER       *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
    416 
    417 
    418     /* Open input in text mode, output is in binary mode */
    419 
    420     InputFile = fopen (InputPathname, "rt");
    421     if (!InputFile)
    422     {
    423         printf ("Could not open input file %s\n", InputPathname);
    424         return (-1);
    425     }
    426 
    427     if (!AxIsFileAscii (InputFile))
    428     {
    429         fclose (InputFile);
    430         return (-1);
    431     }
    432 
    433     /* Dump the headers for all tables found in the input file */
    434 
    435     printf ("\nSignature  Length      Revision   OemId    OemTableId"
    436         "   OemRevision CompilerId CompilerRevision\n\n");
    437 
    438     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    439     {
    440         /* Ignore empty lines and lines that start with a space */
    441 
    442         if (AxIsEmptyLine (Gbl_LineBuffer) ||
    443             (Gbl_LineBuffer[0] == ' '))
    444         {
    445             continue;
    446         }
    447 
    448         /* Get the 36 byte header and display the fields */
    449 
    450         HeaderSize = AxGetTableHeader (InputFile, Header);
    451         if (HeaderSize < 16)
    452         {
    453             continue;
    454         }
    455 
    456         /* RSDP has an oddball signature and header */
    457 
    458         if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
    459         {
    460             AxCheckAscii ((char *) &Header[9], 6);
    461             printf ("%7.4s                          \"%6.6s\"\n", "RSDP",
    462                 &Header[9]);
    463             Gbl_TableCount++;
    464             continue;
    465         }
    466 
    467         /* Minimum size for table with standard header */
    468 
    469         if (HeaderSize < sizeof (ACPI_TABLE_HEADER))
    470         {
    471             continue;
    472         }
    473 
    474         if (!AcpiUtValidNameseg (TableHeader->Signature))
    475         {
    476             continue;
    477         }
    478 
    479         /* Signature and Table length */
    480 
    481         Gbl_TableCount++;
    482         printf ("%7.4s   0x%8.8X", TableHeader->Signature,
    483             TableHeader->Length);
    484 
    485         /* FACS has only signature and length */
    486 
    487         if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS"))
    488         {
    489             printf ("\n");
    490             continue;
    491         }
    492 
    493         /* OEM IDs and Compiler IDs */
    494 
    495         AxCheckAscii (TableHeader->OemId, 6);
    496         AxCheckAscii (TableHeader->OemTableId, 8);
    497         AxCheckAscii (TableHeader->AslCompilerId, 4);
    498 
    499         printf (
    500             "     0x%2.2X    \"%6.6s\"  \"%8.8s\"   0x%8.8X"
    501             "    \"%4.4s\"     0x%8.8X\n",
    502             TableHeader->Revision, TableHeader->OemId,
    503             TableHeader->OemTableId, TableHeader->OemRevision,
    504             TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
    505     }
    506 
    507     printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
    508     fclose (InputFile);
    509     return (0);
    510 }
    511 
    512 
    513 /*******************************************************************************
    514  *
    515  * FUNCTION:    AxIsFileAscii
    516  *
    517  * PARAMETERS:  Handle              - To open input file
    518  *
    519  * RETURN:      TRUE if file is entirely ASCII and printable
    520  *
    521  * DESCRIPTION: Verify that the input file is entirely ASCII.
    522  *
    523  ******************************************************************************/
    524 
    525 static BOOLEAN
    526 AxIsFileAscii (
    527     FILE                    *Handle)
    528 {
    529     UINT8                   Byte;
    530 
    531 
    532     /* Read the entire file */
    533 
    534     while (fread (&Byte, 1, 1, Handle) == 1)
    535     {
    536         /* Check for an ASCII character */
    537 
    538         if (!ACPI_IS_ASCII (Byte))
    539         {
    540             goto ErrorExit;
    541         }
    542 
    543         /* Ensure character is either printable or a "space" char */
    544 
    545         else if (!isprint (Byte) && !isspace (Byte))
    546         {
    547             goto ErrorExit;
    548         }
    549     }
    550 
    551     /* File is OK (100% ASCII) */
    552 
    553     fseek (Handle, 0, SEEK_SET);
    554     return (TRUE);
    555 
    556 ErrorExit:
    557 
    558     printf ("File is binary (contains non-text or non-ascii characters)\n");
    559     fseek (Handle, 0, SEEK_SET);
    560     return (FALSE);
    561 
    562 }
    563