Sync ACPICA with Intel's version 20160108.
[dragonfly.git] / sys / contrib / dev / acpica / source / compiler / aslstartup.c
1 /******************************************************************************
2  *
3  * Module Name: aslstartup - Compiler startup routines, called from main
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2016, 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 "actables.h"
46 #include "acdisasm.h"
47 #include "acapps.h"
48
49 #define _COMPONENT          ACPI_COMPILER
50         ACPI_MODULE_NAME    ("aslstartup")
51
52
53 /* Local prototypes */
54
55 static UINT8
56 AslDetectSourceFileType (
57     ASL_FILE_INFO           *Info);
58
59 static ACPI_STATUS
60 AslDoDisassembly (
61     void);
62
63
64 /* Globals */
65
66 static BOOLEAN          AslToFile = TRUE;
67
68
69 /*******************************************************************************
70  *
71  * FUNCTION:    AslInitializeGlobals
72  *
73  * PARAMETERS:  None
74  *
75  * RETURN:      None
76  *
77  * DESCRIPTION: Re-initialize globals needed to restart the compiler. This
78  *              allows multiple files to be disassembled and/or compiled.
79  *
80  ******************************************************************************/
81
82 void
83 AslInitializeGlobals (
84     void)
85 {
86     UINT32                  i;
87
88
89     /* Init compiler globals */
90
91     Gbl_SyntaxError = 0;
92     Gbl_CurrentColumn = 0;
93     Gbl_CurrentLineNumber = 1;
94     Gbl_LogicalLineNumber = 1;
95     Gbl_CurrentLineOffset = 0;
96     Gbl_InputFieldCount = 0;
97     Gbl_InputByteCount = 0;
98     Gbl_NsLookupCount = 0;
99     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
100
101     Gbl_ErrorLog = NULL;
102     Gbl_NextError = NULL;
103     Gbl_Signature = NULL;
104     Gbl_FileType = 0;
105
106     TotalExecutableOpcodes = 0;
107     TotalNamedObjects = 0;
108     TotalKeywords = 0;
109     TotalParseNodes = 0;
110     TotalMethods = 0;
111     TotalAllocations = 0;
112     TotalAllocated = 0;
113     TotalFolds = 0;
114
115     AslGbl_NextEvent = 0;
116     for (i = 0; i < ASL_NUM_REPORT_LEVELS; i++)
117     {
118         Gbl_ExceptionCount[i] = 0;
119     }
120
121     for (i = ASL_FILE_INPUT; i <= ASL_MAX_FILE_TYPE; i++)
122     {
123         Gbl_Files[i].Handle = NULL;
124         Gbl_Files[i].Filename = NULL;
125     }
126 }
127
128
129 /*******************************************************************************
130  *
131  * FUNCTION:    AslDetectSourceFileType
132  *
133  * PARAMETERS:  Info            - Name/Handle for the file (must be open)
134  *
135  * RETURN:      File Type
136  *
137  * DESCRIPTION: Determine the type of the input file. Either binary (contains
138  *              non-ASCII characters), ASL file, or an ACPI Data Table file.
139  *
140  ******************************************************************************/
141
142 static UINT8
143 AslDetectSourceFileType (
144     ASL_FILE_INFO           *Info)
145 {
146     char                    *FileChar;
147     UINT8                   Type = ASL_INPUT_TYPE_ASCII_DATA; /* default */
148     ACPI_STATUS             Status;
149
150
151     /* Check for 100% ASCII source file (comments are ignored) */
152
153     Status = FlIsFileAsciiSource (Info->Filename, FALSE);
154     if (ACPI_SUCCESS (Status))
155     {
156         /*
157          * File contains ASCII source code. Determine if this is an ASL
158          * file or an ACPI data table file.
159          */
160         while (fgets (Gbl_CurrentLineBuffer, Gbl_LineBufferSize, Info->Handle))
161         {
162             /* Uppercase the buffer for caseless compare */
163
164             FileChar = Gbl_CurrentLineBuffer;
165             while (*FileChar)
166             {
167                 *FileChar = (char) toupper ((int) *FileChar);
168                 FileChar++;
169             }
170
171             /* Presence of "DefinitionBlock" indicates actual ASL code */
172
173             if (strstr (Gbl_CurrentLineBuffer, "DEFINITIONBLOCK"))
174             {
175                 /* Appears to be an ASL file */
176
177                 Type = ASL_INPUT_TYPE_ASCII_ASL;
178                 goto Cleanup;
179             }
180         }
181
182         /* Appears to be an ASCII data table source file */
183
184         Type = ASL_INPUT_TYPE_ASCII_DATA;
185         goto Cleanup;
186     }
187
188     /* We have some sort of binary table, check for valid ACPI table */
189
190     fseek (Info->Handle, 0, SEEK_SET);
191
192     Status = AcValidateTableHeader (Info->Handle, 0);
193     if (ACPI_SUCCESS (Status))
194     {
195         fprintf (stderr,
196             "Binary file appears to be a valid ACPI table, disassembling\n");
197
198         Type = ASL_INPUT_TYPE_BINARY_ACPI_TABLE;
199         goto Cleanup;
200     }
201
202     Type = ASL_INPUT_TYPE_BINARY;
203
204
205 Cleanup:
206
207     /* Must seek back to the start of the file */
208
209     fseek (Info->Handle, 0, SEEK_SET);
210     return (Type);
211 }
212
213
214 /*******************************************************************************
215  *
216  * FUNCTION:    AslDoDisassembly
217  *
218  * PARAMETERS:  None
219  *
220  * RETURN:      Status
221  *
222  * DESCRIPTION: Initiate AML file disassembly. Uses ACPICA subsystem to build
223  *              namespace.
224  *
225  ******************************************************************************/
226
227 static ACPI_STATUS
228 AslDoDisassembly (
229     void)
230 {
231     ACPI_STATUS             Status;
232
233
234     /* ACPICA subsystem initialization */
235
236     Status = AdInitialize ();
237     if (ACPI_FAILURE (Status))
238     {
239         return (Status);
240     }
241
242     Status = AcpiAllocateRootTable (4);
243     if (ACPI_FAILURE (Status))
244     {
245         AcpiOsPrintf ("Could not initialize ACPI Table Manager, %s\n",
246             AcpiFormatException (Status));
247         return (Status);
248     }
249
250     /* Handle additional output files for disassembler */
251
252     Gbl_FileType = ASL_INPUT_TYPE_BINARY_ACPI_TABLE;
253     Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix);
254
255     /* This is where the disassembly happens */
256
257     AcpiGbl_DmOpt_Disasm = TRUE;
258     Status = AdAmlDisassemble (AslToFile,
259         Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_OutputFilenamePrefix,
260         &Gbl_Files[ASL_FILE_INPUT].Filename);
261     if (ACPI_FAILURE (Status))
262     {
263         return (Status);
264     }
265
266     /* Check if any control methods were unresolved */
267
268     AcpiDmUnresolvedWarning (0);
269
270     /* Shutdown compiler and ACPICA subsystem */
271
272     AeClearErrorLog ();
273     (void) AcpiTerminate ();
274
275     /*
276      * Gbl_Files[ASL_FILE_INPUT].Filename was replaced with the
277      * .DSL disassembly file, which can now be compiled if requested
278      */
279     if (Gbl_DoCompile)
280     {
281         AcpiOsPrintf ("\nCompiling \"%s\"\n",
282             Gbl_Files[ASL_FILE_INPUT].Filename);
283         return (AE_CTRL_CONTINUE);
284     }
285
286     /* No need to free the filename string */
287
288     Gbl_Files[ASL_FILE_INPUT].Filename = NULL;
289
290     CmDeleteCaches ();
291     return (AE_OK);
292 }
293
294
295 /*******************************************************************************
296  *
297  * FUNCTION:    AslDoOneFile
298  *
299  * PARAMETERS:  Filename        - Name of the file
300  *
301  * RETURN:      Status
302  *
303  * DESCRIPTION: Process a single file - either disassemble, compile, or both
304  *
305  ******************************************************************************/
306
307 ACPI_STATUS
308 AslDoOneFile (
309     char                    *Filename)
310 {
311     ACPI_STATUS             Status;
312
313
314     /* Re-initialize "some" compiler/preprocessor globals */
315
316     AslInitializeGlobals ();
317     PrInitializeGlobals ();
318
319     /*
320      * Extract the directory path. This path is used for possible include
321      * files and the optional AML filename embedded in the input file
322      * DefinitionBlock declaration.
323      */
324     Status = FlSplitInputPathname (Filename, &Gbl_DirectoryPath, NULL);
325     if (ACPI_FAILURE (Status))
326     {
327         return (Status);
328     }
329
330     /* Take a copy of the input filename, convert any backslashes */
331
332     Gbl_Files[ASL_FILE_INPUT].Filename =
333         UtStringCacheCalloc (strlen (Filename) + 1);
334
335     strcpy (Gbl_Files[ASL_FILE_INPUT].Filename, Filename);
336     UtConvertBackslashes (Gbl_Files[ASL_FILE_INPUT].Filename);
337
338     /*
339      * AML Disassembly (Optional)
340      */
341     if (Gbl_DisasmFlag)
342     {
343         Status = AslDoDisassembly ();
344         if (Status != AE_CTRL_CONTINUE)
345         {
346             return (Status);
347         }
348     }
349
350     /*
351      * Open the input file. Here, this should be an ASCII source file,
352      * either an ASL file or a Data Table file
353      */
354     Status = FlOpenInputFile (Gbl_Files[ASL_FILE_INPUT].Filename);
355     if (ACPI_FAILURE (Status))
356     {
357         AePrintErrorLog (ASL_FILE_STDERR);
358         return (AE_ERROR);
359     }
360
361     Gbl_OriginalInputFileSize = FlGetFileSize (ASL_FILE_INPUT);
362
363     /* Determine input file type */
364
365     Gbl_FileType = AslDetectSourceFileType (&Gbl_Files[ASL_FILE_INPUT]);
366     if (Gbl_FileType == ASL_INPUT_TYPE_BINARY)
367     {
368         return (AE_ERROR);
369     }
370
371     /*
372      * If -p not specified, we will use the input filename as the
373      * output filename prefix
374      */
375     if (Gbl_UseDefaultAmlFilename)
376     {
377         Gbl_OutputFilenamePrefix = Gbl_Files[ASL_FILE_INPUT].Filename;
378     }
379
380     /* Open the optional output files (listings, etc.) */
381
382     Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix);
383     if (ACPI_FAILURE (Status))
384     {
385         AePrintErrorLog (ASL_FILE_STDERR);
386         return (AE_ERROR);
387     }
388
389     /*
390      * Compilation of ASL source versus DataTable source uses different
391      * compiler subsystems
392      */
393     switch (Gbl_FileType)
394     {
395     /*
396      * Data Table Compilation
397      */
398     case ASL_INPUT_TYPE_ASCII_DATA:
399
400         Status = DtDoCompile ();
401         if (ACPI_FAILURE (Status))
402         {
403             return (Status);
404         }
405
406         if (Gbl_Signature)
407         {
408             Gbl_Signature = NULL;
409         }
410
411         /* Check if any errors occurred during compile */
412
413         Status = AslCheckForErrorExit ();
414         if (ACPI_FAILURE (Status))
415         {
416             return (Status);
417         }
418
419         /* Cleanup (for next source file) and exit */
420
421         AeClearErrorLog ();
422         PrTerminatePreprocessor ();
423         return (Status);
424
425     /*
426      * ASL Compilation
427      */
428     case ASL_INPUT_TYPE_ASCII_ASL:
429
430         /* ACPICA subsystem initialization */
431
432         Status = AdInitialize ();
433         if (ACPI_FAILURE (Status))
434         {
435             return (Status);
436         }
437
438         (void) CmDoCompile ();
439         (void) AcpiTerminate ();
440
441         /* Check if any errors occurred during compile */
442
443         Status = AslCheckForErrorExit ();
444         if (ACPI_FAILURE (Status))
445         {
446             return (Status);
447         }
448
449         /* Cleanup (for next source file) and exit */
450
451         AeClearErrorLog ();
452         PrTerminatePreprocessor ();
453         return (AE_OK);
454
455     /*
456      * Binary ACPI table was auto-detected, disassemble it
457      */
458     case ASL_INPUT_TYPE_BINARY_ACPI_TABLE:
459
460         /* We have what appears to be an ACPI table, disassemble it */
461
462         FlCloseFile (ASL_FILE_INPUT);
463         Gbl_DoCompile = FALSE;
464         Gbl_DisasmFlag = TRUE;
465         Status = AslDoDisassembly ();
466         return (Status);
467
468     /* Unknown binary table */
469
470     case ASL_INPUT_TYPE_BINARY:
471
472         AePrintErrorLog (ASL_FILE_STDERR);
473         return (AE_ERROR);
474
475     default:
476
477         printf ("Unknown file type %X\n", Gbl_FileType);
478         return (AE_ERROR);
479     }
480 }
481
482
483 /*******************************************************************************
484  *
485  * FUNCTION:    AslCheckForErrorExit
486  *
487  * PARAMETERS:  None. Examines global exception count array
488  *
489  * RETURN:      Status
490  *
491  * DESCRIPTION: Determine if compiler should abort with error status
492  *
493  ******************************************************************************/
494
495 ACPI_STATUS
496 AslCheckForErrorExit (
497     void)
498 {
499
500     /*
501      * Return non-zero exit code if there have been errors, unless the
502      * global ignore error flag has been set
503      */
504     if (!Gbl_IgnoreErrors)
505     {
506         if (Gbl_ExceptionCount[ASL_ERROR] > 0)
507         {
508             return (AE_ERROR);
509         }
510
511         /* Optionally treat warnings as errors */
512
513         if (Gbl_WarningsAsErrors)
514         {
515             if ((Gbl_ExceptionCount[ASL_WARNING] > 0)  ||
516                 (Gbl_ExceptionCount[ASL_WARNING2] > 0) ||
517                 (Gbl_ExceptionCount[ASL_WARNING3] > 0))
518             {
519                 return (AE_ERROR);
520             }
521         }
522     }
523
524     return (AE_OK);
525 }