1 /****************************************************************************** 2 * 3 * Module Name: adisasm - Application-level disassembler routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, 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 45 #include <contrib/dev/acpica/include/acpi.h> 46 #include <contrib/dev/acpica/include/accommon.h> 47 #include <contrib/dev/acpica/include/acparser.h> 48 #include <contrib/dev/acpica/include/amlcode.h> 49 #include <contrib/dev/acpica/include/acdebug.h> 50 #include <contrib/dev/acpica/include/acdisasm.h> 51 #include <contrib/dev/acpica/include/acdispat.h> 52 #include <contrib/dev/acpica/include/acnamesp.h> 53 #include <contrib/dev/acpica/include/actables.h> 54 #include <contrib/dev/acpica/include/acapps.h> 55 56 #include <stdio.h> 57 #include <time.h> 58 59 60 #define _COMPONENT ACPI_TOOLS 61 ACPI_MODULE_NAME ("adisasm") 62 63 /* 64 * Older versions of Bison won't emit this external in the generated header. 65 * Newer versions do emit the external, so we don't need to do it. 66 */ 67 #ifndef ASLCOMPILER_ASLCOMPILERPARSE_H 68 extern int AslCompilerdebug; 69 #endif 70 71 ACPI_STATUS 72 LsDisplayNamespace ( 73 void); 74 75 void 76 LsSetupNsList ( 77 void *Handle); 78 79 80 /* Local prototypes */ 81 82 static UINT32 83 AdGetFileSize ( 84 FILE *File); 85 86 static void 87 AdCreateTableHeader ( 88 char *Filename, 89 ACPI_TABLE_HEADER *Table); 90 91 static ACPI_STATUS 92 AdDeferredParse ( 93 ACPI_PARSE_OBJECT *Op, 94 UINT8 *Aml, 95 UINT32 AmlLength); 96 97 static ACPI_STATUS 98 AdParseDeferredOps ( 99 ACPI_PARSE_OBJECT *Root); 100 101 102 /* Stubs for ASL compiler */ 103 104 #ifndef ACPI_ASL_COMPILER 105 BOOLEAN 106 AcpiDsIsResultUsed ( 107 ACPI_PARSE_OBJECT *Op, 108 ACPI_WALK_STATE *WalkState) 109 { 110 return TRUE; 111 } 112 113 ACPI_STATUS 114 AcpiDsMethodError ( 115 ACPI_STATUS Status, 116 ACPI_WALK_STATE *WalkState) 117 { 118 return (Status); 119 } 120 #endif 121 122 ACPI_STATUS 123 AcpiNsLoadTable ( 124 UINT32 TableIndex, 125 ACPI_NAMESPACE_NODE *Node) 126 { 127 return (AE_NOT_IMPLEMENTED); 128 } 129 130 ACPI_STATUS 131 AcpiDsRestartControlMethod ( 132 ACPI_WALK_STATE *WalkState, 133 ACPI_OPERAND_OBJECT *ReturnDesc) 134 { 135 return (AE_OK); 136 } 137 138 void 139 AcpiDsTerminateControlMethod ( 140 ACPI_OPERAND_OBJECT *MethodDesc, 141 ACPI_WALK_STATE *WalkState) 142 { 143 return; 144 } 145 146 ACPI_STATUS 147 AcpiDsCallControlMethod ( 148 ACPI_THREAD_STATE *Thread, 149 ACPI_WALK_STATE *WalkState, 150 ACPI_PARSE_OBJECT *Op) 151 { 152 return (AE_OK); 153 } 154 155 ACPI_STATUS 156 AcpiDsMethodDataInitArgs ( 157 ACPI_OPERAND_OBJECT **Params, 158 UINT32 MaxParamCount, 159 ACPI_WALK_STATE *WalkState) 160 { 161 return (AE_OK); 162 } 163 164 165 static ACPI_TABLE_DESC LocalTables[1]; 166 static ACPI_PARSE_OBJECT *AcpiGbl_ParseOpRoot; 167 168 169 /******************************************************************************* 170 * 171 * FUNCTION: AdGetFileSize 172 * 173 * PARAMETERS: File - Open file handle 174 * 175 * RETURN: File Size 176 * 177 * DESCRIPTION: Get current file size. Uses seek-to-EOF. File must be open. 178 * 179 ******************************************************************************/ 180 181 static UINT32 182 AdGetFileSize ( 183 FILE *File) 184 { 185 UINT32 FileSize; 186 long Offset; 187 188 189 Offset = ftell (File); 190 191 fseek (File, 0, SEEK_END); 192 FileSize = (UINT32) ftell (File); 193 194 /* Restore file pointer */ 195 196 fseek (File, Offset, SEEK_SET); 197 return (FileSize); 198 } 199 200 201 /******************************************************************************* 202 * 203 * FUNCTION: AdInitialize 204 * 205 * PARAMETERS: None 206 * 207 * RETURN: Status 208 * 209 * DESCRIPTION: ACPICA and local initialization 210 * 211 ******************************************************************************/ 212 213 ACPI_STATUS 214 AdInitialize ( 215 void) 216 { 217 ACPI_STATUS Status; 218 219 220 /* ACPI CA subsystem initialization */ 221 222 Status = AcpiOsInitialize (); 223 if (ACPI_FAILURE (Status)) 224 { 225 return (Status); 226 } 227 228 Status = AcpiUtInitGlobals (); 229 if (ACPI_FAILURE (Status)) 230 { 231 return (Status); 232 } 233 234 Status = AcpiUtMutexInitialize (); 235 if (ACPI_FAILURE (Status)) 236 { 237 return (Status); 238 } 239 240 Status = AcpiNsRootInitialize (); 241 if (ACPI_FAILURE (Status)) 242 { 243 return (Status); 244 } 245 246 /* Setup the Table Manager (cheat - there is no RSDT) */ 247 248 AcpiGbl_RootTableList.MaxTableCount = 1; 249 AcpiGbl_RootTableList.CurrentTableCount = 0; 250 AcpiGbl_RootTableList.Tables = LocalTables; 251 252 return (Status); 253 } 254 255 256 /****************************************************************************** 257 * 258 * FUNCTION: AdAmlDisassemble 259 * 260 * PARAMETERS: Filename - AML input filename 261 * OutToFile - TRUE if output should go to a file 262 * Prefix - Path prefix for output 263 * OutFilename - where the filename is returned 264 * GetAllTables - TRUE if all tables are desired 265 * 266 * RETURN: Status 267 * 268 * DESCRIPTION: Disassemble an entire ACPI table 269 * 270 *****************************************************************************/ 271 272 ACPI_STATUS 273 AdAmlDisassemble ( 274 BOOLEAN OutToFile, 275 char *Filename, 276 char *Prefix, 277 char **OutFilename, 278 BOOLEAN GetAllTables) 279 { 280 ACPI_STATUS Status; 281 char *DisasmFilename = NULL; 282 char *ExternalFilename; 283 ACPI_EXTERNAL_FILE *ExternalFileList = AcpiGbl_ExternalFileList; 284 FILE *File = NULL; 285 ACPI_TABLE_HEADER *Table = NULL; 286 ACPI_TABLE_HEADER *ExternalTable; 287 ACPI_OWNER_ID OwnerId; 288 289 290 /* 291 * Input: AML code from either a file or via GetTables (memory or 292 * registry) 293 */ 294 if (Filename) 295 { 296 Status = AcpiDbGetTableFromFile (Filename, &Table); 297 if (ACPI_FAILURE (Status)) 298 { 299 return Status; 300 } 301 302 /* 303 * External filenames separated by commas 304 * Example: iasl -e file1,file2,file3 -d xxx.aml 305 */ 306 while (ExternalFileList) 307 { 308 ExternalFilename = ExternalFileList->Path; 309 if (!ACPI_STRCMP (ExternalFilename, Filename)) 310 { 311 /* Next external file */ 312 313 ExternalFileList = ExternalFileList->Next; 314 315 continue; 316 } 317 318 Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable); 319 if (ACPI_FAILURE (Status)) 320 { 321 return Status; 322 } 323 324 /* Load external table for symbol resolution */ 325 326 if (ExternalTable) 327 { 328 Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE); 329 if (ACPI_FAILURE (Status)) 330 { 331 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n", 332 AcpiFormatException (Status)); 333 return Status; 334 } 335 336 /* 337 * Load namespace from names created within control methods 338 * Set owner id of nodes in external table 339 */ 340 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 341 AcpiGbl_RootNode, OwnerId); 342 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 343 } 344 345 /* Next external file */ 346 347 ExternalFileList = ExternalFileList->Next; 348 } 349 350 /* Clear external list generated by Scope in external tables */ 351 352 if (AcpiGbl_ExternalFileList) 353 { 354 AcpiDmClearExternalList (); 355 } 356 } 357 else 358 { 359 Status = AdGetLocalTables (Filename, GetAllTables); 360 if (ACPI_FAILURE (Status)) 361 { 362 AcpiOsPrintf ("Could not get ACPI tables, %s\n", 363 AcpiFormatException (Status)); 364 return Status; 365 } 366 367 if (!AcpiGbl_DbOpt_disasm) 368 { 369 return AE_OK; 370 } 371 372 /* Obtained the local tables, just disassemble the DSDT */ 373 374 Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table); 375 if (ACPI_FAILURE (Status)) 376 { 377 AcpiOsPrintf ("Could not get DSDT, %s\n", 378 AcpiFormatException (Status)); 379 return Status; 380 } 381 382 AcpiOsPrintf ("\nDisassembly of DSDT\n"); 383 Prefix = AdGenerateFilename ("dsdt", Table->OemTableId); 384 } 385 386 /* 387 * Output: ASL code. Redirect to a file if requested 388 */ 389 if (OutToFile) 390 { 391 /* Create/Open a disassembly output file */ 392 393 DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY); 394 if (!OutFilename) 395 { 396 fprintf (stderr, "Could not generate output filename\n"); 397 Status = AE_ERROR; 398 goto Cleanup; 399 } 400 401 File = fopen (DisasmFilename, "w+"); 402 if (!File) 403 { 404 fprintf (stderr, "Could not open output file %s\n", DisasmFilename); 405 Status = AE_ERROR; 406 goto Cleanup; 407 } 408 409 AcpiOsRedirectOutput (File); 410 } 411 412 *OutFilename = DisasmFilename; 413 414 if (!AcpiUtIsAmlTable (Table)) 415 { 416 AdDisassemblerHeader (Filename); 417 AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n", 418 Table->Signature); 419 AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength] " 420 "FieldName : FieldValue\n */\n\n"); 421 422 AcpiDmDumpDataTable (Table); 423 fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n", 424 Table->Signature); 425 fprintf (stderr, "Formatted output: %s - %u bytes\n", 426 DisasmFilename, AdGetFileSize (File)); 427 } 428 else 429 { 430 /* Always parse the tables, only option is what to display */ 431 432 Status = AdParseTable (Table, &OwnerId, TRUE, FALSE); 433 if (ACPI_FAILURE (Status)) 434 { 435 AcpiOsPrintf ("Could not parse ACPI tables, %s\n", 436 AcpiFormatException (Status)); 437 goto Cleanup; 438 } 439 440 if (AslCompilerdebug) 441 { 442 AcpiOsPrintf ("/**** Before second load\n"); 443 444 LsSetupNsList (File); 445 LsDisplayNamespace (); 446 AcpiOsPrintf ("*****/\n"); 447 } 448 449 /* Load namespace from names created within control methods */ 450 451 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, 452 AcpiGbl_RootNode, OwnerId); 453 454 /* 455 * Cross reference the namespace here, in order to 456 * generate External() statements 457 */ 458 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, 459 AcpiGbl_RootNode, OwnerId); 460 461 if (AslCompilerdebug) 462 { 463 AcpiDmDumpTree (AcpiGbl_ParseOpRoot); 464 } 465 466 /* Find possible calls to external control methods */ 467 468 AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot); 469 470 /* 471 * If we found any external control methods, we must reparse 472 * the entire tree with the new information (namely, the 473 * number of arguments per method) 474 */ 475 if (AcpiDmGetExternalMethodCount ()) 476 { 477 fprintf (stderr, 478 "\nFound %u external control methods, " 479 "reparsing with new information\n", 480 AcpiDmGetExternalMethodCount ()); 481 482 /* Reparse, rebuild namespace. no need to xref namespace */ 483 484 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 485 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); 486 487 AcpiGbl_RootNode = NULL; 488 AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME; 489 AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED; 490 AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE; 491 AcpiGbl_RootNodeStruct.Parent = NULL; 492 AcpiGbl_RootNodeStruct.Child = NULL; 493 AcpiGbl_RootNodeStruct.Peer = NULL; 494 AcpiGbl_RootNodeStruct.Object = NULL; 495 AcpiGbl_RootNodeStruct.Flags = 0; 496 497 Status = AcpiNsRootInitialize (); 498 AcpiDmAddExternalsToNamespace (); 499 500 /* Parse the table again. No need to reload it, however */ 501 502 Status = AdParseTable (Table, NULL, FALSE, FALSE); 503 if (ACPI_FAILURE (Status)) 504 { 505 AcpiOsPrintf ("Could not parse ACPI tables, %s\n", 506 AcpiFormatException (Status)); 507 goto Cleanup; 508 } 509 510 if (AslCompilerdebug) 511 { 512 AcpiOsPrintf ("/**** After second load and resource conversion\n"); 513 LsSetupNsList (File); 514 LsDisplayNamespace (); 515 AcpiOsPrintf ("*****/\n"); 516 517 AcpiDmDumpTree (AcpiGbl_ParseOpRoot); 518 } 519 } 520 521 /* 522 * Now that the namespace is finalized, we can perform namespace 523 * transforms. 524 * 525 * 1) Convert fixed-offset references to resource descriptors 526 * to symbolic references (Note: modifies namespace) 527 */ 528 AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode); 529 530 /* Optional displays */ 531 532 if (AcpiGbl_DbOpt_disasm) 533 { 534 AdDisplayTables (Filename, Table); 535 fprintf (stderr, "Disassembly completed\n"); 536 fprintf (stderr, "ASL Output: %s - %u bytes\n", 537 DisasmFilename, AdGetFileSize (File)); 538 } 539 } 540 541 Cleanup: 542 543 if (Table && !AcpiUtIsAmlTable (Table)) 544 { 545 ACPI_FREE (Table); 546 } 547 548 if (DisasmFilename) 549 { 550 ACPI_FREE (DisasmFilename); 551 } 552 553 if (OutToFile && File) 554 { 555 if (AslCompilerdebug) /* Display final namespace, with transforms */ 556 { 557 LsSetupNsList (File); 558 LsDisplayNamespace (); 559 } 560 561 fclose (File); 562 AcpiOsRedirectOutput (stdout); 563 } 564 565 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); 566 AcpiGbl_ParseOpRoot = NULL; 567 return (Status); 568 } 569 570 571 /****************************************************************************** 572 * 573 * FUNCTION: AdDisassemblerHeader 574 * 575 * PARAMETERS: Filename - Input file for the table 576 * 577 * RETURN: None 578 * 579 * DESCRIPTION: Create the disassembler header, including ACPI CA signon with 580 * current time and date. 581 * 582 *****************************************************************************/ 583 584 void 585 AdDisassemblerHeader ( 586 char *Filename) 587 { 588 time_t Timer; 589 590 time (&Timer); 591 592 /* Header and input table info */ 593 594 AcpiOsPrintf ("/*\n"); 595 AcpiOsPrintf (ACPI_COMMON_HEADER ("AML Disassembler", " * ")); 596 597 AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer)); 598 AcpiOsPrintf (" *\n"); 599 } 600 601 602 /****************************************************************************** 603 * 604 * FUNCTION: AdCreateTableHeader 605 * 606 * PARAMETERS: Filename - Input file for the table 607 * Table - Pointer to the raw table 608 * 609 * RETURN: None 610 * 611 * DESCRIPTION: Create the ASL table header, including ACPI CA signon with 612 * current time and date. 613 * 614 *****************************************************************************/ 615 616 static void 617 AdCreateTableHeader ( 618 char *Filename, 619 ACPI_TABLE_HEADER *Table) 620 { 621 char *NewFilename; 622 UINT8 Checksum; 623 624 625 /* 626 * Print file header and dump original table header 627 */ 628 AdDisassemblerHeader (Filename); 629 630 AcpiOsPrintf (" * Original Table Header:\n"); 631 AcpiOsPrintf (" * Signature \"%4.4s\"\n", Table->Signature); 632 AcpiOsPrintf (" * Length 0x%8.8X (%u)\n", Table->Length, Table->Length); 633 634 /* Print and validate the revision */ 635 636 AcpiOsPrintf (" * Revision 0x%2.2X", Table->Revision); 637 638 switch (Table->Revision) 639 { 640 case 0: 641 AcpiOsPrintf (" **** Invalid Revision"); 642 break; 643 644 case 1: 645 /* Revision of DSDT controls the ACPI integer width */ 646 647 if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT)) 648 { 649 AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support"); 650 } 651 break; 652 653 default: 654 break; 655 } 656 AcpiOsPrintf ("\n"); 657 658 /* Print and validate the table checksum */ 659 660 AcpiOsPrintf (" * Checksum 0x%2.2X", Table->Checksum); 661 662 Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length); 663 if (Checksum) 664 { 665 AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X", 666 (UINT8) (Table->Checksum - Checksum)); 667 } 668 AcpiOsPrintf ("\n"); 669 670 AcpiOsPrintf (" * OEM ID \"%.6s\"\n", Table->OemId); 671 AcpiOsPrintf (" * OEM Table ID \"%.8s\"\n", Table->OemTableId); 672 AcpiOsPrintf (" * OEM Revision 0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision); 673 AcpiOsPrintf (" * Compiler ID \"%.4s\"\n", Table->AslCompilerId); 674 AcpiOsPrintf (" * Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision); 675 AcpiOsPrintf (" */\n\n"); 676 677 /* Create AML output filename based on input filename */ 678 679 if (Filename) 680 { 681 NewFilename = FlGenerateFilename (Filename, "aml"); 682 } 683 else 684 { 685 NewFilename = ACPI_ALLOCATE_ZEROED (9); 686 strncat (NewFilename, Table->Signature, 4); 687 strcat (NewFilename, ".aml"); 688 } 689 690 /* Open the ASL definition block */ 691 692 AcpiOsPrintf ( 693 "DefinitionBlock (\"%s\", \"%4.4s\", %hu, \"%.6s\", \"%.8s\", 0x%8.8X)\n", 694 NewFilename, Table->Signature, Table->Revision, 695 Table->OemId, Table->OemTableId, Table->OemRevision); 696 697 ACPI_FREE (NewFilename); 698 } 699 700 701 /****************************************************************************** 702 * 703 * FUNCTION: AdDisplayTables 704 * 705 * PARAMETERS: Filename - Input file for the table 706 * Table - Pointer to the raw table 707 * 708 * RETURN: Status 709 * 710 * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables 711 * 712 *****************************************************************************/ 713 714 ACPI_STATUS 715 AdDisplayTables ( 716 char *Filename, 717 ACPI_TABLE_HEADER *Table) 718 { 719 720 721 if (!AcpiGbl_ParseOpRoot) 722 { 723 return AE_NOT_EXIST; 724 } 725 726 if (!AcpiGbl_DbOpt_verbose) 727 { 728 AdCreateTableHeader (Filename, Table); 729 } 730 731 AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX); 732 733 if (AcpiGbl_DbOpt_verbose) 734 { 735 AcpiOsPrintf ("\n\nTable Header:\n"); 736 AcpiUtDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER), 737 DB_BYTE_DISPLAY, ACPI_UINT32_MAX); 738 739 AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length); 740 AcpiUtDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)), Table->Length, 741 DB_BYTE_DISPLAY, ACPI_UINT32_MAX); 742 } 743 744 return AE_OK; 745 } 746 747 748 /****************************************************************************** 749 * 750 * FUNCTION: AdDeferredParse 751 * 752 * PARAMETERS: Op - Root Op of the deferred opcode 753 * Aml - Pointer to the raw AML 754 * AmlLength - Length of the AML 755 * 756 * RETURN: Status 757 * 758 * DESCRIPTION: Parse one deferred opcode 759 * (Methods, operation regions, etc.) 760 * 761 *****************************************************************************/ 762 763 static ACPI_STATUS 764 AdDeferredParse ( 765 ACPI_PARSE_OBJECT *Op, 766 UINT8 *Aml, 767 UINT32 AmlLength) 768 { 769 ACPI_WALK_STATE *WalkState; 770 ACPI_STATUS Status; 771 ACPI_PARSE_OBJECT *SearchOp; 772 ACPI_PARSE_OBJECT *StartOp; 773 UINT32 BaseAmlOffset; 774 ACPI_PARSE_OBJECT *ExtraOp; 775 776 777 ACPI_FUNCTION_TRACE (AdDeferredParse); 778 779 780 fprintf (stderr, "."); 781 782 if (!Aml || !AmlLength) 783 { 784 return_ACPI_STATUS (AE_OK); 785 } 786 787 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing %s [%4.4s]\n", 788 Op->Common.AmlOpName, (char *) &Op->Named.Name)); 789 790 WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 791 if (!WalkState) 792 { 793 return_ACPI_STATUS (AE_NO_MEMORY); 794 } 795 796 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml, 797 AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 798 if (ACPI_FAILURE (Status)) 799 { 800 return_ACPI_STATUS (Status); 801 } 802 803 /* Parse the method */ 804 805 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 806 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 807 Status = AcpiPsParseAml (WalkState); 808 809 /* 810 * We need to update all of the Aml offsets, since the parser thought 811 * that the method began at offset zero. In reality, it began somewhere 812 * within the ACPI table, at the BaseAmlOffset. Walk the entire tree that 813 * was just created and update the AmlOffset in each Op 814 */ 815 BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1; 816 StartOp = (Op->Common.Value.Arg)->Common.Next; 817 SearchOp = StartOp; 818 819 /* Walk the parse tree */ 820 821 while (SearchOp) 822 { 823 SearchOp->Common.AmlOffset += BaseAmlOffset; 824 SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp); 825 } 826 827 /* 828 * Link the newly parsed subtree into the main parse tree 829 */ 830 switch (Op->Common.AmlOpcode) 831 { 832 case AML_BUFFER_OP: 833 case AML_PACKAGE_OP: 834 case AML_VAR_PACKAGE_OP: 835 836 switch (Op->Common.AmlOpcode) 837 { 838 case AML_PACKAGE_OP: 839 ExtraOp = Op->Common.Value.Arg; 840 ExtraOp = ExtraOp->Common.Next; 841 Op->Common.Value.Arg = ExtraOp->Common.Value.Arg; 842 break; 843 844 case AML_VAR_PACKAGE_OP: 845 case AML_BUFFER_OP: 846 default: 847 ExtraOp = Op->Common.Value.Arg; 848 Op->Common.Value.Arg = ExtraOp->Common.Value.Arg; 849 break; 850 } 851 852 /* Must point all parents to the main tree */ 853 854 StartOp = Op; 855 SearchOp = StartOp; 856 while (SearchOp) 857 { 858 if (SearchOp->Common.Parent == ExtraOp) 859 { 860 SearchOp->Common.Parent = Op; 861 } 862 SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp); 863 } 864 break; 865 866 default: 867 break; 868 } 869 870 return_ACPI_STATUS (AE_OK); 871 } 872 873 874 /****************************************************************************** 875 * 876 * FUNCTION: AdParseDeferredOps 877 * 878 * PARAMETERS: Root - Root of the parse tree 879 * 880 * RETURN: Status 881 * 882 * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.) 883 * 884 *****************************************************************************/ 885 886 static ACPI_STATUS 887 AdParseDeferredOps ( 888 ACPI_PARSE_OBJECT *Root) 889 { 890 ACPI_PARSE_OBJECT *Op = Root; 891 ACPI_STATUS Status = AE_OK; 892 const ACPI_OPCODE_INFO *OpInfo; 893 894 895 ACPI_FUNCTION_NAME (AdParseDeferredOps); 896 fprintf (stderr, "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n"); 897 898 while (Op) 899 { 900 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 901 if (!(OpInfo->Flags & AML_DEFER)) 902 { 903 Op = AcpiPsGetDepthNext (Root, Op); 904 continue; 905 } 906 907 switch (Op->Common.AmlOpcode) 908 { 909 case AML_METHOD_OP: 910 case AML_BUFFER_OP: 911 case AML_PACKAGE_OP: 912 case AML_VAR_PACKAGE_OP: 913 914 Status = AdDeferredParse (Op, Op->Named.Data, Op->Named.Length); 915 if (ACPI_FAILURE (Status)) 916 { 917 return_ACPI_STATUS (Status); 918 } 919 break; 920 921 case AML_REGION_OP: 922 case AML_DATA_REGION_OP: 923 case AML_CREATE_QWORD_FIELD_OP: 924 case AML_CREATE_DWORD_FIELD_OP: 925 case AML_CREATE_WORD_FIELD_OP: 926 case AML_CREATE_BYTE_FIELD_OP: 927 case AML_CREATE_BIT_FIELD_OP: 928 case AML_CREATE_FIELD_OP: 929 case AML_BANK_FIELD_OP: 930 931 /* Nothing to do in these cases */ 932 933 break; 934 935 default: 936 ACPI_ERROR ((AE_INFO, "Unhandled deferred opcode [%s]", 937 Op->Common.AmlOpName)); 938 break; 939 } 940 941 Op = AcpiPsGetDepthNext (Root, Op); 942 } 943 944 fprintf (stderr, "\n"); 945 return Status; 946 } 947 948 949 /****************************************************************************** 950 * 951 * FUNCTION: AdGetLocalTables 952 * 953 * PARAMETERS: Filename - Not used 954 * GetAllTables - TRUE if all tables are desired 955 * 956 * RETURN: Status 957 * 958 * DESCRIPTION: Get the ACPI tables from either memory or a file 959 * 960 *****************************************************************************/ 961 962 ACPI_STATUS 963 AdGetLocalTables ( 964 char *Filename, 965 BOOLEAN GetAllTables) 966 { 967 ACPI_STATUS Status; 968 ACPI_TABLE_HEADER TableHeader; 969 ACPI_TABLE_HEADER *NewTable; 970 UINT32 NumTables; 971 UINT32 PointerSize; 972 UINT32 TableIndex; 973 974 975 if (GetAllTables) 976 { 977 ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_RSDT); 978 AcpiOsTableOverride (&TableHeader, &NewTable); 979 if (!NewTable) 980 { 981 fprintf (stderr, "Could not obtain RSDT\n"); 982 return AE_NO_ACPI_TABLES; 983 } 984 else 985 { 986 AdWriteTable (NewTable, NewTable->Length, 987 ACPI_SIG_RSDT, NewTable->OemTableId); 988 } 989 990 if (ACPI_COMPARE_NAME (NewTable->Signature, ACPI_SIG_RSDT)) 991 { 992 PointerSize = sizeof (UINT32); 993 } 994 else 995 { 996 PointerSize = sizeof (UINT64); 997 } 998 999 /* 1000 * Determine the number of tables pointed to by the RSDT/XSDT. 1001 * This is defined by the ACPI Specification to be the number of 1002 * pointers contained within the RSDT/XSDT. The size of the pointers 1003 * is architecture-dependent. 1004 */ 1005 NumTables = (NewTable->Length - sizeof (ACPI_TABLE_HEADER)) / PointerSize; 1006 AcpiOsPrintf ("There are %u tables defined in the %4.4s\n\n", 1007 NumTables, NewTable->Signature); 1008 1009 /* Get the FADT */ 1010 1011 ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_FADT); 1012 AcpiOsTableOverride (&TableHeader, &NewTable); 1013 if (NewTable) 1014 { 1015 AdWriteTable (NewTable, NewTable->Length, 1016 ACPI_SIG_FADT, NewTable->OemTableId); 1017 } 1018 AcpiOsPrintf ("\n"); 1019 1020 /* Don't bother with FACS, it is usually all zeros */ 1021 } 1022 1023 /* Always get the DSDT */ 1024 1025 ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT); 1026 AcpiOsTableOverride (&TableHeader, &NewTable); 1027 if (NewTable) 1028 { 1029 AdWriteTable (NewTable, NewTable->Length, 1030 ACPI_SIG_DSDT, NewTable->OemTableId); 1031 1032 /* Store DSDT in the Table Manager */ 1033 1034 Status = AcpiTbStoreTable (0, NewTable, NewTable->Length, 1035 0, &TableIndex); 1036 if (ACPI_FAILURE (Status)) 1037 { 1038 fprintf (stderr, "Could not store DSDT\n"); 1039 return AE_NO_ACPI_TABLES; 1040 } 1041 } 1042 else 1043 { 1044 fprintf (stderr, "Could not obtain DSDT\n"); 1045 return AE_NO_ACPI_TABLES; 1046 } 1047 1048 #if 0 1049 /* TBD: Future implementation */ 1050 1051 AcpiOsPrintf ("\n"); 1052 1053 /* Get all SSDTs */ 1054 1055 ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_SSDT); 1056 do 1057 { 1058 NewTable = NULL; 1059 Status = AcpiOsTableOverride (&TableHeader, &NewTable); 1060 1061 } while (NewTable); 1062 #endif 1063 1064 return AE_OK; 1065 } 1066 1067 1068 /****************************************************************************** 1069 * 1070 * FUNCTION: AdParseTable 1071 * 1072 * PARAMETERS: Table - Pointer to the raw table 1073 * OwnerId - Returned OwnerId of the table 1074 * LoadTable - If add table to the global table list 1075 * External - If this is an external table 1076 * 1077 * RETURN: Status 1078 * 1079 * DESCRIPTION: Parse the DSDT. 1080 * 1081 *****************************************************************************/ 1082 1083 ACPI_STATUS 1084 AdParseTable ( 1085 ACPI_TABLE_HEADER *Table, 1086 ACPI_OWNER_ID *OwnerId, 1087 BOOLEAN LoadTable, 1088 BOOLEAN External) 1089 { 1090 ACPI_STATUS Status = AE_OK; 1091 ACPI_WALK_STATE *WalkState; 1092 UINT8 *AmlStart; 1093 UINT32 AmlLength; 1094 UINT32 TableIndex; 1095 1096 1097 if (!Table) 1098 { 1099 return AE_NOT_EXIST; 1100 } 1101 1102 /* Pass 1: Parse everything except control method bodies */ 1103 1104 fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature); 1105 1106 AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER); 1107 AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)); 1108 1109 /* Create the root object */ 1110 1111 AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp (); 1112 if (!AcpiGbl_ParseOpRoot) 1113 { 1114 return AE_NO_MEMORY; 1115 } 1116 1117 /* Create and initialize a new walk state */ 1118 1119 WalkState = AcpiDsCreateWalkState (0, 1120 AcpiGbl_ParseOpRoot, NULL, NULL); 1121 if (!WalkState) 1122 { 1123 return (AE_NO_MEMORY); 1124 } 1125 1126 Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot, 1127 NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 1128 if (ACPI_FAILURE (Status)) 1129 { 1130 return (Status); 1131 } 1132 1133 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 1134 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 1135 1136 Status = AcpiPsParseAml (WalkState); 1137 if (ACPI_FAILURE (Status)) 1138 { 1139 return Status; 1140 } 1141 1142 /* If LoadTable is FALSE, we are parsing the last loaded table */ 1143 1144 TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1; 1145 1146 /* Pass 2 */ 1147 1148 if (LoadTable) 1149 { 1150 Status = AcpiTbStoreTable ((ACPI_PHYSICAL_ADDRESS) Table, Table, 1151 Table->Length, ACPI_TABLE_ORIGIN_ALLOCATED, &TableIndex); 1152 if (ACPI_FAILURE (Status)) 1153 { 1154 return Status; 1155 } 1156 Status = AcpiTbAllocateOwnerId (TableIndex); 1157 if (ACPI_FAILURE (Status)) 1158 { 1159 return Status; 1160 } 1161 if (OwnerId) 1162 { 1163 Status = AcpiTbGetOwnerId (TableIndex, OwnerId); 1164 if (ACPI_FAILURE (Status)) 1165 { 1166 return Status; 1167 } 1168 } 1169 } 1170 1171 fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature); 1172 1173 Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL); 1174 if (ACPI_FAILURE (Status)) 1175 { 1176 return (Status); 1177 } 1178 1179 /* No need to parse control methods of external table */ 1180 1181 if (External) 1182 { 1183 return AE_OK; 1184 } 1185 1186 /* Pass 3: Parse control methods and link their parse trees into the main parse tree */ 1187 1188 Status = AdParseDeferredOps (AcpiGbl_ParseOpRoot); 1189 1190 /* Process Resource Templates */ 1191 1192 AcpiDmFindResources (AcpiGbl_ParseOpRoot); 1193 1194 fprintf (stderr, "Parsing completed\n"); 1195 return AE_OK; 1196 } 1197 1198 1199