1 /****************************************************************************** 2 * 3 * Module Name: adisasm - Application-level disassembler routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 <contrib/dev/acpica/compiler/aslcompiler.h> 45 #include <contrib/dev/acpica/include/amlcode.h> 46 #include <contrib/dev/acpica/include/acdisasm.h> 47 #include <contrib/dev/acpica/include/acdispat.h> 48 #include <contrib/dev/acpica/include/acnamesp.h> 49 #include <contrib/dev/acpica/include/acparser.h> 50 #include <contrib/dev/acpica/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 = AcGetAllTablesFromFile (Filename, 196 ACPI_GET_ALL_TABLES, &ListHead); 197 if (ACPI_FAILURE (Status)) 198 { 199 AcpiOsPrintf ("Could not get ACPI tables from %s, %s\n", 200 Filename, AcpiFormatException (Status)); 201 return (Status); 202 } 203 204 /* Process any user-specified files for external objects */ 205 206 Status = AdDoExternalFileList (Filename); 207 if (ACPI_FAILURE (Status)) 208 { 209 return (Status); 210 } 211 } 212 else 213 { 214 Status = AdGetLocalTables (); 215 if (ACPI_FAILURE (Status)) 216 { 217 AcpiOsPrintf ("Could not get ACPI tables, %s\n", 218 AcpiFormatException (Status)); 219 return (Status); 220 } 221 222 if (!AcpiGbl_DmOpt_Disasm) 223 { 224 return (AE_OK); 225 } 226 227 /* Obtained the local tables, just disassemble the DSDT */ 228 229 Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table); 230 if (ACPI_FAILURE (Status)) 231 { 232 AcpiOsPrintf ("Could not get DSDT, %s\n", 233 AcpiFormatException (Status)); 234 return (Status); 235 } 236 237 AcpiOsPrintf ("\nDisassembly of DSDT\n"); 238 Prefix = AdGenerateFilename ("dsdt", Table->OemTableId); 239 } 240 241 /* 242 * Output: ASL code. Redirect to a file if requested 243 */ 244 if (OutToFile) 245 { 246 /* Create/Open a disassembly output file */ 247 248 DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY); 249 if (!DisasmFilename) 250 { 251 fprintf (stderr, "Could not generate output filename\n"); 252 Status = AE_ERROR; 253 goto Cleanup; 254 } 255 256 File = fopen (DisasmFilename, "w+"); 257 if (!File) 258 { 259 fprintf (stderr, "Could not open output file %s\n", 260 DisasmFilename); 261 Status = AE_ERROR; 262 goto Cleanup; 263 } 264 265 AcpiOsRedirectOutput (File); 266 } 267 268 *OutFilename = DisasmFilename; 269 270 /* Disassemble all AML tables within the file */ 271 272 while (ListHead) 273 { 274 Status = AdDisassembleOneTable (ListHead->Table, 275 File, Filename, DisasmFilename); 276 if (ACPI_FAILURE (Status)) 277 { 278 break; 279 } 280 281 ListHead = ListHead->Next; 282 } 283 284 Cleanup: 285 286 if (Table && 287 !AcpiGbl_ForceAmlDisassembly && 288 !AcpiUtIsAmlTable (Table)) 289 { 290 ACPI_FREE (Table); 291 } 292 293 if (File) 294 { 295 fclose (File); 296 AcpiOsRedirectOutput (stdout); 297 } 298 299 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 300 AcpiGbl_ParseOpRoot = NULL; 301 return (Status); 302 } 303 304 305 /****************************************************************************** 306 * 307 * FUNCTION: AdDisassembleOneTable 308 * 309 * PARAMETERS: Table - Raw AML table 310 * File - Pointer for the input file 311 * Filename - AML input filename 312 * DisasmFilename - Output filename 313 * 314 * RETURN: Status 315 * 316 * DESCRIPTION: Disassemble a single ACPI table. AML or data table. 317 * 318 *****************************************************************************/ 319 320 static ACPI_STATUS 321 AdDisassembleOneTable ( 322 ACPI_TABLE_HEADER *Table, 323 FILE *File, 324 char *Filename, 325 char *DisasmFilename) 326 { 327 ACPI_STATUS Status; 328 ACPI_OWNER_ID OwnerId; 329 330 331 /* ForceAmlDisassembly means to assume the table contains valid AML */ 332 333 if (!AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table)) 334 { 335 AdDisassemblerHeader (Filename, ACPI_IS_DATA_TABLE); 336 337 /* This is a "Data Table" (non-AML table) */ 338 339 AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n", 340 Table->Signature); 341 AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength] " 342 "FieldName : FieldValue\n */\n\n"); 343 344 AcpiDmDumpDataTable (Table); 345 fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n", 346 Table->Signature); 347 348 if (File) 349 { 350 fprintf (stderr, "Formatted output: %s - %u bytes\n", 351 DisasmFilename, CmGetFileSize (File)); 352 } 353 354 return (AE_OK); 355 } 356 357 /* 358 * This is an AML table (DSDT or SSDT). 359 * Always parse the tables, only option is what to display 360 */ 361 Status = AdParseTable (Table, &OwnerId, TRUE, FALSE); 362 if (ACPI_FAILURE (Status)) 363 { 364 AcpiOsPrintf ("Could not parse ACPI tables, %s\n", 365 AcpiFormatException (Status)); 366 return (Status); 367 } 368 369 /* Debug output, namespace and parse tree */ 370 371 if (AslCompilerdebug && File) 372 { 373 AcpiOsPrintf ("/**** Before second load\n"); 374 375 NsSetupNamespaceListing (File); 376 NsDisplayNamespace (); 377 378 AcpiOsPrintf ("*****/\n"); 379 } 380 381 /* Load namespace from names created within control methods */ 382 383 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 384 AcpiGbl_RootNode, OwnerId); 385 386 /* 387 * Cross reference the namespace here, in order to 388 * generate External() statements 389 */ 390 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, 391 AcpiGbl_RootNode, OwnerId); 392 393 if (AslCompilerdebug) 394 { 395 AcpiDmDumpTree (AcpiGbl_ParseOpRoot); 396 } 397 398 /* Find possible calls to external control methods */ 399 400 AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot); 401 402 /* 403 * If we found any external control methods, we must reparse 404 * the entire tree with the new information (namely, the 405 * number of arguments per method) 406 */ 407 if (AcpiDmGetExternalMethodCount ()) 408 { 409 Status = AdReparseOneTable (Table, File, OwnerId); 410 if (ACPI_FAILURE (Status)) 411 { 412 return (Status); 413 } 414 } 415 416 /* 417 * Now that the namespace is finalized, we can perform namespace 418 * transforms. 419 * 420 * 1) Convert fixed-offset references to resource descriptors 421 * to symbolic references (Note: modifies namespace) 422 */ 423 AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode); 424 425 /* Optional displays */ 426 427 if (AcpiGbl_DmOpt_Disasm) 428 { 429 /* This is the real disassembly */ 430 431 AdDisplayTables (Filename, Table); 432 433 /* Dump hex table if requested (-vt) */ 434 435 AcpiDmDumpDataTable (Table); 436 437 fprintf (stderr, "Disassembly completed\n"); 438 if (File) 439 { 440 fprintf (stderr, "ASL Output: %s - %u bytes\n", 441 DisasmFilename, CmGetFileSize (File)); 442 } 443 444 if (Gbl_MapfileFlag) 445 { 446 fprintf (stderr, "%14s %s - %u bytes\n", 447 Gbl_Files[ASL_FILE_MAP_OUTPUT].ShortDescription, 448 Gbl_Files[ASL_FILE_MAP_OUTPUT].Filename, 449 FlGetFileSize (ASL_FILE_MAP_OUTPUT)); 450 } 451 } 452 453 return (AE_OK); 454 } 455 456 457 /****************************************************************************** 458 * 459 * FUNCTION: AdReparseOneTable 460 * 461 * PARAMETERS: Table - Raw AML table 462 * File - Pointer for the input file 463 * OwnerId - ID for this table 464 * 465 * RETURN: Status 466 * 467 * DESCRIPTION: Reparse a table that has already been loaded. Used to 468 * integrate information about external control methods. 469 * These methods may have been previously parsed incorrectly. 470 * 471 *****************************************************************************/ 472 473 static ACPI_STATUS 474 AdReparseOneTable ( 475 ACPI_TABLE_HEADER *Table, 476 FILE *File, 477 ACPI_OWNER_ID OwnerId) 478 { 479 ACPI_STATUS Status; 480 481 482 fprintf (stderr, 483 "\nFound %u external control methods, " 484 "reparsing with new information\n", 485 AcpiDmGetExternalMethodCount ()); 486 487 /* Reparse, rebuild namespace */ 488 489 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 490 AcpiGbl_ParseOpRoot = NULL; 491 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); 492 493 AcpiGbl_RootNode = NULL; 494 AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME; 495 AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED; 496 AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE; 497 AcpiGbl_RootNodeStruct.Parent = NULL; 498 AcpiGbl_RootNodeStruct.Child = NULL; 499 AcpiGbl_RootNodeStruct.Peer = NULL; 500 AcpiGbl_RootNodeStruct.Object = NULL; 501 AcpiGbl_RootNodeStruct.Flags = 0; 502 503 Status = AcpiNsRootInitialize (); 504 if (ACPI_FAILURE (Status)) 505 { 506 return (Status); 507 } 508 509 /* New namespace, add the external definitions first */ 510 511 AcpiDmAddExternalsToNamespace (); 512 513 /* Parse the table again. No need to reload it, however */ 514 515 Status = AdParseTable (Table, NULL, FALSE, FALSE); 516 if (ACPI_FAILURE (Status)) 517 { 518 AcpiOsPrintf ("Could not parse ACPI tables, %s\n", 519 AcpiFormatException (Status)); 520 return (Status); 521 } 522 523 /* Cross reference the namespace again */ 524 525 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 526 AcpiGbl_RootNode, OwnerId); 527 528 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, 529 AcpiGbl_RootNode, OwnerId); 530 531 /* Debug output - namespace and parse tree */ 532 533 if (AslCompilerdebug) 534 { 535 AcpiOsPrintf ("/**** After second load and resource conversion\n"); 536 if (File) 537 { 538 NsSetupNamespaceListing (File); 539 NsDisplayNamespace (); 540 } 541 542 AcpiOsPrintf ("*****/\n"); 543 AcpiDmDumpTree (AcpiGbl_ParseOpRoot); 544 } 545 546 return (AE_OK); 547 } 548 549 550 /****************************************************************************** 551 * 552 * FUNCTION: AdDoExternalFileList 553 * 554 * PARAMETERS: Filename - Input file for the table 555 * 556 * RETURN: Status 557 * 558 * DESCRIPTION: Process all tables found in the -e external files list 559 * 560 *****************************************************************************/ 561 562 static ACPI_STATUS 563 AdDoExternalFileList ( 564 char *Filename) 565 { 566 ACPI_EXTERNAL_FILE *ExternalFileList; 567 char *ExternalFilename; 568 ACPI_NEW_TABLE_DESC *ExternalListHead = NULL; 569 ACPI_STATUS Status; 570 ACPI_STATUS GlobalStatus = AE_OK; 571 ACPI_OWNER_ID OwnerId; 572 573 574 /* 575 * External filenames are specified on the command line like this: 576 * Example: iasl -e file1,file2,file3 -d xxx.aml 577 */ 578 ExternalFileList = AcpiGbl_ExternalFileList; 579 580 /* Process each external file */ 581 582 while (ExternalFileList) 583 { 584 ExternalFilename = ExternalFileList->Path; 585 if (!strcmp (ExternalFilename, Filename)) 586 { 587 /* Next external file */ 588 589 ExternalFileList = ExternalFileList->Next; 590 continue; 591 } 592 593 AcpiOsPrintf ("External object resolution file %16s\n", 594 ExternalFilename); 595 596 Status = AcGetAllTablesFromFile ( 597 ExternalFilename, ACPI_GET_ONLY_AML_TABLES, &ExternalListHead); 598 if (ACPI_FAILURE (Status)) 599 { 600 if (Status == AE_TYPE) 601 { 602 ExternalFileList = ExternalFileList->Next; 603 GlobalStatus = AE_TYPE; 604 Status = AE_OK; 605 continue; 606 } 607 608 return (Status); 609 } 610 611 /* Load external tables for symbol resolution */ 612 613 while (ExternalListHead) 614 { 615 Status = AdParseTable ( 616 ExternalListHead->Table, &OwnerId, TRUE, TRUE); 617 if (ACPI_FAILURE (Status)) 618 { 619 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n", 620 AcpiFormatException (Status)); 621 return (Status); 622 } 623 624 /* 625 * Load namespace from names created within control methods 626 * Set owner id of nodes in external table 627 */ 628 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 629 AcpiGbl_RootNode, OwnerId); 630 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 631 632 ExternalListHead = ExternalListHead->Next; 633 } 634 635 /* Next external file */ 636 637 ExternalFileList = ExternalFileList->Next; 638 } 639 640 if (ACPI_FAILURE (GlobalStatus)) 641 { 642 return (GlobalStatus); 643 } 644 645 /* Clear external list generated by Scope in external tables */ 646 647 if (AcpiGbl_ExternalFileList) 648 { 649 AcpiDmClearExternalList (); 650 } 651 652 /* Load any externals defined in the optional external ref file */ 653 654 AcpiDmGetExternalsFromFile (); 655 return (AE_OK); 656 } 657