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 <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/actables.h>
47#include <contrib/dev/acpica/include/acapps.h>
48
49#ifdef ACPI_ASL_COMPILER
50#include <contrib/dev/acpica/compiler/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
62static ACPI_STATUS
63AcpiUtCheckTextModeCorruption (
64    UINT8                   *Table,
65    UINT32                  TableLength,
66    UINT32                  FileLength);
67
68static ACPI_STATUS
69AcpiUtReadTable (
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
91static ACPI_STATUS
92AcpiUtCheckTextModeCorruption (
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
164static ACPI_STATUS
165AcpiUtReadTable (
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
316ACPI_STATUS
317AcpiUtReadTableFromFile (
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
353Exit:
354    fclose(File);
355    return (Status);
356}
357
358#endif
359