1 /******************************************************************************
   2  *
   3  * Module Name: apdump - Dump routines for ACPI tables (acpidump)
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 "acpidump.h"
  45 
  46 
  47 /* Local prototypes */
  48 
  49 static int
  50 ApDumpTableBuffer (
  51     ACPI_TABLE_HEADER       *Table,
  52     UINT32                  Instance,
  53     ACPI_PHYSICAL_ADDRESS   Address);
  54 
  55 
  56 /******************************************************************************
  57  *
  58  * FUNCTION:    ApIsValidHeader
  59  *
  60  * PARAMETERS:  Table               - Pointer to table to be validated
  61  *
  62  * RETURN:      TRUE if the header appears to be valid. FALSE otherwise
  63  *
  64  * DESCRIPTION: Check for a valid ACPI table header
  65  *
  66  ******************************************************************************/
  67 
  68 BOOLEAN
  69 ApIsValidHeader (
  70     ACPI_TABLE_HEADER       *Table)
  71 {
  72     if (!ACPI_VALIDATE_RSDP_SIG (Table->Signature))
  73     {
  74         /* Make sure signature is all ASCII and a valid ACPI name */
  75 
  76         if (!AcpiUtValidAcpiName (Table->Signature))
  77         {
  78             fprintf (stderr, "Table signature (0x%8.8X) is invalid\n",
  79                 *(UINT32 *) Table->Signature);
  80             return (FALSE);
  81         }
  82 
  83         /* Check for minimum table length */
  84 
  85         if (Table->Length < sizeof (ACPI_TABLE_HEADER))
  86         {
  87             fprintf (stderr, "Table length (0x%8.8X) is invalid\n",
  88                 Table->Length);
  89             return (FALSE);
  90         }
  91     }
  92 
  93     return (TRUE);
  94 }
  95 
  96 
  97 /******************************************************************************
  98  *
  99  * FUNCTION:    ApIsValidChecksum
 100  *
 101  * PARAMETERS:  Table               - Pointer to table to be validated
 102  *
 103  * RETURN:      TRUE if the checksum appears to be valid. FALSE otherwise
 104  *
 105  * DESCRIPTION: Check for a valid ACPI table checksum
 106  *
 107  ******************************************************************************/
 108 
 109 BOOLEAN
 110 ApIsValidChecksum (
 111     ACPI_TABLE_HEADER       *Table)
 112 {
 113     ACPI_STATUS             Status;
 114     ACPI_TABLE_RSDP         *Rsdp;
 115 
 116 
 117     if (ACPI_VALIDATE_RSDP_SIG (Table->Signature))
 118     {
 119         /*
 120          * Checksum for RSDP.
 121          * Note: Other checksums are computed during the table dump.
 122          */
 123 
 124         Rsdp = ACPI_CAST_PTR (ACPI_TABLE_RSDP, Table);
 125         Status = AcpiTbValidateRsdp (Rsdp);
 126     }
 127     else
 128     {
 129         Status = AcpiTbVerifyChecksum (Table, Table->Length);
 130     }
 131 
 132     if (ACPI_FAILURE (Status))
 133     {
 134         fprintf (stderr, "%4.4s: Warning: wrong checksum\n",
 135             Table->Signature);
 136     }
 137 
 138     return (AE_OK);
 139 }
 140 
 141 
 142 /******************************************************************************
 143  *
 144  * FUNCTION:    ApGetTableLength
 145  *
 146  * PARAMETERS:  Table               - Pointer to the table
 147  *
 148  * RETURN:      Table length
 149  *
 150  * DESCRIPTION: Obtain table length according to table signature
 151  *
 152  ******************************************************************************/
 153 
 154 UINT32
 155 ApGetTableLength (
 156     ACPI_TABLE_HEADER       *Table)
 157 {
 158     ACPI_TABLE_RSDP         *Rsdp;
 159 
 160 
 161     /* Check if table is valid */
 162 
 163     if (!ApIsValidHeader (Table))
 164     {
 165         return (0);
 166     }
 167 
 168     if (ACPI_VALIDATE_RSDP_SIG (Table->Signature))
 169     {
 170         Rsdp = ACPI_CAST_PTR (ACPI_TABLE_RSDP, Table);
 171         return (Rsdp->Length);
 172     }
 173     else
 174     {
 175         return (Table->Length);
 176     }
 177 }
 178 
 179 
 180 /******************************************************************************
 181  *
 182  * FUNCTION:    ApDumpTableBuffer
 183  *
 184  * PARAMETERS:  Table               - ACPI table to be dumped
 185  *              Instance            - ACPI table instance no. to be dumped
 186  *              Address             - Physical address of the table
 187  *
 188  * RETURN:      None
 189  *
 190  * DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a
 191  *              header that is compatible with the AcpiXtract utility.
 192  *
 193  ******************************************************************************/
 194 
 195 static int
 196 ApDumpTableBuffer (
 197     ACPI_TABLE_HEADER       *Table,
 198     UINT32                  Instance,
 199     ACPI_PHYSICAL_ADDRESS   Address)
 200 {
 201     UINT32                  TableLength;
 202 
 203 
 204     TableLength = ApGetTableLength (Table);
 205 
 206     /* Print only the header if requested */
 207 
 208     if (Gbl_SummaryMode)
 209     {
 210         AcpiTbPrintTableHeader (Address, Table);
 211         return (0);
 212     }
 213 
 214     /* Dump to binary file if requested */
 215 
 216     if (Gbl_BinaryMode)
 217     {
 218         return (ApWriteToBinaryFile (Table, Instance));
 219     }
 220 
 221     /*
 222      * Dump the table with header for use with acpixtract utility
 223      * Note: simplest to just always emit a 64-bit address. AcpiXtract
 224      * utility can handle this.
 225      */
 226     printf ("%4.4s @ 0x%8.8X%8.8X\n", Table->Signature,
 227         ACPI_FORMAT_UINT64 (Address));
 228 
 229     AcpiUtDumpBuffer (ACPI_CAST_PTR (UINT8, Table), TableLength,
 230         DB_BYTE_DISPLAY, 0);
 231     printf ("\n");
 232     return (0);
 233 }
 234 
 235 
 236 /******************************************************************************
 237  *
 238  * FUNCTION:    ApDumpAllTables
 239  *
 240  * PARAMETERS:  None
 241  *
 242  * RETURN:      Status
 243  *
 244  * DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the
 245  *              tables that we can possibly get).
 246  *
 247  ******************************************************************************/
 248 
 249 int
 250 ApDumpAllTables (
 251     void)
 252 {
 253     ACPI_TABLE_HEADER       *Table;
 254     UINT32                  Instance = 0;
 255     ACPI_PHYSICAL_ADDRESS   Address;
 256     ACPI_STATUS             Status;
 257     UINT32                  i;
 258 
 259 
 260     /* Get and dump all available ACPI tables */
 261 
 262     for (i = 0; i < AP_MAX_ACPI_FILES; i++)
 263     {
 264         Status = AcpiOsGetTableByIndex (i, &Table, &Instance, &Address);
 265         if (ACPI_FAILURE (Status))
 266         {
 267             /* AE_LIMIT means that no more tables are available */
 268 
 269             if (Status == AE_LIMIT)
 270             {
 271                 return (0);
 272             }
 273             else if (i == 0)
 274             {
 275                 fprintf (stderr, "Could not get ACPI tables, %s\n",
 276                     AcpiFormatException (Status));
 277                 return (-1);
 278             }
 279             else
 280             {
 281                 fprintf (stderr, "Could not get ACPI table at index %u, %s\n",
 282                     i, AcpiFormatException (Status));
 283                 continue;
 284             }
 285         }
 286 
 287         if (ApDumpTableBuffer (Table, Instance, Address))
 288         {
 289             return (-1);
 290         }
 291         free (Table);
 292     }
 293 
 294     /* Something seriously bad happened if the loop terminates here */
 295 
 296     return (-1);
 297 }
 298 
 299 
 300 /******************************************************************************
 301  *
 302  * FUNCTION:    ApDumpTableByAddress
 303  *
 304  * PARAMETERS:  AsciiAddress        - Address for requested ACPI table
 305  *
 306  * RETURN:      Status
 307  *
 308  * DESCRIPTION: Get an ACPI table via a physical address and dump it.
 309  *
 310  ******************************************************************************/
 311 
 312 int
 313 ApDumpTableByAddress (
 314     char                    *AsciiAddress)
 315 {
 316     ACPI_PHYSICAL_ADDRESS   Address;
 317     ACPI_TABLE_HEADER       *Table;
 318     ACPI_STATUS             Status;
 319     int                     TableStatus;
 320     UINT64                  LongAddress;
 321 
 322 
 323     /* Convert argument to an integer physical address */
 324 
 325     Status = AcpiUtStrtoul64 (AsciiAddress, 0, &LongAddress);
 326     if (ACPI_FAILURE (Status))
 327     {
 328         fprintf (stderr, "%s: Could not convert to a physical address\n",
 329             AsciiAddress);
 330         return (-1);
 331     }
 332 
 333     Address = (ACPI_PHYSICAL_ADDRESS) LongAddress;
 334     Status = AcpiOsGetTableByAddress (Address, &Table);
 335     if (ACPI_FAILURE (Status))
 336     {
 337         fprintf (stderr, "Could not get table at 0x%8.8X%8.8X, %s\n",
 338             ACPI_FORMAT_UINT64 (Address),
 339             AcpiFormatException (Status));
 340         return (-1);
 341     }
 342 
 343     TableStatus = ApDumpTableBuffer (Table, 0, Address);
 344     free (Table);
 345     return (TableStatus);
 346 }
 347 
 348 
 349 /******************************************************************************
 350  *
 351  * FUNCTION:    ApDumpTableByName
 352  *
 353  * PARAMETERS:  Signature           - Requested ACPI table signature
 354  *
 355  * RETURN:      Status
 356  *
 357  * DESCRIPTION: Get an ACPI table via a signature and dump it. Handles
 358  *              multiple tables with the same signature (SSDTs).
 359  *
 360  ******************************************************************************/
 361 
 362 int
 363 ApDumpTableByName (
 364     char                    *Signature)
 365 {
 366     char                    LocalSignature [ACPI_NAME_SIZE + 1];
 367     UINT32                  Instance;
 368     ACPI_TABLE_HEADER       *Table;
 369     ACPI_PHYSICAL_ADDRESS   Address;
 370     ACPI_STATUS             Status;
 371 
 372 
 373     if (strlen (Signature) != ACPI_NAME_SIZE)
 374     {
 375         fprintf (stderr,
 376             "Invalid table signature [%s]: must be exactly 4 characters\n",
 377             Signature);
 378         return (-1);
 379     }
 380 
 381     /* Table signatures are expected to be uppercase */
 382 
 383     strcpy (LocalSignature, Signature);
 384     AcpiUtStrupr (LocalSignature);
 385 
 386     /* To be friendly, handle tables whose signatures do not match the name */
 387 
 388     if (ACPI_COMPARE_NAME (LocalSignature, "FADT"))
 389     {
 390         strcpy (LocalSignature, ACPI_SIG_FADT);
 391     }
 392     else if (ACPI_COMPARE_NAME (LocalSignature, "MADT"))
 393     {
 394         strcpy (LocalSignature, ACPI_SIG_MADT);
 395     }
 396 
 397     /* Dump all instances of this signature (to handle multiple SSDTs) */
 398 
 399     for (Instance = 0; Instance < AP_MAX_ACPI_FILES; Instance++)
 400     {
 401         Status = AcpiOsGetTableByName (LocalSignature, Instance,
 402             &Table, &Address);
 403         if (ACPI_FAILURE (Status))
 404         {
 405             /* AE_LIMIT means that no more tables are available */
 406 
 407             if (Status == AE_LIMIT)
 408             {
 409                 return (0);
 410             }
 411 
 412             fprintf (stderr,
 413                 "Could not get ACPI table with signature [%s], %s\n",
 414                 LocalSignature, AcpiFormatException (Status));
 415             return (-1);
 416         }
 417 
 418         if (ApDumpTableBuffer (Table, Instance, Address))
 419         {
 420             return (-1);
 421         }
 422         free (Table);
 423     }
 424 
 425     /* Something seriously bad happened if the loop terminates here */
 426 
 427     return (-1);
 428 }
 429 
 430 
 431 /******************************************************************************
 432  *
 433  * FUNCTION:    ApDumpTableFromFile
 434  *
 435  * PARAMETERS:  Pathname            - File containing the binary ACPI table
 436  *
 437  * RETURN:      Status
 438  *
 439  * DESCRIPTION: Dump an ACPI table from a binary file
 440  *
 441  ******************************************************************************/
 442 
 443 int
 444 ApDumpTableFromFile (
 445     char                    *Pathname)
 446 {
 447     ACPI_TABLE_HEADER       *Table;
 448     UINT32                  FileSize = 0;
 449     int                     TableStatus;
 450 
 451 
 452     /* Get the entire ACPI table from the file */
 453 
 454     Table = ApGetTableFromFile (Pathname, &FileSize);
 455     if (!Table)
 456     {
 457         return (-1);
 458     }
 459 
 460     /* File must be at least as long as the table length */
 461 
 462     if (Table->Length > FileSize)
 463     {
 464         fprintf (stderr,
 465             "Table length (0x%X) is too large for input file (0x%X) %s\n",
 466             Table->Length, FileSize, Pathname);
 467         return (-1);
 468     }
 469 
 470     if (Gbl_VerboseMode)
 471     {
 472         fprintf (stderr,
 473             "Input file:  %s contains table [%4.4s], 0x%X (%u) bytes\n",
 474             Pathname, Table->Signature, FileSize, FileSize);
 475     }
 476 
 477     TableStatus = ApDumpTableBuffer (Table, 0, 0);
 478     free (Table);
 479     return (TableStatus);
 480 }
 481 
 482 
 483 /******************************************************************************
 484  *
 485  * FUNCTION:    AcpiOs* print functions
 486  *
 487  * DESCRIPTION: Used for linkage with ACPICA modules
 488  *
 489  ******************************************************************************/
 490 
 491 void ACPI_INTERNAL_VAR_XFACE
 492 AcpiOsPrintf (
 493     const char              *Fmt,
 494     ...)
 495 {
 496     va_list                 Args;
 497 
 498     va_start (Args, Fmt);
 499     vfprintf (stdout, Fmt, Args);
 500     va_end (Args);
 501 }
 502 
 503 void
 504 AcpiOsVprintf (
 505     const char              *Fmt,
 506     va_list                 Args)
 507 {
 508     vfprintf (stdout, Fmt, Args);
 509 }