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