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