1/******************************************************************************
2 *
3 * Module Name: aslstartup - Compiler startup routines, called from main
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, 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
45#include <contrib/dev/acpica/compiler/aslcompiler.h>
46#include <contrib/dev/acpica/include/actables.h>
47#include <contrib/dev/acpica/include/acdisasm.h>
48#include <contrib/dev/acpica/include/acapps.h>
49
50#define _COMPONENT          ACPI_COMPILER
51        ACPI_MODULE_NAME    ("aslstartup")
52
53
54#define ASL_MAX_FILES   256
55static char             *FileList[ASL_MAX_FILES];
56static BOOLEAN          AslToFile = TRUE;
57
58
59/* Local prototypes */
60
61static char **
62AsDoWildcard (
63    char                    *DirectoryPathname,
64    char                    *FileSpecifier);
65
66static UINT8
67AslDetectSourceFileType (
68    ASL_FILE_INFO           *Info);
69
70static ACPI_STATUS
71AslDoDisassembly (
72    void);
73
74
75/*******************************************************************************
76 *
77 * FUNCTION:    AslInitializeGlobals
78 *
79 * PARAMETERS:  None
80 *
81 * RETURN:      None
82 *
83 * DESCRIPTION: Re-initialize globals needed to restart the compiler. This
84 *              allows multiple files to be disassembled and/or compiled.
85 *
86 ******************************************************************************/
87
88void
89AslInitializeGlobals (
90    void)
91{
92    UINT32                  i;
93
94
95    /* Init compiler globals */
96
97    Gbl_CurrentColumn = 0;
98    Gbl_CurrentLineNumber = 1;
99    Gbl_LogicalLineNumber = 1;
100    Gbl_CurrentLineOffset = 0;
101    Gbl_InputFieldCount = 0;
102    Gbl_InputByteCount = 0;
103    Gbl_NsLookupCount = 0;
104    Gbl_LineBufPtr = Gbl_CurrentLineBuffer;
105
106    Gbl_ErrorLog = NULL;
107    Gbl_NextError = NULL;
108    Gbl_Signature = NULL;
109    Gbl_FileType = 0;
110
111    TotalExecutableOpcodes = 0;
112    TotalNamedObjects = 0;
113    TotalKeywords = 0;
114    TotalParseNodes = 0;
115    TotalMethods = 0;
116    TotalAllocations = 0;
117    TotalAllocated = 0;
118    TotalFolds = 0;
119
120    AslGbl_NextEvent = 0;
121    for (i = 0; i < ASL_NUM_REPORT_LEVELS; i++)
122    {
123        Gbl_ExceptionCount[i] = 0;
124    }
125
126    for (i = ASL_FILE_INPUT; i <= ASL_MAX_FILE_TYPE; i++)
127    {
128        Gbl_Files[i].Handle = NULL;
129        Gbl_Files[i].Filename = NULL;
130    }
131}
132
133
134/******************************************************************************
135 *
136 * FUNCTION:    AsDoWildcard
137 *
138 * PARAMETERS:  None
139 *
140 * RETURN:      None
141 *
142 * DESCRIPTION: Process files via wildcards. This function is for the Windows
143 *              case only.
144 *
145 ******************************************************************************/
146
147static char **
148AsDoWildcard (
149    char                    *DirectoryPathname,
150    char                    *FileSpecifier)
151{
152#ifdef WIN32
153    void                    *DirInfo;
154    char                    *Filename;
155    int                     FileCount;
156
157
158    FileCount = 0;
159
160    /* Open parent directory */
161
162    DirInfo = AcpiOsOpenDirectory (DirectoryPathname, FileSpecifier, REQUEST_FILE_ONLY);
163    if (!DirInfo)
164    {
165        /* Either the directory of file does not exist */
166
167        Gbl_Files[ASL_FILE_INPUT].Filename = FileSpecifier;
168        FlFileError (ASL_FILE_INPUT, ASL_MSG_OPEN);
169        AslAbort ();
170    }
171
172    /* Process each file that matches the wildcard specification */
173
174    while ((Filename = AcpiOsGetNextFilename (DirInfo)))
175    {
176        /* Add the filename to the file list */
177
178        FileList[FileCount] = AcpiOsAllocate (strlen (Filename) + 1);
179        strcpy (FileList[FileCount], Filename);
180        FileCount++;
181
182        if (FileCount >= ASL_MAX_FILES)
183        {
184            printf ("Max files reached\n");
185            FileList[0] = NULL;
186            return (FileList);
187        }
188    }
189
190    /* Cleanup */
191
192    AcpiOsCloseDirectory (DirInfo);
193    FileList[FileCount] = NULL;
194    return (FileList);
195
196#else
197    /*
198     * Linux/Unix cases - Wildcards are expanded by the shell automatically.
199     * Just return the filename in a null terminated list
200     */
201    FileList[0] = AcpiOsAllocate (strlen (FileSpecifier) + 1);
202    strcpy (FileList[0], FileSpecifier);
203    FileList[1] = NULL;
204
205    return (FileList);
206#endif
207}
208
209
210/*******************************************************************************
211 *
212 * FUNCTION:    AslDetectSourceFileType
213 *
214 * PARAMETERS:  Info            - Name/Handle for the file (must be open)
215 *
216 * RETURN:      File Type
217 *
218 * DESCRIPTION: Determine the type of the input file. Either binary (contains
219 *              non-ASCII characters), ASL file, or an ACPI Data Table file.
220 *
221 ******************************************************************************/
222
223static UINT8
224AslDetectSourceFileType (
225    ASL_FILE_INFO           *Info)
226{
227    char                    *FileChar;
228    UINT8                   Type;
229    ACPI_STATUS             Status;
230
231
232    /* Check for a valid binary ACPI table */
233
234    Status = FlCheckForAcpiTable (Info->Handle);
235    if (ACPI_SUCCESS (Status))
236    {
237        Type = ASL_INPUT_TYPE_ACPI_TABLE;
238        goto Cleanup;
239    }
240
241    /* Check for 100% ASCII source file (comments are ignored) */
242
243    Status = FlCheckForAscii (Info->Handle, Info->Filename, TRUE);
244    if (ACPI_FAILURE (Status))
245    {
246        printf ("Non-ascii input file - %s\n", Info->Filename);
247
248        if (!Gbl_IgnoreErrors)
249        {
250            Type = ASL_INPUT_TYPE_BINARY;
251            goto Cleanup;
252        }
253    }
254
255    /*
256     * File is ASCII. Determine if this is an ASL file or an ACPI data
257     * table file.
258     */
259    while (fgets (Gbl_CurrentLineBuffer, Gbl_LineBufferSize, Info->Handle))
260    {
261        /* Uppercase the buffer for caseless compare */
262
263        FileChar = Gbl_CurrentLineBuffer;
264        while (*FileChar)
265        {
266            *FileChar = (char) toupper ((int) *FileChar);
267            FileChar++;
268        }
269
270        /* Presence of "DefinitionBlock" indicates actual ASL code */
271
272        if (strstr (Gbl_CurrentLineBuffer, "DEFINITIONBLOCK"))
273        {
274            /* Appears to be an ASL file */
275
276            Type = ASL_INPUT_TYPE_ASCII_ASL;
277            goto Cleanup;
278        }
279    }
280
281    /* Not an ASL source file, default to a data table source file */
282
283    Type = ASL_INPUT_TYPE_ASCII_DATA;
284
285Cleanup:
286
287    /* Must seek back to the start of the file */
288
289    fseek (Info->Handle, 0, SEEK_SET);
290    return (Type);
291}
292
293
294/*******************************************************************************
295 *
296 * FUNCTION:    AslDoDisassembly
297 *
298 * PARAMETERS:  None
299 *
300 * RETURN:      Status
301 *
302 * DESCRIPTION: Initiate AML file disassembly. Uses ACPICA subsystem to build
303 *              namespace.
304 *
305 ******************************************************************************/
306
307static ACPI_STATUS
308AslDoDisassembly (
309    void)
310{
311    ACPI_STATUS             Status;
312
313
314    /* ACPICA subsystem initialization */
315
316    Status = AdInitialize ();
317    if (ACPI_FAILURE (Status))
318    {
319        return (Status);
320    }
321
322    Status = AcpiAllocateRootTable (4);
323    if (ACPI_FAILURE (Status))
324    {
325        AcpiOsPrintf ("Could not initialize ACPI Table Manager, %s\n",
326            AcpiFormatException (Status));
327        return (Status);
328    }
329
330    /* This is where the disassembly happens */
331
332    AcpiGbl_DbOpt_disasm = TRUE;
333    Status = AdAmlDisassemble (AslToFile,
334        Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_OutputFilenamePrefix,
335        &Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_GetAllTables);
336    if (ACPI_FAILURE (Status))
337    {
338        return (Status);
339    }
340
341    /* Check if any control methods were unresolved */
342
343    AcpiDmUnresolvedWarning (0);
344
345#if 0
346    /* TBD: Handle additional output files for disassembler */
347
348    Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix);
349    NsDisplayNamespace ();
350#endif
351
352    /* Shutdown compiler and ACPICA subsystem */
353
354    AeClearErrorLog ();
355    (void) AcpiTerminate ();
356
357    /*
358     * Gbl_Files[ASL_FILE_INPUT].Filename was replaced with the
359     * .DSL disassembly file, which can now be compiled if requested
360     */
361    if (Gbl_DoCompile)
362    {
363        AcpiOsPrintf ("\nCompiling \"%s\"\n",
364            Gbl_Files[ASL_FILE_INPUT].Filename);
365        return (AE_CTRL_CONTINUE);
366    }
367
368    ACPI_FREE (Gbl_Files[ASL_FILE_INPUT].Filename);
369    Gbl_Files[ASL_FILE_INPUT].Filename = NULL;
370    return (AE_OK);
371}
372
373
374/*******************************************************************************
375 *
376 * FUNCTION:    AslDoOneFile
377 *
378 * PARAMETERS:  Filename        - Name of the file
379 *
380 * RETURN:      Status
381 *
382 * DESCRIPTION: Process a single file - either disassemble, compile, or both
383 *
384 ******************************************************************************/
385
386ACPI_STATUS
387AslDoOneFile (
388    char                    *Filename)
389{
390    ACPI_STATUS             Status;
391
392
393    /* Re-initialize "some" compiler/preprocessor globals */
394
395    AslInitializeGlobals ();
396    PrInitializeGlobals ();
397
398    Gbl_Files[ASL_FILE_INPUT].Filename = Filename;
399
400    /*
401     * AML Disassembly (Optional)
402     */
403    if (Gbl_DisasmFlag || Gbl_GetAllTables)
404    {
405        Status = AslDoDisassembly ();
406        if (Status != AE_CTRL_CONTINUE)
407        {
408            return (Status);
409        }
410    }
411
412    /*
413     * Open the input file. Here, this should be an ASCII source file,
414     * either an ASL file or a Data Table file
415     */
416    Status = FlOpenInputFile (Gbl_Files[ASL_FILE_INPUT].Filename);
417    if (ACPI_FAILURE (Status))
418    {
419        AePrintErrorLog (ASL_FILE_STDERR);
420        return (AE_ERROR);
421    }
422
423    /* Determine input file type */
424
425    Gbl_FileType = AslDetectSourceFileType (&Gbl_Files[ASL_FILE_INPUT]);
426    if (Gbl_FileType == ASL_INPUT_TYPE_BINARY)
427    {
428        return (AE_ERROR);
429    }
430
431    /*
432     * If -p not specified, we will use the input filename as the
433     * output filename prefix
434     */
435    if (Gbl_UseDefaultAmlFilename)
436    {
437        Gbl_OutputFilenamePrefix = Gbl_Files[ASL_FILE_INPUT].Filename;
438    }
439
440    /* Open the optional output files (listings, etc.) */
441
442    Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix);
443    if (ACPI_FAILURE (Status))
444    {
445        AePrintErrorLog (ASL_FILE_STDERR);
446        return (AE_ERROR);
447    }
448
449    /*
450     * Compilation of ASL source versus DataTable source uses different
451     * compiler subsystems
452     */
453    switch (Gbl_FileType)
454    {
455    /*
456     * Data Table Compilation
457     */
458    case ASL_INPUT_TYPE_ASCII_DATA:
459
460        Status = DtDoCompile ();
461        if (ACPI_FAILURE (Status))
462        {
463            return (Status);
464        }
465
466        if (Gbl_Signature)
467        {
468            ACPI_FREE (Gbl_Signature);
469            Gbl_Signature = NULL;
470        }
471
472        /* Check if any errors occurred during compile */
473
474        Status = AslCheckForErrorExit ();
475        if (ACPI_FAILURE (Status))
476        {
477            return (Status);
478        }
479
480        /* Cleanup (for next source file) and exit */
481
482        AeClearErrorLog ();
483        PrTerminatePreprocessor ();
484        return (Status);
485
486    /*
487     * ASL Compilation
488     */
489    case ASL_INPUT_TYPE_ASCII_ASL:
490
491        /* ACPICA subsystem initialization */
492
493        Status = AdInitialize ();
494        if (ACPI_FAILURE (Status))
495        {
496            return (Status);
497        }
498
499        (void) CmDoCompile ();
500        (void) AcpiTerminate ();
501
502        /* Check if any errors occurred during compile */
503
504        Status = AslCheckForErrorExit ();
505        if (ACPI_FAILURE (Status))
506        {
507            return (Status);
508        }
509
510        /* Cleanup (for next source file) and exit */
511
512        AeClearErrorLog ();
513        PrTerminatePreprocessor ();
514        return (AE_OK);
515
516    /*
517     * Binary ACPI table was auto-detected, disassemble it
518     */
519    case ASL_INPUT_TYPE_ACPI_TABLE:
520
521        /* We have what appears to be an ACPI table, disassemble it */
522
523        FlCloseFile (ASL_FILE_INPUT);
524        Gbl_DoCompile = FALSE;
525        Gbl_DisasmFlag = TRUE;
526        Status = AslDoDisassembly ();
527        return (Status);
528
529    /* Unknown binary table */
530
531    case ASL_INPUT_TYPE_BINARY:
532
533        AePrintErrorLog (ASL_FILE_STDERR);
534        return (AE_ERROR);
535
536    default:
537
538        printf ("Unknown file type %X\n", Gbl_FileType);
539        return (AE_ERROR);
540    }
541}
542
543
544/*******************************************************************************
545 *
546 * FUNCTION:    AslDoOnePathname
547 *
548 * PARAMETERS:  Pathname            - Full pathname, possibly with wildcards
549 *
550 * RETURN:      Status
551 *
552 * DESCRIPTION: Process one pathname, possible terminated with a wildcard
553 *              specification. If a wildcard, it is expanded and the multiple
554 *              files are processed.
555 *
556 ******************************************************************************/
557
558ACPI_STATUS
559AslDoOnePathname (
560    char                    *Pathname,
561    ASL_PATHNAME_CALLBACK   PathCallback)
562{
563    ACPI_STATUS             Status = AE_OK;
564    char                    **WildcardList;
565    char                    *Filename;
566    char                    *FullPathname;
567
568
569    /* Split incoming path into a directory/filename combo */
570
571    Status = FlSplitInputPathname (Pathname, &Gbl_DirectoryPath, &Filename);
572    if (ACPI_FAILURE (Status))
573    {
574        return (Status);
575    }
576
577    /* Expand possible wildcard into a file list (Windows/DOS only) */
578
579    WildcardList = AsDoWildcard (Gbl_DirectoryPath, Filename);
580    while (*WildcardList)
581    {
582        FullPathname = ACPI_ALLOCATE (
583            strlen (Gbl_DirectoryPath) + strlen (*WildcardList) + 1);
584
585        /* Construct a full path to the file */
586
587        strcpy (FullPathname, Gbl_DirectoryPath);
588        strcat (FullPathname, *WildcardList);
589
590        /*
591         * If -p not specified, we will use the input filename as the
592         * output filename prefix
593         */
594        if (Gbl_UseDefaultAmlFilename)
595        {
596            Gbl_OutputFilenamePrefix = FullPathname;
597        }
598
599        /* Save status from all compiles */
600
601        Status |= (*PathCallback) (FullPathname);
602
603        ACPI_FREE (FullPathname);
604        ACPI_FREE (*WildcardList);
605        *WildcardList = NULL;
606        WildcardList++;
607    }
608
609    ACPI_FREE (Gbl_DirectoryPath);
610    ACPI_FREE (Filename);
611    return (Status);
612}
613
614
615/*******************************************************************************
616 *
617 * FUNCTION:    AslCheckForErrorExit
618 *
619 * PARAMETERS:  None. Examines global exception count array
620 *
621 * RETURN:      Status
622 *
623 * DESCRIPTION: Determine if compiler should abort with error status
624 *
625 ******************************************************************************/
626
627ACPI_STATUS
628AslCheckForErrorExit (
629    void)
630{
631
632    /*
633     * Return non-zero exit code if there have been errors, unless the
634     * global ignore error flag has been set
635     */
636    if (!Gbl_IgnoreErrors)
637    {
638        if (Gbl_ExceptionCount[ASL_ERROR] > 0)
639        {
640            return (AE_ERROR);
641        }
642
643        /* Optionally treat warnings as errors */
644
645        if (Gbl_WarningsAsErrors)
646        {
647            if ((Gbl_ExceptionCount[ASL_WARNING] > 0)  ||
648                (Gbl_ExceptionCount[ASL_WARNING2] > 0) ||
649                (Gbl_ExceptionCount[ASL_WARNING3] > 0))
650            {
651                return (AE_ERROR);
652            }
653        }
654    }
655
656    return (AE_OK);
657}
658