xref: /netbsd-src/sys/external/bsd/acpica/dist/tools/acpiexec/aemain.c (revision 82ad575716605df31379cf04a2f3efbc97b8a6f5)
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 
54 UINT8                   AcpiGbl_RegionFillValue = 0;
55 BOOLEAN                 AcpiGbl_IgnoreErrors = FALSE;
56 BOOLEAN                 AcpiGbl_DbOpt_NoRegionSupport = FALSE;
57 BOOLEAN                 AcpiGbl_DebugTimeout = FALSE;
58 
59 static UINT8            AcpiGbl_BatchMode = 0;
60 static char             BatchBuffer[128];
61 static AE_TABLE_DESC    *AeTableListHead = NULL;
62 
63 #define ASL_MAX_FILES   256
64 static 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 
82 static void
83 usage (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 
127 static ACPI_STATUS
128 AcpiDbRunBatchMode (
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 
176 static char *
177 FlStrdup (
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 
212 ACPI_STATUS
213 FlSplitInputPathname (
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 
286 static char **
287 AsDoWildcard (
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 
365 int ACPI_SYSTEM_XFACE
366 main (
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 
659 enterloop:
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