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