Home | History | Annotate | Line # | Download | only in acpixtract
acpixtract.c revision 1.1.1.2.4.2
      1 
      2 /******************************************************************************
      3  *
      4  * Module Name: acpixtract - convert ascii ACPI tables to binary
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2011, 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 <stdio.h>
     46 #include <stdlib.h>
     47 #include <string.h>
     48 #include <ctype.h>
     49 
     50 
     51 /* Note: This is a 32-bit program only */
     52 
     53 #define VERSION             0x20100107
     54 #define FIND_HEADER         0
     55 #define EXTRACT_DATA        1
     56 #define BUFFER_SIZE         256
     57 
     58 
     59 /* Local prototypes */
     60 
     61 static void
     62 CheckAscii (
     63     char                    *Name,
     64     int                     Count);
     65 
     66 static void
     67 NormalizeSignature (
     68     char                    *Signature);
     69 
     70 static unsigned int
     71 GetNextInstance (
     72     char                    *InputPathname,
     73     char                    *Signature);
     74 
     75 static int
     76 ExtractTables (
     77     char                    *InputPathname,
     78     char                    *Signature,
     79     unsigned int            MinimumInstances);
     80 
     81 static size_t
     82 GetTableHeader (
     83     FILE                    *InputFile,
     84     unsigned char           *OutputData);
     85 
     86 static unsigned int
     87 CountTableInstances (
     88     char                    *InputPathname,
     89     char                    *Signature);
     90 
     91 static int
     92 ListTables (
     93     char                    *InputPathname);
     94 
     95 static size_t
     96 ConvertLine (
     97     char                    *InputLine,
     98     unsigned char           *OutputData);
     99 
    100 static void
    101 DisplayUsage (
    102     void);
    103 
    104 
    105 typedef struct acpi_table_header
    106 {
    107     char                    Signature[4];
    108     int                     Length;
    109     unsigned char           Revision;
    110     unsigned char           Checksum;
    111     char                    OemId[6];
    112     char                    OemTableId[8];
    113     int                     OemRevision;
    114     char                    AslCompilerId[4];
    115     int                     AslCompilerRevision;
    116 
    117 } ACPI_TABLE_HEADER;
    118 
    119 struct TableInfo
    120 {
    121     unsigned int            Signature;
    122     unsigned int            Instances;
    123     unsigned int            NextInstance;
    124     struct TableInfo        *Next;
    125 };
    126 
    127 static struct TableInfo     *ListHead = NULL;
    128 static char                 Filename[16];
    129 static unsigned char        Data[16];
    130 
    131 
    132 /******************************************************************************
    133  *
    134  * FUNCTION:    DisplayUsage
    135  *
    136  * DESCRIPTION: Usage message
    137  *
    138  ******************************************************************************/
    139 
    140 static void
    141 DisplayUsage (
    142     void)
    143 {
    144 
    145     printf ("Usage: acpixtract [option] <InputFile>\n");
    146     printf ("\nExtract binary ACPI tables from text acpidump output\n");
    147     printf ("Default invocation extracts all DSDTs and SSDTs\n");
    148     printf ("Version %8.8X\n\n", VERSION);
    149     printf ("Options:\n");
    150     printf (" -a                    Extract all tables, not just DSDT/SSDT\n");
    151     printf (" -l                    List table summaries, do not extract\n");
    152     printf (" -s<Signature>         Extract all tables named <Signature>\n");
    153     printf ("\n");
    154 }
    155 
    156 
    157 /*******************************************************************************
    158  *
    159  * FUNCTION:    CheckAscii
    160  *
    161  * PARAMETERS:  Name                - Ascii string, at least as long as Count
    162  *              Count               - Number of characters to check
    163  *
    164  * RETURN:      None
    165  *
    166  * DESCRIPTION: Ensure that the requested number of characters are printable
    167  *              Ascii characters. Sets non-printable and null chars to <space>.
    168  *
    169  ******************************************************************************/
    170 
    171 static void
    172 CheckAscii (
    173     char                    *Name,
    174     int                     Count)
    175 {
    176     int                     i;
    177 
    178 
    179     for (i = 0; i < Count; i++)
    180     {
    181         if (!Name[i] || !isprint ((int) Name[i]))
    182         {
    183             Name[i] = ' ';
    184         }
    185     }
    186 }
    187 
    188 
    189 /*******************************************************************************
    190  *
    191  * FUNCTION:    NormalizeSignature
    192  *
    193  * PARAMETERS:  Name                - Ascii string containing an ACPI signature
    194  *
    195  * RETURN:      None
    196  *
    197  * DESCRIPTION: Change "RSD PTR" to "RSDP"
    198  *
    199  ******************************************************************************/
    200 
    201 static void
    202 NormalizeSignature (
    203     char                    *Signature)
    204 {
    205 
    206     if (!strncmp (Signature, "RSD ", 4))
    207     {
    208         Signature[3] = 'P';
    209     }
    210 }
    211 
    212 
    213 /******************************************************************************
    214  *
    215  * FUNCTION:    ConvertLine
    216  *
    217  * PARAMETERS:  InputLine           - One line from the input acpidump file
    218  *              OutputData          - Where the converted data is returned
    219  *
    220  * RETURN:      The number of bytes actually converted
    221  *
    222  * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes)
    223  *
    224  ******************************************************************************/
    225 
    226 static size_t
    227 ConvertLine (
    228     char                    *InputLine,
    229     unsigned char           *OutputData)
    230 {
    231     char                    *End;
    232     int                     BytesConverted;
    233     int                     Converted[16];
    234     int                     i;
    235 
    236 
    237     /* Terminate the input line at the end of the actual data (for sscanf) */
    238 
    239     End = strstr (InputLine + 2, "  ");
    240     if (!End)
    241     {
    242         return (0); /* Don't understand the format */
    243     }
    244     *End = 0;
    245 
    246     /*
    247      * Convert one line of table data, of the form:
    248      * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline>
    249      *
    250      * Example:
    251      * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08  _SB_LNKD........
    252      */
    253     BytesConverted = sscanf (InputLine,
    254         "%*s %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
    255         &Converted[0],  &Converted[1],  &Converted[2],  &Converted[3],
    256         &Converted[4],  &Converted[5],  &Converted[6],  &Converted[7],
    257         &Converted[8],  &Converted[9],  &Converted[10], &Converted[11],
    258         &Converted[12], &Converted[13], &Converted[14], &Converted[15]);
    259 
    260     /* Pack converted data into a byte array */
    261 
    262     for (i = 0; i < BytesConverted; i++)
    263     {
    264         OutputData[i] = (unsigned char) Converted[i];
    265     }
    266 
    267     return ((size_t) BytesConverted);
    268 }
    269 
    270 
    271 /******************************************************************************
    272  *
    273  * FUNCTION:    GetTableHeader
    274  *
    275  * PARAMETERS:  InputFile           - Handle for the input acpidump file
    276  *              OutputData          - Where the table header is returned
    277  *
    278  * RETURN:      The actual number of bytes converted
    279  *
    280  * DESCRIPTION: Extract and convert an ACPI table header
    281  *
    282  ******************************************************************************/
    283 
    284 static size_t
    285 GetTableHeader (
    286     FILE                    *InputFile,
    287     unsigned char           *OutputData)
    288 {
    289     size_t                  BytesConverted;
    290     size_t                  TotalConverted = 0;
    291     char                    Buffer[BUFFER_SIZE];
    292     int                     i;
    293 
    294 
    295     /* Get the full 36 byte header, requires 3 lines */
    296 
    297     for (i = 0; i < 3; i++)
    298     {
    299         if (!fgets (Buffer, BUFFER_SIZE, InputFile))
    300         {
    301             return (TotalConverted);
    302         }
    303 
    304         BytesConverted = ConvertLine (Buffer, OutputData);
    305         TotalConverted += BytesConverted;
    306         OutputData += 16;
    307 
    308         if (BytesConverted != 16)
    309         {
    310             return (TotalConverted);
    311         }
    312     }
    313 
    314     return (TotalConverted);
    315 }
    316 
    317 
    318 /******************************************************************************
    319  *
    320  * FUNCTION:    CountTableInstances
    321  *
    322  * PARAMETERS:  InputPathname       - Filename for acpidump file
    323  *              Signature           - Requested signature to count
    324  *
    325  * RETURN:      The number of instances of the signature
    326  *
    327  * DESCRIPTION: Count the instances of tables with the given signature within
    328  *              the input acpidump file.
    329  *
    330  ******************************************************************************/
    331 
    332 static unsigned int
    333 CountTableInstances (
    334     char                    *InputPathname,
    335     char                    *Signature)
    336 {
    337     char                    Buffer[BUFFER_SIZE];
    338     FILE                    *InputFile;
    339     unsigned int            Instances = 0;
    340 
    341 
    342     InputFile = fopen (InputPathname, "rt");
    343     if (!InputFile)
    344     {
    345         printf ("Could not open %s\n", InputPathname);
    346         return (0);
    347     }
    348 
    349     /* Count the number of instances of this signature */
    350 
    351     while (fgets (Buffer, BUFFER_SIZE, InputFile))
    352     {
    353         /* Ignore empty lines and lines that start with a space */
    354 
    355         if ((Buffer[0] == ' ') ||
    356             (Buffer[0] == '\n'))
    357         {
    358             continue;
    359         }
    360 
    361         NormalizeSignature (Buffer);
    362         if (!strncmp (Buffer, Signature, 4))
    363         {
    364             Instances++;
    365         }
    366     }
    367 
    368     fclose (InputFile);
    369     return (Instances);
    370 }
    371 
    372 
    373 /******************************************************************************
    374  *
    375  * FUNCTION:    GetNextInstance
    376  *
    377  * PARAMETERS:  InputPathname       - Filename for acpidump file
    378  *              Signature           - Requested ACPI signature
    379  *
    380  * RETURN:      The next instance number for this signature. Zero if this
    381  *              is the first instance of this signature.
    382  *
    383  * DESCRIPTION: Get the next instance number of the specified table. If this
    384  *              is the first instance of the table, create a new instance
    385  *              block. Note: only SSDT and PSDT tables can have multiple
    386  *              instances.
    387  *
    388  ******************************************************************************/
    389 
    390 static unsigned int
    391 GetNextInstance (
    392     char                    *InputPathname,
    393     char                    *Signature)
    394 {
    395     struct TableInfo        *Info;
    396 
    397 
    398     Info = ListHead;
    399     while (Info)
    400     {
    401         if (*(unsigned int *) Signature == Info->Signature)
    402         {
    403             break;
    404         }
    405 
    406         Info = Info->Next;
    407     }
    408 
    409     if (!Info)
    410     {
    411         /* Signature not found, create new table info block */
    412 
    413         Info = malloc (sizeof (struct TableInfo));
    414         if (!Info)
    415         {
    416             printf ("Could not allocate memory\n");
    417             exit (0);
    418         }
    419 
    420         Info->Signature = *(unsigned int *) Signature;
    421         Info->Instances = CountTableInstances (InputPathname, Signature);
    422         Info->NextInstance = 1;
    423         Info->Next = ListHead;
    424         ListHead = Info;
    425     }
    426 
    427     if (Info->Instances > 1)
    428     {
    429         return (Info->NextInstance++);
    430     }
    431 
    432     return (0);
    433 }
    434 
    435 
    436 /******************************************************************************
    437  *
    438  * FUNCTION:    ExtractTables
    439  *
    440  * PARAMETERS:  InputPathname       - Filename for acpidump file
    441  *              Signature           - Requested ACPI signature to extract.
    442  *                                    NULL means extract ALL tables.
    443  *              MinimumInstances    - Min instances that are acceptable
    444  *
    445  * RETURN:      Status
    446  *
    447  * DESCRIPTION: Convert text ACPI tables to binary
    448  *
    449  ******************************************************************************/
    450 
    451 static int
    452 ExtractTables (
    453     char                    *InputPathname,
    454     char                    *Signature,
    455     unsigned int            MinimumInstances)
    456 {
    457     char                    Buffer[BUFFER_SIZE];
    458     FILE                    *InputFile;
    459     FILE                    *OutputFile = NULL;
    460     size_t                  BytesWritten;
    461     size_t                  TotalBytesWritten = 0;
    462     size_t                  BytesConverted;
    463     unsigned int            State = FIND_HEADER;
    464     unsigned int            FoundTable = 0;
    465     unsigned int            Instances = 0;
    466     unsigned int            ThisInstance;
    467     char                    ThisSignature[4];
    468     int                     Status = 0;
    469 
    470 
    471     /* Open input in text mode, output is in binary mode */
    472 
    473     InputFile = fopen (InputPathname, "rt");
    474     if (!InputFile)
    475     {
    476         printf ("Could not open %s\n", InputPathname);
    477         return (-1);
    478     }
    479 
    480     if (Signature)
    481     {
    482         /* Are there enough instances of the table to continue? */
    483 
    484         NormalizeSignature (Signature);
    485 
    486         Instances = CountTableInstances (InputPathname, Signature);
    487         if (Instances < MinimumInstances)
    488         {
    489             printf ("Table %s was not found in %s\n", Signature, InputPathname);
    490             Status = -1;
    491             goto CleanupAndExit;
    492         }
    493 
    494         if (Instances == 0)
    495         {
    496             goto CleanupAndExit;
    497         }
    498     }
    499 
    500     /* Convert all instances of the table to binary */
    501 
    502     while (fgets (Buffer, BUFFER_SIZE, InputFile))
    503     {
    504         switch (State)
    505         {
    506         case FIND_HEADER:
    507 
    508             /* Ignore empty lines and lines that start with a space */
    509 
    510             if ((Buffer[0] == ' ') ||
    511                 (Buffer[0] == '\n'))
    512             {
    513                 continue;
    514             }
    515 
    516             NormalizeSignature (Buffer);
    517             strncpy (ThisSignature, Buffer, 4);
    518 
    519             if (Signature)
    520             {
    521                 /* Ignore signatures that don't match */
    522 
    523                 if (strncmp (ThisSignature, Signature, 4))
    524                 {
    525                     continue;
    526                 }
    527             }
    528 
    529             /*
    530              * Get the instance number for this signature. Only the
    531              * SSDT and PSDT tables can have multiple instances.
    532              */
    533             ThisInstance = GetNextInstance (InputPathname, ThisSignature);
    534 
    535             /* Build an output filename and create/open the output file */
    536 
    537             if (ThisInstance > 0)
    538             {
    539                 sprintf (Filename, "%4.4s%u.dat", ThisSignature, ThisInstance);
    540             }
    541             else
    542             {
    543                 sprintf (Filename, "%4.4s.dat", ThisSignature);
    544             }
    545 
    546             OutputFile = fopen (Filename, "w+b");
    547             if (!OutputFile)
    548             {
    549                 printf ("Could not open %s\n", Filename);
    550                 Status = -1;
    551                 goto CleanupAndExit;
    552             }
    553 
    554             State = EXTRACT_DATA;
    555             TotalBytesWritten = 0;
    556             FoundTable = 1;
    557             continue;
    558 
    559         case EXTRACT_DATA:
    560 
    561             /* Empty line or non-data line terminates the data */
    562 
    563             if ((Buffer[0] == '\n') ||
    564                 (Buffer[0] != ' '))
    565             {
    566                 fclose (OutputFile);
    567                 OutputFile = NULL;
    568                 State = FIND_HEADER;
    569 
    570                 printf ("Acpi table [%4.4s] - %u bytes written to %s\n",
    571                     ThisSignature, (unsigned int) TotalBytesWritten, Filename);
    572                 continue;
    573             }
    574 
    575             /* Convert the ascii data (one line of text) to binary */
    576 
    577             BytesConverted = ConvertLine (Buffer, Data);
    578 
    579             /* Write the binary data */
    580 
    581             BytesWritten = fwrite (Data, 1, BytesConverted, OutputFile);
    582             if (BytesWritten != BytesConverted)
    583             {
    584                 printf ("Write error on %s\n", Filename);
    585                 fclose (OutputFile);
    586                 OutputFile = NULL;
    587                 Status = -1;
    588                 goto CleanupAndExit;
    589             }
    590 
    591             TotalBytesWritten += BytesConverted;
    592             continue;
    593 
    594         default:
    595             Status = -1;
    596             goto CleanupAndExit;
    597         }
    598     }
    599 
    600     if (!FoundTable)
    601     {
    602         printf ("Table %s was not found in %s\n", Signature, InputPathname);
    603     }
    604 
    605 
    606 CleanupAndExit:
    607 
    608     if (OutputFile)
    609     {
    610         fclose (OutputFile);
    611         if (State == EXTRACT_DATA)
    612         {
    613             /* Received an EOF while extracting data */
    614 
    615             printf ("Acpi table [%4.4s] - %u bytes written to %s\n",
    616                 ThisSignature, (unsigned int) TotalBytesWritten, Filename);
    617         }
    618     }
    619 
    620     fclose (InputFile);
    621     return (Status);
    622 }
    623 
    624 
    625 /******************************************************************************
    626  *
    627  * FUNCTION:    ListTables
    628  *
    629  * PARAMETERS:  InputPathname       - Filename for acpidump file
    630  *
    631  * RETURN:      Status
    632  *
    633  * DESCRIPTION: Display info for all ACPI tables found in input. Does not
    634  *              perform an actual extraction of the tables.
    635  *
    636  ******************************************************************************/
    637 
    638 static int
    639 ListTables (
    640     char                    *InputPathname)
    641 {
    642     FILE                    *InputFile;
    643     char                    Buffer[BUFFER_SIZE];
    644     size_t                  HeaderSize;
    645     unsigned char           Header[48];
    646     int                     TableCount = 0;
    647     ACPI_TABLE_HEADER       *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
    648 
    649 
    650     /* Open input in text mode, output is in binary mode */
    651 
    652     InputFile = fopen (InputPathname, "rt");
    653     if (!InputFile)
    654     {
    655         printf ("Could not open %s\n", InputPathname);
    656         return (-1);
    657     }
    658 
    659     /* Dump the headers for all tables found in the input file */
    660 
    661     printf ("\nSignature Length Revision  OemId     OemTableId"
    662             "   OemRevision CompilerId CompilerRevision\n\n");
    663 
    664     while (fgets (Buffer, BUFFER_SIZE, InputFile))
    665     {
    666         /* Ignore empty lines and lines that start with a space */
    667 
    668         if ((Buffer[0] == ' ') ||
    669             (Buffer[0] == '\n'))
    670         {
    671             continue;
    672         }
    673 
    674         /* Get the 36 byte header and display the fields */
    675 
    676         HeaderSize = GetTableHeader (InputFile, Header);
    677         if (HeaderSize < 16)
    678         {
    679             continue;
    680         }
    681 
    682         /* RSDP has an oddball signature and header */
    683 
    684         if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
    685         {
    686             CheckAscii ((char *) &Header[9], 6);
    687             printf ("%8.4s                   \"%6.6s\"\n", "RSDP", &Header[9]);
    688             TableCount++;
    689             continue;
    690         }
    691 
    692         /* Minimum size for table with standard header */
    693 
    694         if (HeaderSize < 36)
    695         {
    696             continue;
    697         }
    698 
    699         /* Signature and Table length */
    700 
    701         TableCount++;
    702         printf ("%8.4s % 7d", TableHeader->Signature, TableHeader->Length);
    703 
    704         /* FACS has only signature and length */
    705 
    706         if (!strncmp (TableHeader->Signature, "FACS", 4))
    707         {
    708             printf ("\n");
    709             continue;
    710         }
    711 
    712         /* OEM IDs and Compiler IDs */
    713 
    714         CheckAscii (TableHeader->OemId, 6);
    715         CheckAscii (TableHeader->OemTableId, 8);
    716         CheckAscii (TableHeader->AslCompilerId, 4);
    717 
    718         printf ("     %2.2X    \"%6.6s\"  \"%8.8s\"    %8.8X    \"%4.4s\"     %8.8X\n",
    719             TableHeader->Revision, TableHeader->OemId,
    720             TableHeader->OemTableId, TableHeader->OemRevision,
    721             TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
    722     }
    723 
    724     printf ("\nFound %u ACPI tables [%8.8X]\n", TableCount, VERSION);
    725     fclose (InputFile);
    726     return (0);
    727 }
    728 
    729 
    730 /******************************************************************************
    731  *
    732  * FUNCTION:    main
    733  *
    734  * DESCRIPTION: C main function
    735  *
    736  ******************************************************************************/
    737 
    738 int
    739 main (
    740     int                     argc,
    741     char                    *argv[])
    742 {
    743     int                     Status;
    744 
    745 
    746     if (argc < 2)
    747     {
    748         DisplayUsage ();
    749         return (0);
    750     }
    751 
    752     if (argv[1][0] == '-')
    753     {
    754         if (argc < 3)
    755         {
    756             DisplayUsage ();
    757             return (0);
    758         }
    759 
    760         switch (argv[1][1])
    761         {
    762         case 'a':
    763 
    764             /* Extract all tables found */
    765 
    766             return (ExtractTables (argv[2], NULL, 0));
    767 
    768         case 'l':
    769 
    770             /* List tables only, do not extract */
    771 
    772             return (ListTables (argv[2]));
    773 
    774         case 's':
    775 
    776             /* Extract only tables with this signature */
    777 
    778             return (ExtractTables (argv[2], &argv[1][2], 1));
    779 
    780         default:
    781             DisplayUsage ();
    782             return (0);
    783         }
    784     }
    785 
    786     /*
    787      * Default output is the DSDT and all SSDTs. One DSDT is required,
    788      * any SSDTs are optional.
    789      */
    790     Status = ExtractTables (argv[1], "DSDT", 1);
    791     if (Status)
    792     {
    793         return (Status);
    794     }
    795 
    796     Status = ExtractTables (argv[1], "SSDT", 0);
    797     return (Status);
    798 }
    799 
    800 
    801