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