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