1 /******************************************************************************
2  *
3  * Module Name: aslascii - ASCII detection and support 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 "aslcompiler.h"
45 #include <acapps.h>
46 
47 #define _COMPONENT          ACPI_COMPILER
48         ACPI_MODULE_NAME    ("aslascii")
49 
50 
51 /* Local prototypes */
52 
53 static void
54 FlConsumeAnsiComment (
55     FILE                    *Handle,
56     ASL_FILE_STATUS         *Status);
57 
58 static void
59 FlConsumeNewComment (
60     FILE                    *Handle,
61     ASL_FILE_STATUS         *Status);
62 
63 
64 /*******************************************************************************
65  *
66  * FUNCTION:    FlCheckForAcpiTable
67  *
68  * PARAMETERS:  Handle              - Open input file
69  *
70  * RETURN:      Status
71  *
72  * DESCRIPTION: Determine if a file seems to be a binary ACPI table, via the
73  *              following checks on what would be the table header:
74  *              0) File must be at least as long as an ACPI_TABLE_HEADER
75  *              1) The header length field must match the file size
76  *              2) Signature, OemId, OemTableId, AslCompilerId must be ASCII
77  *
78  ******************************************************************************/
79 
80 ACPI_STATUS
81 FlCheckForAcpiTable (
82     FILE                    *Handle)
83 {
84     ACPI_TABLE_HEADER       Table;
85     UINT32                  FileSize;
86     size_t                  Actual;
87     UINT32                  i;
88 
89 
90     /* Read a potential table header */
91 
92     Actual = fread (&Table, 1, sizeof (ACPI_TABLE_HEADER), Handle);
93     fseek (Handle, 0, SEEK_SET);
94 
95     if (Actual < sizeof (ACPI_TABLE_HEADER))
96     {
97         return (AE_ERROR);
98     }
99 
100     /* Header length field must match the file size */
101 
102     FileSize = CmGetFileSize (Handle);
103     if (Table.Length != FileSize)
104     {
105         return (AE_ERROR);
106     }
107 
108     /*
109      * These fields must be ASCII:
110      * Signature, OemId, OemTableId, AslCompilerId.
111      * We allow a NULL terminator in OemId and OemTableId.
112      */
113     for (i = 0; i < ACPI_NAME_SIZE; i++)
114     {
115         if (!ACPI_IS_ASCII ((UINT8) Table.Signature[i]))
116         {
117             return (AE_ERROR);
118         }
119 
120         if (!ACPI_IS_ASCII ((UINT8) Table.AslCompilerId[i]))
121         {
122             return (AE_ERROR);
123         }
124     }
125 
126     for (i = 0; (i < ACPI_OEM_ID_SIZE) && (Table.OemId[i]); i++)
127     {
128         if (!ACPI_IS_ASCII ((UINT8) Table.OemId[i]))
129         {
130             return (AE_ERROR);
131         }
132     }
133 
134     for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (Table.OemTableId[i]); i++)
135     {
136         if (!ACPI_IS_ASCII ((UINT8) Table.OemTableId[i]))
137         {
138             return (AE_ERROR);
139         }
140     }
141 
142     printf ("Binary file appears to be a valid ACPI table, disassembling\n");
143     return (AE_OK);
144 }
145 
146 
147 /*******************************************************************************
148  *
149  * FUNCTION:    FlCheckForAscii
150  *
151  * PARAMETERS:  Filename            - Full input filename
152  *              DisplayErrors       - TRUE if error messages desired
153  *
154  * RETURN:      Status
155  *
156  * DESCRIPTION: Verify that the input file is entirely ASCII. Ignores characters
157  *              within comments. Note: does not handle nested comments and does
158  *              not handle comment delimiters within string literals. However,
159  *              on the rare chance this happens and an invalid character is
160  *              missed, the parser will catch the error by failing in some
161  *              spectactular manner.
162  *
163  ******************************************************************************/
164 
165 ACPI_STATUS
166 FlCheckForAscii (
167     char                    *Filename,
168     BOOLEAN                 DisplayErrors)
169 {
170     UINT8                   Byte;
171     ACPI_SIZE               BadBytes = 0;
172     BOOLEAN                 OpeningComment = FALSE;
173     ASL_FILE_STATUS         Status;
174     FILE                    *Handle;
175 
176 
177     /* Open file in text mode so file offset is always accurate */
178 
179     Handle = fopen (Filename, "rb");
180     if (!Handle)
181     {
182         perror ("Could not open input file");
183         return (AE_ERROR);
184     }
185 
186     Status.Line = 1;
187     Status.Offset = 0;
188 
189     /* Read the entire file */
190 
191     while (fread (&Byte, 1, 1, Handle) == 1)
192     {
193         /* Ignore comment fields (allow non-ascii within) */
194 
195         if (OpeningComment)
196         {
197             /* Check for second comment open delimiter */
198 
199             if (Byte == '*')
200             {
201                 FlConsumeAnsiComment (Handle, &Status);
202             }
203 
204             if (Byte == '/')
205             {
206                 FlConsumeNewComment (Handle, &Status);
207             }
208 
209             /* Reset */
210 
211             OpeningComment = FALSE;
212         }
213         else if (Byte == '/')
214         {
215             OpeningComment = TRUE;
216         }
217 
218         /* Check for an ASCII character */
219 
220         if (!ACPI_IS_ASCII (Byte))
221         {
222             if ((BadBytes < 10) && (DisplayErrors))
223             {
224                 AcpiOsPrintf (
225                     "Found non-ASCII character in source text: "
226                     "0x%2.2X in line %u, file offset 0x%2.2X\n",
227                     Byte, Status.Line, Status.Offset);
228             }
229             BadBytes++;
230         }
231 
232         /* Ensure character is either printable or a "space" char */
233 
234         else if (!isprint (Byte) && !isspace (Byte))
235         {
236             if ((BadBytes < 10) && (DisplayErrors))
237             {
238                 AcpiOsPrintf (
239                     "Found invalid character in source text: "
240                     "0x%2.2X in line %u, file offset 0x%2.2X\n",
241                     Byte, Status.Line, Status.Offset);
242             }
243             BadBytes++;
244         }
245 
246         /* Update line counter as necessary */
247 
248         if (Byte == 0x0A)
249         {
250             Status.Line++;
251         }
252 
253         Status.Offset++;
254     }
255 
256     fclose (Handle);
257 
258     /* Were there any non-ASCII characters in the file? */
259 
260     if (BadBytes)
261     {
262         if (DisplayErrors)
263         {
264             AcpiOsPrintf (
265                 "Total %u invalid characters found in input source text, "
266                 "could be a binary file\n", BadBytes);
267             AslError (ASL_ERROR, ASL_MSG_NON_ASCII, NULL, Filename);
268         }
269 
270         return (AE_BAD_CHARACTER);
271     }
272 
273     /* File is OK (100% ASCII) */
274 
275     return (AE_OK);
276 }
277 
278 
279 /*******************************************************************************
280  *
281  * FUNCTION:    FlConsumeAnsiComment
282  *
283  * PARAMETERS:  Handle              - Open input file
284  *              Status              - File current status struct
285  *
286  * RETURN:      Number of lines consumed
287  *
288  * DESCRIPTION: Step over a normal slash-star type comment
289  *
290  ******************************************************************************/
291 
292 static void
293 FlConsumeAnsiComment (
294     FILE                    *Handle,
295     ASL_FILE_STATUS         *Status)
296 {
297     UINT8                   Byte;
298     BOOLEAN                 ClosingComment = FALSE;
299 
300 
301     while (fread (&Byte, 1, 1, Handle) == 1)
302     {
303         /* Scan until comment close is found */
304 
305         if (ClosingComment)
306         {
307             if (Byte == '/')
308             {
309                 Status->Offset++;
310                 return;
311             }
312 
313             if (Byte != '*')
314             {
315                 /* Reset */
316 
317                 ClosingComment = FALSE;
318             }
319         }
320         else if (Byte == '*')
321         {
322             ClosingComment = TRUE;
323         }
324 
325         /* Maintain line count */
326 
327         if (Byte == 0x0A)
328         {
329             Status->Line++;
330         }
331 
332         Status->Offset++;
333     }
334 }
335 
336 
337 /*******************************************************************************
338  *
339  * FUNCTION:    FlConsumeNewComment
340  *
341  * PARAMETERS:  Handle              - Open input file
342  *              Status              - File current status struct
343  *
344  * RETURN:      Number of lines consumed
345  *
346  * DESCRIPTION: Step over a slash-slash type of comment
347  *
348  ******************************************************************************/
349 
350 static void
351 FlConsumeNewComment (
352     FILE                    *Handle,
353     ASL_FILE_STATUS         *Status)
354 {
355     UINT8                   Byte;
356 
357 
358     while (fread (&Byte, 1, 1, Handle) == 1)
359     {
360         Status->Offset++;
361 
362         /* Comment ends at newline */
363 
364         if (Byte == 0x0A)
365         {
366             Status->Line++;
367             return;
368         }
369     }
370 }
371