aemain.c revision 1.1.1.5
1/******************************************************************************
2 *
3 * Module Name: aemain - Main routine for the AcpiExec utility
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 "aecommon.h"
45
46#define _COMPONENT          ACPI_TOOLS
47        ACPI_MODULE_NAME    ("aemain")
48
49
50/*
51 * Main routine for the ACPI user-space execution utility.
52 *
53 * Portability note: The utility depends upon the host for command-line
54 * wildcard support - it is not implemented locally. For example:
55 *
56 * Linux/Unix systems: Shell expands wildcards automatically.
57 *
58 * Windows: The setargv.obj module must be linked in to automatically
59 * expand wildcards.
60 */
61extern BOOLEAN              AcpiGbl_DebugTimeout;
62
63/* Local prototypes */
64
65static int
66AeDoOptions (
67    int                     argc,
68    char                    **argv);
69
70static ACPI_STATUS
71AcpiDbRunBatchMode (
72    void);
73
74
75#define AE_BUFFER_SIZE              1024
76#define ASL_MAX_FILES               256
77
78/* Execution modes */
79
80#define AE_MODE_COMMAND_LOOP        0   /* Normal command execution loop */
81#define AE_MODE_BATCH_MULTIPLE      1   /* -b option to execute a command line */
82#define AE_MODE_BATCH_SINGLE        2   /* -m option to execute a single control method */
83
84
85/* Globals */
86
87UINT8                       AcpiGbl_RegionFillValue = 0;
88BOOLEAN                     AcpiGbl_IgnoreErrors = FALSE;
89BOOLEAN                     AcpiGbl_DbOpt_NoRegionSupport = FALSE;
90UINT8                       AcpiGbl_UseHwReducedFadt = FALSE;
91BOOLEAN                     AcpiGbl_DoInterfaceTests = FALSE;
92BOOLEAN                     AcpiGbl_LoadTestTables = FALSE;
93static UINT8                AcpiGbl_ExecutionMode = AE_MODE_COMMAND_LOOP;
94static char                 BatchBuffer[AE_BUFFER_SIZE];    /* Batch command buffer */
95static AE_TABLE_DESC        *AeTableListHead = NULL;
96
97#define ACPIEXEC_NAME               "AML Execution/Debug Utility"
98#define AE_SUPPORTED_OPTIONS        "?b:d:e:f:ghm^orv^:x:"
99
100
101/* Stubs for the disassembler */
102
103void
104MpSaveGpioInfo (
105    ACPI_PARSE_OBJECT       *Op,
106    AML_RESOURCE            *Resource,
107    UINT32                  PinCount,
108    UINT16                  *PinList,
109    char                    *DeviceName)
110{
111}
112
113void
114MpSaveSerialInfo (
115    ACPI_PARSE_OBJECT       *Op,
116    AML_RESOURCE            *Resource,
117    char                    *DeviceName)
118{
119}
120
121
122/******************************************************************************
123 *
124 * FUNCTION:    usage
125 *
126 * PARAMETERS:  None
127 *
128 * RETURN:      None
129 *
130 * DESCRIPTION: Print a usage message
131 *
132 *****************************************************************************/
133
134static void
135usage (
136    void)
137{
138
139    ACPI_USAGE_HEADER ("acpiexec [options] AMLfile1 AMLfile2 ...");
140
141    ACPI_OPTION ("-b \"CommandLine\"",  "Batch mode command line execution (cmd1;cmd2;...)");
142    ACPI_OPTION ("-h -?",               "Display this help message");
143    ACPI_OPTION ("-m [Method]",         "Batch mode method execution. Default=MAIN");
144    printf ("\n");
145
146    ACPI_OPTION ("-da",                 "Disable method abort on error");
147    ACPI_OPTION ("-di",                 "Disable execution of STA/INI methods during init");
148    ACPI_OPTION ("-do",                 "Disable Operation Region address simulation");
149    ACPI_OPTION ("-dr",                 "Disable repair of method return values");
150    ACPI_OPTION ("-ds",                 "Disable method auto-serialization");
151    ACPI_OPTION ("-dt",                 "Disable allocation tracking (performance)");
152    printf ("\n");
153
154    ACPI_OPTION ("-ef",                 "Enable display of final memory statistics");
155    ACPI_OPTION ("-ei",                 "Enable additional tests for ACPICA interfaces");
156    ACPI_OPTION ("-el",                 "Enable loading of additional test tables");
157    ACPI_OPTION ("-es",                 "Enable Interpreter Slack Mode");
158    ACPI_OPTION ("-et",                 "Enable debug semaphore timeout");
159    printf ("\n");
160
161    ACPI_OPTION ("-f <Value>",          "Operation Region initialization fill value");
162    ACPI_OPTION ("-r",                  "Use hardware-reduced FADT V5");
163    ACPI_OPTION ("-v",                  "Display version information");
164    ACPI_OPTION ("-vi",                 "Verbose initialization output");
165    ACPI_OPTION ("-vr",                 "Verbose region handler output");
166    ACPI_OPTION ("-x <DebugLevel>",     "Debug output level");
167}
168
169
170/******************************************************************************
171 *
172 * FUNCTION:    AeDoOptions
173 *
174 * PARAMETERS:  argc/argv           - Standard argc/argv
175 *
176 * RETURN:      Status
177 *
178 * DESCRIPTION: Command line option processing
179 *
180 *****************************************************************************/
181
182static int
183AeDoOptions (
184    int                     argc,
185    char                    **argv)
186{
187    int                     j;
188
189
190    while ((j = AcpiGetopt (argc, argv, AE_SUPPORTED_OPTIONS)) != ACPI_OPT_END) switch (j)
191    {
192    case 'b':
193
194        if (strlen (AcpiGbl_Optarg) > (AE_BUFFER_SIZE -1))
195        {
196            printf ("**** The length of command line (%u) exceeded maximum (%u)\n",
197                (UINT32) strlen (AcpiGbl_Optarg), (AE_BUFFER_SIZE -1));
198            return (-1);
199        }
200        AcpiGbl_ExecutionMode = AE_MODE_BATCH_MULTIPLE;
201        strcpy (BatchBuffer, AcpiGbl_Optarg);
202        break;
203
204    case 'd':
205
206        switch (AcpiGbl_Optarg[0])
207        {
208        case 'a':
209
210            AcpiGbl_IgnoreErrors = TRUE;
211            break;
212
213        case 'i':
214
215            AcpiGbl_DbOpt_ini_methods = FALSE;
216            break;
217
218        case 'o':
219
220            AcpiGbl_DbOpt_NoRegionSupport = TRUE;
221            break;
222
223        case 'r':
224
225            AcpiGbl_DisableAutoRepair = TRUE;
226            break;
227
228        case 's':
229
230            AcpiGbl_AutoSerializeMethods = FALSE;
231            break;
232
233        case 't':
234
235            #ifdef ACPI_DBG_TRACK_ALLOCATIONS
236                AcpiGbl_DisableMemTracking = TRUE;
237            #endif
238            break;
239
240        default:
241
242            printf ("Unknown option: -d%s\n", AcpiGbl_Optarg);
243            return (-1);
244        }
245        break;
246
247    case 'e':
248
249        switch (AcpiGbl_Optarg[0])
250        {
251        case 'f':
252
253            #ifdef ACPI_DBG_TRACK_ALLOCATIONS
254                AcpiGbl_DisplayFinalMemStats = TRUE;
255            #endif
256            break;
257
258        case 'i':
259
260            AcpiGbl_DoInterfaceTests = TRUE;
261            break;
262
263        case 'l':
264
265            AcpiGbl_LoadTestTables = TRUE;
266            break;
267
268        case 's':
269
270            AcpiGbl_EnableInterpreterSlack = TRUE;
271            printf ("Enabling AML Interpreter slack mode\n");
272            break;
273
274        case 't':
275
276            AcpiGbl_DebugTimeout = TRUE;
277            break;
278
279        default:
280
281            printf ("Unknown option: -e%s\n", AcpiGbl_Optarg);
282            return (-1);
283        }
284        break;
285
286    case 'f':
287
288        AcpiGbl_RegionFillValue = (UINT8) strtoul (AcpiGbl_Optarg, NULL, 0);
289        break;
290
291    case 'g':
292
293        AcpiGbl_DbOpt_tables = TRUE;
294        AcpiGbl_DbFilename = NULL;
295        break;
296
297    case 'h':
298    case '?':
299
300        usage();
301        return (0);
302
303    case 'm':
304
305        AcpiGbl_ExecutionMode = AE_MODE_BATCH_SINGLE;
306        switch (AcpiGbl_Optarg[0])
307        {
308        case '^':
309
310            strcpy (BatchBuffer, "MAIN");
311            break;
312
313        default:
314
315            strcpy (BatchBuffer, AcpiGbl_Optarg);
316            break;
317        }
318        break;
319
320    case 'o':
321
322        AcpiGbl_DbOpt_disasm = TRUE;
323        AcpiGbl_DbOpt_stats = TRUE;
324        break;
325
326    case 'r':
327
328        AcpiGbl_UseHwReducedFadt = TRUE;
329        printf ("Using ACPI 5.0 Hardware Reduced Mode via version 5 FADT\n");
330        break;
331
332    case 'v':
333
334        switch (AcpiGbl_Optarg[0])
335        {
336        case '^':  /* -v: (Version): signon already emitted, just exit */
337
338            (void) AcpiOsTerminate ();
339            exit (0);
340
341        case 'i':
342
343            AcpiDbgLevel |= ACPI_LV_INIT_NAMES;
344            break;
345
346        case 'r':
347
348            AcpiGbl_DisplayRegionAccess = TRUE;
349            break;
350
351        default:
352
353            printf ("Unknown option: -v%s\n", AcpiGbl_Optarg);
354            return (-1);
355        }
356        break;
357
358    case 'x':
359
360        AcpiDbgLevel = strtoul (AcpiGbl_Optarg, NULL, 0);
361        AcpiGbl_DbConsoleDebugLevel = AcpiDbgLevel;
362        printf ("Debug Level: 0x%8.8X\n", AcpiDbgLevel);
363        break;
364
365    default:
366
367        usage();
368        return (-1);
369    }
370
371    return (0);
372}
373
374
375/******************************************************************************
376 *
377 * FUNCTION:    main
378 *
379 * PARAMETERS:  argc, argv
380 *
381 * RETURN:      Status
382 *
383 * DESCRIPTION: Main routine for AcpiExec utility
384 *
385 *****************************************************************************/
386
387int ACPI_SYSTEM_XFACE
388main (
389    int                     argc,
390    char                    **argv)
391{
392    ACPI_STATUS             Status;
393    UINT32                  InitFlags;
394    ACPI_TABLE_HEADER       *Table = NULL;
395    UINT32                  TableCount;
396    AE_TABLE_DESC           *TableDesc;
397
398
399    ACPI_DEBUG_INITIALIZE (); /* For debug version only */
400    signal (SIGINT, AeCtrlCHandler);
401
402    /* Init debug globals */
403
404    AcpiDbgLevel = ACPI_NORMAL_DEFAULT;
405    AcpiDbgLayer = 0xFFFFFFFF;
406
407    /* Init ACPICA and start debugger thread */
408
409    Status = AcpiInitializeSubsystem ();
410    AE_CHECK_OK (AcpiInitializeSubsystem, Status);
411    if (ACPI_FAILURE (Status))
412    {
413        goto ErrorExit;
414    }
415
416    printf (ACPI_COMMON_SIGNON (ACPIEXEC_NAME));
417    if (argc < 2)
418    {
419        usage ();
420        (void) AcpiOsTerminate ();
421        return (0);
422    }
423
424    /* Get the command line options */
425
426    if (AeDoOptions (argc, argv))
427    {
428        goto ErrorExit;
429    }
430
431    /* The remaining arguments are filenames for ACPI tables */
432
433    if (!argv[AcpiGbl_Optind])
434    {
435        goto EnterDebugger;
436    }
437
438    AcpiGbl_DbOpt_tables = TRUE;
439    TableCount = 0;
440
441    /* Get each of the ACPI table files on the command line */
442
443    while (argv[AcpiGbl_Optind])
444    {
445        /* Get one entire table */
446
447        Status = AcpiUtReadTableFromFile (argv[AcpiGbl_Optind], &Table);
448        if (ACPI_FAILURE (Status))
449        {
450            printf ("**** Could not get table from file %s, %s\n",
451                argv[AcpiGbl_Optind], AcpiFormatException (Status));
452            goto ErrorExit;
453        }
454
455        /* Ignore non-AML tables, we can't use them. Except for an FADT */
456
457        if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_FADT) &&
458            !AcpiUtIsAmlTable (Table))
459        {
460            ACPI_INFO ((AE_INFO,
461                "Table [%4.4s] is not an AML table, ignoring",
462                Table->Signature));
463            AcpiOsFree (Table);
464        }
465        else
466        {
467            /* Allocate and link a table descriptor */
468
469            TableDesc = AcpiOsAllocate (sizeof (AE_TABLE_DESC));
470            TableDesc->Table = Table;
471            TableDesc->Next = AeTableListHead;
472            AeTableListHead = TableDesc;
473
474            TableCount++;
475        }
476
477        AcpiGbl_Optind++;
478    }
479
480    printf ("\n");
481
482    /* Build a local RSDT with all tables and let ACPICA process the RSDT */
483
484    Status = AeBuildLocalTables (TableCount, AeTableListHead);
485    if (ACPI_FAILURE (Status))
486    {
487        goto ErrorExit;
488    }
489
490    Status = AeInstallTables ();
491    if (ACPI_FAILURE (Status))
492    {
493        printf ("**** Could not load ACPI tables, %s\n",
494            AcpiFormatException (Status));
495        goto EnterDebugger;
496    }
497
498    /*
499     * Install most of the handlers.
500     * Override some default region handlers, especially SystemMemory
501     */
502    Status = AeInstallEarlyHandlers ();
503    if (ACPI_FAILURE (Status))
504    {
505        goto EnterDebugger;
506    }
507
508    /* Setup initialization flags for ACPICA */
509
510    InitFlags = (ACPI_NO_HANDLER_INIT | ACPI_NO_ACPI_ENABLE);
511    if (!AcpiGbl_DbOpt_ini_methods)
512    {
513        InitFlags |= (ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT);
514    }
515
516    /*
517     * Main initialization for ACPICA subsystem
518     * TBD: Need a way to call this after the ACPI table "LOAD" command
519     */
520    Status = AcpiEnableSubsystem (InitFlags);
521    if (ACPI_FAILURE (Status))
522    {
523        printf ("**** Could not EnableSubsystem, %s\n",
524            AcpiFormatException (Status));
525        goto EnterDebugger;
526    }
527
528    /*
529     * Install handlers for "device driver" space IDs (EC,SMBus, etc.)
530     * and fixed event handlers
531     */
532    AeInstallLateHandlers ();
533
534    /* Finish the ACPICA initialization */
535
536    Status = AcpiInitializeObjects (InitFlags);
537    if (ACPI_FAILURE (Status))
538    {
539        printf ("**** Could not InitializeObjects, %s\n",
540            AcpiFormatException (Status));
541        goto EnterDebugger;
542    }
543
544    AeMiscellaneousTests ();
545
546
547EnterDebugger:
548
549    /* Exit if error above and we are in one of the batch modes */
550
551    if (ACPI_FAILURE (Status) && (AcpiGbl_ExecutionMode > 0))
552    {
553        goto ErrorExit;
554    }
555
556    /* Run a batch command or enter the command loop */
557
558    switch (AcpiGbl_ExecutionMode)
559    {
560    default:
561    case AE_MODE_COMMAND_LOOP:
562
563        AcpiDbUserCommands (ACPI_DEBUGGER_COMMAND_PROMPT, NULL);
564        break;
565
566    case AE_MODE_BATCH_MULTIPLE:
567
568        AcpiDbRunBatchMode ();
569        break;
570
571    case AE_MODE_BATCH_SINGLE:
572
573        AcpiDbExecute (BatchBuffer, NULL, NULL, EX_NO_SINGLE_STEP);
574        Status = AcpiTerminate ();
575        break;
576    }
577
578    return (0);
579
580
581ErrorExit:
582
583    (void) AcpiOsTerminate ();
584    return (-1);
585}
586
587
588/******************************************************************************
589 *
590 * FUNCTION:    AcpiDbRunBatchMode
591 *
592 * PARAMETERS:  BatchCommandLine    - A semicolon separated list of commands
593 *                                    to be executed.
594 *                                    Use only commas to separate elements of
595 *                                    particular command.
596 * RETURN:      Status
597 *
598 * DESCRIPTION: For each command of list separated by ';' prepare the command
599 *              buffer and pass it to AcpiDbCommandDispatch.
600 *
601 *****************************************************************************/
602
603static ACPI_STATUS
604AcpiDbRunBatchMode (
605    void)
606{
607    ACPI_STATUS             Status;
608    char                    *Ptr = BatchBuffer;
609    char                    *Cmd = Ptr;
610    UINT8                   Run = 0;
611
612
613    AcpiGbl_MethodExecuting = FALSE;
614    AcpiGbl_StepToNextCall = FALSE;
615
616    while (*Ptr)
617    {
618        if (*Ptr == ',')
619        {
620            /* Convert commas to spaces */
621            *Ptr = ' ';
622        }
623        else if (*Ptr == ';')
624        {
625            *Ptr = '\0';
626            Run = 1;
627        }
628
629        Ptr++;
630
631        if (Run || (*Ptr == '\0'))
632        {
633            (void) AcpiDbCommandDispatch (Cmd, NULL, NULL);
634            Run = 0;
635            Cmd = Ptr;
636        }
637    }
638
639    Status = AcpiTerminate ();
640    return (Status);
641}
642