linux/drivers/acpi/acpica/utfileio.c
<<
>>
Prefs
   1/*******************************************************************************
   2 *
   3 * Module Name: utfileio - simple file I/O routines
   4 *
   5 ******************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2015, 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 <acpi/acpi.h>
  45#include "accommon.h"
  46#include "actables.h"
  47#include "acapps.h"
  48
  49#ifdef ACPI_ASL_COMPILER
  50#include "aslcompiler.h"
  51#endif
  52
  53#define _COMPONENT          ACPI_CA_DEBUGGER
  54ACPI_MODULE_NAME("utfileio")
  55
  56#ifdef ACPI_APPLICATION
  57/* Local prototypes */
  58static acpi_status
  59acpi_ut_check_text_mode_corruption(u8 *table,
  60                                   u32 table_length, u32 file_length);
  61
  62static acpi_status
  63acpi_ut_read_table(FILE * fp,
  64                   struct acpi_table_header **table, u32 *table_length);
  65
  66/*******************************************************************************
  67 *
  68 * FUNCTION:    acpi_ut_check_text_mode_corruption
  69 *
  70 * PARAMETERS:  table           - Table buffer
  71 *              table_length    - Length of table from the table header
  72 *              file_length     - Length of the file that contains the table
  73 *
  74 * RETURN:      Status
  75 *
  76 * DESCRIPTION: Check table for text mode file corruption where all linefeed
  77 *              characters (LF) have been replaced by carriage return linefeed
  78 *              pairs (CR/LF).
  79 *
  80 ******************************************************************************/
  81
  82static acpi_status
  83acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length)
  84{
  85        u32 i;
  86        u32 pairs = 0;
  87
  88        if (table_length != file_length) {
  89                ACPI_WARNING((AE_INFO,
  90                              "File length (0x%X) is not the same as the table length (0x%X)",
  91                              file_length, table_length));
  92        }
  93
  94        /* Scan entire table to determine if each LF has been prefixed with a CR */
  95
  96        for (i = 1; i < file_length; i++) {
  97                if (table[i] == 0x0A) {
  98                        if (table[i - 1] != 0x0D) {
  99
 100                                /* The LF does not have a preceding CR, table not corrupted */
 101
 102                                return (AE_OK);
 103                        } else {
 104                                /* Found a CR/LF pair */
 105
 106                                pairs++;
 107                        }
 108                        i++;
 109                }
 110        }
 111
 112        if (!pairs) {
 113                return (AE_OK);
 114        }
 115
 116        /*
 117         * Entire table scanned, each CR is part of a CR/LF pair --
 118         * meaning that the table was treated as a text file somewhere.
 119         *
 120         * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the
 121         * original table are left untouched by the text conversion process --
 122         * meaning that we cannot simply replace CR/LF pairs with LFs.
 123         */
 124        acpi_os_printf("Table has been corrupted by text mode conversion\n");
 125        acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs);
 126        acpi_os_printf("Table cannot be repaired!\n");
 127        return (AE_BAD_VALUE);
 128}
 129
 130/*******************************************************************************
 131 *
 132 * FUNCTION:    acpi_ut_read_table
 133 *
 134 * PARAMETERS:  fp              - File that contains table
 135 *              table           - Return value, buffer with table
 136 *              table_length    - Return value, length of table
 137 *
 138 * RETURN:      Status
 139 *
 140 * DESCRIPTION: Load the DSDT from the file pointer
 141 *
 142 ******************************************************************************/
 143
 144static acpi_status
 145acpi_ut_read_table(FILE * fp,
 146                   struct acpi_table_header **table, u32 *table_length)
 147{
 148        struct acpi_table_header table_header;
 149        u32 actual;
 150        acpi_status status;
 151        u32 file_size;
 152        u8 standard_header = TRUE;
 153        s32 count;
 154
 155        /* Get the file size */
 156
 157        file_size = cm_get_file_size(fp);
 158        if (file_size == ACPI_UINT32_MAX) {
 159                return (AE_ERROR);
 160        }
 161
 162        if (file_size < 4) {
 163                return (AE_BAD_HEADER);
 164        }
 165
 166        /* Read the signature */
 167
 168        fseek(fp, 0, SEEK_SET);
 169
 170        count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
 171        if (count != sizeof(struct acpi_table_header)) {
 172                acpi_os_printf("Could not read the table header\n");
 173                return (AE_BAD_HEADER);
 174        }
 175
 176        /* The RSDP table does not have standard ACPI header */
 177
 178        if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) {
 179                *table_length = file_size;
 180                standard_header = FALSE;
 181        } else {
 182
 183#if 0
 184                /* Validate the table header/length */
 185
 186                status = acpi_tb_validate_table_header(&table_header);
 187                if (ACPI_FAILURE(status)) {
 188                        acpi_os_printf("Table header is invalid!\n");
 189                        return (status);
 190                }
 191#endif
 192
 193                /* File size must be at least as long as the Header-specified length */
 194
 195                if (table_header.length > file_size) {
 196                        acpi_os_printf
 197                            ("TableHeader length [0x%X] greater than the input file size [0x%X]\n",
 198                             table_header.length, file_size);
 199
 200#ifdef ACPI_ASL_COMPILER
 201                        acpi_os_printf("File is corrupt or is ASCII text -- "
 202                                       "it must be a binary file\n");
 203#endif
 204                        return (AE_BAD_HEADER);
 205                }
 206#ifdef ACPI_OBSOLETE_CODE
 207                /* We only support a limited number of table types */
 208
 209                if (!ACPI_COMPARE_NAME
 210                    ((char *)table_header.signature, ACPI_SIG_DSDT)
 211                    && !ACPI_COMPARE_NAME((char *)table_header.signature,
 212                                          ACPI_SIG_PSDT)
 213                    && !ACPI_COMPARE_NAME((char *)table_header.signature,
 214                                          ACPI_SIG_SSDT)) {
 215                        acpi_os_printf
 216                            ("Table signature [%4.4s] is invalid or not supported\n",
 217                             (char *)table_header.signature);
 218                        ACPI_DUMP_BUFFER(&table_header,
 219                                         sizeof(struct acpi_table_header));
 220                        return (AE_ERROR);
 221                }
 222#endif
 223
 224                *table_length = table_header.length;
 225        }
 226
 227        /* Allocate a buffer for the table */
 228
 229        *table = acpi_os_allocate((size_t) file_size);
 230        if (!*table) {
 231                acpi_os_printf
 232                    ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n",
 233                     table_header.signature, *table_length);
 234                return (AE_NO_MEMORY);
 235        }
 236
 237        /* Get the rest of the table */
 238
 239        fseek(fp, 0, SEEK_SET);
 240        actual = fread(*table, 1, (size_t) file_size, fp);
 241        if (actual == file_size) {
 242                if (standard_header) {
 243
 244                        /* Now validate the checksum */
 245
 246                        status = acpi_tb_verify_checksum((void *)*table,
 247                                                         ACPI_CAST_PTR(struct
 248                                                                       acpi_table_header,
 249                                                                       *table)->
 250                                                         length);
 251
 252                        if (status == AE_BAD_CHECKSUM) {
 253                                status =
 254                                    acpi_ut_check_text_mode_corruption((u8 *)
 255                                                                       *table,
 256                                                                       file_size,
 257                                                                       (*table)->
 258                                                                       length);
 259                                return (status);
 260                        }
 261                }
 262                return (AE_OK);
 263        }
 264
 265        if (actual > 0) {
 266                acpi_os_printf("Warning - reading table, asked for %X got %X\n",
 267                               file_size, actual);
 268                return (AE_OK);
 269        }
 270
 271        acpi_os_printf("Error - could not read the table file\n");
 272        acpi_os_free(*table);
 273        *table = NULL;
 274        *table_length = 0;
 275        return (AE_ERROR);
 276}
 277
 278/*******************************************************************************
 279 *
 280 * FUNCTION:    acpi_ut_read_table_from_file
 281 *
 282 * PARAMETERS:  filename         - File where table is located
 283 *              table            - Where a pointer to the table is returned
 284 *
 285 * RETURN:      Status
 286 *
 287 * DESCRIPTION: Get an ACPI table from a file
 288 *
 289 ******************************************************************************/
 290
 291acpi_status
 292acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table)
 293{
 294        FILE *file;
 295        u32 file_size;
 296        u32 table_length;
 297        acpi_status status = AE_ERROR;
 298
 299        /* Open the file, get current size */
 300
 301        file = fopen(filename, "rb");
 302        if (!file) {
 303                perror("Could not open input file");
 304                return (status);
 305        }
 306
 307        file_size = cm_get_file_size(file);
 308        if (file_size == ACPI_UINT32_MAX) {
 309                goto exit;
 310        }
 311
 312        /* Get the entire file */
 313
 314        fprintf(stderr,
 315                "Reading ACPI table from file %10s - Length %.8u (0x%06X)\n",
 316                filename, file_size, file_size);
 317
 318        status = acpi_ut_read_table(file, table, &table_length);
 319        if (ACPI_FAILURE(status)) {
 320                acpi_os_printf("Could not get table from the file\n");
 321        }
 322
 323exit:
 324        fclose(file);
 325        return (status);
 326}
 327
 328#endif
 329