aemain.c revision 1.1.1.3
1/******************************************************************************
2 *
3 * Module Name: aemain - Main routine for the AcpiExec utility
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2011, 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 "aecommon.h"
45
46#ifdef _DEBUG
47#include <crtdbg.h>
48#endif
49
50#define _COMPONENT          PARSER
51        ACPI_MODULE_NAME    ("aemain")
52
53
54UINT8                   AcpiGbl_RegionFillValue = 0;
55BOOLEAN                 AcpiGbl_IgnoreErrors = FALSE;
56BOOLEAN                 AcpiGbl_DbOpt_NoRegionSupport = FALSE;
57BOOLEAN                 AcpiGbl_DebugTimeout = FALSE;
58
59static UINT8            AcpiGbl_BatchMode = 0;
60static char             BatchBuffer[128];
61static AE_TABLE_DESC    *AeTableListHead = NULL;
62
63#define ASL_MAX_FILES   256
64static char             *FileList[ASL_MAX_FILES];
65
66
67#define AE_SUPPORTED_OPTIONS    "?b:d:e:f:gm^ovx:"
68
69
70/******************************************************************************
71 *
72 * FUNCTION:    usage
73 *
74 * PARAMETERS:  None
75 *
76 * RETURN:      None
77 *
78 * DESCRIPTION: Print a usage message
79 *
80 *****************************************************************************/
81
82static void
83usage (void)
84{
85    printf ("Usage: acpiexec [options] AMLfile1 AMLfile2 ...\n\n");
86
87    printf ("Where:\n");
88    printf ("   -?                  Display this message\n");
89    printf ("   -b <CommandLine>    Batch mode command execution\n");
90    printf ("   -m [Method]         Batch mode method execution. Default=MAIN\n");
91    printf ("\n");
92
93    printf ("   -da                 Disable method abort on error\n");
94    printf ("   -di                 Disable execution of STA/INI methods during init\n");
95    printf ("   -do                 Disable Operation Region address simulation\n");
96    printf ("   -dr                 Disable repair of method return values\n");
97    printf ("   -dt                 Disable allocation tracking (performance)\n");
98    printf ("\n");
99
100    printf ("   -ef                 Enable display of final memory statistics\n");
101    printf ("   -em                 Enable Interpreter Serialized Mode\n");
102    printf ("   -es                 Enable Interpreter Slack Mode\n");
103    printf ("   -et                 Enable debug semaphore timeout\n");
104    printf ("\n");
105
106    printf ("   -f <Value>          Operation Region initialization fill value\n");
107    printf ("   -v                  Verbose initialization output\n");
108    printf ("   -x <DebugLevel>     Debug output level\n");
109}
110
111
112/******************************************************************************
113 *
114 * FUNCTION:    AcpiDbRunBatchMode
115 *
116 * PARAMETERS:  BatchCommandLine    - A semicolon separated list of commands
117 *                                    to be executed.
118 *                                    Use only commas to separate elements of
119 *                                    particular command.
120 * RETURN:      Status
121 *
122 * DESCRIPTION: For each command of list separated by ';' prepare the command
123 *              buffer and pass it to AcpiDbCommandDispatch.
124 *
125 *****************************************************************************/
126
127static ACPI_STATUS
128AcpiDbRunBatchMode (
129    void)
130{
131    ACPI_STATUS             Status;
132    char                    *Ptr = BatchBuffer;
133    char                    *Cmd = Ptr;
134    UINT8                   Run = 0;
135
136
137    AcpiGbl_MethodExecuting = FALSE;
138    AcpiGbl_StepToNextCall = FALSE;
139
140    while (*Ptr)
141    {
142        if (*Ptr == ',')
143        {
144            /* Convert commas to spaces */
145            *Ptr = ' ';
146        }
147        else if (*Ptr == ';')
148        {
149            *Ptr = '\0';
150            Run = 1;
151        }
152
153        Ptr++;
154
155        if (Run || (*Ptr == '\0'))
156        {
157            (void) AcpiDbCommandDispatch (Cmd, NULL, NULL);
158            Run = 0;
159            Cmd = Ptr;
160        }
161    }
162
163    Status = AcpiTerminate ();
164    return (Status);
165}
166
167
168/*******************************************************************************
169 *
170 * FUNCTION:    FlStrdup
171 *
172 * DESCRIPTION: Local strdup function
173 *
174 ******************************************************************************/
175
176static char *
177FlStrdup (
178    char                *String)
179{
180    char                *NewString;
181
182
183    NewString = AcpiOsAllocate (strlen (String) + 1);
184    if (!NewString)
185    {
186        return (NULL);
187    }
188
189    strcpy (NewString, String);
190    return (NewString);
191}
192
193
194/*******************************************************************************
195 *
196 * FUNCTION:    FlSplitInputPathname
197 *
198 * PARAMETERS:  InputFilename       - The user-specified ASL source file to be
199 *                                    compiled
200 *              OutDirectoryPath    - Where the directory path prefix is
201 *                                    returned
202 *              OutFilename         - Where the filename part is returned
203 *
204 * RETURN:      Status
205 *
206 * DESCRIPTION: Split the input path into a directory and filename part
207 *              1) Directory part used to open include files
208 *              2) Filename part used to generate output filenames
209 *
210 ******************************************************************************/
211
212ACPI_STATUS
213FlSplitInputPathname (
214    char                    *InputPath,
215    char                    **OutDirectoryPath,
216    char                    **OutFilename)
217{
218    char                    *Substring;
219    char                    *DirectoryPath;
220    char                    *Filename;
221
222
223    *OutDirectoryPath = NULL;
224    *OutFilename = NULL;
225
226    if (!InputPath)
227    {
228        return (AE_OK);
229    }
230
231    /* Get the path to the input filename's directory */
232
233    DirectoryPath = FlStrdup (InputPath);
234    if (!DirectoryPath)
235    {
236        return (AE_NO_MEMORY);
237    }
238
239    Substring = strrchr (DirectoryPath, '\\');
240    if (!Substring)
241    {
242        Substring = strrchr (DirectoryPath, '/');
243        if (!Substring)
244        {
245            Substring = strrchr (DirectoryPath, ':');
246        }
247    }
248
249    if (!Substring)
250    {
251        DirectoryPath[0] = 0;
252        Filename = FlStrdup (InputPath);
253    }
254    else
255    {
256        Filename = FlStrdup (Substring + 1);
257        *(Substring+1) = 0;
258    }
259
260    if (!Filename)
261    {
262        return (AE_NO_MEMORY);
263    }
264
265    *OutDirectoryPath = DirectoryPath;
266    *OutFilename = Filename;
267
268    return (AE_OK);
269}
270
271
272/******************************************************************************
273 *
274 * FUNCTION:    AsDoWildcard
275 *
276 * PARAMETERS:  DirectoryPathname   - Path to parent directory
277 *              FileSpecifier       - the wildcard specification (*.c, etc.)
278 *
279 * RETURN:      Pointer to a list of filenames
280 *
281 * DESCRIPTION: Process files via wildcards. This function is for the Windows
282 *              case only.
283 *
284 ******************************************************************************/
285
286static char **
287AsDoWildcard (
288    char                    *DirectoryPathname,
289    char                    *FileSpecifier)
290{
291#ifdef WIN32
292    void                    *DirInfo;
293    char                    *Filename;
294    int                     FileCount;
295
296
297    FileCount = 0;
298
299    /* Open parent directory */
300
301    DirInfo = AcpiOsOpenDirectory (DirectoryPathname, FileSpecifier, REQUEST_FILE_ONLY);
302    if (!DirInfo)
303    {
304        /* Either the directory or file does not exist */
305
306        printf ("File or directory %s%s does not exist\n", DirectoryPathname, FileSpecifier);
307        return (NULL);
308    }
309
310    /* Process each file that matches the wildcard specification */
311
312    while ((Filename = AcpiOsGetNextFilename (DirInfo)))
313    {
314        /* Add the filename to the file list */
315
316        FileList[FileCount] = AcpiOsAllocate (strlen (Filename) + 1);
317        strcpy (FileList[FileCount], Filename);
318        FileCount++;
319
320        if (FileCount >= ASL_MAX_FILES)
321        {
322            printf ("Max files reached\n");
323            FileList[0] = NULL;
324            return (FileList);
325        }
326    }
327
328    /* Cleanup */
329
330    AcpiOsCloseDirectory (DirInfo);
331    FileList[FileCount] = NULL;
332    return (FileList);
333
334#else
335    if (!FileSpecifier)
336    {
337        return (NULL);
338    }
339
340    /*
341     * Linux/Unix cases - Wildcards are expanded by the shell automatically.
342     * Just return the filename in a null terminated list
343     */
344    FileList[0] = AcpiOsAllocate (strlen (FileSpecifier) + 1);
345    strcpy (FileList[0], FileSpecifier);
346    FileList[1] = NULL;
347
348    return (FileList);
349#endif
350}
351
352
353/******************************************************************************
354 *
355 * FUNCTION:    main
356 *
357 * PARAMETERS:  argc, argv
358 *
359 * RETURN:      Status
360 *
361 * DESCRIPTION: Main routine for AcpiDump utility
362 *
363 *****************************************************************************/
364
365int ACPI_SYSTEM_XFACE
366main (
367    int                     argc,
368    char                    **argv)
369{
370    int                     j;
371    ACPI_STATUS             Status;
372    UINT32                  InitFlags;
373    ACPI_TABLE_HEADER       *Table = NULL;
374    UINT32                  TableCount;
375    AE_TABLE_DESC           *TableDesc;
376    char                    **WildcardList;
377    char                    *Filename;
378    char                    *Directory;
379    char                    *FullPathname;
380
381
382#ifdef _DEBUG
383    _CrtSetDbgFlag (_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF |
384                    _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
385#endif
386
387    printf (ACPI_COMMON_SIGNON ("AML Execution/Debug Utility"));
388
389    if (argc < 2)
390    {
391        usage ();
392        return (0);
393    }
394
395    signal (SIGINT, AeCtrlCHandler);
396
397    /* Init globals */
398
399    AcpiDbgLevel = ACPI_NORMAL_DEFAULT;
400    AcpiDbgLayer = 0xFFFFFFFF;
401
402    /* Init ACPI and start debugger thread */
403
404    Status = AcpiInitializeSubsystem ();
405    AE_CHECK_OK (AcpiInitializeSubsystem, Status);
406
407    /* Get the command line options */
408
409    while ((j = AcpiGetopt (argc, argv, AE_SUPPORTED_OPTIONS)) != EOF) switch(j)
410    {
411    case 'b':
412        if (strlen (AcpiGbl_Optarg) > 127)
413        {
414            printf ("**** The length of command line (%u) exceeded maximum (127)\n",
415                (UINT32) strlen (AcpiGbl_Optarg));
416            return (-1);
417        }
418        AcpiGbl_BatchMode = 1;
419        strcpy (BatchBuffer, AcpiGbl_Optarg);
420        break;
421
422    case 'd':
423        switch (AcpiGbl_Optarg[0])
424        {
425        case 'a':
426            AcpiGbl_IgnoreErrors = TRUE;
427            break;
428
429        case 'i':
430            AcpiGbl_DbOpt_ini_methods = FALSE;
431            break;
432
433        case 'o':
434            AcpiGbl_DbOpt_NoRegionSupport = TRUE;
435            break;
436
437        case 'r':
438            AcpiGbl_DisableAutoRepair = TRUE;
439            break;
440
441        case 't':
442            #ifdef ACPI_DBG_TRACK_ALLOCATIONS
443                AcpiGbl_DisableMemTracking = TRUE;
444            #endif
445            break;
446
447        default:
448            printf ("Unknown option: -d%s\n", AcpiGbl_Optarg);
449            return (-1);
450        }
451        break;
452
453    case 'e':
454        switch (AcpiGbl_Optarg[0])
455        {
456        case 'f':
457            #ifdef ACPI_DBG_TRACK_ALLOCATIONS
458                AcpiGbl_DisplayFinalMemStats = TRUE;
459            #endif
460            break;
461
462        case 'm':
463            AcpiGbl_AllMethodsSerialized = TRUE;
464            printf ("Enabling AML Interpreter serialized mode\n");
465            break;
466
467        case 's':
468            AcpiGbl_EnableInterpreterSlack = TRUE;
469            printf ("Enabling AML Interpreter slack mode\n");
470            break;
471
472        case 't':
473            AcpiGbl_DebugTimeout = TRUE;
474            break;
475
476        default:
477            printf ("Unknown option: -e%s\n", AcpiGbl_Optarg);
478            return (-1);
479        }
480        break;
481
482    case 'f':
483        AcpiGbl_RegionFillValue = (UINT8) strtoul (AcpiGbl_Optarg, NULL, 0);
484        break;
485
486    case 'g':
487        AcpiGbl_DbOpt_tables = TRUE;
488        AcpiGbl_DbFilename = NULL;
489        break;
490
491    case 'm':
492        AcpiGbl_BatchMode = 2;
493        switch (AcpiGbl_Optarg[0])
494        {
495        case '^':
496            strcpy (BatchBuffer, "MAIN");
497            break;
498
499        default:
500            strcpy (BatchBuffer, AcpiGbl_Optarg);
501            break;
502        }
503        break;
504
505    case 'o':
506        AcpiGbl_DbOpt_disasm = TRUE;
507        AcpiGbl_DbOpt_stats = TRUE;
508        break;
509
510    case 'v':
511        AcpiDbgLevel |= ACPI_LV_INIT_NAMES;
512        break;
513
514    case 'x':
515        AcpiDbgLevel = strtoul (AcpiGbl_Optarg, NULL, 0);
516        AcpiGbl_DbConsoleDebugLevel = AcpiDbgLevel;
517        printf ("Debug Level: 0x%8.8X\n", AcpiDbgLevel);
518        break;
519
520    case '?':
521    case 'h':
522    default:
523        usage();
524        return (-1);
525    }
526
527
528    InitFlags = (ACPI_NO_HANDLER_INIT | ACPI_NO_ACPI_ENABLE);
529    if (!AcpiGbl_DbOpt_ini_methods)
530    {
531        InitFlags |= (ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT);
532    }
533
534    /* The remaining arguments are filenames for ACPI tables */
535
536    if (argv[AcpiGbl_Optind])
537    {
538        AcpiGbl_DbOpt_tables = TRUE;
539        TableCount = 0;
540
541        /* Get each of the ACPI table files on the command line */
542
543        while (argv[AcpiGbl_Optind])
544        {
545            /* Split incoming path into a directory/filename combo */
546
547            Status = FlSplitInputPathname (argv[AcpiGbl_Optind], &Directory, &Filename);
548            if (ACPI_FAILURE (Status))
549            {
550                return (Status);
551            }
552
553            /* Expand wildcards (Windows only) */
554
555            WildcardList = AsDoWildcard (Directory, Filename);
556            if (!WildcardList)
557            {
558                return (-1);
559            }
560
561            while (*WildcardList)
562            {
563                FullPathname = AcpiOsAllocate (
564                    strlen (Directory) + strlen (*WildcardList) + 1);
565
566                /* Construct a full path to the file */
567
568                strcpy (FullPathname, Directory);
569                strcat (FullPathname, *WildcardList);
570
571                /* Get one table */
572
573                Status = AcpiDbReadTableFromFile (FullPathname, &Table);
574                if (ACPI_FAILURE (Status))
575                {
576                    printf ("**** Could not get input table %s, %s\n", FullPathname,
577                        AcpiFormatException (Status));
578                    goto enterloop;
579                }
580
581                AcpiOsFree (FullPathname);
582                AcpiOsFree (*WildcardList);
583                *WildcardList = NULL;
584                WildcardList++;
585
586                /*
587                 * Ignore an FACS or RSDT, we can't use them.
588                 */
589                if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_FACS) ||
590                    ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_RSDT))
591                {
592                    AcpiOsFree (Table);
593                    continue;
594                }
595
596                /* Allocate and link a table descriptor */
597
598                TableDesc = AcpiOsAllocate (sizeof (AE_TABLE_DESC));
599                TableDesc->Table = Table;
600                TableDesc->Next = AeTableListHead;
601                AeTableListHead = TableDesc;
602
603                TableCount++;
604            }
605
606            AcpiGbl_Optind++;
607        }
608
609        /* Build a local RSDT with all tables and let ACPICA process the RSDT */
610
611        Status = AeBuildLocalTables (TableCount, AeTableListHead);
612        if (ACPI_FAILURE (Status))
613        {
614            return (-1);
615        }
616
617        Status = AeInstallTables ();
618        if (ACPI_FAILURE (Status))
619        {
620            printf ("**** Could not load ACPI tables, %s\n", AcpiFormatException (Status));
621            goto enterloop;
622        }
623
624         /*
625          * Install most of the handlers.
626          * Override some default region handlers, especially SystemMemory
627          */
628        Status = AeInstallEarlyHandlers ();
629        if (ACPI_FAILURE (Status))
630        {
631            goto enterloop;
632        }
633
634        /*
635         * TBD: Need a way to call this after the "LOAD" command
636         */
637        Status = AcpiEnableSubsystem (InitFlags);
638        if (ACPI_FAILURE (Status))
639        {
640            printf ("**** Could not EnableSubsystem, %s\n", AcpiFormatException (Status));
641            goto enterloop;
642        }
643
644        Status = AcpiInitializeObjects (InitFlags);
645        if (ACPI_FAILURE (Status))
646        {
647            printf ("**** Could not InitializeObjects, %s\n", AcpiFormatException (Status));
648            goto enterloop;
649        }
650
651        /*
652         * Install handlers for "device driver" space IDs (EC,SMBus, etc.)
653         * and fixed event handlers
654         */
655        AeInstallLateHandlers ();
656        AeMiscellaneousTests ();
657    }
658
659enterloop:
660
661    if (AcpiGbl_BatchMode == 1)
662    {
663        AcpiDbRunBatchMode ();
664    }
665    else if (AcpiGbl_BatchMode == 2)
666    {
667        AcpiDbExecute (BatchBuffer, NULL, NULL, EX_NO_SINGLE_STEP);
668    }
669    else
670    {
671        /* Enter the debugger command loop */
672
673        AcpiDbUserCommands (ACPI_DEBUGGER_COMMAND_PROMPT, NULL);
674    }
675
676    return (0);
677}
678
679