1/*******************************************************************************
2 *
3 * Module Name: utfileio - simple file I/O routines
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 <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			status = fl_check_for_ascii(fp, NULL, FALSE);
202			if (ACPI_SUCCESS(status)) {
203				acpi_os_printf
204				    ("File appears to be ASCII only, must be binary\n");
205			}
206#endif
207			return (AE_BAD_HEADER);
208		}
209#ifdef ACPI_OBSOLETE_CODE
210		/* We only support a limited number of table types */
211
212		if (!ACPI_COMPARE_NAME
213		    ((char *)table_header.signature, ACPI_SIG_DSDT)
214		    && !ACPI_COMPARE_NAME((char *)table_header.signature,
215					  ACPI_SIG_PSDT)
216		    && !ACPI_COMPARE_NAME((char *)table_header.signature,
217					  ACPI_SIG_SSDT)) {
218			acpi_os_printf
219			    ("Table signature [%4.4s] is invalid or not supported\n",
220			     (char *)table_header.signature);
221			ACPI_DUMP_BUFFER(&table_header,
222					 sizeof(struct acpi_table_header));
223			return (AE_ERROR);
224		}
225#endif
226
227		*table_length = table_header.length;
228	}
229
230	/* Allocate a buffer for the table */
231
232	*table = acpi_os_allocate((size_t) file_size);
233	if (!*table) {
234		acpi_os_printf
235		    ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n",
236		     table_header.signature, *table_length);
237		return (AE_NO_MEMORY);
238	}
239
240	/* Get the rest of the table */
241
242	fseek(fp, 0, SEEK_SET);
243	actual = fread(*table, 1, (size_t) file_size, fp);
244	if (actual == file_size) {
245		if (standard_header) {
246
247			/* Now validate the checksum */
248
249			status = acpi_tb_verify_checksum((void *)*table,
250							 ACPI_CAST_PTR(struct
251								       acpi_table_header,
252								       *table)->
253							 length);
254
255			if (status == AE_BAD_CHECKSUM) {
256				status =
257				    acpi_ut_check_text_mode_corruption((u8 *)
258								       *table,
259								       file_size,
260								       (*table)->
261								       length);
262				return (status);
263			}
264		}
265		return (AE_OK);
266	}
267
268	if (actual > 0) {
269		acpi_os_printf("Warning - reading table, asked for %X got %X\n",
270			       file_size, actual);
271		return (AE_OK);
272	}
273
274	acpi_os_printf("Error - could not read the table file\n");
275	acpi_os_free(*table);
276	*table = NULL;
277	*table_length = 0;
278	return (AE_ERROR);
279}
280
281/*******************************************************************************
282 *
283 * FUNCTION:    acpi_ut_read_table_from_file
284 *
285 * PARAMETERS:  filename         - File where table is located
286 *              table            - Where a pointer to the table is returned
287 *
288 * RETURN:      Status
289 *
290 * DESCRIPTION: Get an ACPI table from a file
291 *
292 ******************************************************************************/
293
294acpi_status
295acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table)
296{
297	FILE *file;
298	u32 file_size;
299	u32 table_length;
300	acpi_status status = AE_ERROR;
301
302	/* Open the file, get current size */
303
304	file = fopen(filename, "rb");
305	if (!file) {
306		perror("Could not open input file");
307		return (status);
308	}
309
310	file_size = cm_get_file_size(file);
311	if (file_size == ACPI_UINT32_MAX) {
312		goto exit;
313	}
314
315	/* Get the entire file */
316
317	fprintf(stderr,
318		"Loading Acpi table from file %10s - Length %.8u (%06X)\n",
319		filename, file_size, file_size);
320
321	status = acpi_ut_read_table(file, table, &table_length);
322	if (ACPI_FAILURE(status)) {
323		acpi_os_printf("Could not get table from the file\n");
324	}
325
326exit:
327	fclose(file);
328	return (status);
329}
330
331#endif
332