1 /****************************************************************************** 2 * 3 * Module Name: adisasm - Application-level disassembler routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 "aslcompiler.h" 45 #include "amlcode.h" 46 #include "acdisasm.h" 47 #include "acdispat.h" 48 #include "acnamesp.h" 49 #include "acparser.h" 50 #include "acapps.h" 51 52 #include <stdio.h> 53 54 55 #define _COMPONENT ACPI_TOOLS 56 ACPI_MODULE_NAME ("adisasm") 57 58 /* Local prototypes */ 59 60 static ACPI_STATUS 61 AdDoExternalFileList ( 62 char *Filename); 63 64 static ACPI_STATUS 65 AdDisassembleOneTable ( 66 ACPI_TABLE_HEADER *Table, 67 FILE *File, 68 char *Filename, 69 char *DisasmFilename); 70 71 static ACPI_STATUS 72 AdReparseOneTable ( 73 ACPI_TABLE_HEADER *Table, 74 FILE *File, 75 ACPI_OWNER_ID OwnerId); 76 77 78 ACPI_TABLE_DESC LocalTables[1]; 79 ACPI_PARSE_OBJECT *AcpiGbl_ParseOpRoot; 80 81 82 /* Stubs for everything except ASL compiler */ 83 84 #ifndef ACPI_ASL_COMPILER 85 BOOLEAN 86 AcpiDsIsResultUsed ( 87 ACPI_PARSE_OBJECT *Op, 88 ACPI_WALK_STATE *WalkState) 89 { 90 return (TRUE); 91 } 92 93 ACPI_STATUS 94 AcpiDsMethodError ( 95 ACPI_STATUS Status, 96 ACPI_WALK_STATE *WalkState) 97 { 98 return (Status); 99 } 100 #endif 101 102 103 /******************************************************************************* 104 * 105 * FUNCTION: AdInitialize 106 * 107 * PARAMETERS: None 108 * 109 * RETURN: Status 110 * 111 * DESCRIPTION: ACPICA and local initialization 112 * 113 ******************************************************************************/ 114 115 ACPI_STATUS 116 AdInitialize ( 117 void) 118 { 119 ACPI_STATUS Status; 120 121 122 /* ACPICA subsystem initialization */ 123 124 Status = AcpiOsInitialize (); 125 if (ACPI_FAILURE (Status)) 126 { 127 return (Status); 128 } 129 130 Status = AcpiUtInitGlobals (); 131 if (ACPI_FAILURE (Status)) 132 { 133 return (Status); 134 } 135 136 Status = AcpiUtMutexInitialize (); 137 if (ACPI_FAILURE (Status)) 138 { 139 return (Status); 140 } 141 142 Status = AcpiNsRootInitialize (); 143 if (ACPI_FAILURE (Status)) 144 { 145 return (Status); 146 } 147 148 /* Setup the Table Manager (cheat - there is no RSDT) */ 149 150 AcpiGbl_RootTableList.MaxTableCount = 1; 151 AcpiGbl_RootTableList.CurrentTableCount = 0; 152 AcpiGbl_RootTableList.Tables = LocalTables; 153 154 return (Status); 155 } 156 157 158 /****************************************************************************** 159 * 160 * FUNCTION: AdAmlDisassemble 161 * 162 * PARAMETERS: Filename - AML input filename 163 * OutToFile - TRUE if output should go to a file 164 * Prefix - Path prefix for output 165 * OutFilename - where the filename is returned 166 * 167 * RETURN: Status 168 * 169 * DESCRIPTION: Disassembler entry point. Disassemble an entire ACPI table. 170 * 171 *****************************************************************************/ 172 173 ACPI_STATUS 174 AdAmlDisassemble ( 175 BOOLEAN OutToFile, 176 char *Filename, 177 char *Prefix, 178 char **OutFilename) 179 { 180 ACPI_STATUS Status; 181 char *DisasmFilename = NULL; 182 FILE *File = NULL; 183 ACPI_TABLE_HEADER *Table = NULL; 184 ACPI_NEW_TABLE_DESC *ListHead = NULL; 185 186 187 /* 188 * Input: AML code from either a file or via GetTables (memory or 189 * registry) 190 */ 191 if (Filename) 192 { 193 /* Get the list of all AML tables in the file */ 194 195 Status = AcpiAcGetAllTablesFromFile (Filename, 196 ACPI_GET_ALL_TABLES, &ListHead); 197 if (ACPI_FAILURE (Status)) 198 { 199 return (Status); 200 } 201 202 /* Process any user-specified files for external objects */ 203 204 Status = AdDoExternalFileList (Filename); 205 if (ACPI_FAILURE (Status)) 206 { 207 return (Status); 208 } 209 } 210 else 211 { 212 Status = AdGetLocalTables (); 213 if (ACPI_FAILURE (Status)) 214 { 215 AcpiOsPrintf ("Could not get ACPI tables, %s\n", 216 AcpiFormatException (Status)); 217 return (Status); 218 } 219 220 if (!AcpiGbl_DmOpt_Disasm) 221 { 222 return (AE_OK); 223 } 224 225 /* Obtained the local tables, just disassemble the DSDT */ 226 227 Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table); 228 if (ACPI_FAILURE (Status)) 229 { 230 AcpiOsPrintf ("Could not get DSDT, %s\n", 231 AcpiFormatException (Status)); 232 return (Status); 233 } 234 235 AcpiOsPrintf ("\nDisassembly of DSDT\n"); 236 Prefix = AdGenerateFilename ("dsdt", Table->OemTableId); 237 } 238 239 /* 240 * Output: ASL code. Redirect to a file if requested 241 */ 242 if (OutToFile) 243 { 244 /* Create/Open a disassembly output file */ 245 246 DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY); 247 if (!DisasmFilename) 248 { 249 fprintf (stderr, "Could not generate output filename\n"); 250 Status = AE_ERROR; 251 goto Cleanup; 252 } 253 254 File = fopen (DisasmFilename, "w+"); 255 if (!File) 256 { 257 fprintf (stderr, "Could not open output file %s\n", 258 DisasmFilename); 259 Status = AE_ERROR; 260 goto Cleanup; 261 } 262 263 AcpiOsRedirectOutput (File); 264 } 265 266 *OutFilename = DisasmFilename; 267 268 /* Disassemble all AML tables within the file */ 269 270 while (ListHead) 271 { 272 Status = AdDisassembleOneTable (ListHead->Table, 273 File, Filename, DisasmFilename); 274 if (ACPI_FAILURE (Status)) 275 { 276 break; 277 } 278 279 ListHead = ListHead->Next; 280 } 281 282 Cleanup: 283 284 // check! 285 #if 0 286 if (Table && !AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table)) 287 { 288 ACPI_FREE (Table); 289 } 290 #endif 291 292 if (File) 293 { 294 fclose (File); 295 AcpiOsRedirectOutput (stdout); 296 } 297 298 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 299 AcpiGbl_ParseOpRoot = NULL; 300 return (Status); 301 } 302 303 304 /****************************************************************************** 305 * 306 * FUNCTION: AdDisassembleOneTable 307 * 308 * PARAMETERS: Table - Raw AML table 309 * File - Pointer for the input file 310 * Filename - AML input filename 311 * DisasmFilename - Output filename 312 * 313 * RETURN: Status 314 * 315 * DESCRIPTION: Disassemble a single ACPI table. AML or data table. 316 * 317 *****************************************************************************/ 318 319 static ACPI_STATUS 320 AdDisassembleOneTable ( 321 ACPI_TABLE_HEADER *Table, 322 FILE *File, 323 char *Filename, 324 char *DisasmFilename) 325 { 326 ACPI_STATUS Status; 327 ACPI_OWNER_ID OwnerId; 328 329 330 /* ForceAmlDisassembly means to assume the table contains valid AML */ 331 332 if (!AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table)) 333 { 334 AdDisassemblerHeader (Filename, ACPI_IS_DATA_TABLE); 335 336 /* This is a "Data Table" (non-AML table) */ 337 338 AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n", 339 Table->Signature); 340 AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength] " 341 "FieldName : FieldValue\n */\n\n"); 342 343 AcpiDmDumpDataTable (Table); 344 fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n", 345 Table->Signature); 346 347 if (File) 348 { 349 fprintf (stderr, "Formatted output: %s - %u bytes\n", 350 DisasmFilename, CmGetFileSize (File)); 351 } 352 353 return (AE_OK); 354 } 355 356 /* 357 * This is an AML table (DSDT or SSDT). 358 * Always parse the tables, only option is what to display 359 */ 360 Status = AdParseTable (Table, &OwnerId, TRUE, FALSE); 361 if (ACPI_FAILURE (Status)) 362 { 363 AcpiOsPrintf ("Could not parse ACPI tables, %s\n", 364 AcpiFormatException (Status)); 365 return (Status); 366 } 367 368 /* Debug output, namespace and parse tree */ 369 370 if (AslCompilerdebug && File) 371 { 372 AcpiOsPrintf ("/**** Before second load\n"); 373 374 NsSetupNamespaceListing (File); 375 NsDisplayNamespace (); 376 377 AcpiOsPrintf ("*****/\n"); 378 } 379 380 /* Load namespace from names created within control methods */ 381 382 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 383 AcpiGbl_RootNode, OwnerId); 384 385 /* 386 * Cross reference the namespace here, in order to 387 * generate External() statements 388 */ 389 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, 390 AcpiGbl_RootNode, OwnerId); 391 392 if (AslCompilerdebug) 393 { 394 AcpiDmDumpTree (AcpiGbl_ParseOpRoot); 395 } 396 397 /* Find possible calls to external control methods */ 398 399 AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot); 400 401 /* 402 * If we found any external control methods, we must reparse 403 * the entire tree with the new information (namely, the 404 * number of arguments per method) 405 */ 406 if (AcpiDmGetExternalMethodCount ()) 407 { 408 Status = AdReparseOneTable (Table, File, OwnerId); 409 if (ACPI_FAILURE (Status)) 410 { 411 return (Status); 412 } 413 } 414 415 /* 416 * Now that the namespace is finalized, we can perform namespace 417 * transforms. 418 * 419 * 1) Convert fixed-offset references to resource descriptors 420 * to symbolic references (Note: modifies namespace) 421 */ 422 AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode); 423 424 /* Optional displays */ 425 426 if (AcpiGbl_DmOpt_Disasm) 427 { 428 /* This is the real disassembly */ 429 430 AdDisplayTables (Filename, Table); 431 432 /* Dump hex table if requested (-vt) */ 433 434 AcpiDmDumpDataTable (Table); 435 436 fprintf (stderr, "Disassembly completed\n"); 437 if (File) 438 { 439 fprintf (stderr, "ASL Output: %s - %u bytes\n", 440 DisasmFilename, CmGetFileSize (File)); 441 } 442 443 if (Gbl_MapfileFlag) 444 { 445 fprintf (stderr, "%14s %s - %u bytes\n", 446 Gbl_Files[ASL_FILE_MAP_OUTPUT].ShortDescription, 447 Gbl_Files[ASL_FILE_MAP_OUTPUT].Filename, 448 FlGetFileSize (ASL_FILE_MAP_OUTPUT)); 449 } 450 } 451 452 return (AE_OK); 453 } 454 455 456 /****************************************************************************** 457 * 458 * FUNCTION: AdReparseOneTable 459 * 460 * PARAMETERS: Table - Raw AML table 461 * File - Pointer for the input file 462 * OwnerId - ID for this table 463 * 464 * RETURN: Status 465 * 466 * DESCRIPTION: Reparse a table that has already been loaded. Used to 467 * integrate information about external control methods. 468 * These methods may have been previously parsed incorrectly. 469 * 470 *****************************************************************************/ 471 472 static ACPI_STATUS 473 AdReparseOneTable ( 474 ACPI_TABLE_HEADER *Table, 475 FILE *File, 476 ACPI_OWNER_ID OwnerId) 477 { 478 ACPI_STATUS Status; 479 480 481 fprintf (stderr, 482 "\nFound %u external control methods, " 483 "reparsing with new information\n", 484 AcpiDmGetExternalMethodCount ()); 485 486 /* Reparse, rebuild namespace */ 487 488 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 489 AcpiGbl_ParseOpRoot = NULL; 490 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); 491 492 AcpiGbl_RootNode = NULL; 493 AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME; 494 AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED; 495 AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE; 496 AcpiGbl_RootNodeStruct.Parent = NULL; 497 AcpiGbl_RootNodeStruct.Child = NULL; 498 AcpiGbl_RootNodeStruct.Peer = NULL; 499 AcpiGbl_RootNodeStruct.Object = NULL; 500 AcpiGbl_RootNodeStruct.Flags = 0; 501 502 Status = AcpiNsRootInitialize (); 503 if (ACPI_FAILURE (Status)) 504 { 505 return (Status); 506 } 507 508 /* New namespace, add the external definitions first */ 509 510 AcpiDmAddExternalsToNamespace (); 511 512 /* Parse the table again. No need to reload it, however */ 513 514 Status = AdParseTable (Table, NULL, FALSE, FALSE); 515 if (ACPI_FAILURE (Status)) 516 { 517 AcpiOsPrintf ("Could not parse ACPI tables, %s\n", 518 AcpiFormatException (Status)); 519 return (Status); 520 } 521 522 /* Cross reference the namespace again */ 523 524 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 525 AcpiGbl_RootNode, OwnerId); 526 527 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, 528 AcpiGbl_RootNode, OwnerId); 529 530 /* Debug output - namespace and parse tree */ 531 532 if (AslCompilerdebug) 533 { 534 AcpiOsPrintf ("/**** After second load and resource conversion\n"); 535 if (File) 536 { 537 NsSetupNamespaceListing (File); 538 NsDisplayNamespace (); 539 } 540 541 AcpiOsPrintf ("*****/\n"); 542 AcpiDmDumpTree (AcpiGbl_ParseOpRoot); 543 } 544 545 return (AE_OK); 546 } 547 548 549 /****************************************************************************** 550 * 551 * FUNCTION: AdDoExternalFileList 552 * 553 * PARAMETERS: Filename - Input file for the table 554 * 555 * RETURN: Status 556 * 557 * DESCRIPTION: Process all tables found in the -e external files list 558 * 559 *****************************************************************************/ 560 561 static ACPI_STATUS 562 AdDoExternalFileList ( 563 char *Filename) 564 { 565 ACPI_EXTERNAL_FILE *ExternalFileList; 566 char *ExternalFilename; 567 ACPI_NEW_TABLE_DESC *ExternalListHead = NULL; 568 ACPI_STATUS Status; 569 ACPI_STATUS GlobalStatus = AE_OK; 570 ACPI_OWNER_ID OwnerId; 571 572 573 /* 574 * External filenames are specified on the command line like this: 575 * Example: iasl -e file1,file2,file3 -d xxx.aml 576 */ 577 ExternalFileList = AcpiGbl_ExternalFileList; 578 579 /* Process each external file */ 580 581 while (ExternalFileList) 582 { 583 ExternalFilename = ExternalFileList->Path; 584 if (!strcmp (ExternalFilename, Filename)) 585 { 586 /* Next external file */ 587 588 ExternalFileList = ExternalFileList->Next; 589 continue; 590 } 591 592 AcpiOsPrintf ("External object resolution file %16s\n", 593 ExternalFilename); 594 595 Status = AcpiAcGetAllTablesFromFile ( 596 ExternalFilename, ACPI_GET_ONLY_AML_TABLES, &ExternalListHead); 597 if (ACPI_FAILURE (Status)) 598 { 599 if (Status == AE_TYPE) 600 { 601 ExternalFileList = ExternalFileList->Next; 602 GlobalStatus = AE_TYPE; 603 Status = AE_OK; 604 continue; 605 } 606 607 return (Status); 608 } 609 610 /* Load external tables for symbol resolution */ 611 612 while (ExternalListHead) 613 { 614 Status = AdParseTable ( 615 ExternalListHead->Table, &OwnerId, TRUE, TRUE); 616 if (ACPI_FAILURE (Status)) 617 { 618 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n", 619 AcpiFormatException (Status)); 620 return (Status); 621 } 622 623 /* 624 * Load namespace from names created within control methods 625 * Set owner id of nodes in external table 626 */ 627 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 628 AcpiGbl_RootNode, OwnerId); 629 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 630 631 ExternalListHead = ExternalListHead->Next; 632 } 633 634 /* Next external file */ 635 636 ExternalFileList = ExternalFileList->Next; 637 } 638 639 if (ACPI_FAILURE (GlobalStatus)) 640 { 641 return (GlobalStatus); 642 } 643 644 /* Clear external list generated by Scope in external tables */ 645 646 if (AcpiGbl_ExternalFileList) 647 { 648 AcpiDmClearExternalList (); 649 } 650 651 /* Load any externals defined in the optional external ref file */ 652 653 AcpiDmGetExternalsFromFile (); 654 return (AE_OK); 655 } 656