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