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