1 /******************************************************************************
2  *
3  * Module Name: dmtables - disassembler ACPI table support
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 "aslcompiler.h"
45 #include "acdispat.h"
46 #include "acnamesp.h"
47 #include "actables.h"
48 #include "acparser.h"
49 #include "acapps.h"
50 
51 
52 #define _COMPONENT          ACPI_TOOLS
53         ACPI_MODULE_NAME    ("dmtables")
54 
55 
56 /* Local prototypes */
57 
58 static void
59 AdCreateTableHeader (
60     char                    *Filename,
61     ACPI_TABLE_HEADER       *Table);
62 
63 static ACPI_STATUS
64 AdStoreTable (
65     ACPI_TABLE_HEADER       *Table,
66     UINT32                  *TableIndex);
67 
68 
69 extern ACPI_TABLE_DESC      LocalTables[1];
70 extern ACPI_PARSE_OBJECT    *AcpiGbl_ParseOpRoot;
71 
72 
73 /******************************************************************************
74  *
75  * FUNCTION:    AdDisassemblerHeader
76  *
77  * PARAMETERS:  Filename            - Input file for the table
78  *              TableType           - Either AML or DataTable
79  *
80  * RETURN:      None
81  *
82  * DESCRIPTION: Create the disassembler header, including ACPICA signon with
83  *              current time and date.
84  *
85  *****************************************************************************/
86 
87 void
88 AdDisassemblerHeader (
89     char                    *Filename,
90     UINT8                   TableType)
91 {
92     time_t                  Timer;
93 
94 
95     time (&Timer);
96 
97     /* Header and input table info */
98 
99     AcpiOsPrintf ("/*\n");
100     AcpiOsPrintf (ACPI_COMMON_HEADER (AML_DISASSEMBLER_NAME, " * "));
101 
102     if (TableType == ACPI_IS_AML_TABLE)
103     {
104         if (AcpiGbl_CstyleDisassembly)
105         {
106             AcpiOsPrintf (
107                 " * Disassembling to symbolic ASL+ operators\n"
108                 " *\n");
109         }
110         else
111         {
112             AcpiOsPrintf (
113                 " * Disassembling to non-symbolic legacy ASL operators\n"
114                 " *\n");
115         }
116     }
117 
118     AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer));
119     AcpiOsPrintf (" *\n");
120 }
121 
122 
123 /******************************************************************************
124  *
125  * FUNCTION:    AdCreateTableHeader
126  *
127  * PARAMETERS:  Filename            - Input file for the table
128  *              Table               - Pointer to the raw table
129  *
130  * RETURN:      None
131  *
132  * DESCRIPTION: Create the ASL table header, including ACPICA signon with
133  *              current time and date.
134  *
135  *****************************************************************************/
136 
137 static void
138 AdCreateTableHeader (
139     char                    *Filename,
140     ACPI_TABLE_HEADER       *Table)
141 {
142     UINT8                   Checksum;
143 
144 
145     /* Reset globals for External statements */
146 
147     AcpiGbl_NumExternalMethods = 0;
148     AcpiGbl_ResolvedExternalMethods = 0;
149 
150     /*
151      * Print file header and dump original table header
152      */
153     AdDisassemblerHeader (Filename, ACPI_IS_AML_TABLE);
154 
155     AcpiOsPrintf (" * Original Table Header:\n");
156     AcpiOsPrintf (" *     Signature        \"%4.4s\"\n",    Table->Signature);
157     AcpiOsPrintf (" *     Length           0x%8.8X (%u)\n", Table->Length, Table->Length);
158 
159     /* Print and validate the revision */
160 
161     AcpiOsPrintf (" *     Revision         0x%2.2X",      Table->Revision);
162 
163     switch (Table->Revision)
164     {
165     case 0:
166 
167         AcpiOsPrintf (" **** Invalid Revision");
168         break;
169 
170     case 1:
171 
172         /* Revision of DSDT controls the ACPI integer width */
173 
174         if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT))
175         {
176             AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support");
177         }
178         break;
179 
180     default:
181 
182         break;
183     }
184 
185     /* Print and validate the table checksum */
186 
187     AcpiOsPrintf ("\n *     Checksum         0x%2.2X",        Table->Checksum);
188 
189     Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length);
190     if (Checksum)
191     {
192         AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X",
193             (UINT8) (Table->Checksum - Checksum));
194     }
195 
196     AcpiOsPrintf ("\n");
197     AcpiOsPrintf (" *     OEM ID           \"%.6s\"\n",     Table->OemId);
198     AcpiOsPrintf (" *     OEM Table ID     \"%.8s\"\n",     Table->OemTableId);
199     AcpiOsPrintf (" *     OEM Revision     0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision);
200     AcpiOsPrintf (" *     Compiler ID      \"%.4s\"\n",     Table->AslCompilerId);
201     AcpiOsPrintf (" *     Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision);
202     AcpiOsPrintf (" */\n");
203 
204     /*
205      * Open the ASL definition block.
206      *
207      * Note: the AMLFilename string is left zero-length in order to just let
208      * the compiler create it when the disassembled file is compiled. This
209      * makes it easier to rename the disassembled ASL file if needed.
210      */
211     AcpiOsPrintf (
212         "DefinitionBlock (\"\", \"%4.4s\", %hu, \"%.6s\", \"%.8s\", 0x%8.8X)\n",
213         Table->Signature, Table->Revision,
214         Table->OemId, Table->OemTableId, Table->OemRevision);
215 }
216 
217 
218 /******************************************************************************
219  *
220  * FUNCTION:    AdDisplayTables
221  *
222  * PARAMETERS:  Filename            - Input file for the table
223  *              Table               - Pointer to the raw table
224  *
225  * RETURN:      Status
226  *
227  * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
228  *
229  *****************************************************************************/
230 
231 ACPI_STATUS
232 AdDisplayTables (
233     char                    *Filename,
234     ACPI_TABLE_HEADER       *Table)
235 {
236 
237 
238     if (!AcpiGbl_ParseOpRoot)
239     {
240         return (AE_NOT_EXIST);
241     }
242 
243     if (!AcpiGbl_DmOpt_Listing)
244     {
245         AdCreateTableHeader (Filename, Table);
246     }
247 
248     AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX);
249     MpEmitMappingInfo ();
250 
251     if (AcpiGbl_DmOpt_Listing)
252     {
253         AcpiOsPrintf ("\n\nTable Header:\n");
254         AcpiUtDebugDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
255             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
256 
257         AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
258         AcpiUtDebugDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)),
259             Table->Length, DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
260     }
261 
262     return (AE_OK);
263 }
264 
265 
266 /*******************************************************************************
267  *
268  * FUNCTION:    AdStoreTable
269  *
270  * PARAMETERS:  Table               - Table header
271  *              TableIndex          - Where the table index is returned
272  *
273  * RETURN:      Status and table index.
274  *
275  * DESCRIPTION: Add an ACPI table to the global table list
276  *
277  ******************************************************************************/
278 
279 static ACPI_STATUS
280 AdStoreTable (
281     ACPI_TABLE_HEADER       *Table,
282     UINT32                  *TableIndex)
283 {
284     ACPI_STATUS             Status;
285     ACPI_TABLE_DESC         *TableDesc;
286 
287 
288     Status = AcpiTbGetNextTableDescriptor (TableIndex, &TableDesc);
289     if (ACPI_FAILURE (Status))
290     {
291         return (Status);
292     }
293 
294     /* Initialize added table */
295 
296     AcpiTbInitTableDescriptor (TableDesc, ACPI_PTR_TO_PHYSADDR (Table),
297         ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, Table);
298     Status = AcpiTbValidateTable (TableDesc);
299     return (Status);
300 }
301 
302 
303 /******************************************************************************
304  *
305  * FUNCTION:    AdGetLocalTables
306  *
307  * PARAMETERS:  None
308  *
309  * RETURN:      Status
310  *
311  * DESCRIPTION: Get the ACPI tables from either memory or a file
312  *
313  *****************************************************************************/
314 
315 ACPI_STATUS
316 AdGetLocalTables (
317     void)
318 {
319     ACPI_STATUS             Status;
320     ACPI_TABLE_HEADER       TableHeader;
321     ACPI_TABLE_HEADER       *NewTable;
322     UINT32                  TableIndex;
323 
324 
325     /* Get the DSDT via table override */
326 
327     ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT);
328     AcpiOsTableOverride (&TableHeader, &NewTable);
329     if (!NewTable)
330     {
331         fprintf (stderr, "Could not obtain DSDT\n");
332         return (AE_NO_ACPI_TABLES);
333     }
334 
335     AdWriteTable (NewTable, NewTable->Length,
336         ACPI_SIG_DSDT, NewTable->OemTableId);
337 
338     /* Store DSDT in the Table Manager */
339 
340     Status = AdStoreTable (NewTable, &TableIndex);
341     if (ACPI_FAILURE (Status))
342     {
343         fprintf (stderr, "Could not store DSDT\n");
344         return (AE_NO_ACPI_TABLES);
345     }
346 
347     return (AE_OK);
348 }
349 
350 
351 /******************************************************************************
352  *
353  * FUNCTION:    AdParseTable
354  *
355  * PARAMETERS:  Table               - Pointer to the raw table
356  *              OwnerId             - Returned OwnerId of the table
357  *              LoadTable           - If add table to the global table list
358  *              External            - If this is an external table
359  *
360  * RETURN:      Status
361  *
362  * DESCRIPTION: Parse an ACPI AML table
363  *
364  *****************************************************************************/
365 
366 ACPI_STATUS
367 AdParseTable (
368     ACPI_TABLE_HEADER       *Table,
369     ACPI_OWNER_ID           *OwnerId,
370     BOOLEAN                 LoadTable,
371     BOOLEAN                 External)
372 {
373     ACPI_STATUS             Status = AE_OK;
374     ACPI_WALK_STATE         *WalkState;
375     UINT8                   *AmlStart;
376     UINT32                  AmlLength;
377     UINT32                  TableIndex;
378 
379 
380     if (!Table)
381     {
382         return (AE_NOT_EXIST);
383     }
384 
385     /* Pass 1:  Parse everything except control method bodies */
386 
387     fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
388 
389     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
390     AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
391 
392     /* Create the root object */
393 
394     AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp (AmlStart);
395     if (!AcpiGbl_ParseOpRoot)
396     {
397         return (AE_NO_MEMORY);
398     }
399 
400     /* Create and initialize a new walk state */
401 
402     WalkState = AcpiDsCreateWalkState (0, AcpiGbl_ParseOpRoot, NULL, NULL);
403     if (!WalkState)
404     {
405         return (AE_NO_MEMORY);
406     }
407 
408     Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot,
409         NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
410     if (ACPI_FAILURE (Status))
411     {
412         return (Status);
413     }
414 
415     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
416     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
417 
418     Status = AcpiPsParseAml (WalkState);
419     if (ACPI_FAILURE (Status))
420     {
421         return (Status);
422     }
423 
424     /* If LoadTable is FALSE, we are parsing the last loaded table */
425 
426     TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1;
427 
428     /* Pass 2 */
429 
430     if (LoadTable)
431     {
432         Status = AdStoreTable (Table, &TableIndex);
433         if (ACPI_FAILURE (Status))
434         {
435             return (Status);
436         }
437         Status = AcpiTbAllocateOwnerId (TableIndex);
438         if (ACPI_FAILURE (Status))
439         {
440             return (Status);
441         }
442         if (OwnerId)
443         {
444             Status = AcpiTbGetOwnerId (TableIndex, OwnerId);
445             if (ACPI_FAILURE (Status))
446             {
447                 return (Status);
448             }
449         }
450     }
451 
452     fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
453 
454     Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL);
455     if (ACPI_FAILURE (Status))
456     {
457         return (Status);
458     }
459 
460     /* No need to parse control methods of external table */
461 
462     if (External)
463     {
464         return (AE_OK);
465     }
466 
467     /*
468      * Pass 3: Parse control methods and link their parse trees
469      * into the main parse tree
470      */
471     fprintf (stderr,
472         "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
473 
474     Status = AcpiDmParseDeferredOps (AcpiGbl_ParseOpRoot);
475     fprintf (stderr, "\n");
476 
477     /* Process Resource Templates */
478 
479     AcpiDmFindResources (AcpiGbl_ParseOpRoot);
480 
481     fprintf (stderr, "Parsing completed\n");
482     return (AE_OK);
483 }
484