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