Home | History | Annotate | Line # | Download | only in acpixtract
axutils.c revision 1.1.1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: axutils - Utility functions for acpixtract tool.
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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 /*******************************************************************************
     48  *
     49  * FUNCTION:    AxCheckAscii
     50  *
     51  * PARAMETERS:  Name                - Ascii string, at least as long as Count
     52  *              Count               - Number of characters to check
     53  *
     54  * RETURN:      None
     55  *
     56  * DESCRIPTION: Ensure that the requested number of characters are printable
     57  *              Ascii characters. Sets non-printable and null chars to <space>.
     58  *
     59  ******************************************************************************/
     60 
     61 void
     62 AxCheckAscii (
     63     char                    *Name,
     64     int                     Count)
     65 {
     66     int                     i;
     67 
     68 
     69     for (i = 0; i < Count; i++)
     70     {
     71         if (!Name[i] || !isprint ((int) Name[i]))
     72         {
     73             Name[i] = ' ';
     74         }
     75     }
     76 }
     77 
     78 
     79 /*******************************************************************************
     80  *
     81  * FUNCTION:    AxIsFileAscii
     82  *
     83  * PARAMETERS:  Handle              - To open input file
     84  *
     85  * RETURN:      TRUE if file is entirely ASCII and printable
     86  *
     87  * DESCRIPTION: Verify that the input file is entirely ASCII.
     88  *
     89  ******************************************************************************/
     90 
     91 BOOLEAN
     92 AxIsFileAscii (
     93     FILE                    *Handle)
     94 {
     95     UINT8                   Byte;
     96     UINT32                  Offset = 0;
     97 
     98 
     99     /* Read the entire file */
    100 
    101     fseek (Handle, 0, SEEK_SET);
    102     while (fread (&Byte, 1, 1, Handle) == 1)
    103     {
    104         /*
    105          * Ignore null characters. Some acpidump-type utilities insert
    106          * a few of these, probably a bug in the utility. As long as these
    107          * characters are in lines that are tossed (non-data), they
    108          * won't cause a problem.
    109          */
    110         if (!Byte)
    111         {
    112             continue;
    113         }
    114 
    115         /* Check for an ASCII character */
    116 
    117         if (!ACPI_IS_ASCII (Byte))
    118         {
    119             printf ("Found non-ascii char: %2.2X at file offset %u (0x%X)\n",
    120                 Byte, Offset, Offset);
    121             if (!Gbl_ForceExtraction)
    122             {
    123                 goto ErrorExit;
    124             }
    125         }
    126 
    127         /* Ensure character is either printable or a "space" char */
    128 
    129         else if (!isprint (Byte) && !isspace (Byte))
    130         {
    131             printf ("Found non-printable char: %2.2X at file offset %u (0x%X)\n",
    132                 Byte, Offset, Offset);
    133             if (!Gbl_ForceExtraction)
    134             {
    135                 goto ErrorExit;
    136             }
    137         }
    138 
    139         Offset++;
    140     }
    141 
    142     /* File is OK (100% ASCII) */
    143 
    144     fseek (Handle, 0, SEEK_SET);
    145     return (TRUE);
    146 
    147 ErrorExit:
    148 
    149     printf ("File appears to be binary "
    150         "(contains non-text or non-ascii characters)\n");
    151     fseek (Handle, 0, SEEK_SET);
    152     return (FALSE);
    153 }
    154 
    155 
    156 /******************************************************************************
    157  *
    158  * FUNCTION:    AxIsEmptyLine
    159  *
    160  * PARAMETERS:  Buffer              - Line from input file
    161  *
    162  * RETURN:      TRUE if line is empty (zero or more blanks only)
    163  *
    164  * DESCRIPTION: Determine if an input line is empty.
    165  *
    166  ******************************************************************************/
    167 
    168 BOOLEAN
    169 AxIsEmptyLine (
    170     char                    *Buffer)
    171 {
    172 
    173     /* Skip all spaces */
    174 
    175     while (*Buffer == ' ')
    176     {
    177         Buffer++;
    178     }
    179 
    180     /* Line is empty when a Unix or DOS-style line terminator is found. */
    181 
    182     if ((*Buffer == '\r') || (*Buffer == '\n'))
    183     {
    184         return (1);
    185     }
    186 
    187     return (0);
    188 }
    189 
    190 
    191 /******************************************************************************
    192  *
    193  * FUNCTION:    AxIsHexDataLine
    194  *
    195  * PARAMETERS:  None
    196  *
    197  * RETURN:      Status. 1 if the table header is valid, 0 otherwise.
    198  *
    199  * DESCRIPTION: Check for a valid line of hex data of the form:
    200  *
    201  *  00a0: 0c 00 00 00 03 00 00 00 43 48 41 35 0c 00 00 00  ........CHA5....
    202  *
    203  ******************************************************************************/
    204 
    205 BOOLEAN
    206 AxIsHexDataLine (
    207     void)
    208 {
    209 
    210     if (AxIsEmptyLine (Gbl_LineBuffer) ||
    211         (Gbl_LineBuffer[0] != ' '))
    212     {
    213         return (FALSE);
    214     }
    215 
    216     if (!strstr (Gbl_LineBuffer, ": "))
    217     {
    218         /* Not valid data line */
    219 
    220         return (FALSE);
    221     }
    222 
    223     return (TRUE);
    224 }
    225 
    226 
    227 /******************************************************************************
    228  *
    229  * FUNCTION:    AxIsDataBlockHeader
    230  *
    231  * PARAMETERS:  None
    232  *
    233  * RETURN:      Status. 1 if the table header is valid, 0 otherwise.
    234  *
    235  * DESCRIPTION: Check if the ACPI table identifier in the input acpidump text
    236  *              file is valid (of the form: <sig> @ <addr>).
    237  *
    238  ******************************************************************************/
    239 
    240 BOOLEAN
    241 AxIsDataBlockHeader (
    242     void)
    243 {
    244 
    245     /* Ignore lines that are too short to be header lines */
    246 
    247     if (strlen (Gbl_LineBuffer) < AX_MIN_BLOCK_HEADER_LENGTH)
    248     {
    249         return (FALSE);
    250     }
    251 
    252     /* Ignore empty lines and lines that start with a space */
    253 
    254     if (AxIsEmptyLine (Gbl_LineBuffer) ||
    255         (Gbl_LineBuffer[0] == ' '))
    256     {
    257         return (FALSE);
    258     }
    259 
    260     /*
    261      * Ignore lines that are not headers of the form <sig> @ <addr>.
    262      * Basically, just look for the '@' symbol, surrounded by spaces.
    263      *
    264      * Examples of headers that must be supported:
    265      *
    266      * DSDT @ 0x737e4000
    267      * XSDT @ 0x737f2fff
    268      * RSD PTR @ 0xf6cd0
    269      * SSDT @ (nil)
    270      */
    271     if (!AX_IS_TABLE_BLOCK_HEADER)
    272     {
    273         return (FALSE);
    274     }
    275 
    276     AxNormalizeSignature (Gbl_LineBuffer);
    277     return (TRUE);
    278 }
    279 
    280 
    281 /*******************************************************************************
    282  *
    283  * FUNCTION:    AxNormalizeSignature
    284  *
    285  * PARAMETERS:  Name                - Ascii string containing an ACPI signature
    286  *
    287  * RETURN:      None
    288  *
    289  * DESCRIPTION: Change "RSD PTR" to "RSDP"
    290  *
    291  ******************************************************************************/
    292 
    293 void
    294 AxNormalizeSignature (
    295     char                    *Signature)
    296 {
    297 
    298     if (!strncmp (Signature, "RSD ", 4))
    299     {
    300         Signature[3] = 'P';
    301     }
    302 }
    303 
    304 
    305 /******************************************************************************
    306  *
    307  * FUNCTION:    AxConvertToBinary
    308  *
    309  * PARAMETERS:  InputLine           - One line from the input acpidump file
    310  *              OutputData          - Where the converted data is returned
    311  *
    312  * RETURN:      The number of bytes actually converted
    313  *
    314  * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes)
    315  *
    316  * NOTE: Assumes the input data line has been validated to be of the form:
    317  *
    318  *  0010: 48 53 57 55 4c 54 2d 52 01 00 00 00 49 4e 54 4c  HSWULT-R....INTL
    319  *
    320  ******************************************************************************/
    321 
    322 size_t
    323 AxConvertToBinary (
    324     char                    *InputLine,
    325     unsigned char           *OutputData)
    326 {
    327     int                     BytesConverted;
    328     int                     Converted[16];
    329     int                     i;
    330 
    331 
    332     /*
    333      * Terminate input line immediately after the data. Otherwise, the
    334      * second line below will not scan correctly.
    335      *
    336      *    00b0: 03 00 00 00 43 48 41 36 0c 00 00 00 03 00 00 00  ....CHA6........
    337      *    00c0: 43 48 41 37                                      CHA7
    338      */
    339     InputLine [AX_END_OF_HEX_DATA] = 0;
    340 
    341     /*
    342      * Convert one line of table data, of the form:
    343      * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline>
    344      *
    345      * Example:
    346      * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08  _SB_LNKD........
    347      */
    348     BytesConverted = sscanf (InputLine,
    349         "%*s %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X",
    350         &Converted[0],  &Converted[1],  &Converted[2],  &Converted[3],
    351         &Converted[4],  &Converted[5],  &Converted[6],  &Converted[7],
    352         &Converted[8],  &Converted[9],  &Converted[10], &Converted[11],
    353         &Converted[12], &Converted[13], &Converted[14], &Converted[15]);
    354 
    355     /* Pack converted data into a byte array */
    356 
    357     for (i = 0; i < BytesConverted; i++)
    358     {
    359         OutputData[i] = (unsigned char) Converted[i];
    360     }
    361 
    362     return ((size_t) BytesConverted);
    363 }
    364 
    365 
    366 /******************************************************************************
    367  *
    368  * FUNCTION:    AxCountTableInstances
    369  *
    370  * PARAMETERS:  InputPathname       - Filename for acpidump file
    371  *              Signature           - Requested signature to count
    372  *
    373  * RETURN:      The number of instances of the signature
    374  *
    375  * DESCRIPTION: Count the instances of tables with the given signature within
    376  *              the input acpidump file.
    377  *
    378  ******************************************************************************/
    379 
    380 unsigned int
    381 AxCountTableInstances (
    382     char                    *InputPathname,
    383     char                    *Signature)
    384 {
    385     FILE                    *InputFile;
    386     unsigned int            Instances = 0;
    387 
    388 
    389     InputFile = fopen (InputPathname, "r");
    390     if (!InputFile)
    391     {
    392         printf ("Could not open input file %s\n", InputPathname);
    393         return (0);
    394     }
    395 
    396     /* Count the number of instances of this signature */
    397 
    398     while (fgets (Gbl_InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    399     {
    400         /* Ignore empty lines and lines that start with a space */
    401 
    402         if (AxIsEmptyLine (Gbl_InstanceBuffer) ||
    403             (Gbl_InstanceBuffer[0] == ' '))
    404         {
    405             continue;
    406         }
    407 
    408         AxNormalizeSignature (Gbl_InstanceBuffer);
    409         if (ACPI_COMPARE_NAME (Gbl_InstanceBuffer, Signature))
    410         {
    411             Instances++;
    412         }
    413     }
    414 
    415     fclose (InputFile);
    416     return (Instances);
    417 }
    418 
    419 
    420 /******************************************************************************
    421  *
    422  * FUNCTION:    AxGetNextInstance
    423  *
    424  * PARAMETERS:  InputPathname       - Filename for acpidump file
    425  *              Signature           - Requested ACPI signature
    426  *
    427  * RETURN:      The next instance number for this signature. Zero if this
    428  *              is the first instance of this signature.
    429  *
    430  * DESCRIPTION: Get the next instance number of the specified table. If this
    431  *              is the first instance of the table, create a new instance
    432  *              block. Note: only SSDT and PSDT tables can have multiple
    433  *              instances.
    434  *
    435  ******************************************************************************/
    436 
    437 unsigned int
    438 AxGetNextInstance (
    439     char                    *InputPathname,
    440     char                    *Signature)
    441 {
    442     AX_TABLE_INFO           *Info;
    443 
    444 
    445     Info = Gbl_TableListHead;
    446     while (Info)
    447     {
    448         if (*(UINT32 *) Signature == Info->Signature)
    449         {
    450             break;
    451         }
    452 
    453         Info = Info->Next;
    454     }
    455 
    456     if (!Info)
    457     {
    458         /* Signature not found, create new table info block */
    459 
    460         Info = malloc (sizeof (AX_TABLE_INFO));
    461         if (!Info)
    462         {
    463             printf ("Could not allocate memory (0x%X bytes)\n",
    464                 (unsigned int) sizeof (AX_TABLE_INFO));
    465             exit (0);
    466         }
    467 
    468         Info->Signature = *(UINT32 *) Signature;
    469         Info->Instances = AxCountTableInstances (InputPathname, Signature);
    470         Info->NextInstance = 1;
    471         Info->Next = Gbl_TableListHead;
    472         Gbl_TableListHead = Info;
    473     }
    474 
    475     if (Info->Instances > 1)
    476     {
    477         return (Info->NextInstance++);
    478     }
    479 
    480     return (0);
    481 }
    482 
    483 
    484 /******************************************************************************
    485  *
    486  * FUNCTION:    AxConvertAndWrite
    487  *
    488  * PARAMETERS:  OutputFile              - Where to write the binary data
    489  *              ThisSignature           - Signature of current ACPI table
    490  *              ThisTableBytesWritten   - Total count of data written
    491  *
    492  * RETURN:      Length of the converted line
    493  *
    494  * DESCRIPTION: Convert one line of input hex ascii text to binary, and write
    495  *              the binary data to the table output file.
    496  *
    497  * NOTE: Assumes the input data line has been validated to be of the form:
    498  *
    499  *  0010: 48 53 57 55 4c 54 2d 52 01 00 00 00 49 4e 54 4c  HSWULT-R....INTL
    500  *
    501  ******************************************************************************/
    502 
    503 long
    504 AxConvertAndWrite (
    505     FILE                    *OutputFile,
    506     char                    *ThisSignature,
    507     unsigned int            ThisTableBytesWritten)
    508 {
    509     size_t                  BytesWritten;
    510     size_t                  BytesConverted;
    511 
    512 
    513     /* Convert one line of ascii hex data to binary */
    514 
    515     BytesConverted = AxConvertToBinary (Gbl_LineBuffer, Gbl_BinaryData);
    516 
    517     /* Write the binary data */
    518 
    519     if (!BytesConverted)
    520     {
    521         return (0);
    522     }
    523 
    524     BytesWritten = fwrite (Gbl_BinaryData, 1, BytesConverted, OutputFile);
    525     if (BytesWritten != BytesConverted)
    526     {
    527         printf ("Error while writing file %s\n", Gbl_OutputFilename);
    528         return (-1);
    529     }
    530 
    531     return (BytesWritten);
    532 }
    533 
    534 
    535 /******************************************************************************
    536  *
    537  * FUNCTION:    AxDumpTableHeader
    538  *
    539  * PARAMETERS:  Header          - A binary ACPI table header
    540  *
    541  * RETURN:      None
    542  *
    543  * DESCRIPTION: Display the contents of a standard ACPI table header
    544  *
    545  ******************************************************************************/
    546 
    547 void
    548 AxDumpTableHeader (
    549     unsigned char           *Header)
    550 {
    551     ACPI_TABLE_HEADER       *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
    552     ACPI_TABLE_RSDP         *Rsdp = (ACPI_TABLE_RSDP *) (void *) Header;
    553     ACPI_TABLE_FACS         *Facs = (ACPI_TABLE_FACS *) (void *) Header;
    554 
    555 
    556     /* RSDP has an oddball signature and header */
    557 
    558     if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
    559     {
    560         AxCheckAscii ((char *) &Header[9], 6);
    561 
    562         Gbl_TableCount++;
    563         printf (" %.2u) %5.4s  0x%8.8X  0x%2.2X  \"%6.6s\"\n",
    564             Gbl_TableCount, "RSDP", Rsdp->Length, Rsdp->Revision, Rsdp->OemId);
    565         return;
    566     }
    567 
    568     if (!AcpiUtValidNameseg (TableHeader->Signature))
    569     {
    570         return;
    571     }
    572 
    573     /* Signature and Table length */
    574 
    575     Gbl_TableCount++;
    576     printf (" %.2u) %5.4s  0x%8.8X", Gbl_TableCount, TableHeader->Signature,
    577         TableHeader->Length);
    578 
    579     /* FACS has only signature and length */
    580 
    581     if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS"))
    582     {
    583         printf ("  0x%2.2X\n", Facs->Version);
    584         return;
    585     }
    586 
    587     /* OEM IDs and Compiler IDs */
    588 
    589     AxCheckAscii (TableHeader->OemId, 6);
    590     AxCheckAscii (TableHeader->OemTableId, 8);
    591     AxCheckAscii (TableHeader->AslCompilerId, 4);
    592 
    593     printf (
    594         "  0x%2.2X  \"%6.6s\"  \"%8.8s\"  0x%8.8X"
    595         "  \"%4.4s\"   0x%8.8X\n",
    596         TableHeader->Revision, TableHeader->OemId,
    597         TableHeader->OemTableId, TableHeader->OemRevision,
    598         TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
    599 }
    600 
    601 
    602 #ifdef _AX_FUTURE_ENHANCEMENTS
    603 
    604 /* Possible enhancement to validate table lengths */
    605 
    606 void
    607 AxCheckTableLengths (
    608     UINT32                  ByteCount,
    609     UINT32                  AmlByteCount)
    610 {
    611 
    612     if (AmlByteCount == 0)
    613     {
    614         return;
    615     }
    616 
    617     if (ByteCount == 0)
    618     {
    619         return;
    620     }
    621 
    622     if ((ByteCount < sizeof (ACPI_TABLE_HEADER)) &&
    623         (ByteCount >= ACPI_NAME_SIZE))
    624     {
    625         printf ("  : (Table too short for an ACPI table)");
    626     }
    627 
    628     else if (ByteCount != AmlByteCount)
    629     {
    630         printf ("  : (Hex data length mismatch with AML length 0x%X)",
    631             AmlByteCount);
    632     }
    633 
    634     printf ("\n");
    635 }
    636 #endif
    637