Home | History | Annotate | Line # | Download | only in acpixtract
axutils.c revision 1.1.1.5
      1 /******************************************************************************
      2  *
      3  * Module Name: axutils - Utility functions for acpixtract tool.
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2018, 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     char                    *ColonDelimiter;
    328     int                     BytesConverted;
    329     int                     Converted[16];
    330     int                     i;
    331 
    332 
    333     /*
    334      * Terminate input line immediately after the data. Otherwise, the
    335      * second line below will not scan correctly.
    336      *
    337      * This handles varying lengths for the offset: line prefix. This support
    338      * for tables larger than 1mb was added 05/2018.
    339      *
    340      *    00b0: 03 00 00 00 43 48 41 36 0c 00 00 00 03 00 00 00  ....CHA6........
    341      *    00c0: 43 48 41 37                                      CHA7
    342      *
    343      *    012340b0: 03 00 00 00 43 48 41 36 0c 00 00 00 03 00 00 00  ....CHA6........
    344      *    012340c0: 43 48 41 37                                      CHA7
    345      */
    346     ColonDelimiter = strchr (InputLine, ':');
    347     ColonDelimiter [AX_HEX_DATA_LENGTH] = 0;
    348 
    349     /*
    350      * Convert one line of table data, of the form:
    351      * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline>
    352      *
    353      * Example:
    354      * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08  _SB_LNKD........
    355      */
    356     BytesConverted = sscanf (InputLine,
    357         "%*s %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X",
    358         &Converted[0],  &Converted[1],  &Converted[2],  &Converted[3],
    359         &Converted[4],  &Converted[5],  &Converted[6],  &Converted[7],
    360         &Converted[8],  &Converted[9],  &Converted[10], &Converted[11],
    361         &Converted[12], &Converted[13], &Converted[14], &Converted[15]);
    362 
    363     /* Pack converted data into a byte array */
    364 
    365     for (i = 0; i < BytesConverted; i++)
    366     {
    367         OutputData[i] = (unsigned char) Converted[i];
    368     }
    369 
    370     return ((size_t) BytesConverted);
    371 }
    372 
    373 
    374 /******************************************************************************
    375  *
    376  * FUNCTION:    AxCountTableInstances
    377  *
    378  * PARAMETERS:  InputPathname       - Filename for acpidump file
    379  *              Signature           - Requested signature to count
    380  *
    381  * RETURN:      The number of instances of the signature
    382  *
    383  * DESCRIPTION: Count the instances of tables with the given signature within
    384  *              the input acpidump file.
    385  *
    386  ******************************************************************************/
    387 
    388 unsigned int
    389 AxCountTableInstances (
    390     char                    *InputPathname,
    391     char                    *Signature)
    392 {
    393     FILE                    *InputFile;
    394     unsigned int            Instances = 0;
    395 
    396 
    397     InputFile = fopen (InputPathname, "r");
    398     if (!InputFile)
    399     {
    400         printf ("Could not open input file %s\n", InputPathname);
    401         return (0);
    402     }
    403 
    404     /* Count the number of instances of this signature */
    405 
    406     while (fgets (Gbl_InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile))
    407     {
    408         /* Ignore empty lines and lines that start with a space */
    409 
    410         if (AxIsEmptyLine (Gbl_InstanceBuffer) ||
    411             (Gbl_InstanceBuffer[0] == ' '))
    412         {
    413             continue;
    414         }
    415 
    416         AxNormalizeSignature (Gbl_InstanceBuffer);
    417         if (ACPI_COMPARE_NAME (Gbl_InstanceBuffer, Signature))
    418         {
    419             Instances++;
    420         }
    421     }
    422 
    423     fclose (InputFile);
    424     return (Instances);
    425 }
    426 
    427 
    428 /******************************************************************************
    429  *
    430  * FUNCTION:    AxGetNextInstance
    431  *
    432  * PARAMETERS:  InputPathname       - Filename for acpidump file
    433  *              Signature           - Requested ACPI signature
    434  *
    435  * RETURN:      The next instance number for this signature. Zero if this
    436  *              is the first instance of this signature.
    437  *
    438  * DESCRIPTION: Get the next instance number of the specified table. If this
    439  *              is the first instance of the table, create a new instance
    440  *              block. Note: only SSDT and PSDT tables can have multiple
    441  *              instances.
    442  *
    443  ******************************************************************************/
    444 
    445 unsigned int
    446 AxGetNextInstance (
    447     char                    *InputPathname,
    448     char                    *Signature)
    449 {
    450     AX_TABLE_INFO           *Info;
    451 
    452 
    453     Info = Gbl_TableListHead;
    454     while (Info)
    455     {
    456         if (*(UINT32 *) Signature == Info->Signature)
    457         {
    458             break;
    459         }
    460 
    461         Info = Info->Next;
    462     }
    463 
    464     if (!Info)
    465     {
    466         /* Signature not found, create new table info block */
    467 
    468         Info = malloc (sizeof (AX_TABLE_INFO));
    469         if (!Info)
    470         {
    471             printf ("Could not allocate memory (0x%X bytes)\n",
    472                 (unsigned int) sizeof (AX_TABLE_INFO));
    473             exit (0);
    474         }
    475 
    476         Info->Signature = *(UINT32 *) Signature;
    477         Info->Instances = AxCountTableInstances (InputPathname, Signature);
    478         Info->NextInstance = 1;
    479         Info->Next = Gbl_TableListHead;
    480         Gbl_TableListHead = Info;
    481     }
    482 
    483     if (Info->Instances > 1)
    484     {
    485         return (Info->NextInstance++);
    486     }
    487 
    488     return (0);
    489 }
    490 
    491 
    492 /******************************************************************************
    493  *
    494  * FUNCTION:    AxConvertAndWrite
    495  *
    496  * PARAMETERS:  OutputFile              - Where to write the binary data
    497  *              ThisSignature           - Signature of current ACPI table
    498  *              ThisTableBytesWritten   - Total count of data written
    499  *
    500  * RETURN:      Length of the converted line
    501  *
    502  * DESCRIPTION: Convert one line of input hex ascii text to binary, and write
    503  *              the binary data to the table output file.
    504  *
    505  * NOTE: Assumes the input data line has been validated to be of the form:
    506  *
    507  *  0010: 48 53 57 55 4c 54 2d 52 01 00 00 00 49 4e 54 4c  HSWULT-R....INTL
    508  *
    509  ******************************************************************************/
    510 
    511 long
    512 AxConvertAndWrite (
    513     FILE                    *OutputFile,
    514     char                    *ThisSignature,
    515     unsigned int            ThisTableBytesWritten)
    516 {
    517     size_t                  BytesWritten;
    518     size_t                  BytesConverted;
    519 
    520 
    521     /* Convert one line of ascii hex data to binary */
    522 
    523     BytesConverted = AxConvertToBinary (Gbl_LineBuffer, Gbl_BinaryData);
    524 
    525     /* Write the binary data */
    526 
    527     if (!BytesConverted)
    528     {
    529         return (0);
    530     }
    531 
    532     BytesWritten = fwrite (Gbl_BinaryData, 1, BytesConverted, OutputFile);
    533     if (BytesWritten != BytesConverted)
    534     {
    535         printf ("Error while writing file %s\n", Gbl_OutputFilename);
    536         return (-1);
    537     }
    538 
    539     return (BytesWritten);
    540 }
    541 
    542 
    543 /******************************************************************************
    544  *
    545  * FUNCTION:    AxDumpTableHeader
    546  *
    547  * PARAMETERS:  Header          - A binary ACPI table header
    548  *
    549  * RETURN:      None
    550  *
    551  * DESCRIPTION: Display the contents of a standard ACPI table header
    552  *
    553  ******************************************************************************/
    554 
    555 void
    556 AxDumpTableHeader (
    557     unsigned char           *Header)
    558 {
    559     ACPI_TABLE_HEADER       *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
    560     ACPI_TABLE_RSDP         *Rsdp = (ACPI_TABLE_RSDP *) (void *) Header;
    561     ACPI_TABLE_FACS         *Facs = (ACPI_TABLE_FACS *) (void *) Header;
    562 
    563 
    564     /* RSDP has an oddball signature and header */
    565 
    566     if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
    567     {
    568         AxCheckAscii ((char *) &Header[9], 6);
    569 
    570         Gbl_TableCount++;
    571         printf (" %.2u) %5.4s  0x%8.8X  0x%2.2X  \"%6.6s\"\n",
    572             Gbl_TableCount, "RSDP", Rsdp->Length, Rsdp->Revision, Rsdp->OemId);
    573         return;
    574     }
    575 
    576     if (!AcpiUtValidNameseg (TableHeader->Signature))
    577     {
    578         return;
    579     }
    580 
    581     /* Signature and Table length */
    582 
    583     Gbl_TableCount++;
    584     printf (" %.2u) %5.4s  0x%8.8X", Gbl_TableCount, TableHeader->Signature,
    585         TableHeader->Length);
    586 
    587     /* FACS has only signature and length */
    588 
    589     if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS"))
    590     {
    591         printf ("  0x%2.2X\n", Facs->Version);
    592         return;
    593     }
    594 
    595     /* OEM IDs and Compiler IDs */
    596 
    597     AxCheckAscii (TableHeader->OemId, 6);
    598     AxCheckAscii (TableHeader->OemTableId, 8);
    599     AxCheckAscii (TableHeader->AslCompilerId, 4);
    600 
    601     printf (
    602         "  0x%2.2X  \"%6.6s\"  \"%8.8s\"  0x%8.8X"
    603         "  \"%4.4s\"   0x%8.8X\n",
    604         TableHeader->Revision, TableHeader->OemId,
    605         TableHeader->OemTableId, TableHeader->OemRevision,
    606         TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
    607 }
    608 
    609 
    610 #ifdef _AX_FUTURE_ENHANCEMENTS
    611 
    612 /* Possible enhancement to validate table lengths */
    613 
    614 void
    615 AxCheckTableLengths (
    616     UINT32                  ByteCount,
    617     UINT32                  AmlByteCount)
    618 {
    619 
    620     if (AmlByteCount == 0)
    621     {
    622         return;
    623     }
    624 
    625     if (ByteCount == 0)
    626     {
    627         return;
    628     }
    629 
    630     if ((ByteCount < sizeof (ACPI_TABLE_HEADER)) &&
    631         (ByteCount >= ACPI_NAME_SIZE))
    632     {
    633         printf ("  : (Table too short for an ACPI table)");
    634     }
    635 
    636     else if (ByteCount != AmlByteCount)
    637     {
    638         printf ("  : (Hex data length mismatch with AML length 0x%X)",
    639             AmlByteCount);
    640     }
    641 
    642     printf ("\n");
    643 }
    644 #endif
    645