1 /*******************************************************************************
   2  *
   3  * Module Name: dbfileio - Debugger file I/O commands. These can't usually
   4  *              be used when running the debugger in Ring 0 (Kernel mode)
   5  *
   6  ******************************************************************************/
   7 
   8 /*
   9  * Copyright (C) 2000 - 2011, Intel Corp.
  10  * All rights reserved.
  11  *
  12  * Redistribution and use in source and binary forms, with or without
  13  * modification, are permitted provided that the following conditions
  14  * are met:
  15  * 1. Redistributions of source code must retain the above copyright
  16  *    notice, this list of conditions, and the following disclaimer,
  17  *    without modification.
  18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  19  *    substantially similar to the "NO WARRANTY" disclaimer below
  20  *    ("Disclaimer") and any redistribution must be conditioned upon
  21  *    including a substantially similar Disclaimer requirement for further
  22  *    binary redistribution.
  23  * 3. Neither the names of the above-listed copyright holders nor the names
  24  *    of any contributors may be used to endorse or promote products derived
  25  *    from this software without specific prior written permission.
  26  *
  27  * Alternatively, this software may be distributed under the terms of the
  28  * GNU General Public License ("GPL") version 2 as published by the Free
  29  * Software Foundation.
  30  *
  31  * NO WARRANTY
  32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42  * POSSIBILITY OF SUCH DAMAGES.
  43  */
  44 
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acdebug.h"
  49 
  50 #ifdef ACPI_APPLICATION
  51 #include "actables.h"
  52 #endif
  53 
  54 #if (defined ACPI_DEBUGGER || defined ACPI_DISASSEMBLER)
  55 
  56 #define _COMPONENT          ACPI_CA_DEBUGGER
  57         ACPI_MODULE_NAME    ("dbfileio")
  58 
  59 /*
  60  * NOTE: this is here for lack of a better place. It is used in all
  61  * flavors of the debugger, need LCD file
  62  */
  63 #ifdef ACPI_APPLICATION
  64 #include <stdio.h>
  65 FILE                        *AcpiGbl_DebugFile = NULL;
  66 #endif
  67 
  68 
  69 #ifdef ACPI_DEBUGGER
  70 
  71 /* Local prototypes */
  72 
  73 #ifdef ACPI_APPLICATION
  74 
  75 static ACPI_STATUS
  76 AcpiDbCheckTextModeCorruption (
  77     UINT8                   *Table,
  78     UINT32                  TableLength,
  79     UINT32                  FileLength);
  80 
  81 #endif
  82 
  83 /*******************************************************************************
  84  *
  85  * FUNCTION:    AcpiDbCloseDebugFile
  86  *
  87  * PARAMETERS:  None
  88  *
  89  * RETURN:      None
  90  *
  91  * DESCRIPTION: If open, close the current debug output file
  92  *
  93  ******************************************************************************/
  94 
  95 void
  96 AcpiDbCloseDebugFile (
  97     void)
  98 {
  99 
 100 #ifdef ACPI_APPLICATION
 101 
 102     if (AcpiGbl_DebugFile)
 103     {
 104        fclose (AcpiGbl_DebugFile);
 105        AcpiGbl_DebugFile = NULL;
 106        AcpiGbl_DbOutputToFile = FALSE;
 107        AcpiOsPrintf ("Debug output file %s closed\n", AcpiGbl_DbDebugFilename);
 108     }
 109 #endif
 110 }
 111 
 112 
 113 /*******************************************************************************
 114  *
 115  * FUNCTION:    AcpiDbOpenDebugFile
 116  *
 117  * PARAMETERS:  Name                - Filename to open
 118  *
 119  * RETURN:      None
 120  *
 121  * DESCRIPTION: Open a file where debug output will be directed.
 122  *
 123  ******************************************************************************/
 124 
 125 void
 126 AcpiDbOpenDebugFile (
 127     char                    *Name)
 128 {
 129 
 130 #ifdef ACPI_APPLICATION
 131 
 132     AcpiDbCloseDebugFile ();
 133     AcpiGbl_DebugFile = fopen (Name, "w+");
 134     if (AcpiGbl_DebugFile)
 135     {
 136         AcpiOsPrintf ("Debug output file %s opened\n", Name);
 137         ACPI_STRCPY (AcpiGbl_DbDebugFilename, Name);
 138         AcpiGbl_DbOutputToFile = TRUE;
 139     }
 140     else
 141     {
 142         AcpiOsPrintf ("Could not open debug file %s\n", Name);
 143     }
 144 
 145 #endif
 146 }
 147 #endif
 148 
 149 
 150 #ifdef ACPI_APPLICATION
 151 /*******************************************************************************
 152  *
 153  * FUNCTION:    AcpiDbCheckTextModeCorruption
 154  *
 155  * PARAMETERS:  Table           - Table buffer
 156  *              TableLength     - Length of table from the table header
 157  *              FileLength      - Length of the file that contains the table
 158  *
 159  * RETURN:      Status
 160  *
 161  * DESCRIPTION: Check table for text mode file corruption where all linefeed
 162  *              characters (LF) have been replaced by carriage return linefeed
 163  *              pairs (CR/LF).
 164  *
 165  ******************************************************************************/
 166 
 167 static ACPI_STATUS
 168 AcpiDbCheckTextModeCorruption (
 169     UINT8                   *Table,
 170     UINT32                  TableLength,
 171     UINT32                  FileLength)
 172 {
 173     UINT32                  i;
 174     UINT32                  Pairs = 0;
 175 
 176 
 177     if (TableLength != FileLength)
 178     {
 179         ACPI_WARNING ((AE_INFO,
 180             "File length (0x%X) is not the same as the table length (0x%X)",
 181             FileLength, TableLength));
 182     }
 183 
 184     /* Scan entire table to determine if each LF has been prefixed with a CR */
 185 
 186     for (i = 1; i < FileLength; i++)
 187     {
 188         if (Table[i] == 0x0A)
 189         {
 190             if (Table[i - 1] != 0x0D)
 191             {
 192                 /* The LF does not have a preceding CR, table not corrupted */
 193 
 194                 return (AE_OK);
 195             }
 196             else
 197             {
 198                 /* Found a CR/LF pair */
 199 
 200                 Pairs++;
 201             }
 202             i++;
 203         }
 204     }
 205 
 206     if (!Pairs)
 207     {
 208         return (AE_OK);
 209     }
 210 
 211     /*
 212      * Entire table scanned, each CR is part of a CR/LF pair --
 213      * meaning that the table was treated as a text file somewhere.
 214      *
 215      * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the
 216      * original table are left untouched by the text conversion process --
 217      * meaning that we cannot simply replace CR/LF pairs with LFs.
 218      */
 219     AcpiOsPrintf ("Table has been corrupted by text mode conversion\n");
 220     AcpiOsPrintf ("All LFs (%u) were changed to CR/LF pairs\n", Pairs);
 221     AcpiOsPrintf ("Table cannot be repaired!\n");
 222     return (AE_BAD_VALUE);
 223 }
 224 
 225 
 226 /*******************************************************************************
 227  *
 228  * FUNCTION:    AcpiDbReadTable
 229  *
 230  * PARAMETERS:  fp              - File that contains table
 231  *              Table           - Return value, buffer with table
 232  *              TableLength     - Return value, length of table
 233  *
 234  * RETURN:      Status
 235  *
 236  * DESCRIPTION: Load the DSDT from the file pointer
 237  *
 238  ******************************************************************************/
 239 
 240 static ACPI_STATUS
 241 AcpiDbReadTable (
 242     FILE                    *fp,
 243     ACPI_TABLE_HEADER       **Table,
 244     UINT32                  *TableLength)
 245 {
 246     ACPI_TABLE_HEADER       TableHeader;
 247     UINT32                  Actual;
 248     ACPI_STATUS             Status;
 249     UINT32                  FileSize;
 250     BOOLEAN                 StandardHeader = TRUE;
 251 
 252 
 253     /* Get the file size */
 254 
 255     fseek (fp, 0, SEEK_END);
 256     FileSize = (UINT32) ftell (fp);
 257     fseek (fp, 0, SEEK_SET);
 258 
 259     if (FileSize < 4)
 260     {
 261         return (AE_BAD_HEADER);
 262     }
 263 
 264     /* Read the signature */
 265 
 266     if (fread (&TableHeader, 1, 4, fp) != 4)
 267     {
 268         AcpiOsPrintf ("Could not read the table signature\n");
 269         return (AE_BAD_HEADER);
 270     }
 271 
 272     fseek (fp, 0, SEEK_SET);
 273 
 274     /* The RSDT and FACS tables do not have standard ACPI headers */
 275 
 276     if (ACPI_COMPARE_NAME (TableHeader.Signature, "RSD ") ||
 277         ACPI_COMPARE_NAME (TableHeader.Signature, "FACS"))
 278     {
 279         *TableLength = FileSize;
 280         StandardHeader = FALSE;
 281     }
 282     else
 283     {
 284         /* Read the table header */
 285 
 286         if (fread (&TableHeader, 1, sizeof (TableHeader), fp) !=
 287                 sizeof (ACPI_TABLE_HEADER))
 288         {
 289             AcpiOsPrintf ("Could not read the table header\n");
 290             return (AE_BAD_HEADER);
 291         }
 292 
 293 #if 0
 294         /* Validate the table header/length */
 295 
 296         Status = AcpiTbValidateTableHeader (&TableHeader);
 297         if (ACPI_FAILURE (Status))
 298         {
 299             AcpiOsPrintf ("Table header is invalid!\n");
 300             return (Status);
 301         }
 302 #endif
 303 
 304         /* File size must be at least as long as the Header-specified length */
 305 
 306         if (TableHeader.Length > FileSize)
 307         {
 308             AcpiOsPrintf (
 309                 "TableHeader length [0x%X] greater than the input file size [0x%X]\n",
 310                 TableHeader.Length, FileSize);
 311             return (AE_BAD_HEADER);
 312         }
 313 
 314 #ifdef ACPI_OBSOLETE_CODE
 315         /* We only support a limited number of table types */
 316 
 317         if (ACPI_STRNCMP ((char *) TableHeader.Signature, DSDT_SIG, 4) &&
 318             ACPI_STRNCMP ((char *) TableHeader.Signature, PSDT_SIG, 4) &&
 319             ACPI_STRNCMP ((char *) TableHeader.Signature, SSDT_SIG, 4))
 320         {
 321             AcpiOsPrintf ("Table signature [%4.4s] is invalid or not supported\n",
 322                 (char *) TableHeader.Signature);
 323             ACPI_DUMP_BUFFER (&TableHeader, sizeof (ACPI_TABLE_HEADER));
 324             return (AE_ERROR);
 325         }
 326 #endif
 327 
 328         *TableLength = TableHeader.Length;
 329     }
 330 
 331     /* Allocate a buffer for the table */
 332 
 333     *Table = AcpiOsAllocate ((size_t) FileSize);
 334     if (!*Table)
 335     {
 336         AcpiOsPrintf (
 337             "Could not allocate memory for ACPI table %4.4s (size=0x%X)\n",
 338             TableHeader.Signature, *TableLength);
 339         return (AE_NO_MEMORY);
 340     }
 341 
 342     /* Get the rest of the table */
 343 
 344     fseek (fp, 0, SEEK_SET);
 345     Actual = fread (*Table, 1, (size_t) FileSize, fp);
 346     if (Actual == FileSize)
 347     {
 348         if (StandardHeader)
 349         {
 350             /* Now validate the checksum */
 351 
 352             Status = AcpiTbVerifyChecksum ((void *) *Table,
 353                         ACPI_CAST_PTR (ACPI_TABLE_HEADER, *Table)->Length);
 354 
 355             if (Status == AE_BAD_CHECKSUM)
 356             {
 357                 Status = AcpiDbCheckTextModeCorruption ((UINT8 *) *Table,
 358                             FileSize, (*Table)->Length);
 359                 return (Status);
 360             }
 361         }
 362         return (AE_OK);
 363     }
 364 
 365     if (Actual > 0)
 366     {
 367         AcpiOsPrintf ("Warning - reading table, asked for %X got %X\n",
 368             FileSize, Actual);
 369         return (AE_OK);
 370     }
 371 
 372     AcpiOsPrintf ("Error - could not read the table file\n");
 373     AcpiOsFree (*Table);
 374     *Table = NULL;
 375     *TableLength = 0;
 376 
 377     return (AE_ERROR);
 378 }
 379 
 380 
 381 /*******************************************************************************
 382  *
 383  * FUNCTION:    AeLocalLoadTable
 384  *
 385  * PARAMETERS:  Table           - pointer to a buffer containing the entire
 386  *                                table to be loaded
 387  *
 388  * RETURN:      Status
 389  *
 390  * DESCRIPTION: This function is called to load a table from the caller's
 391  *              buffer. The buffer must contain an entire ACPI Table including
 392  *              a valid header. The header fields will be verified, and if it
 393  *              is determined that the table is invalid, the call will fail.
 394  *
 395  ******************************************************************************/
 396 
 397 static ACPI_STATUS
 398 AeLocalLoadTable (
 399     ACPI_TABLE_HEADER       *Table)
 400 {
 401     ACPI_STATUS             Status = AE_OK;
 402 /*    ACPI_TABLE_DESC         TableInfo; */
 403 
 404 
 405     ACPI_FUNCTION_TRACE (AeLocalLoadTable);
 406 #if 0
 407 
 408 
 409     if (!Table)
 410     {
 411         return_ACPI_STATUS (AE_BAD_PARAMETER);
 412     }
 413 
 414     TableInfo.Pointer = Table;
 415     Status = AcpiTbRecognizeTable (&TableInfo, ACPI_TABLE_ALL);
 416     if (ACPI_FAILURE (Status))
 417     {
 418         return_ACPI_STATUS (Status);
 419     }
 420 
 421     /* Install the new table into the local data structures */
 422 
 423     Status = AcpiTbInstallTable (&TableInfo);
 424     if (ACPI_FAILURE (Status))
 425     {
 426         if (Status == AE_ALREADY_EXISTS)
 427         {
 428             /* Table already exists, no error */
 429 
 430             Status = AE_OK;
 431         }
 432 
 433         /* Free table allocated by AcpiTbGetTable */
 434 
 435         AcpiTbDeleteSingleTable (&TableInfo);
 436         return_ACPI_STATUS (Status);
 437     }
 438 
 439 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
 440 
 441     Status = AcpiNsLoadTable (TableInfo.InstalledDesc, AcpiGbl_RootNode);
 442     if (ACPI_FAILURE (Status))
 443     {
 444         /* Uninstall table and free the buffer */
 445 
 446         AcpiTbDeleteTablesByType (ACPI_TABLE_ID_DSDT);
 447         return_ACPI_STATUS (Status);
 448     }
 449 #endif
 450 #endif
 451 
 452     return_ACPI_STATUS (Status);
 453 }
 454 
 455 
 456 /*******************************************************************************
 457  *
 458  * FUNCTION:    AcpiDbReadTableFromFile
 459  *
 460  * PARAMETERS:  Filename         - File where table is located
 461  *              Table            - Where a pointer to the table is returned
 462  *
 463  * RETURN:      Status
 464  *
 465  * DESCRIPTION: Get an ACPI table from a file
 466  *
 467  ******************************************************************************/
 468 
 469 ACPI_STATUS
 470 AcpiDbReadTableFromFile (
 471     char                    *Filename,
 472     ACPI_TABLE_HEADER       **Table)
 473 {
 474     FILE                    *fp;
 475     UINT32                  TableLength;
 476     ACPI_STATUS             Status;
 477 
 478 
 479     /* Open the file */
 480 
 481     fp = fopen (Filename, "rb");
 482     if (!fp)
 483     {
 484         AcpiOsPrintf ("Could not open input file %s\n", Filename);
 485         return (AE_ERROR);
 486     }
 487 
 488     /* Get the entire file */
 489 
 490     fprintf (stderr, "Loading Acpi table from file %s\n", Filename);
 491     Status = AcpiDbReadTable (fp, Table, &TableLength);
 492     fclose(fp);
 493 
 494     if (ACPI_FAILURE (Status))
 495     {
 496         AcpiOsPrintf ("Could not get table from the file\n");
 497         return (Status);
 498     }
 499 
 500     return (AE_OK);
 501  }
 502 #endif
 503 
 504 
 505 /*******************************************************************************
 506  *
 507  * FUNCTION:    AcpiDbGetTableFromFile
 508  *
 509  * PARAMETERS:  Filename        - File where table is located
 510  *              ReturnTable     - Where a pointer to the table is returned
 511  *
 512  * RETURN:      Status
 513  *
 514  * DESCRIPTION: Load an ACPI table from a file
 515  *
 516  ******************************************************************************/
 517 
 518 ACPI_STATUS
 519 AcpiDbGetTableFromFile (
 520     char                    *Filename,
 521     ACPI_TABLE_HEADER       **ReturnTable)
 522 {
 523 #ifdef ACPI_APPLICATION
 524     ACPI_STATUS             Status;
 525     ACPI_TABLE_HEADER       *Table;
 526     BOOLEAN                 IsAmlTable = TRUE;
 527 
 528 
 529     Status = AcpiDbReadTableFromFile (Filename, &Table);
 530     if (ACPI_FAILURE (Status))
 531     {
 532         return (Status);
 533     }
 534 
 535 #ifdef ACPI_DATA_TABLE_DISASSEMBLY
 536     IsAmlTable = AcpiUtIsAmlTable (Table);
 537 #endif
 538 
 539     if (IsAmlTable)
 540     {
 541         /* Attempt to recognize and install the table */
 542 
 543         Status = AeLocalLoadTable (Table);
 544         if (ACPI_FAILURE (Status))
 545         {
 546             if (Status == AE_ALREADY_EXISTS)
 547             {
 548                 AcpiOsPrintf ("Table %4.4s is already installed\n",
 549                     Table->Signature);
 550             }
 551             else
 552             {
 553                 AcpiOsPrintf ("Could not install table, %s\n",
 554                     AcpiFormatException (Status));
 555             }
 556 
 557             return (Status);
 558         }
 559 
 560         fprintf (stderr,
 561             "Acpi table [%4.4s] successfully installed and loaded\n",
 562             Table->Signature);
 563     }
 564 
 565     AcpiGbl_AcpiHardwarePresent = FALSE;
 566     if (ReturnTable)
 567     {
 568         *ReturnTable = Table;
 569     }
 570 
 571 
 572 #endif  /* ACPI_APPLICATION */
 573     return (AE_OK);
 574 }
 575 
 576 #endif  /* ACPI_DEBUGGER */
 577