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