1 /******************************************************************************
3 * Module Name: adisasm - Application-level disassembler routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2015, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
44 #include "aslcompiler.h"
57 #define _COMPONENT ACPI_TOOLS
58 ACPI_MODULE_NAME ("adisasm")
60 /* Local prototypes */
65 ACPI_TABLE_HEADER *Table);
69 ACPI_TABLE_HEADER *Table,
72 /* Stubs for ASL compiler */
74 #ifndef ACPI_ASL_COMPILER
77 ACPI_PARSE_OBJECT *Op,
78 ACPI_WALK_STATE *WalkState)
86 ACPI_WALK_STATE *WalkState)
95 ACPI_NAMESPACE_NODE *Node)
97 return (AE_NOT_IMPLEMENTED);
101 AcpiDsRestartControlMethod (
102 ACPI_WALK_STATE *WalkState,
103 ACPI_OPERAND_OBJECT *ReturnDesc)
109 AcpiDsTerminateControlMethod (
110 ACPI_OPERAND_OBJECT *MethodDesc,
111 ACPI_WALK_STATE *WalkState)
117 AcpiDsCallControlMethod (
118 ACPI_THREAD_STATE *Thread,
119 ACPI_WALK_STATE *WalkState,
120 ACPI_PARSE_OBJECT *Op)
126 AcpiDsMethodDataInitArgs (
127 ACPI_OPERAND_OBJECT **Params,
128 UINT32 MaxParamCount,
129 ACPI_WALK_STATE *WalkState)
135 static ACPI_TABLE_DESC LocalTables[1];
136 ACPI_PARSE_OBJECT *AcpiGbl_ParseOpRoot;
139 /*******************************************************************************
141 * FUNCTION: AdInitialize
147 * DESCRIPTION: ACPICA and local initialization
149 ******************************************************************************/
158 /* ACPICA subsystem initialization */
160 Status = AcpiOsInitialize ();
161 if (ACPI_FAILURE (Status))
166 Status = AcpiUtInitGlobals ();
167 if (ACPI_FAILURE (Status))
172 Status = AcpiUtMutexInitialize ();
173 if (ACPI_FAILURE (Status))
178 Status = AcpiNsRootInitialize ();
179 if (ACPI_FAILURE (Status))
184 /* Setup the Table Manager (cheat - there is no RSDT) */
186 AcpiGbl_RootTableList.MaxTableCount = 1;
187 AcpiGbl_RootTableList.CurrentTableCount = 0;
188 AcpiGbl_RootTableList.Tables = LocalTables;
194 /******************************************************************************
196 * FUNCTION: AdAmlDisassemble
198 * PARAMETERS: Filename - AML input filename
199 * OutToFile - TRUE if output should go to a file
200 * Prefix - Path prefix for output
201 * OutFilename - where the filename is returned
205 * DESCRIPTION: Disassemble an entire ACPI table
207 *****************************************************************************/
217 ACPI_STATUS GlobalStatus = AE_OK;
218 char *DisasmFilename = NULL;
219 char *ExternalFilename;
220 ACPI_EXTERNAL_FILE *ExternalFileList = AcpiGbl_ExternalFileList;
222 ACPI_TABLE_HEADER *Table = NULL;
223 ACPI_TABLE_HEADER *ExternalTable;
224 ACPI_OWNER_ID OwnerId;
228 * Input: AML code from either a file or via GetTables (memory or
233 Status = AcpiDbGetTableFromFile (Filename, &Table, FALSE);
234 if (ACPI_FAILURE (Status))
240 * External filenames separated by commas
241 * Example: iasl -e file1,file2,file3 -d xxx.aml
243 while (ExternalFileList)
245 ExternalFilename = ExternalFileList->Path;
246 if (!strcmp (ExternalFilename, Filename))
248 /* Next external file */
250 ExternalFileList = ExternalFileList->Next;
254 Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable, TRUE);
255 if (ACPI_FAILURE (Status))
257 if (Status == AE_TYPE)
259 ExternalFileList = ExternalFileList->Next;
260 GlobalStatus = AE_TYPE;
267 /* Load external table for symbol resolution */
271 Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE);
272 if (ACPI_FAILURE (Status))
274 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
275 AcpiFormatException (Status));
280 * Load namespace from names created within control methods
281 * Set owner id of nodes in external table
283 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
284 AcpiGbl_RootNode, OwnerId);
285 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
288 /* Next external file */
290 ExternalFileList = ExternalFileList->Next;
293 if (ACPI_FAILURE (GlobalStatus))
295 return (GlobalStatus);
298 /* Clear external list generated by Scope in external tables */
300 if (AcpiGbl_ExternalFileList)
302 AcpiDmClearExternalList ();
305 /* Load any externals defined in the optional external ref file */
307 AcpiDmGetExternalsFromFile ();
311 Status = AdGetLocalTables ();
312 if (ACPI_FAILURE (Status))
314 AcpiOsPrintf ("Could not get ACPI tables, %s\n",
315 AcpiFormatException (Status));
319 if (!AcpiGbl_DbOpt_Disasm)
324 /* Obtained the local tables, just disassemble the DSDT */
326 Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
327 if (ACPI_FAILURE (Status))
329 AcpiOsPrintf ("Could not get DSDT, %s\n",
330 AcpiFormatException (Status));
334 AcpiOsPrintf ("\nDisassembly of DSDT\n");
335 Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
339 * Output: ASL code. Redirect to a file if requested
343 /* Create/Open a disassembly output file */
345 DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
348 fprintf (stderr, "Could not generate output filename\n");
353 File = fopen (DisasmFilename, "w+");
356 fprintf (stderr, "Could not open output file %s\n", DisasmFilename);
361 AcpiOsRedirectOutput (File);
364 *OutFilename = DisasmFilename;
366 /* ForceAmlDisassembly means to assume the table contains valid AML */
368 if (!AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table))
370 AdDisassemblerHeader (Filename, ACPI_IS_DATA_TABLE);
371 AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
373 AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength] "
374 "FieldName : FieldValue\n */\n\n");
376 AcpiDmDumpDataTable (Table);
377 fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n",
382 fprintf (stderr, "Formatted output: %s - %u bytes\n",
383 DisasmFilename, CmGetFileSize (File));
388 /* Always parse the tables, only option is what to display */
390 Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
391 if (ACPI_FAILURE (Status))
393 AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
394 AcpiFormatException (Status));
398 if (AslCompilerdebug)
400 AcpiOsPrintf ("/**** Before second load\n");
404 NsSetupNamespaceListing (File);
405 NsDisplayNamespace ();
407 AcpiOsPrintf ("*****/\n");
410 /* Load namespace from names created within control methods */
412 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
413 AcpiGbl_RootNode, OwnerId);
416 * Cross reference the namespace here, in order to
417 * generate External() statements
419 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
420 AcpiGbl_RootNode, OwnerId);
422 if (AslCompilerdebug)
424 AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
427 /* Find possible calls to external control methods */
429 AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
432 * If we found any external control methods, we must reparse
433 * the entire tree with the new information (namely, the
434 * number of arguments per method)
436 if (AcpiDmGetExternalMethodCount ())
439 "\nFound %u external control methods, "
440 "reparsing with new information\n",
441 AcpiDmGetExternalMethodCount ());
443 /* Reparse, rebuild namespace */
445 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
446 AcpiGbl_ParseOpRoot = NULL;
447 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
449 AcpiGbl_RootNode = NULL;
450 AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
451 AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
452 AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE;
453 AcpiGbl_RootNodeStruct.Parent = NULL;
454 AcpiGbl_RootNodeStruct.Child = NULL;
455 AcpiGbl_RootNodeStruct.Peer = NULL;
456 AcpiGbl_RootNodeStruct.Object = NULL;
457 AcpiGbl_RootNodeStruct.Flags = 0;
459 Status = AcpiNsRootInitialize ();
461 /* New namespace, add the external definitions first */
463 AcpiDmAddExternalsToNamespace ();
465 /* Parse the table again. No need to reload it, however */
467 Status = AdParseTable (Table, NULL, FALSE, FALSE);
468 if (ACPI_FAILURE (Status))
470 AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
471 AcpiFormatException (Status));
475 /* Cross reference the namespace again */
477 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
478 AcpiGbl_RootNode, OwnerId);
480 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
481 AcpiGbl_RootNode, OwnerId);
483 if (AslCompilerdebug)
485 AcpiOsPrintf ("/**** After second load and resource conversion\n");
488 NsSetupNamespaceListing (File);
489 NsDisplayNamespace ();
491 AcpiOsPrintf ("*****/\n");
493 AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
498 * Now that the namespace is finalized, we can perform namespace
501 * 1) Convert fixed-offset references to resource descriptors
502 * to symbolic references (Note: modifies namespace)
504 AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
506 /* Optional displays */
508 if (AcpiGbl_DbOpt_Disasm)
510 /* This is the real disassembly */
512 AdDisplayTables (Filename, Table);
514 /* Dump hex table if requested (-vt) */
516 AcpiDmDumpDataTable (Table);
518 fprintf (stderr, "Disassembly completed\n");
521 fprintf (stderr, "ASL Output: %s - %u bytes\n",
522 DisasmFilename, CmGetFileSize (File));
527 fprintf (stderr, "%14s %s - %u bytes\n",
528 Gbl_Files[ASL_FILE_MAP_OUTPUT].ShortDescription,
529 Gbl_Files[ASL_FILE_MAP_OUTPUT].Filename,
530 FlGetFileSize (ASL_FILE_MAP_OUTPUT));
537 if (Table && !AcpiGbl_ForceAmlDisassembly &&!AcpiUtIsAmlTable (Table))
544 if (AslCompilerdebug) /* Display final namespace, with transforms */
546 NsSetupNamespaceListing (File);
547 NsDisplayNamespace ();
551 AcpiOsRedirectOutput (stdout);
554 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
555 AcpiGbl_ParseOpRoot = NULL;
560 /******************************************************************************
562 * FUNCTION: AdDisassemblerHeader
564 * PARAMETERS: Filename - Input file for the table
565 * TableType - Either AML or DataTable
569 * DESCRIPTION: Create the disassembler header, including ACPICA signon with
570 * current time and date.
572 *****************************************************************************/
575 AdDisassemblerHeader (
584 /* Header and input table info */
586 AcpiOsPrintf ("/*\n");
587 AcpiOsPrintf (ACPI_COMMON_HEADER (AML_DISASSEMBLER_NAME, " * "));
589 if (TableType == ACPI_IS_AML_TABLE)
591 if (AcpiGbl_CstyleDisassembly)
594 " * Disassembling to symbolic ASL+ operators\n"
600 " * Disassembling to non-symbolic legacy ASL operators\n"
605 AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer));
606 AcpiOsPrintf (" *\n");
610 /******************************************************************************
612 * FUNCTION: AdCreateTableHeader
614 * PARAMETERS: Filename - Input file for the table
615 * Table - Pointer to the raw table
619 * DESCRIPTION: Create the ASL table header, including ACPICA signon with
620 * current time and date.
622 *****************************************************************************/
625 AdCreateTableHeader (
627 ACPI_TABLE_HEADER *Table)
634 * Print file header and dump original table header
636 AdDisassemblerHeader (Filename, ACPI_IS_AML_TABLE);
638 AcpiOsPrintf (" * Original Table Header:\n");
639 AcpiOsPrintf (" * Signature \"%4.4s\"\n", Table->Signature);
640 AcpiOsPrintf (" * Length 0x%8.8X (%u)\n", Table->Length, Table->Length);
642 /* Print and validate the revision */
644 AcpiOsPrintf (" * Revision 0x%2.2X", Table->Revision);
646 switch (Table->Revision)
650 AcpiOsPrintf (" **** Invalid Revision");
655 /* Revision of DSDT controls the ACPI integer width */
657 if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT))
659 AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support");
669 /* Print and validate the table checksum */
671 AcpiOsPrintf (" * Checksum 0x%2.2X", Table->Checksum);
673 Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length);
676 AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X",
677 (UINT8) (Table->Checksum - Checksum));
681 AcpiOsPrintf (" * OEM ID \"%.6s\"\n", Table->OemId);
682 AcpiOsPrintf (" * OEM Table ID \"%.8s\"\n", Table->OemTableId);
683 AcpiOsPrintf (" * OEM Revision 0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision);
684 AcpiOsPrintf (" * Compiler ID \"%.4s\"\n", Table->AslCompilerId);
685 AcpiOsPrintf (" * Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision);
686 AcpiOsPrintf (" */\n");
688 /* Create AML output filename based on input filename */
692 NewFilename = FlGenerateFilename (Filename, "aml");
696 NewFilename = UtStringCacheCalloc (9);
699 strncat (NewFilename, Table->Signature, 4);
700 strcat (NewFilename, ".aml");
706 AcpiOsPrintf (" **** Could not generate AML output filename\n");
710 /* Open the ASL definition block */
713 "DefinitionBlock (\"%s\", \"%4.4s\", %hu, \"%.6s\", \"%.8s\", 0x%8.8X)\n",
714 NewFilename, Table->Signature, Table->Revision,
715 Table->OemId, Table->OemTableId, Table->OemRevision);
719 /******************************************************************************
721 * FUNCTION: AdDisplayTables
723 * PARAMETERS: Filename - Input file for the table
724 * Table - Pointer to the raw table
728 * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
730 *****************************************************************************/
735 ACPI_TABLE_HEADER *Table)
739 if (!AcpiGbl_ParseOpRoot)
741 return (AE_NOT_EXIST);
744 if (!AcpiGbl_DbOpt_Verbose)
746 AdCreateTableHeader (Filename, Table);
749 AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX);
750 MpEmitMappingInfo ();
752 if (AcpiGbl_DbOpt_Verbose)
754 AcpiOsPrintf ("\n\nTable Header:\n");
755 AcpiUtDebugDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
756 DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
758 AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
759 AcpiUtDebugDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)),
760 Table->Length, DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
767 /*******************************************************************************
769 * FUNCTION: AdStoreTable
771 * PARAMETERS: Table - Table header
772 * TableIndex - Where the table index is returned
774 * RETURN: Status and table index.
776 * DESCRIPTION: Add an ACPI table to the global table list
778 ******************************************************************************/
782 ACPI_TABLE_HEADER *Table,
786 ACPI_TABLE_DESC *TableDesc;
789 Status = AcpiTbGetNextTableDescriptor (TableIndex, &TableDesc);
790 if (ACPI_FAILURE (Status))
795 /* Initialize added table */
797 AcpiTbInitTableDescriptor (TableDesc, ACPI_PTR_TO_PHYSADDR (Table),
798 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, Table);
799 AcpiTbValidateTable (TableDesc);
804 /******************************************************************************
806 * FUNCTION: AdGetLocalTables
812 * DESCRIPTION: Get the ACPI tables from either memory or a file
814 *****************************************************************************/
821 ACPI_TABLE_HEADER TableHeader;
822 ACPI_TABLE_HEADER *NewTable;
826 /* Get the DSDT via table override */
828 ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT);
829 AcpiOsTableOverride (&TableHeader, &NewTable);
832 fprintf (stderr, "Could not obtain DSDT\n");
833 return (AE_NO_ACPI_TABLES);
836 AdWriteTable (NewTable, NewTable->Length,
837 ACPI_SIG_DSDT, NewTable->OemTableId);
839 /* Store DSDT in the Table Manager */
841 Status = AdStoreTable (NewTable, &TableIndex);
842 if (ACPI_FAILURE (Status))
844 fprintf (stderr, "Could not store DSDT\n");
845 return (AE_NO_ACPI_TABLES);
852 /******************************************************************************
854 * FUNCTION: AdParseTable
856 * PARAMETERS: Table - Pointer to the raw table
857 * OwnerId - Returned OwnerId of the table
858 * LoadTable - If add table to the global table list
859 * External - If this is an external table
863 * DESCRIPTION: Parse the DSDT.
865 *****************************************************************************/
869 ACPI_TABLE_HEADER *Table,
870 ACPI_OWNER_ID *OwnerId,
874 ACPI_STATUS Status = AE_OK;
875 ACPI_WALK_STATE *WalkState;
883 return (AE_NOT_EXIST);
886 /* Pass 1: Parse everything except control method bodies */
888 fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
890 AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
891 AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
893 /* Create the root object */
895 AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp ();
896 if (!AcpiGbl_ParseOpRoot)
898 return (AE_NO_MEMORY);
901 /* Create and initialize a new walk state */
903 WalkState = AcpiDsCreateWalkState (0,
904 AcpiGbl_ParseOpRoot, NULL, NULL);
907 return (AE_NO_MEMORY);
910 Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot,
911 NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
912 if (ACPI_FAILURE (Status))
917 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
918 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
920 Status = AcpiPsParseAml (WalkState);
921 if (ACPI_FAILURE (Status))
926 /* If LoadTable is FALSE, we are parsing the last loaded table */
928 TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1;
934 Status = AdStoreTable (Table, &TableIndex);
935 if (ACPI_FAILURE (Status))
939 Status = AcpiTbAllocateOwnerId (TableIndex);
940 if (ACPI_FAILURE (Status))
946 Status = AcpiTbGetOwnerId (TableIndex, OwnerId);
947 if (ACPI_FAILURE (Status))
954 fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
956 Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL);
957 if (ACPI_FAILURE (Status))
962 /* No need to parse control methods of external table */
970 * Pass 3: Parse control methods and link their parse trees
971 * into the main parse tree
974 "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
975 Status = AcpiDmParseDeferredOps (AcpiGbl_ParseOpRoot);
976 fprintf (stderr, "\n");
978 /* Process Resource Templates */
980 AcpiDmFindResources (AcpiGbl_ParseOpRoot);
982 fprintf (stderr, "Parsing completed\n");