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