1 /******************************************************************************
2  *
3  * Module Name: aslstartup - Compiler startup routines, called from main
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 "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_CurrentColumn = 0;
92     Gbl_CurrentLineNumber = 1;
93     Gbl_LogicalLineNumber = 1;
94     Gbl_CurrentLineOffset = 0;
95     Gbl_InputFieldCount = 0;
96     Gbl_InputByteCount = 0;
97     Gbl_NsLookupCount = 0;
98     Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
99 
100     Gbl_ErrorLog = NULL;
101     Gbl_NextError = NULL;
102     Gbl_Signature = NULL;
103     Gbl_FileType = 0;
104 
105     TotalExecutableOpcodes = 0;
106     TotalNamedObjects = 0;
107     TotalKeywords = 0;
108     TotalParseNodes = 0;
109     TotalMethods = 0;
110     TotalAllocations = 0;
111     TotalAllocated = 0;
112     TotalFolds = 0;
113 
114     AslGbl_NextEvent = 0;
115     for (i = 0; i < ASL_NUM_REPORT_LEVELS; i++)
116     {
117         Gbl_ExceptionCount[i] = 0;
118     }
119 
120     for (i = ASL_FILE_INPUT; i <= ASL_MAX_FILE_TYPE; i++)
121     {
122         Gbl_Files[i].Handle = NULL;
123         Gbl_Files[i].Filename = NULL;
124     }
125 }
126 
127 
128 /*******************************************************************************
129  *
130  * FUNCTION:    AslDetectSourceFileType
131  *
132  * PARAMETERS:  Info            - Name/Handle for the file (must be open)
133  *
134  * RETURN:      File Type
135  *
136  * DESCRIPTION: Determine the type of the input file. Either binary (contains
137  *              non-ASCII characters), ASL file, or an ACPI Data Table file.
138  *
139  ******************************************************************************/
140 
141 static UINT8
142 AslDetectSourceFileType (
143     ASL_FILE_INFO           *Info)
144 {
145     char                    *FileChar;
146     UINT8                   Type;
147     ACPI_STATUS             Status;
148 
149 
150     /* Check for a valid binary ACPI table */
151 
152     Status = FlCheckForAcpiTable (Info->Handle);
153     if (ACPI_SUCCESS (Status))
154     {
155         Type = ASL_INPUT_TYPE_ACPI_TABLE;
156         goto Cleanup;
157     }
158 
159     /* Check for 100% ASCII source file (comments are ignored) */
160 
161     Status = FlCheckForAscii (Info->Handle, Info->Filename, TRUE);
162     if (ACPI_FAILURE (Status))
163     {
164         printf ("Non-ascii input file - %s\n", Info->Filename);
165 
166         if (!Gbl_IgnoreErrors)
167         {
168             Type = ASL_INPUT_TYPE_BINARY;
169             goto Cleanup;
170         }
171     }
172 
173     /*
174      * File is ASCII. Determine if this is an ASL file or an ACPI data
175      * table file.
176      */
177     while (fgets (Gbl_CurrentLineBuffer, Gbl_LineBufferSize, Info->Handle))
178     {
179         /* Uppercase the buffer for caseless compare */
180 
181         FileChar = Gbl_CurrentLineBuffer;
182         while (*FileChar)
183         {
184             *FileChar = (char) toupper ((int) *FileChar);
185             FileChar++;
186         }
187 
188         /* Presence of "DefinitionBlock" indicates actual ASL code */
189 
190         if (strstr (Gbl_CurrentLineBuffer, "DEFINITIONBLOCK"))
191         {
192             /* Appears to be an ASL file */
193 
194             Type = ASL_INPUT_TYPE_ASCII_ASL;
195             goto Cleanup;
196         }
197     }
198 
199     /* Not an ASL source file, default to a data table source file */
200 
201     Type = ASL_INPUT_TYPE_ASCII_DATA;
202 
203 Cleanup:
204 
205     /* Must seek back to the start of the file */
206 
207     fseek (Info->Handle, 0, SEEK_SET);
208     return (Type);
209 }
210 
211 
212 /*******************************************************************************
213  *
214  * FUNCTION:    AslDoDisassembly
215  *
216  * PARAMETERS:  None
217  *
218  * RETURN:      Status
219  *
220  * DESCRIPTION: Initiate AML file disassembly. Uses ACPICA subsystem to build
221  *              namespace.
222  *
223  ******************************************************************************/
224 
225 static ACPI_STATUS
226 AslDoDisassembly (
227     void)
228 {
229     ACPI_STATUS             Status;
230 
231 
232     /* ACPICA subsystem initialization */
233 
234     Status = AdInitialize ();
235     if (ACPI_FAILURE (Status))
236     {
237         return (Status);
238     }
239 
240     Status = AcpiAllocateRootTable (4);
241     if (ACPI_FAILURE (Status))
242     {
243         AcpiOsPrintf ("Could not initialize ACPI Table Manager, %s\n",
244             AcpiFormatException (Status));
245         return (Status);
246     }
247 
248     /* This is where the disassembly happens */
249 
250     AcpiGbl_DbOpt_disasm = TRUE;
251     Status = AdAmlDisassemble (AslToFile,
252         Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_OutputFilenamePrefix,
253         &Gbl_Files[ASL_FILE_INPUT].Filename);
254     if (ACPI_FAILURE (Status))
255     {
256         return (Status);
257     }
258 
259     /* Check if any control methods were unresolved */
260 
261     AcpiDmUnresolvedWarning (0);
262 
263 #if 0
264     /* TBD: Handle additional output files for disassembler */
265 
266     Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix);
267     NsDisplayNamespace ();
268 #endif
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     /* Determine input file type */
362 
363     Gbl_FileType = AslDetectSourceFileType (&Gbl_Files[ASL_FILE_INPUT]);
364     if (Gbl_FileType == ASL_INPUT_TYPE_BINARY)
365     {
366         return (AE_ERROR);
367     }
368 
369     /*
370      * If -p not specified, we will use the input filename as the
371      * output filename prefix
372      */
373     if (Gbl_UseDefaultAmlFilename)
374     {
375         Gbl_OutputFilenamePrefix = Gbl_Files[ASL_FILE_INPUT].Filename;
376     }
377 
378     /* Open the optional output files (listings, etc.) */
379 
380     Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix);
381     if (ACPI_FAILURE (Status))
382     {
383         AePrintErrorLog (ASL_FILE_STDERR);
384         return (AE_ERROR);
385     }
386 
387     /*
388      * Compilation of ASL source versus DataTable source uses different
389      * compiler subsystems
390      */
391     switch (Gbl_FileType)
392     {
393     /*
394      * Data Table Compilation
395      */
396     case ASL_INPUT_TYPE_ASCII_DATA:
397 
398         Status = DtDoCompile ();
399         if (ACPI_FAILURE (Status))
400         {
401             return (Status);
402         }
403 
404         if (Gbl_Signature)
405         {
406             Gbl_Signature = NULL;
407         }
408 
409         /* Check if any errors occurred during compile */
410 
411         Status = AslCheckForErrorExit ();
412         if (ACPI_FAILURE (Status))
413         {
414             return (Status);
415         }
416 
417         /* Cleanup (for next source file) and exit */
418 
419         AeClearErrorLog ();
420         PrTerminatePreprocessor ();
421         return (Status);
422 
423     /*
424      * ASL Compilation
425      */
426     case ASL_INPUT_TYPE_ASCII_ASL:
427 
428         /* ACPICA subsystem initialization */
429 
430         Status = AdInitialize ();
431         if (ACPI_FAILURE (Status))
432         {
433             return (Status);
434         }
435 
436         (void) CmDoCompile ();
437         (void) AcpiTerminate ();
438 
439         /* Check if any errors occurred during compile */
440 
441         Status = AslCheckForErrorExit ();
442         if (ACPI_FAILURE (Status))
443         {
444             return (Status);
445         }
446 
447         /* Cleanup (for next source file) and exit */
448 
449         AeClearErrorLog ();
450         PrTerminatePreprocessor ();
451         return (AE_OK);
452 
453     /*
454      * Binary ACPI table was auto-detected, disassemble it
455      */
456     case ASL_INPUT_TYPE_ACPI_TABLE:
457 
458         /* We have what appears to be an ACPI table, disassemble it */
459 
460         FlCloseFile (ASL_FILE_INPUT);
461         Gbl_DoCompile = FALSE;
462         Gbl_DisasmFlag = TRUE;
463         Status = AslDoDisassembly ();
464         return (Status);
465 
466     /* Unknown binary table */
467 
468     case ASL_INPUT_TYPE_BINARY:
469 
470         AePrintErrorLog (ASL_FILE_STDERR);
471         return (AE_ERROR);
472 
473     default:
474 
475         printf ("Unknown file type %X\n", Gbl_FileType);
476         return (AE_ERROR);
477     }
478 }
479 
480 
481 /*******************************************************************************
482  *
483  * FUNCTION:    AslCheckForErrorExit
484  *
485  * PARAMETERS:  None. Examines global exception count array
486  *
487  * RETURN:      Status
488  *
489  * DESCRIPTION: Determine if compiler should abort with error status
490  *
491  ******************************************************************************/
492 
493 ACPI_STATUS
494 AslCheckForErrorExit (
495     void)
496 {
497 
498     /*
499      * Return non-zero exit code if there have been errors, unless the
500      * global ignore error flag has been set
501      */
502     if (!Gbl_IgnoreErrors)
503     {
504         if (Gbl_ExceptionCount[ASL_ERROR] > 0)
505         {
506             return (AE_ERROR);
507         }
508 
509         /* Optionally treat warnings as errors */
510 
511         if (Gbl_WarningsAsErrors)
512         {
513             if ((Gbl_ExceptionCount[ASL_WARNING] > 0)  ||
514                 (Gbl_ExceptionCount[ASL_WARNING2] > 0) ||
515                 (Gbl_ExceptionCount[ASL_WARNING3] > 0))
516             {
517                 return (AE_ERROR);
518             }
519         }
520     }
521 
522     return (AE_OK);
523 }
524