xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslstartup.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
1 /******************************************************************************
2  *
3  * Module Name: aslstartup - Compiler startup routines, called from main
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 #include "acconvert.h"
49 
50 #define _COMPONENT          ACPI_COMPILER
51         ACPI_MODULE_NAME    ("aslstartup")
52 
53 
54 /* Local prototypes */
55 
56 static UINT8
57 AslDetectSourceFileType (
58     ASL_FILE_INFO           *Info);
59 
60 
61 /* Globals */
62 
63 static BOOLEAN          AslToFile = TRUE;
64 
65 
66 /*******************************************************************************
67  *
68  * FUNCTION:    AslInitializeGlobals
69  *
70  * PARAMETERS:  None
71  *
72  * RETURN:      None
73  *
74  * DESCRIPTION: Re-initialize globals needed to restart the compiler. This
75  *              allows multiple files to be disassembled and/or compiled.
76  *
77  ******************************************************************************/
78 
79 void
AslInitializeGlobals(void)80 AslInitializeGlobals (
81     void)
82 {
83     UINT32                  i;
84 
85 
86     /* Init compiler globals */
87 
88     AslGbl_SyntaxError = 0;
89     AslGbl_CurrentColumn = 0;
90     AslGbl_CurrentLineNumber = 1;
91     AslGbl_LogicalLineNumber = 1;
92     AslGbl_CurrentLineOffset = 0;
93     AslGbl_InputFieldCount = 0;
94     AslGbl_InputByteCount = 0;
95     AslGbl_NsLookupCount = 0;
96     AslGbl_LineBufPtr = AslGbl_CurrentLineBuffer;
97 
98     AslGbl_ErrorLog = NULL;
99     AslGbl_NextError = NULL;
100     AslGbl_Signature = NULL;
101     AslGbl_FileType = 0;
102 
103     AslGbl_TotalExecutableOpcodes = 0;
104     AslGbl_TotalNamedObjects = 0;
105     AslGbl_TotalKeywords = 0;
106     AslGbl_TotalParseNodes = 0;
107     AslGbl_TotalMethods = 0;
108     AslGbl_TotalAllocations = 0;
109     AslGbl_TotalAllocated = 0;
110     AslGbl_TotalFolds = 0;
111 
112     AslGbl_NextEvent = 0;
113     for (i = 0; i < ASL_NUM_REPORT_LEVELS; i++)
114     {
115         AslGbl_ExceptionCount[i] = 0;
116     }
117 
118     if (AcpiGbl_CaptureComments)
119     {
120         AslGbl_CommentState.SpacesBefore          = 0;
121         AslGbl_CommentState.CommentType           = 1;
122         AslGbl_CommentState.LatestParseOp         = NULL;
123         AslGbl_CommentState.ParsingParenBraceNode = NULL;
124         AslGbl_CommentState.CaptureComments       = TRUE;
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
AslDetectSourceFileType(ASL_FILE_INFO * Info)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 (AslGbl_CurrentLineBuffer, AslGbl_LineBufferSize, Info->Handle))
161         {
162             /* Uppercase the buffer for caseless compare */
163 
164             FileChar = AslGbl_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 (AslGbl_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     /*
189      * We have some sort of binary table; reopen in binary mode, then
190      * check for valid ACPI table
191      */
192     fclose (Info->Handle);
193     Info->Handle = fopen (Info->Filename, "rb");
194     if (!Info->Handle)
195     {
196         fprintf (stderr, "Could not open input file %s\n",
197             Info->Filename);
198     }
199 
200     Status = AcValidateTableHeader (Info->Handle, 0);
201     if (ACPI_SUCCESS (Status))
202     {
203         fprintf (stderr,
204             "Binary file appears to be a valid ACPI table, disassembling\n");
205 
206         Type = ASL_INPUT_TYPE_BINARY_ACPI_TABLE;
207         goto Cleanup;
208     }
209     else
210     {
211         fprintf (stderr,
212             "Binary file does not contain a valid standard ACPI table\n");
213     }
214 
215     Type = ASL_INPUT_TYPE_BINARY;
216 
217 
218 Cleanup:
219 
220     /* Must seek back to the start of the file */
221 
222     fseek (Info->Handle, 0, SEEK_SET);
223     return (Type);
224 }
225 
226 
227 /*******************************************************************************
228  *
229  * FUNCTION:    AslDoDisassembly
230  *
231  * PARAMETERS:  None
232  *
233  * RETURN:      Status
234  *
235  * DESCRIPTION: Initiate AML file disassembly. Uses ACPICA subsystem to build
236  *              namespace. This function assumes that the ACPI subsystem has
237  *              been initialized. The caller of the initialization will also
238  *              terminate the ACPI subsystem.
239  *
240  ******************************************************************************/
241 
242 ACPI_STATUS
AslDoDisassembly(void)243 AslDoDisassembly (
244     void)
245 {
246     ACPI_STATUS             Status;
247 
248 
249     Status = AcpiAllocateRootTable (4);
250     if (ACPI_FAILURE (Status))
251     {
252         AcpiOsPrintf ("Could not initialize ACPI Table Manager, %s\n",
253             AcpiFormatException (Status));
254         return (Status);
255     }
256 
257     /* This is where the disassembly happens */
258 
259     AcpiGbl_DmOpt_Disasm = TRUE;
260     Status = AdAmlDisassemble (AslToFile,
261         AslGbl_Files[ASL_FILE_INPUT].Filename, AslGbl_OutputFilenamePrefix,
262         &AslGbl_Files[ASL_FILE_INPUT].Filename);
263     if (ACPI_FAILURE (Status))
264     {
265         return (Status);
266     }
267 
268     /* Check if any control methods were unresolved */
269 
270     AcpiDmUnresolvedWarning (0);
271 
272     /* Clear Error log */
273 
274     AeClearErrorLog ();
275 
276     /*
277      * AslGbl_Files[ASL_FILE_INPUT].Filename was replaced with the
278      * .DSL disassembly file, which can now be compiled if requested
279      */
280     if (AslGbl_DoCompile)
281     {
282         AcpiOsPrintf ("\nCompiling \"%s\"\n",
283             AslGbl_Files[ASL_FILE_INPUT].Filename);
284         return (AE_CTRL_CONTINUE);
285     }
286 
287     return (AE_OK);
288 }
289 
290 
291 /*******************************************************************************
292  *
293  * FUNCTION:    AslDoOneFile
294  *
295  * PARAMETERS:  Filename        - Name of the file
296  *
297  * RETURN:      Status
298  *
299  * DESCRIPTION: Process a single file - either disassemble, compile, or both
300  *
301  ******************************************************************************/
302 
303 ACPI_STATUS
AslDoOneFile(char * Filename)304 AslDoOneFile (
305     char                    *Filename)
306 {
307     ACPI_STATUS             Status;
308     UINT8                   Event;
309     ASL_GLOBAL_FILE_NODE    *FileNode;
310 
311 
312     /* Re-initialize "some" compiler/preprocessor globals */
313 
314     AslInitializeGlobals ();
315     PrInitializeGlobals ();
316 
317     /*
318      * Extract the directory path. This path is used for possible include
319      * files and the optional AML filename embedded in the input file
320      * DefinitionBlock declaration.
321      */
322     Status = FlSplitInputPathname (Filename, &AslGbl_DirectoryPath, NULL);
323     if (ACPI_FAILURE (Status))
324     {
325         return (Status);
326     }
327 
328     /*
329      * There was an input file detected at this point. Each input ASL file is
330      * associated with one global file node consisting of the input file and
331      * all output files associated with it. This is useful when compiling
332      * multiple files in one command.
333      */
334     Status = FlInitOneFile(Filename);
335     if (ACPI_FAILURE (Status))
336     {
337         return (AE_ERROR);
338     }
339 
340     /* Take a copy of the input filename, convert any backslashes */
341 
342     AslGbl_Files[ASL_FILE_INPUT].Filename =
343         UtLocalCacheCalloc (strlen (Filename) + 1);
344 
345     strcpy (AslGbl_Files[ASL_FILE_INPUT].Filename, Filename);
346     UtConvertBackslashes (AslGbl_Files[ASL_FILE_INPUT].Filename);
347 
348     /*
349      * Open the input file. Here, this could be an ASCII source file,
350      * either an ASL file or a Data Table file, or a binary AML file
351      * or binary data table file (For disassembly).
352      */
353     Status = FlOpenInputFile (AslGbl_Files[ASL_FILE_INPUT].Filename);
354     if (ACPI_FAILURE (Status))
355     {
356         AePrintErrorLog (ASL_FILE_STDERR);
357         return (AE_ERROR);
358     }
359 
360     FileNode = FlGetCurrentFileNode();
361 
362     /* Determine input file type */
363 
364     AslGbl_FileType = AslDetectSourceFileType (&AslGbl_Files[ASL_FILE_INPUT]);
365     FileNode->FileType = AslGbl_FileType;
366     if (AslGbl_FileType == ASL_INPUT_TYPE_BINARY)
367     {
368         return (AE_ERROR);
369     }
370 
371     FileNode->OriginalInputFileSize = FlGetFileSize (ASL_FILE_INPUT);
372 
373     /*
374      * If -p not specified, we will use the input filename as the
375      * output filename prefix
376      */
377     if (AslGbl_UseDefaultAmlFilename)
378     {
379         AslGbl_OutputFilenamePrefix = AslGbl_Files[ASL_FILE_INPUT].Filename;
380     }
381 
382     /*
383      * Open the output file. Note: by default, the name of this file comes from
384      * the table descriptor within the input file.
385      */
386     if (AslGbl_FileType == ASL_INPUT_TYPE_ASCII_ASL)
387     {
388         Event = UtBeginEvent ("Open AML output file");
389         Status = FlOpenAmlOutputFile (AslGbl_OutputFilenamePrefix);
390         UtEndEvent (Event);
391         if (ACPI_FAILURE (Status))
392         {
393             AePrintErrorLog (ASL_FILE_STDERR);
394             return (AE_ERROR);
395         }
396     }
397 
398     /* Open the optional output files (listings, etc.) */
399 
400     Status = FlOpenMiscOutputFiles (AslGbl_OutputFilenamePrefix);
401     if (ACPI_FAILURE (Status))
402     {
403         AePrintErrorLog (ASL_FILE_STDERR);
404         return (AE_ERROR);
405     }
406 
407     /*
408      * Compilation of ASL source versus DataTable source uses different
409      * compiler subsystems
410      */
411     switch (AslGbl_FileType)
412     {
413     /*
414      * Data Table Compilation
415      */
416     case ASL_INPUT_TYPE_ASCII_DATA:
417 
418         Status = DtDoCompile ();
419         if (ACPI_FAILURE (Status))
420         {
421             return (Status);
422         }
423 
424         if (AslGbl_Signature)
425         {
426             AslGbl_Signature = NULL;
427         }
428 
429         /* Check if any errors occurred during compile */
430 
431         Status = AslCheckForErrorExit ();
432         if (ACPI_FAILURE (Status))
433         {
434             return (Status);
435         }
436 
437         /* Cleanup (for next source file) and exit */
438 
439         AeClearErrorLog ();
440         PrTerminatePreprocessor ();
441         return (Status);
442 
443     /*
444      * ASL Compilation
445      */
446     case ASL_INPUT_TYPE_ASCII_ASL:
447 
448         Status = CmDoCompile ();
449         if (ACPI_FAILURE (Status))
450         {
451             PrTerminatePreprocessor ();
452             return (Status);
453         }
454 
455         /*
456          * At this point, we know how many lines are in the input file. Save it
457          * to display for post-compilation summary.
458          */
459         FileNode->TotalLineCount = AslGbl_CurrentLineNumber;
460         return (AE_OK);
461 
462     /*
463      * Binary ACPI table was auto-detected, disassemble it
464      */
465     case ASL_INPUT_TYPE_BINARY_ACPI_TABLE:
466 
467         /* We have what appears to be an ACPI table, disassemble it */
468 
469         FlCloseFile (ASL_FILE_INPUT);
470         AslGbl_DoCompile = FALSE;
471         AcpiGbl_DisasmFlag = TRUE;
472         Status = AslDoDisassembly ();
473         return (Status);
474 
475     /* Unknown binary table */
476 
477     case ASL_INPUT_TYPE_BINARY:
478 
479         AePrintErrorLog (ASL_FILE_STDERR);
480         return (AE_ERROR);
481 
482     default:
483 
484         printf ("Unknown file type %X\n", AslGbl_FileType);
485         return (AE_ERROR);
486     }
487 }
488 
489 
490 /*******************************************************************************
491  *
492  * FUNCTION:    AslCheckForErrorExit
493  *
494  * PARAMETERS:  None. Examines global exception count array
495  *
496  * RETURN:      Status
497  *
498  * DESCRIPTION: Determine if compiler should abort with error status
499  *
500  ******************************************************************************/
501 
502 ACPI_STATUS
AslCheckForErrorExit(void)503 AslCheckForErrorExit (
504     void)
505 {
506 
507     /*
508      * Return non-zero exit code if there have been errors, unless the
509      * global ignore error flag has been set
510      */
511     if (!AslGbl_IgnoreErrors)
512     {
513         if (AslGbl_ExceptionCount[ASL_ERROR] > 0)
514         {
515             return (AE_ERROR);
516         }
517 
518         /* Optionally treat warnings as errors */
519 
520         if (AslGbl_WarningsAsErrors)
521         {
522             if ((AslGbl_ExceptionCount[ASL_WARNING] > 0)  ||
523                 (AslGbl_ExceptionCount[ASL_WARNING2] > 0) ||
524                 (AslGbl_ExceptionCount[ASL_WARNING3] > 0))
525             {
526                 AslError (ASL_ERROR, ASL_MSG_WARNING_AS_ERROR, NULL,
527                     "(reporting warnings as errors)");
528                 return (AE_ERROR);
529             }
530         }
531     }
532 
533     return (AE_OK);
534 }
535