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 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 /* ForceAmlDisassembly means to assume the table contains valid AML */ 330 331 if (!AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table)) 332 { 333 AdDisassemblerHeader (Filename, ACPI_IS_DATA_TABLE); 334 335 /* This is a "Data Table" (non-AML table) */ 336 337 AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n", 338 Table->Signature); 339 AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength] " 340 "FieldName : FieldValue\n */\n\n"); 341 342 AcpiDmDumpDataTable (Table); 343 fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n", 344 Table->Signature); 345 346 if (File) 347 { 348 fprintf (stderr, "Formatted output: %s - %u bytes\n", 349 DisasmFilename, CmGetFileSize (File)); 350 } 351 352 return (AE_OK); 353 } 354 355 /* 356 * This is an AML table (DSDT or SSDT). 357 * Always parse the tables, only option is what to display 358 */ 359 Status = AdParseTable (Table, &OwnerId, TRUE, FALSE); 360 if (ACPI_FAILURE (Status)) 361 { 362 AcpiOsPrintf ("Could not parse ACPI tables, %s\n", 363 AcpiFormatException (Status)); 364 return (Status); 365 } 366 367 /* Debug output, namespace and parse tree */ 368 369 if (AslCompilerdebug && File) 370 { 371 AcpiOsPrintf ("/**** Before second load\n"); 372 373 NsSetupNamespaceListing (File); 374 NsDisplayNamespace (); 375 376 AcpiOsPrintf ("*****/\n"); 377 } 378 379 /* Load namespace from names created within control methods */ 380 381 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 382 AcpiGbl_RootNode, OwnerId); 383 384 /* 385 * Cross reference the namespace here, in order to 386 * generate External() statements 387 */ 388 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, 389 AcpiGbl_RootNode, OwnerId); 390 391 if (AslCompilerdebug) 392 { 393 AcpiDmDumpTree (AcpiGbl_ParseOpRoot); 394 } 395 396 /* Find possible calls to external control methods */ 397 398 AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot); 399 400 /* 401 * If we found any external control methods, we must reparse 402 * the entire tree with the new information (namely, the 403 * number of arguments per method) 404 */ 405 if (AcpiDmGetExternalMethodCount ()) 406 { 407 Status = AdReparseOneTable (Table, File, OwnerId); 408 if (ACPI_FAILURE (Status)) 409 { 410 return (Status); 411 } 412 } 413 414 /* 415 * Now that the namespace is finalized, we can perform namespace 416 * transforms. 417 * 418 * 1) Convert fixed-offset references to resource descriptors 419 * to symbolic references (Note: modifies namespace) 420 */ 421 AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode); 422 423 /* Optional displays */ 424 425 if (AcpiGbl_DmOpt_Disasm) 426 { 427 /* This is the real disassembly */ 428 429 AdDisplayTables (Filename, Table); 430 431 /* Dump hex table if requested (-vt) */ 432 433 AcpiDmDumpDataTable (Table); 434 435 fprintf (stderr, "Disassembly completed\n"); 436 if (File) 437 { 438 fprintf (stderr, "ASL Output: %s - %u bytes\n", 439 DisasmFilename, CmGetFileSize (File)); 440 } 441 442 if (Gbl_MapfileFlag) 443 { 444 fprintf (stderr, "%14s %s - %u bytes\n", 445 Gbl_Files[ASL_FILE_MAP_OUTPUT].ShortDescription, 446 Gbl_Files[ASL_FILE_MAP_OUTPUT].Filename, 447 FlGetFileSize (ASL_FILE_MAP_OUTPUT)); 448 } 449 } 450 451 return (AE_OK); 452 } 453 454 455 /****************************************************************************** 456 * 457 * FUNCTION: AdReparseOneTable 458 * 459 * PARAMETERS: Table - Raw AML table 460 * File - Pointer for the input file 461 * OwnerId - ID for this table 462 * 463 * RETURN: Status 464 * 465 * DESCRIPTION: Reparse a table that has already been loaded. Used to 466 * integrate information about external control methods. 467 * These methods may have been previously parsed incorrectly. 468 * 469 *****************************************************************************/ 470 471 static ACPI_STATUS 472 AdReparseOneTable ( 473 ACPI_TABLE_HEADER *Table, 474 FILE *File, 475 ACPI_OWNER_ID OwnerId) 476 { 477 ACPI_STATUS Status; 478 479 480 fprintf (stderr, 481 "\nFound %u external control methods, " 482 "reparsing with new information\n", 483 AcpiDmGetExternalMethodCount ()); 484 485 /* Reparse, rebuild namespace */ 486 487 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 488 AcpiGbl_ParseOpRoot = NULL; 489 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); 490 491 AcpiGbl_RootNode = NULL; 492 AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME; 493 AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED; 494 AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE; 495 AcpiGbl_RootNodeStruct.Parent = NULL; 496 AcpiGbl_RootNodeStruct.Child = NULL; 497 AcpiGbl_RootNodeStruct.Peer = NULL; 498 AcpiGbl_RootNodeStruct.Object = NULL; 499 AcpiGbl_RootNodeStruct.Flags = 0; 500 501 Status = AcpiNsRootInitialize (); 502 if (ACPI_FAILURE (Status)) 503 { 504 return (Status); 505 } 506 507 /* New namespace, add the external definitions first */ 508 509 AcpiDmAddExternalsToNamespace (); 510 511 /* Parse the table again. No need to reload it, however */ 512 513 Status = AdParseTable (Table, NULL, FALSE, FALSE); 514 if (ACPI_FAILURE (Status)) 515 { 516 AcpiOsPrintf ("Could not parse ACPI tables, %s\n", 517 AcpiFormatException (Status)); 518 return (Status); 519 } 520 521 /* Cross reference the namespace again */ 522 523 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 524 AcpiGbl_RootNode, OwnerId); 525 526 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, 527 AcpiGbl_RootNode, OwnerId); 528 529 /* Debug output - namespace and parse tree */ 530 531 if (AslCompilerdebug) 532 { 533 AcpiOsPrintf ("/**** After second load and resource conversion\n"); 534 if (File) 535 { 536 NsSetupNamespaceListing (File); 537 NsDisplayNamespace (); 538 } 539 540 AcpiOsPrintf ("*****/\n"); 541 AcpiDmDumpTree (AcpiGbl_ParseOpRoot); 542 } 543 544 return (AE_OK); 545 } 546 547 548 /****************************************************************************** 549 * 550 * FUNCTION: AdDoExternalFileList 551 * 552 * PARAMETERS: Filename - Input file for the table 553 * 554 * RETURN: Status 555 * 556 * DESCRIPTION: Process all tables found in the -e external files list 557 * 558 *****************************************************************************/ 559 560 static ACPI_STATUS 561 AdDoExternalFileList ( 562 char *Filename) 563 { 564 ACPI_EXTERNAL_FILE *ExternalFileList; 565 char *ExternalFilename; 566 ACPI_NEW_TABLE_DESC *ExternalListHead = NULL; 567 ACPI_STATUS Status; 568 ACPI_STATUS GlobalStatus = AE_OK; 569 ACPI_OWNER_ID OwnerId; 570 571 572 /* 573 * External filenames are specified on the command line like this: 574 * Example: iasl -e file1,file2,file3 -d xxx.aml 575 */ 576 ExternalFileList = AcpiGbl_ExternalFileList; 577 578 /* Process each external file */ 579 580 while (ExternalFileList) 581 { 582 ExternalFilename = ExternalFileList->Path; 583 if (!strcmp (ExternalFilename, Filename)) 584 { 585 /* Next external file */ 586 587 ExternalFileList = ExternalFileList->Next; 588 continue; 589 } 590 591 AcpiOsPrintf ("External object resolution file %16s\n", 592 ExternalFilename); 593 594 Status = AcGetAllTablesFromFile ( 595 ExternalFilename, ACPI_GET_ONLY_AML_TABLES, &ExternalListHead); 596 if (ACPI_FAILURE (Status)) 597 { 598 if (Status == AE_TYPE) 599 { 600 ExternalFileList = ExternalFileList->Next; 601 GlobalStatus = AE_TYPE; 602 Status = AE_OK; 603 continue; 604 } 605 606 return (Status); 607 } 608 609 /* Load external tables for symbol resolution */ 610 611 while (ExternalListHead) 612 { 613 Status = AdParseTable ( 614 ExternalListHead->Table, &OwnerId, TRUE, TRUE); 615 if (ACPI_FAILURE (Status)) 616 { 617 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n", 618 AcpiFormatException (Status)); 619 return (Status); 620 } 621 622 /* 623 * Load namespace from names created within control methods 624 * Set owner id of nodes in external table 625 */ 626 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 627 AcpiGbl_RootNode, OwnerId); 628 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 629 630 ExternalListHead = ExternalListHead->Next; 631 } 632 633 /* Next external file */ 634 635 ExternalFileList = ExternalFileList->Next; 636 } 637 638 if (ACPI_FAILURE (GlobalStatus)) 639 { 640 return (GlobalStatus); 641 } 642 643 /* Clear external list generated by Scope in external tables */ 644 645 if (AcpiGbl_ExternalFileList) 646 { 647 AcpiDmClearExternalList (); 648 } 649 650 /* Load any externals defined in the optional external ref file */ 651 652 AcpiDmGetExternalsFromFile (); 653 return (AE_OK); 654 } 655