1 /******************************************************************************
2  *
3  * Module Name: adisasm - Application-level disassembler routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "amlcode.h"
46 #include "acdisasm.h"
47 #include "acdispat.h"
48 #include "acnamesp.h"
49 #include "acparser.h"
50 #include "acapps.h"
51 #include "acconvert.h"
52 
53 
54 #define _COMPONENT          ACPI_TOOLS
55         ACPI_MODULE_NAME    ("adisasm")
56 
57 /* Local prototypes */
58 
59 static ACPI_STATUS
60 AdDoExternalFileList (
61     char                    *Filename);
62 
63 static ACPI_STATUS
64 AdDisassembleOneTable (
65     ACPI_TABLE_HEADER       *Table,
66     FILE                    *File,
67     char                    *Filename,
68     char                    *DisasmFilename);
69 
70 static ACPI_STATUS
71 AdReparseOneTable (
72     ACPI_TABLE_HEADER       *Table,
73     FILE                    *File,
74     ACPI_OWNER_ID           OwnerId);
75 
76 
77 ACPI_TABLE_DESC             LocalTables[1];
78 ACPI_PARSE_OBJECT           *AcpiGbl_ParseOpRoot;
79 
80 
81 /* Stubs for everything except ASL compiler */
82 
83 #ifndef ACPI_ASL_COMPILER
84 BOOLEAN
AcpiDsIsResultUsed(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)85 AcpiDsIsResultUsed (
86     ACPI_PARSE_OBJECT       *Op,
87     ACPI_WALK_STATE         *WalkState)
88 {
89     return (TRUE);
90 }
91 
92 ACPI_STATUS
AcpiDsMethodError(ACPI_STATUS Status,ACPI_WALK_STATE * WalkState)93 AcpiDsMethodError (
94     ACPI_STATUS             Status,
95     ACPI_WALK_STATE         *WalkState)
96 {
97     return (Status);
98 }
99 #endif
100 
101 
102 /*******************************************************************************
103  *
104  * FUNCTION:    AdInitialize
105  *
106  * PARAMETERS:  None
107  *
108  * RETURN:      Status
109  *
110  * DESCRIPTION: ACPICA and local initialization
111  *
112  ******************************************************************************/
113 
114 ACPI_STATUS
AdInitialize(void)115 AdInitialize (
116     void)
117 {
118     ACPI_STATUS             Status;
119 
120 
121     /* ACPICA subsystem initialization */
122 
123     Status = AcpiOsInitialize ();
124     if (ACPI_FAILURE (Status))
125     {
126         fprintf (stderr, "Could not initialize ACPICA subsystem: %s\n",
127             AcpiFormatException (Status));
128 
129         return (Status);
130     }
131 
132     Status = AcpiUtInitGlobals ();
133     if (ACPI_FAILURE (Status))
134     {
135         fprintf (stderr, "Could not initialize ACPICA globals: %s\n",
136             AcpiFormatException (Status));
137 
138         return (Status);
139     }
140 
141     Status = AcpiUtMutexInitialize ();
142     if (ACPI_FAILURE (Status))
143     {
144         fprintf (stderr, "Could not initialize ACPICA mutex objects: %s\n",
145             AcpiFormatException (Status));
146 
147         return (Status);
148     }
149 
150     Status = AcpiNsRootInitialize ();
151     if (ACPI_FAILURE (Status))
152     {
153         fprintf (stderr, "Could not initialize ACPICA namespace: %s\n",
154             AcpiFormatException (Status));
155 
156         return (Status);
157     }
158 
159     /* Setup the Table Manager (cheat - there is no RSDT) */
160 
161     AcpiGbl_RootTableList.MaxTableCount = 1;
162     AcpiGbl_RootTableList.CurrentTableCount = 0;
163     AcpiGbl_RootTableList.Tables = LocalTables;
164 
165     return (AE_OK);
166 }
167 
168 
169 /******************************************************************************
170  *
171  * FUNCTION:    AdAmlDisassemble
172  *
173  * PARAMETERS:  Filename            - AML input filename
174  *              OutToFile           - TRUE if output should go to a file
175  *              Prefix              - Path prefix for output
176  *              OutFilename         - where the filename is returned
177  *
178  * RETURN:      Status
179  *
180  * DESCRIPTION: Disassembler entry point. Disassemble an entire ACPI table.
181  *
182  *****************************************************************************/
183 
184 ACPI_STATUS
AdAmlDisassemble(BOOLEAN OutToFile,char * Filename,char * Prefix,char ** OutFilename)185 AdAmlDisassemble (
186     BOOLEAN                 OutToFile,
187     char                    *Filename,
188     char                    *Prefix,
189     char                    **OutFilename)
190 {
191     ACPI_STATUS             Status;
192     char                    *DisasmFilename = NULL;
193     FILE                    *File = NULL;
194     ACPI_TABLE_HEADER       *Table = NULL;
195     ACPI_NEW_TABLE_DESC     *ListHead = NULL;
196 
197 
198     /*
199      * Input: AML code from either a file or via GetTables (memory or
200      * registry)
201      */
202     if (Filename)
203     {
204         /* Get the list of all AML tables in the file */
205 
206         Status = AcGetAllTablesFromFile (Filename,
207             ACPI_GET_ALL_TABLES, &ListHead);
208         if (ACPI_FAILURE (Status))
209         {
210             AcpiOsPrintf ("Could not get ACPI tables from %s, %s\n",
211                 Filename, AcpiFormatException (Status));
212             return (Status);
213         }
214 
215         /* Process any user-specified files for external objects */
216 
217         Status = AdDoExternalFileList (Filename);
218         if (ACPI_FAILURE (Status))
219         {
220             return (Status);
221         }
222     }
223     else
224     {
225         Status = AdGetLocalTables ();
226         if (ACPI_FAILURE (Status))
227         {
228             AcpiOsPrintf ("Could not get ACPI tables, %s\n",
229                 AcpiFormatException (Status));
230             return (Status);
231         }
232 
233         if (!AcpiGbl_DmOpt_Disasm)
234         {
235             return (AE_OK);
236         }
237 
238         /* Obtained the local tables, just disassemble the DSDT */
239 
240         Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
241         if (ACPI_FAILURE (Status))
242         {
243             AcpiOsPrintf ("Could not get DSDT, %s\n",
244                 AcpiFormatException (Status));
245             return (Status);
246         }
247 
248         AcpiOsPrintf ("\nDisassembly of DSDT\n");
249         Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
250     }
251 
252     /*
253      * Output: ASL code. Redirect to a file if requested
254      */
255     if (OutToFile)
256     {
257         /* Create/Open a disassembly output file */
258 
259         DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
260         if (!DisasmFilename)
261         {
262             fprintf (stderr, "Could not generate output filename\n");
263             Status = AE_ERROR;
264             goto Cleanup;
265         }
266 
267         File = fopen (DisasmFilename, "w+");
268         if (!File)
269         {
270             fprintf (stderr, "Could not open output file %s\n",
271                 DisasmFilename);
272             Status = AE_ERROR;
273             goto Cleanup;
274         }
275     }
276 
277     *OutFilename = DisasmFilename;
278 
279     /* Disassemble all AML tables within the file */
280 
281     while (ListHead)
282     {
283         Status = AdDisassembleOneTable (ListHead->Table,
284             File, Filename, DisasmFilename);
285         if (ACPI_FAILURE (Status))
286         {
287             break;
288         }
289 
290         ListHead = ListHead->Next;
291     }
292 
293 Cleanup:
294 
295     if (Table &&
296         !AcpiGbl_ForceAmlDisassembly &&
297         !AcpiUtIsAmlTable (Table))
298     {
299         ACPI_FREE (Table);
300     }
301 
302     AcDeleteTableList (ListHead);
303 
304     if (File)
305     {
306         fclose (File);
307         AcpiOsRedirectOutput (stdout);
308     }
309 
310     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
311     AcpiGbl_ParseOpRoot = NULL;
312     return (Status);
313 }
314 
315 
316 /******************************************************************************
317  *
318  * FUNCTION:    AdDisassembleOneTable
319  *
320  * PARAMETERS:  Table               - Raw AML table
321  *              File                - Pointer for the input file
322  *              Filename            - AML input filename
323  *              DisasmFilename      - Output filename
324  *
325  * RETURN:      Status
326  *
327  * DESCRIPTION: Disassemble a single ACPI table. AML or data table.
328  *
329  *****************************************************************************/
330 
331 static ACPI_STATUS
AdDisassembleOneTable(ACPI_TABLE_HEADER * Table,FILE * File,char * Filename,char * DisasmFilename)332 AdDisassembleOneTable (
333     ACPI_TABLE_HEADER       *Table,
334     FILE                    *File,
335     char                    *Filename,
336     char                    *DisasmFilename)
337 {
338     ACPI_STATUS             Status;
339     ACPI_OWNER_ID           OwnerId;
340 
341 
342 #ifdef ACPI_ASL_COMPILER
343 
344     /*
345      * For ASL-/ASL+ converter: replace the temporary "XXXX"
346      * table signature with the original. This "XXXX" makes
347      * it harder for the AML interpreter to run the badaml
348      * (.xxx) file produced from the converter in case if
349      * it fails to get deleted.
350      */
351     if (AcpiGbl_CaptureComments)
352     {
353         strncpy (Table->Signature, AcpiGbl_TableSig, ACPI_NAMESEG_SIZE);
354     }
355 #endif
356 
357     /* ForceAmlDisassembly means to assume the table contains valid AML */
358 
359     if (!AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table))
360     {
361         if (File)
362         {
363             AcpiOsRedirectOutput (File);
364         }
365 
366         AdDisassemblerHeader (Filename, ACPI_IS_DATA_TABLE);
367 
368         /* This is a "Data Table" (non-AML table) */
369 
370         AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
371             AcpiGbl_CDAT ? (char *) AcpiGbl_CDAT : Table->Signature);
372         AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]  "
373             "FieldName : FieldValue (in hex)\n */\n\n");
374 
375         AcpiDmDumpDataTable (Table);
376         fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n",
377             AcpiGbl_CDAT ? (char *) AcpiGbl_CDAT : Table->Signature);
378 
379         if (File)
380         {
381             fprintf (stderr, "Formatted output:  %s - %u bytes\n",
382                 DisasmFilename, CmGetFileSize (File));
383         }
384 
385         return (AE_OK);
386     }
387 
388     /* Initialize the converter output file */
389 
390     ASL_CV_INIT_FILETREE(Table, File);
391 
392     /*
393      * This is an AML table (DSDT or SSDT).
394      * Always parse the tables, only option is what to display
395      */
396     Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
397     if (ACPI_FAILURE (Status))
398     {
399         AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
400             AcpiFormatException (Status));
401         return (Status);
402     }
403 
404     /* Redirect output for code generation and debugging output */
405 
406     if (File)
407     {
408         AcpiOsRedirectOutput (File);
409     }
410 
411     /* Debug output, namespace and parse tree */
412 
413     if (AslCompilerdebug && File)
414     {
415         AcpiOsPrintf ("/**** Before second load\n");
416 
417         NsSetupNamespaceListing (File);
418         NsDisplayNamespace ();
419 
420         AcpiOsPrintf ("*****/\n");
421     }
422 
423     /* Load namespace from names created within control methods */
424 
425     AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
426         AcpiGbl_RootNode, OwnerId);
427 
428     /*
429      * Cross reference the namespace here, in order to
430      * generate External() statements
431      */
432     AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
433         AcpiGbl_RootNode, OwnerId);
434 
435     if (AslCompilerdebug)
436     {
437         AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
438     }
439 
440     /* Find possible calls to external control methods */
441 
442     AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
443 
444     /*
445      * If we found any external control methods, we must reparse
446      * the entire tree with the new information (namely, the
447      * number of arguments per method)
448      */
449     if (AcpiDmGetUnresolvedExternalMethodCount ())
450     {
451         Status = AdReparseOneTable (Table, File, OwnerId);
452         if (ACPI_FAILURE (Status))
453         {
454             return (Status);
455         }
456     }
457 
458     /*
459      * Now that the namespace is finalized, we can perform namespace
460      * transforms.
461      *
462      * 1) Convert fixed-offset references to resource descriptors
463      *    to symbolic references (Note: modifies namespace)
464      */
465     AcpiDmConvertParseObjects (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
466 
467     /* Optional displays */
468 
469     if (AcpiGbl_DmOpt_Disasm)
470     {
471         /* This is the real disassembly */
472 
473         AdDisplayTables (Filename, Table);
474 
475         /* Dump hex table if requested (-vt) */
476 
477         AcpiDmDumpDataTable (Table);
478 
479         fprintf (stderr, "Disassembly completed\n");
480         if (File)
481         {
482             fprintf (stderr, "ASL Output:    %s - %u bytes\n",
483                 DisasmFilename, CmGetFileSize (File));
484         }
485 
486         if (AslGbl_MapfileFlag)
487         {
488             fprintf (stderr, "%14s %s - %u bytes\n",
489                 AslGbl_FileDescs[ASL_FILE_MAP_OUTPUT].ShortDescription,
490                 AslGbl_Files[ASL_FILE_MAP_OUTPUT].Filename,
491                 FlGetFileSize (ASL_FILE_MAP_OUTPUT));
492         }
493     }
494 
495     return (AE_OK);
496 }
497 
498 
499 /******************************************************************************
500  *
501  * FUNCTION:    AdReparseOneTable
502  *
503  * PARAMETERS:  Table               - Raw AML table
504  *              File                - Pointer for the input file
505  *              OwnerId             - ID for this table
506  *
507  * RETURN:      Status
508  *
509  * DESCRIPTION: Reparse a table that has already been loaded. Used to
510  *              integrate information about external control methods.
511  *              These methods may have been previously parsed incorrectly.
512  *
513  *****************************************************************************/
514 
515 static ACPI_STATUS
AdReparseOneTable(ACPI_TABLE_HEADER * Table,FILE * File,ACPI_OWNER_ID OwnerId)516 AdReparseOneTable (
517     ACPI_TABLE_HEADER       *Table,
518     FILE                    *File,
519     ACPI_OWNER_ID           OwnerId)
520 {
521     ACPI_STATUS             Status;
522     ACPI_COMMENT_ADDR_NODE  *AddrListHead;
523 
524 
525     fprintf (stderr,
526         "\nFound %u external control methods, "
527         "reparsing with new information\n",
528         AcpiDmGetUnresolvedExternalMethodCount ());
529 
530     /* Reparse, rebuild namespace */
531 
532     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
533     AcpiGbl_ParseOpRoot = NULL;
534     AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
535 
536     AcpiGbl_RootNode                    = NULL;
537     AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
538     AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
539     AcpiGbl_RootNodeStruct.Type         = ACPI_TYPE_DEVICE;
540     AcpiGbl_RootNodeStruct.Parent       = NULL;
541     AcpiGbl_RootNodeStruct.Child        = NULL;
542     AcpiGbl_RootNodeStruct.Peer         = NULL;
543     AcpiGbl_RootNodeStruct.Object       = NULL;
544     AcpiGbl_RootNodeStruct.Flags        = 0;
545 
546     Status = AcpiNsRootInitialize ();
547     if (ACPI_FAILURE (Status))
548     {
549         return (Status);
550     }
551 
552     /* New namespace, add the external definitions first */
553 
554     AcpiDmAddExternalListToNamespace ();
555 
556     /* For -ca option: clear the list of comment addresses. */
557 
558     while (AcpiGbl_CommentAddrListHead)
559     {
560         AddrListHead= AcpiGbl_CommentAddrListHead;
561         AcpiGbl_CommentAddrListHead = AcpiGbl_CommentAddrListHead->Next;
562         AcpiOsFree(AddrListHead);
563     }
564 
565     /* Parse the table again. No need to reload it, however */
566 
567     Status = AdParseTable (Table, NULL, FALSE, FALSE);
568     if (ACPI_FAILURE (Status))
569     {
570         AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
571             AcpiFormatException (Status));
572         return (Status);
573     }
574 
575     /* Cross reference the namespace again */
576 
577     AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
578         AcpiGbl_RootNode, OwnerId);
579 
580     AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
581         AcpiGbl_RootNode, OwnerId);
582 
583     /* Debug output - namespace and parse tree */
584 
585     if (AslCompilerdebug)
586     {
587         AcpiOsPrintf ("/**** After second load and resource conversion\n");
588         if (File)
589         {
590             NsSetupNamespaceListing (File);
591             NsDisplayNamespace ();
592         }
593 
594         AcpiOsPrintf ("*****/\n");
595         AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
596     }
597 
598     return (AE_OK);
599 }
600 
601 
602 /******************************************************************************
603  *
604  * FUNCTION:    AdDoExternalFileList
605  *
606  * PARAMETERS:  Filename            - Input file for the table
607  *
608  * RETURN:      Status
609  *
610  * DESCRIPTION: Process all tables found in the -e external files list
611  *
612  *****************************************************************************/
613 
614 static ACPI_STATUS
AdDoExternalFileList(char * Filename)615 AdDoExternalFileList (
616     char                    *Filename)
617 {
618     ACPI_EXTERNAL_FILE      *ExternalFileList;
619     char                    *ExternalFilename;
620     ACPI_NEW_TABLE_DESC     *ExternalListHead = NULL;
621     ACPI_STATUS             Status;
622     ACPI_STATUS             GlobalStatus = AE_OK;
623     ACPI_OWNER_ID           OwnerId;
624 
625 
626     /*
627      * External filenames are specified on the command line like this:
628      * Example: iasl -e file1,file2,file3 -d xxx.aml
629      */
630     ExternalFileList = AcpiGbl_ExternalFileList;
631 
632     /* Process each external file */
633 
634     while (ExternalFileList)
635     {
636         ExternalFilename = ExternalFileList->Path;
637         if (!strcmp (ExternalFilename, Filename))
638         {
639             /* Next external file */
640 
641             ExternalFileList = ExternalFileList->Next;
642             continue;
643         }
644 
645         AcpiOsPrintf ("External object resolution file %16s\n",
646             ExternalFilename);
647 
648         Status = AcGetAllTablesFromFile (
649             ExternalFilename, ACPI_GET_ONLY_AML_TABLES, &ExternalListHead);
650         if (ACPI_FAILURE (Status))
651         {
652             if (Status == AE_TYPE)
653             {
654                 ExternalFileList = ExternalFileList->Next;
655                 GlobalStatus = AE_TYPE;
656                 continue;
657             }
658 
659             AcDeleteTableList (ExternalListHead);
660             return (Status);
661         }
662 
663         /* Load external tables for symbol resolution */
664 
665         while (ExternalListHead)
666         {
667             Status = AdParseTable (
668                 ExternalListHead->Table, &OwnerId, TRUE, TRUE);
669             if (ACPI_FAILURE (Status))
670             {
671                 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
672                     AcpiFormatException (Status));
673                 AcDeleteTableList (ExternalListHead);
674                 return (Status);
675             }
676 
677             /*
678              * Load namespace from names created within control methods
679              * Set owner id of nodes in external table
680              */
681             AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
682                 AcpiGbl_RootNode, OwnerId);
683             AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
684 
685             ExternalListHead = ExternalListHead->Next;
686         }
687 
688         /* Next external file */
689 
690         ExternalFileList = ExternalFileList->Next;
691     }
692 
693     AcDeleteTableList (ExternalListHead);
694 
695     if (ACPI_FAILURE (GlobalStatus))
696     {
697         return (GlobalStatus);
698     }
699 
700     /* Clear external list generated by Scope in external tables */
701 
702     if (AcpiGbl_ExternalFileList)
703     {
704         AcpiDmClearExternalList ();
705     }
706 
707     /* Load any externals defined in the optional external ref file */
708 
709     AcpiDmGetExternalsFromFile ();
710     return (AE_OK);
711 }
712