0,0 → 1,334 |
/******************************************************************************* |
* |
* Module Name: utfileio - simple file I/O routines |
* |
******************************************************************************/ |
|
/* |
* Copyright (C) 2000 - 2015, Intel Corp. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions, and the following disclaimer, |
* without modification. |
* 2. Redistributions in binary form must reproduce at minimum a disclaimer |
* substantially similar to the "NO WARRANTY" disclaimer below |
* ("Disclaimer") and any redistribution must be conditioned upon |
* including a substantially similar Disclaimer requirement for further |
* binary redistribution. |
* 3. Neither the names of the above-listed copyright holders nor the names |
* of any contributors may be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* |
* Alternatively, this software may be distributed under the terms of the |
* GNU General Public License ("GPL") version 2 as published by the Free |
* Software Foundation. |
* |
* NO WARRANTY |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGES. |
*/ |
|
#include <acpi/acpi.h> |
#include "accommon.h" |
#include "actables.h" |
#include "acapps.h" |
#include "errno.h" |
|
#ifdef ACPI_ASL_COMPILER |
#include "aslcompiler.h" |
#endif |
|
#define _COMPONENT ACPI_CA_DEBUGGER |
ACPI_MODULE_NAME("utfileio") |
|
#ifdef ACPI_APPLICATION |
/* Local prototypes */ |
static acpi_status |
acpi_ut_check_text_mode_corruption(u8 *table, |
u32 table_length, u32 file_length); |
|
static acpi_status |
acpi_ut_read_table(FILE * fp, |
struct acpi_table_header **table, u32 *table_length); |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_ut_check_text_mode_corruption |
* |
* PARAMETERS: table - Table buffer |
* table_length - Length of table from the table header |
* file_length - Length of the file that contains the table |
* |
* RETURN: Status |
* |
* DESCRIPTION: Check table for text mode file corruption where all linefeed |
* characters (LF) have been replaced by carriage return linefeed |
* pairs (CR/LF). |
* |
******************************************************************************/ |
|
static acpi_status |
acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length) |
{ |
u32 i; |
u32 pairs = 0; |
|
if (table_length != file_length) { |
ACPI_WARNING((AE_INFO, |
"File length (0x%X) is not the same as the table length (0x%X)", |
file_length, table_length)); |
} |
|
/* Scan entire table to determine if each LF has been prefixed with a CR */ |
|
for (i = 1; i < file_length; i++) { |
if (table[i] == 0x0A) { |
if (table[i - 1] != 0x0D) { |
|
/* The LF does not have a preceding CR, table not corrupted */ |
|
return (AE_OK); |
} else { |
/* Found a CR/LF pair */ |
|
pairs++; |
} |
i++; |
} |
} |
|
if (!pairs) { |
return (AE_OK); |
} |
|
/* |
* Entire table scanned, each CR is part of a CR/LF pair -- |
* meaning that the table was treated as a text file somewhere. |
* |
* NOTE: We can't "fix" the table, because any existing CR/LF pairs in the |
* original table are left untouched by the text conversion process -- |
* meaning that we cannot simply replace CR/LF pairs with LFs. |
*/ |
acpi_os_printf("Table has been corrupted by text mode conversion\n"); |
acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs); |
acpi_os_printf("Table cannot be repaired!\n"); |
return (AE_BAD_VALUE); |
} |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_ut_read_table |
* |
* PARAMETERS: fp - File that contains table |
* table - Return value, buffer with table |
* table_length - Return value, length of table |
* |
* RETURN: Status |
* |
* DESCRIPTION: Load the DSDT from the file pointer |
* |
******************************************************************************/ |
|
static acpi_status |
acpi_ut_read_table(FILE * fp, |
struct acpi_table_header **table, u32 *table_length) |
{ |
struct acpi_table_header table_header; |
u32 actual; |
acpi_status status; |
u32 file_size; |
u8 standard_header = TRUE; |
s32 count; |
|
/* Get the file size */ |
|
file_size = cm_get_file_size(fp); |
if (file_size == ACPI_UINT32_MAX) { |
return (AE_ERROR); |
} |
|
if (file_size < 4) { |
return (AE_BAD_HEADER); |
} |
|
/* Read the signature */ |
|
fseek(fp, 0, SEEK_SET); |
|
count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); |
if (count != sizeof(struct acpi_table_header)) { |
acpi_os_printf("Could not read the table header\n"); |
return (AE_BAD_HEADER); |
} |
|
/* The RSDP table does not have standard ACPI header */ |
|
if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) { |
*table_length = file_size; |
standard_header = FALSE; |
} else { |
|
#if 0 |
/* Validate the table header/length */ |
|
status = acpi_tb_validate_table_header(&table_header); |
if (ACPI_FAILURE(status)) { |
acpi_os_printf("Table header is invalid!\n"); |
return (status); |
} |
#endif |
|
/* File size must be at least as long as the Header-specified length */ |
|
if (table_header.length > file_size) { |
acpi_os_printf |
("TableHeader length [0x%X] greater than the input file size [0x%X]\n", |
table_header.length, file_size); |
|
#ifdef ACPI_ASL_COMPILER |
acpi_os_printf("File is corrupt or is ASCII text -- " |
"it must be a binary file\n"); |
#endif |
return (AE_BAD_HEADER); |
} |
#ifdef ACPI_OBSOLETE_CODE |
/* We only support a limited number of table types */ |
|
if (!ACPI_COMPARE_NAME |
((char *)table_header.signature, ACPI_SIG_DSDT) |
&& !ACPI_COMPARE_NAME((char *)table_header.signature, |
ACPI_SIG_PSDT) |
&& !ACPI_COMPARE_NAME((char *)table_header.signature, |
ACPI_SIG_SSDT)) { |
acpi_os_printf |
("Table signature [%4.4s] is invalid or not supported\n", |
(char *)table_header.signature); |
ACPI_DUMP_BUFFER(&table_header, |
sizeof(struct acpi_table_header)); |
return (AE_ERROR); |
} |
#endif |
|
*table_length = table_header.length; |
} |
|
/* Allocate a buffer for the table */ |
|
*table = acpi_os_allocate((size_t) file_size); |
if (!*table) { |
acpi_os_printf |
("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n", |
table_header.signature, *table_length); |
return (AE_NO_MEMORY); |
} |
|
/* Get the rest of the table */ |
|
fseek(fp, 0, SEEK_SET); |
actual = fread(*table, 1, (size_t) file_size, fp); |
if (actual == file_size) { |
if (standard_header) { |
|
/* Now validate the checksum */ |
|
status = acpi_tb_verify_checksum((void *)*table, |
ACPI_CAST_PTR(struct |
acpi_table_header, |
*table)-> |
length); |
|
if (status == AE_BAD_CHECKSUM) { |
status = |
acpi_ut_check_text_mode_corruption((u8 *) |
*table, |
file_size, |
(*table)-> |
length); |
return (status); |
} |
} |
return (AE_OK); |
} |
|
if (actual > 0) { |
acpi_os_printf("Warning - reading table, asked for %X got %X\n", |
file_size, actual); |
return (AE_OK); |
} |
|
acpi_os_printf("Error - could not read the table file\n"); |
acpi_os_free(*table); |
*table = NULL; |
*table_length = 0; |
return (AE_ERROR); |
} |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_ut_read_table_from_file |
* |
* PARAMETERS: filename - File where table is located |
* table - Where a pointer to the table is returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Get an ACPI table from a file |
* |
******************************************************************************/ |
|
acpi_status |
acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table) |
{ |
FILE *file; |
u32 file_size; |
u32 table_length; |
acpi_status status = AE_ERROR; |
|
/* Open the file, get current size */ |
|
file = fopen(filename, "rb"); |
if (!file) { |
perror("Could not open input file"); |
|
if (errno == ENOENT) { |
return (AE_NOT_EXIST); |
} |
|
return (status); |
} |
|
file_size = cm_get_file_size(file); |
if (file_size == ACPI_UINT32_MAX) { |
goto exit; |
} |
|
/* Get the entire file */ |
|
fprintf(stderr, |
"Reading ACPI table from file %12s - Length %.8u (0x%06X)\n", |
filename, file_size, file_size); |
|
status = acpi_ut_read_table(file, table, &table_length); |
if (ACPI_FAILURE(status)) { |
acpi_os_printf("Could not get table from the file\n"); |
} |
|
exit: |
fclose(file); |
return (status); |
} |
|
#endif |