1291333Sjkim/******************************************************************************
2291333Sjkim *
3291333Sjkim * Module Name: dmtables - disassembler ACPI table support
4291333Sjkim *
5291333Sjkim *****************************************************************************/
6291333Sjkim
7291333Sjkim/*
8298714Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9291333Sjkim * All rights reserved.
10291333Sjkim *
11291333Sjkim * Redistribution and use in source and binary forms, with or without
12291333Sjkim * modification, are permitted provided that the following conditions
13291333Sjkim * are met:
14291333Sjkim * 1. Redistributions of source code must retain the above copyright
15291333Sjkim *    notice, this list of conditions, and the following disclaimer,
16291333Sjkim *    without modification.
17291333Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18291333Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19291333Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20291333Sjkim *    including a substantially similar Disclaimer requirement for further
21291333Sjkim *    binary redistribution.
22291333Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23291333Sjkim *    of any contributors may be used to endorse or promote products derived
24291333Sjkim *    from this software without specific prior written permission.
25291333Sjkim *
26291333Sjkim * Alternatively, this software may be distributed under the terms of the
27291333Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28291333Sjkim * Software Foundation.
29291333Sjkim *
30291333Sjkim * NO WARRANTY
31291333Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32291333Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33291333Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34291333Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35291333Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36291333Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37291333Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38291333Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39291333Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40291333Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41291333Sjkim * POSSIBILITY OF SUCH DAMAGES.
42291333Sjkim */
43291333Sjkim
44298714Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45298714Sjkim#include <contrib/dev/acpica/include/acapps.h>
46298714Sjkim#include <contrib/dev/acpica/include/acdispat.h>
47298714Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48298714Sjkim#include <contrib/dev/acpica/include/actables.h>
49298714Sjkim#include <contrib/dev/acpica/include/acparser.h>
50291333Sjkim
51291333Sjkim#include <stdio.h>
52291333Sjkim#include <time.h>
53291333Sjkim
54291333Sjkim#define _COMPONENT          ACPI_TOOLS
55291333Sjkim        ACPI_MODULE_NAME    ("dmtables")
56291333Sjkim
57291333Sjkim
58291333Sjkim/* Local prototypes */
59291333Sjkim
60291333Sjkimstatic void
61291333SjkimAdCreateTableHeader (
62291333Sjkim    char                    *Filename,
63291333Sjkim    ACPI_TABLE_HEADER       *Table);
64291333Sjkim
65291333Sjkimstatic ACPI_STATUS
66291333SjkimAdStoreTable (
67291333Sjkim    ACPI_TABLE_HEADER       *Table,
68291333Sjkim    UINT32                  *TableIndex);
69291333Sjkim
70291333Sjkim
71291333Sjkimextern ACPI_TABLE_DESC      LocalTables[1];
72291333Sjkimextern ACPI_PARSE_OBJECT    *AcpiGbl_ParseOpRoot;
73291333Sjkim
74291333Sjkim
75291333Sjkim/******************************************************************************
76291333Sjkim *
77291333Sjkim * FUNCTION:    AdDisassemblerHeader
78291333Sjkim *
79291333Sjkim * PARAMETERS:  Filename            - Input file for the table
80291333Sjkim *              TableType           - Either AML or DataTable
81291333Sjkim *
82291333Sjkim * RETURN:      None
83291333Sjkim *
84291333Sjkim * DESCRIPTION: Create the disassembler header, including ACPICA signon with
85291333Sjkim *              current time and date.
86291333Sjkim *
87291333Sjkim *****************************************************************************/
88291333Sjkim
89291333Sjkimvoid
90291333SjkimAdDisassemblerHeader (
91291333Sjkim    char                    *Filename,
92291333Sjkim    UINT8                   TableType)
93291333Sjkim{
94291333Sjkim    time_t                  Timer;
95291333Sjkim
96291333Sjkim
97291333Sjkim    time (&Timer);
98291333Sjkim
99291333Sjkim    /* Header and input table info */
100291333Sjkim
101291333Sjkim    AcpiOsPrintf ("/*\n");
102291333Sjkim    AcpiOsPrintf (ACPI_COMMON_HEADER (AML_DISASSEMBLER_NAME, " * "));
103291333Sjkim
104291333Sjkim    if (TableType == ACPI_IS_AML_TABLE)
105291333Sjkim    {
106291333Sjkim        if (AcpiGbl_CstyleDisassembly)
107291333Sjkim        {
108291333Sjkim            AcpiOsPrintf (
109291333Sjkim                " * Disassembling to symbolic ASL+ operators\n"
110291333Sjkim                " *\n");
111291333Sjkim        }
112291333Sjkim        else
113291333Sjkim        {
114291333Sjkim            AcpiOsPrintf (
115291333Sjkim                " * Disassembling to non-symbolic legacy ASL operators\n"
116291333Sjkim                " *\n");
117291333Sjkim        }
118291333Sjkim    }
119291333Sjkim
120291333Sjkim    AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer));
121291333Sjkim    AcpiOsPrintf (" *\n");
122291333Sjkim}
123291333Sjkim
124291333Sjkim
125291333Sjkim/******************************************************************************
126291333Sjkim *
127291333Sjkim * FUNCTION:    AdCreateTableHeader
128291333Sjkim *
129291333Sjkim * PARAMETERS:  Filename            - Input file for the table
130291333Sjkim *              Table               - Pointer to the raw table
131291333Sjkim *
132291333Sjkim * RETURN:      None
133291333Sjkim *
134291333Sjkim * DESCRIPTION: Create the ASL table header, including ACPICA signon with
135291333Sjkim *              current time and date.
136291333Sjkim *
137291333Sjkim *****************************************************************************/
138291333Sjkim
139291333Sjkimstatic void
140291333SjkimAdCreateTableHeader (
141291333Sjkim    char                    *Filename,
142291333Sjkim    ACPI_TABLE_HEADER       *Table)
143291333Sjkim{
144291333Sjkim    UINT8                   Checksum;
145291333Sjkim
146291333Sjkim
147298714Sjkim    /* Reset globals for External statements */
148298714Sjkim
149298714Sjkim    AcpiGbl_NumExternalMethods = 0;
150298714Sjkim    AcpiGbl_ResolvedExternalMethods = 0;
151298714Sjkim
152291333Sjkim    /*
153291333Sjkim     * Print file header and dump original table header
154291333Sjkim     */
155291333Sjkim    AdDisassemblerHeader (Filename, ACPI_IS_AML_TABLE);
156291333Sjkim
157291333Sjkim    AcpiOsPrintf (" * Original Table Header:\n");
158291333Sjkim    AcpiOsPrintf (" *     Signature        \"%4.4s\"\n",    Table->Signature);
159291333Sjkim    AcpiOsPrintf (" *     Length           0x%8.8X (%u)\n", Table->Length, Table->Length);
160291333Sjkim
161291333Sjkim    /* Print and validate the revision */
162291333Sjkim
163291333Sjkim    AcpiOsPrintf (" *     Revision         0x%2.2X",      Table->Revision);
164291333Sjkim
165291333Sjkim    switch (Table->Revision)
166291333Sjkim    {
167291333Sjkim    case 0:
168291333Sjkim
169291333Sjkim        AcpiOsPrintf (" **** Invalid Revision");
170291333Sjkim        break;
171291333Sjkim
172291333Sjkim    case 1:
173291333Sjkim
174291333Sjkim        /* Revision of DSDT controls the ACPI integer width */
175291333Sjkim
176291333Sjkim        if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT))
177291333Sjkim        {
178291333Sjkim            AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support");
179291333Sjkim        }
180291333Sjkim        break;
181291333Sjkim
182291333Sjkim    default:
183291333Sjkim
184291333Sjkim        break;
185291333Sjkim    }
186291333Sjkim
187291333Sjkim    /* Print and validate the table checksum */
188291333Sjkim
189298714Sjkim    AcpiOsPrintf ("\n *     Checksum         0x%2.2X",        Table->Checksum);
190291333Sjkim
191291333Sjkim    Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length);
192291333Sjkim    if (Checksum)
193291333Sjkim    {
194291333Sjkim        AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X",
195291333Sjkim            (UINT8) (Table->Checksum - Checksum));
196291333Sjkim    }
197291333Sjkim
198291333Sjkim    AcpiOsPrintf ("\n");
199291333Sjkim    AcpiOsPrintf (" *     OEM ID           \"%.6s\"\n",     Table->OemId);
200291333Sjkim    AcpiOsPrintf (" *     OEM Table ID     \"%.8s\"\n",     Table->OemTableId);
201291333Sjkim    AcpiOsPrintf (" *     OEM Revision     0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision);
202291333Sjkim    AcpiOsPrintf (" *     Compiler ID      \"%.4s\"\n",     Table->AslCompilerId);
203291333Sjkim    AcpiOsPrintf (" *     Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision);
204291333Sjkim    AcpiOsPrintf (" */\n");
205291333Sjkim
206298714Sjkim    /*
207298714Sjkim     * Open the ASL definition block.
208298714Sjkim     *
209298714Sjkim     * Note: the AMLFilename string is left zero-length in order to just let
210298714Sjkim     * the compiler create it when the disassembled file is compiled. This
211298714Sjkim     * makes it easier to rename the disassembled ASL file if needed.
212298714Sjkim     */
213291333Sjkim    AcpiOsPrintf (
214298714Sjkim        "DefinitionBlock (\"\", \"%4.4s\", %hu, \"%.6s\", \"%.8s\", 0x%8.8X)\n",
215298714Sjkim        Table->Signature, Table->Revision,
216291333Sjkim        Table->OemId, Table->OemTableId, Table->OemRevision);
217291333Sjkim}
218291333Sjkim
219291333Sjkim
220291333Sjkim/******************************************************************************
221291333Sjkim *
222291333Sjkim * FUNCTION:    AdDisplayTables
223291333Sjkim *
224291333Sjkim * PARAMETERS:  Filename            - Input file for the table
225291333Sjkim *              Table               - Pointer to the raw table
226291333Sjkim *
227291333Sjkim * RETURN:      Status
228291333Sjkim *
229291333Sjkim * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
230291333Sjkim *
231291333Sjkim *****************************************************************************/
232291333Sjkim
233291333SjkimACPI_STATUS
234291333SjkimAdDisplayTables (
235291333Sjkim    char                    *Filename,
236291333Sjkim    ACPI_TABLE_HEADER       *Table)
237291333Sjkim{
238291333Sjkim
239291333Sjkim
240291333Sjkim    if (!AcpiGbl_ParseOpRoot)
241291333Sjkim    {
242291333Sjkim        return (AE_NOT_EXIST);
243291333Sjkim    }
244291333Sjkim
245291333Sjkim    if (!AcpiGbl_DmOpt_Listing)
246291333Sjkim    {
247291333Sjkim        AdCreateTableHeader (Filename, Table);
248291333Sjkim    }
249291333Sjkim
250291333Sjkim    AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX);
251291333Sjkim    MpEmitMappingInfo ();
252291333Sjkim
253291333Sjkim    if (AcpiGbl_DmOpt_Listing)
254291333Sjkim    {
255291333Sjkim        AcpiOsPrintf ("\n\nTable Header:\n");
256291333Sjkim        AcpiUtDebugDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
257291333Sjkim            DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
258291333Sjkim
259291333Sjkim        AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
260291333Sjkim        AcpiUtDebugDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)),
261291333Sjkim            Table->Length, DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
262291333Sjkim    }
263291333Sjkim
264291333Sjkim    return (AE_OK);
265291333Sjkim}
266291333Sjkim
267291333Sjkim
268291333Sjkim/*******************************************************************************
269291333Sjkim *
270291333Sjkim * FUNCTION:    AdStoreTable
271291333Sjkim *
272291333Sjkim * PARAMETERS:  Table               - Table header
273291333Sjkim *              TableIndex          - Where the table index is returned
274291333Sjkim *
275291333Sjkim * RETURN:      Status and table index.
276291333Sjkim *
277291333Sjkim * DESCRIPTION: Add an ACPI table to the global table list
278291333Sjkim *
279291333Sjkim ******************************************************************************/
280291333Sjkim
281291333Sjkimstatic ACPI_STATUS
282291333SjkimAdStoreTable (
283291333Sjkim    ACPI_TABLE_HEADER       *Table,
284291333Sjkim    UINT32                  *TableIndex)
285291333Sjkim{
286291333Sjkim    ACPI_STATUS             Status;
287291333Sjkim    ACPI_TABLE_DESC         *TableDesc;
288291333Sjkim
289291333Sjkim
290291333Sjkim    Status = AcpiTbGetNextTableDescriptor (TableIndex, &TableDesc);
291291333Sjkim    if (ACPI_FAILURE (Status))
292291333Sjkim    {
293291333Sjkim        return (Status);
294291333Sjkim    }
295291333Sjkim
296291333Sjkim    /* Initialize added table */
297291333Sjkim
298291333Sjkim    AcpiTbInitTableDescriptor (TableDesc, ACPI_PTR_TO_PHYSADDR (Table),
299291333Sjkim        ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, Table);
300291333Sjkim    Status = AcpiTbValidateTable (TableDesc);
301291333Sjkim    return (Status);
302291333Sjkim}
303291333Sjkim
304291333Sjkim
305291333Sjkim/******************************************************************************
306291333Sjkim *
307291333Sjkim * FUNCTION:    AdGetLocalTables
308291333Sjkim *
309291333Sjkim * PARAMETERS:  None
310291333Sjkim *
311291333Sjkim * RETURN:      Status
312291333Sjkim *
313291333Sjkim * DESCRIPTION: Get the ACPI tables from either memory or a file
314291333Sjkim *
315291333Sjkim *****************************************************************************/
316291333Sjkim
317291333SjkimACPI_STATUS
318291333SjkimAdGetLocalTables (
319291333Sjkim    void)
320291333Sjkim{
321291333Sjkim    ACPI_STATUS             Status;
322291333Sjkim    ACPI_TABLE_HEADER       TableHeader;
323291333Sjkim    ACPI_TABLE_HEADER       *NewTable;
324291333Sjkim    UINT32                  TableIndex;
325291333Sjkim
326291333Sjkim
327291333Sjkim    /* Get the DSDT via table override */
328291333Sjkim
329291333Sjkim    ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT);
330291333Sjkim    AcpiOsTableOverride (&TableHeader, &NewTable);
331291333Sjkim    if (!NewTable)
332291333Sjkim    {
333291333Sjkim        fprintf (stderr, "Could not obtain DSDT\n");
334291333Sjkim        return (AE_NO_ACPI_TABLES);
335291333Sjkim    }
336291333Sjkim
337291333Sjkim    AdWriteTable (NewTable, NewTable->Length,
338291333Sjkim        ACPI_SIG_DSDT, NewTable->OemTableId);
339291333Sjkim
340291333Sjkim    /* Store DSDT in the Table Manager */
341291333Sjkim
342291333Sjkim    Status = AdStoreTable (NewTable, &TableIndex);
343291333Sjkim    if (ACPI_FAILURE (Status))
344291333Sjkim    {
345291333Sjkim        fprintf (stderr, "Could not store DSDT\n");
346291333Sjkim        return (AE_NO_ACPI_TABLES);
347291333Sjkim    }
348291333Sjkim
349291333Sjkim    return (AE_OK);
350291333Sjkim}
351291333Sjkim
352291333Sjkim
353291333Sjkim/******************************************************************************
354291333Sjkim *
355291333Sjkim * FUNCTION:    AdParseTable
356291333Sjkim *
357291333Sjkim * PARAMETERS:  Table               - Pointer to the raw table
358291333Sjkim *              OwnerId             - Returned OwnerId of the table
359291333Sjkim *              LoadTable           - If add table to the global table list
360291333Sjkim *              External            - If this is an external table
361291333Sjkim *
362291333Sjkim * RETURN:      Status
363291333Sjkim *
364291333Sjkim * DESCRIPTION: Parse an ACPI AML table
365291333Sjkim *
366291333Sjkim *****************************************************************************/
367291333Sjkim
368291333SjkimACPI_STATUS
369291333SjkimAdParseTable (
370291333Sjkim    ACPI_TABLE_HEADER       *Table,
371291333Sjkim    ACPI_OWNER_ID           *OwnerId,
372291333Sjkim    BOOLEAN                 LoadTable,
373291333Sjkim    BOOLEAN                 External)
374291333Sjkim{
375291333Sjkim    ACPI_STATUS             Status = AE_OK;
376291333Sjkim    ACPI_WALK_STATE         *WalkState;
377291333Sjkim    UINT8                   *AmlStart;
378291333Sjkim    UINT32                  AmlLength;
379291333Sjkim    UINT32                  TableIndex;
380291333Sjkim
381291333Sjkim
382291333Sjkim    if (!Table)
383291333Sjkim    {
384291333Sjkim        return (AE_NOT_EXIST);
385291333Sjkim    }
386291333Sjkim
387291333Sjkim    /* Pass 1:  Parse everything except control method bodies */
388291333Sjkim
389291333Sjkim    fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
390291333Sjkim
391291333Sjkim    AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
392291333Sjkim    AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
393291333Sjkim
394291333Sjkim    /* Create the root object */
395291333Sjkim
396291333Sjkim    AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp (AmlStart);
397291333Sjkim    if (!AcpiGbl_ParseOpRoot)
398291333Sjkim    {
399291333Sjkim        return (AE_NO_MEMORY);
400291333Sjkim    }
401291333Sjkim
402291333Sjkim    /* Create and initialize a new walk state */
403291333Sjkim
404291333Sjkim    WalkState = AcpiDsCreateWalkState (0, AcpiGbl_ParseOpRoot, NULL, NULL);
405291333Sjkim    if (!WalkState)
406291333Sjkim    {
407291333Sjkim        return (AE_NO_MEMORY);
408291333Sjkim    }
409291333Sjkim
410291333Sjkim    Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot,
411291333Sjkim        NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
412291333Sjkim    if (ACPI_FAILURE (Status))
413291333Sjkim    {
414291333Sjkim        return (Status);
415291333Sjkim    }
416291333Sjkim
417291333Sjkim    WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
418291333Sjkim    WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
419291333Sjkim
420291333Sjkim    Status = AcpiPsParseAml (WalkState);
421291333Sjkim    if (ACPI_FAILURE (Status))
422291333Sjkim    {
423291333Sjkim        return (Status);
424291333Sjkim    }
425291333Sjkim
426291333Sjkim    /* If LoadTable is FALSE, we are parsing the last loaded table */
427291333Sjkim
428291333Sjkim    TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1;
429291333Sjkim
430291333Sjkim    /* Pass 2 */
431291333Sjkim
432291333Sjkim    if (LoadTable)
433291333Sjkim    {
434291333Sjkim        Status = AdStoreTable (Table, &TableIndex);
435291333Sjkim        if (ACPI_FAILURE (Status))
436291333Sjkim        {
437291333Sjkim            return (Status);
438291333Sjkim        }
439291333Sjkim        Status = AcpiTbAllocateOwnerId (TableIndex);
440291333Sjkim        if (ACPI_FAILURE (Status))
441291333Sjkim        {
442291333Sjkim            return (Status);
443291333Sjkim        }
444291333Sjkim        if (OwnerId)
445291333Sjkim        {
446291333Sjkim            Status = AcpiTbGetOwnerId (TableIndex, OwnerId);
447291333Sjkim            if (ACPI_FAILURE (Status))
448291333Sjkim            {
449291333Sjkim                return (Status);
450291333Sjkim            }
451291333Sjkim        }
452291333Sjkim    }
453291333Sjkim
454291333Sjkim    fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
455291333Sjkim
456291333Sjkim    Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL);
457291333Sjkim    if (ACPI_FAILURE (Status))
458291333Sjkim    {
459291333Sjkim        return (Status);
460291333Sjkim    }
461291333Sjkim
462291333Sjkim    /* No need to parse control methods of external table */
463291333Sjkim
464291333Sjkim    if (External)
465291333Sjkim    {
466291333Sjkim        return (AE_OK);
467291333Sjkim    }
468291333Sjkim
469291333Sjkim    /*
470291333Sjkim     * Pass 3: Parse control methods and link their parse trees
471291333Sjkim     * into the main parse tree
472291333Sjkim     */
473291333Sjkim    fprintf (stderr,
474291333Sjkim        "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
475291333Sjkim
476291333Sjkim    Status = AcpiDmParseDeferredOps (AcpiGbl_ParseOpRoot);
477291333Sjkim    fprintf (stderr, "\n");
478291333Sjkim
479291333Sjkim    /* Process Resource Templates */
480291333Sjkim
481291333Sjkim    AcpiDmFindResources (AcpiGbl_ParseOpRoot);
482291333Sjkim
483291333Sjkim    fprintf (stderr, "Parsing completed\n");
484291333Sjkim    return (AE_OK);
485291333Sjkim}
486