Home | History | Annotate | Line # | Download | only in common
dmtbdump.c revision 1.15
      1 /******************************************************************************
      2  *
      3  * Module Name: dmtbdump - Dump ACPI data tables that contain no AML code
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 "acpi.h"
     45 #include "accommon.h"
     46 #include "acdisasm.h"
     47 #include "actables.h"
     48 
     49 /* This module used for application-level code only */
     50 
     51 #define _COMPONENT          ACPI_CA_DISASSEMBLER
     52         ACPI_MODULE_NAME    ("dmtbdump")
     53 
     54 
     55 /* Local prototypes */
     56 
     57 static void
     58 AcpiDmValidateFadtLength (
     59     UINT32                  Revision,
     60     UINT32                  Length);
     61 
     62 
     63 /*******************************************************************************
     64  *
     65  * FUNCTION:    AcpiDmDumpBuffer
     66  *
     67  * PARAMETERS:  Table               - ACPI Table or subtable
     68  *              BufferOffset        - Offset of buffer from Table above
     69  *              Length              - Length of the buffer
     70  *              AbsoluteOffset      - Offset of buffer in the main ACPI table
     71  *              Header              - Name of the buffer field (printed on the
     72  *                                    first line only.)
     73  *
     74  * RETURN:      None
     75  *
     76  * DESCRIPTION: Format the contents of an arbitrary length data buffer (in the
     77  *              disassembler output format.)
     78  *
     79  ******************************************************************************/
     80 
     81 void
     82 AcpiDmDumpBuffer (
     83     void                    *Table,
     84     UINT32                  BufferOffset,
     85     UINT32                  Length,
     86     UINT32                  AbsoluteOffset,
     87     char                    *Header)
     88 {
     89     UINT8                   *Buffer;
     90     UINT32                  i;
     91 
     92 
     93     if (!Length)
     94     {
     95         return;
     96     }
     97 
     98     Buffer = ACPI_CAST_PTR (UINT8, Table) + BufferOffset;
     99     i = 0;
    100 
    101     while (i < Length)
    102     {
    103         if (!(i % 16))
    104         {
    105             /* Insert a backslash - line continuation character */
    106 
    107             if (Length > 16)
    108             {
    109                 AcpiOsPrintf ("\\\n    ");
    110             }
    111         }
    112 
    113         AcpiOsPrintf ("%.02X ", *Buffer);
    114         i++;
    115         Buffer++;
    116         AbsoluteOffset++;
    117     }
    118 
    119     AcpiOsPrintf ("\n");
    120 }
    121 
    122 
    123 /*******************************************************************************
    124  *
    125  * FUNCTION:    AcpiDmDumpUnicode
    126  *
    127  * PARAMETERS:  Table               - ACPI Table or subtable
    128  *              BufferOffset        - Offset of buffer from Table above
    129  *              ByteLength          - Length of the buffer
    130  *
    131  * RETURN:      None
    132  *
    133  * DESCRIPTION: Validate and dump the contents of a buffer that contains
    134  *              unicode data. The output is a standard ASCII string. If it
    135  *              appears that the data is not unicode, the buffer is dumped
    136  *              as hex characters.
    137  *
    138  ******************************************************************************/
    139 
    140 void
    141 AcpiDmDumpUnicode (
    142     void                    *Table,
    143     UINT32                  BufferOffset,
    144     UINT32                  ByteLength)
    145 {
    146     UINT8                   *Buffer;
    147     UINT32                  Length;
    148     UINT32                  i;
    149 
    150 
    151     Buffer = ((UINT8 *) Table) + BufferOffset;
    152     Length = ByteLength - 2; /* Last two bytes are the null terminator */
    153 
    154     /* Ensure all low bytes are entirely printable ASCII */
    155 
    156     for (i = 0; i < Length; i += 2)
    157     {
    158         if (!isprint (Buffer[i]))
    159         {
    160             goto DumpRawBuffer;
    161         }
    162     }
    163 
    164     /* Ensure all high bytes are zero */
    165 
    166     for (i = 1; i < Length; i += 2)
    167     {
    168         if (Buffer[i])
    169         {
    170             goto DumpRawBuffer;
    171         }
    172     }
    173 
    174     /* Dump the buffer as a normal string */
    175 
    176     AcpiOsPrintf ("\"");
    177     for (i = 0; i < Length; i += 2)
    178     {
    179         AcpiOsPrintf ("%c", Buffer[i]);
    180     }
    181 
    182     AcpiOsPrintf ("\"\n");
    183     return;
    184 
    185 DumpRawBuffer:
    186     AcpiDmDumpBuffer (Table, BufferOffset, ByteLength,
    187         BufferOffset, NULL);
    188     AcpiOsPrintf ("\n");
    189 }
    190 
    191 
    192 /*******************************************************************************
    193  *
    194  * FUNCTION:    AcpiDmDumpRsdp
    195  *
    196  * PARAMETERS:  Table               - A RSDP
    197  *
    198  * RETURN:      Length of the table (there is not always a length field,
    199  *              use revision or length if available (ACPI 2.0+))
    200  *
    201  * DESCRIPTION: Format the contents of a RSDP
    202  *
    203  ******************************************************************************/
    204 
    205 UINT32
    206 AcpiDmDumpRsdp (
    207     ACPI_TABLE_HEADER       *Table)
    208 {
    209     ACPI_TABLE_RSDP         *Rsdp = ACPI_CAST_PTR (ACPI_TABLE_RSDP, Table);
    210     UINT32                  Length = sizeof (ACPI_RSDP_COMMON);
    211     UINT8                   Checksum;
    212     ACPI_STATUS             Status;
    213 
    214 
    215     /* Dump the common ACPI 1.0 portion */
    216 
    217     Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp1);
    218     if (ACPI_FAILURE (Status))
    219     {
    220         return (Length);
    221     }
    222 
    223     /* Validate the first checksum */
    224 
    225     Checksum = AcpiUtGenerateChecksum (Rsdp, sizeof (ACPI_RSDP_COMMON),
    226         Rsdp->Checksum);
    227     if (Checksum != Rsdp->Checksum)
    228     {
    229         AcpiOsPrintf ("/* Incorrect Checksum above, should be 0x%2.2X */\n",
    230             Checksum);
    231     }
    232 
    233     /* The RSDP for ACPI 2.0+ contains more data and has a Length field */
    234 
    235     if (Rsdp->Revision > 0)
    236     {
    237         Length = Rsdp->Length;
    238         Status = AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoRsdp2);
    239         if (ACPI_FAILURE (Status))
    240         {
    241             return (Length);
    242         }
    243 
    244         /* Validate the extended checksum over entire RSDP */
    245 
    246         Checksum = AcpiUtGenerateChecksum (Rsdp, sizeof (ACPI_TABLE_RSDP),
    247             Rsdp->ExtendedChecksum);
    248         if (Checksum != Rsdp->ExtendedChecksum)
    249         {
    250             AcpiOsPrintf (
    251                 "/* Incorrect Extended Checksum above, should be 0x%2.2X */\n",
    252                 Checksum);
    253         }
    254     }
    255 
    256     return (Length);
    257 }
    258 
    259 
    260 /*******************************************************************************
    261  *
    262  * FUNCTION:    AcpiDmDumpRsdt
    263  *
    264  * PARAMETERS:  Table               - A RSDT
    265  *
    266  * RETURN:      None
    267  *
    268  * DESCRIPTION: Format the contents of a RSDT
    269  *
    270  ******************************************************************************/
    271 
    272 void
    273 AcpiDmDumpRsdt (
    274     ACPI_TABLE_HEADER       *Table)
    275 {
    276     UINT32                  *Array;
    277     UINT32                  Entries;
    278     UINT32                  Offset;
    279     UINT32                  i;
    280 
    281 
    282     /* Point to start of table pointer array */
    283 
    284     Array = ACPI_CAST_PTR (ACPI_TABLE_RSDT, Table)->TableOffsetEntry;
    285     Offset = sizeof (ACPI_TABLE_HEADER);
    286 
    287     /* RSDT uses 32-bit pointers */
    288 
    289     Entries = (Table->Length - sizeof (ACPI_TABLE_HEADER)) / sizeof (UINT32);
    290 
    291     for (i = 0; i < Entries; i++)
    292     {
    293         AcpiDmLineHeader2 (Offset, sizeof (UINT32), "ACPI Table Address", i);
    294         AcpiOsPrintf ("%8.8X\n", Array[i]);
    295         Offset += sizeof (UINT32);
    296     }
    297 }
    298 
    299 
    300 /*******************************************************************************
    301  *
    302  * FUNCTION:    AcpiDmDumpXsdt
    303  *
    304  * PARAMETERS:  Table               - A XSDT
    305  *
    306  * RETURN:      None
    307  *
    308  * DESCRIPTION: Format the contents of a XSDT
    309  *
    310  ******************************************************************************/
    311 
    312 void
    313 AcpiDmDumpXsdt (
    314     ACPI_TABLE_HEADER       *Table)
    315 {
    316     UINT64                  *Array;
    317     UINT32                  Entries;
    318     UINT32                  Offset;
    319     UINT32                  i;
    320 
    321 
    322     /* Point to start of table pointer array */
    323 
    324     Array = ACPI_CAST_PTR (ACPI_TABLE_XSDT, Table)->TableOffsetEntry;
    325     Offset = sizeof (ACPI_TABLE_HEADER);
    326 
    327     /* XSDT uses 64-bit pointers */
    328 
    329     Entries = (Table->Length - sizeof (ACPI_TABLE_HEADER)) / sizeof (UINT64);
    330 
    331     for (i = 0; i < Entries; i++)
    332     {
    333         AcpiDmLineHeader2 (Offset, sizeof (UINT64), "ACPI Table Address", i);
    334         AcpiOsPrintf ("%8.8X%8.8X\n", ACPI_FORMAT_UINT64 (Array[i]));
    335         Offset += sizeof (UINT64);
    336     }
    337 }
    338 
    339 
    340 /*******************************************************************************
    341  *
    342  * FUNCTION:    AcpiDmDumpFadt
    343  *
    344  * PARAMETERS:  Table               - A FADT
    345  *
    346  * RETURN:      None
    347  *
    348  * DESCRIPTION: Format the contents of a FADT
    349  *
    350  * NOTE:        We cannot depend on the FADT version to indicate the actual
    351  *              contents of the FADT because of BIOS bugs. The table length
    352  *              is the only reliable indicator.
    353  *
    354  ******************************************************************************/
    355 
    356 void
    357 AcpiDmDumpFadt (
    358     ACPI_TABLE_HEADER       *Table)
    359 {
    360     ACPI_STATUS             Status;
    361 
    362 
    363     /* Always dump the minimum FADT revision 1 fields (ACPI 1.0) */
    364 
    365     Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
    366         AcpiDmTableInfoFadt1);
    367     if (ACPI_FAILURE (Status))
    368     {
    369         return;
    370     }
    371 
    372     /* Check for FADT revision 2 fields (ACPI 1.0B MS extensions) */
    373 
    374     if ((Table->Length > ACPI_FADT_V1_SIZE) &&
    375         (Table->Length <= ACPI_FADT_V2_SIZE))
    376     {
    377         Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
    378             AcpiDmTableInfoFadt2);
    379         if (ACPI_FAILURE (Status))
    380         {
    381             return;
    382         }
    383     }
    384 
    385     /* Check for FADT revision 3/4 fields and up (ACPI 2.0+ extended data) */
    386 
    387     else if (Table->Length > ACPI_FADT_V2_SIZE)
    388     {
    389         Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
    390             AcpiDmTableInfoFadt3);
    391         if (ACPI_FAILURE (Status))
    392         {
    393             return;
    394         }
    395 
    396         /* Check for FADT revision 5 fields and up (ACPI 5.0+) */
    397 
    398         if (Table->Length > ACPI_FADT_V3_SIZE)
    399         {
    400             Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
    401                 AcpiDmTableInfoFadt5);
    402             if (ACPI_FAILURE (Status))
    403             {
    404                 return;
    405             }
    406         }
    407 
    408         /* Check for FADT revision 6 fields and up (ACPI 6.0+) */
    409 
    410         if (Table->Length > ACPI_FADT_V3_SIZE)
    411         {
    412             Status = AcpiDmDumpTable (Table->Length, 0, Table, 0,
    413                 AcpiDmTableInfoFadt6);
    414             if (ACPI_FAILURE (Status))
    415             {
    416                 return;
    417             }
    418         }
    419     }
    420 
    421     /* Validate various fields in the FADT, including length */
    422 
    423     AcpiTbCreateLocalFadt (Table, Table->Length);
    424 
    425     /* Validate FADT length against the revision */
    426 
    427     AcpiDmValidateFadtLength (Table->Revision, Table->Length);
    428 }
    429 
    430 
    431 /*******************************************************************************
    432  *
    433  * FUNCTION:    AcpiDmValidateFadtLength
    434  *
    435  * PARAMETERS:  Revision            - FADT revision (Header->Revision)
    436  *              Length              - FADT length (Header->Length
    437  *
    438  * RETURN:      None
    439  *
    440  * DESCRIPTION: Check the FADT revision against the expected table length for
    441  *              that revision. Issue a warning if the length is not what was
    442  *              expected. This seems to be such a common BIOS bug that the
    443  *              FADT revision has been rendered virtually meaningless.
    444  *
    445  ******************************************************************************/
    446 
    447 static void
    448 AcpiDmValidateFadtLength (
    449     UINT32                  Revision,
    450     UINT32                  Length)
    451 {
    452     UINT32                  ExpectedLength;
    453 
    454 
    455     switch (Revision)
    456     {
    457     case 0:
    458 
    459         AcpiOsPrintf ("// ACPI Warning: Invalid FADT revision: 0\n");
    460         return;
    461 
    462     case 1:
    463 
    464         ExpectedLength = ACPI_FADT_V1_SIZE;
    465         break;
    466 
    467     case 2:
    468 
    469         ExpectedLength = ACPI_FADT_V2_SIZE;
    470         break;
    471 
    472     case 3:
    473     case 4:
    474 
    475         ExpectedLength = ACPI_FADT_V3_SIZE;
    476         break;
    477 
    478     case 5:
    479 
    480         ExpectedLength = ACPI_FADT_V5_SIZE;
    481         break;
    482 
    483     default:
    484 
    485         return;
    486     }
    487 
    488     if (Length == ExpectedLength)
    489     {
    490         return;
    491     }
    492 
    493     AcpiOsPrintf (
    494         "\n// ACPI Warning: FADT revision %X does not match length: "
    495         "found %X expected %X\n",
    496         Revision, Length, ExpectedLength);
    497 }
    498