adisasm.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: adisasm - Application-level disassembler routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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/acparser.h>
46#include <contrib/dev/acpica/include/amlcode.h>
47#include <contrib/dev/acpica/include/acdisasm.h>
48#include <contrib/dev/acpica/include/acdispat.h>
49#include <contrib/dev/acpica/include/acnamesp.h>
50#include <contrib/dev/acpica/include/actables.h>
51#include <contrib/dev/acpica/include/acapps.h>
52
53#include <stdio.h>
54#include <time.h>
55
56
57#define _COMPONENT          ACPI_TOOLS
58        ACPI_MODULE_NAME    ("adisasm")
59
60/* Local prototypes */
61
62static void
63AdCreateTableHeader (
64    char                    *Filename,
65    ACPI_TABLE_HEADER       *Table);
66
67/* Stubs for ASL compiler */
68
69#ifndef ACPI_ASL_COMPILER
70BOOLEAN
71AcpiDsIsResultUsed (
72    ACPI_PARSE_OBJECT       *Op,
73    ACPI_WALK_STATE         *WalkState)
74{
75    return TRUE;
76}
77
78ACPI_STATUS
79AcpiDsMethodError (
80    ACPI_STATUS             Status,
81    ACPI_WALK_STATE         *WalkState)
82{
83    return (Status);
84}
85#endif
86
87ACPI_STATUS
88AcpiNsLoadTable (
89    UINT32                  TableIndex,
90    ACPI_NAMESPACE_NODE     *Node)
91{
92    return (AE_NOT_IMPLEMENTED);
93}
94
95ACPI_STATUS
96AcpiDsRestartControlMethod (
97    ACPI_WALK_STATE         *WalkState,
98    ACPI_OPERAND_OBJECT     *ReturnDesc)
99{
100    return (AE_OK);
101}
102
103void
104AcpiDsTerminateControlMethod (
105    ACPI_OPERAND_OBJECT     *MethodDesc,
106    ACPI_WALK_STATE         *WalkState)
107{
108    return;
109}
110
111ACPI_STATUS
112AcpiDsCallControlMethod (
113    ACPI_THREAD_STATE       *Thread,
114    ACPI_WALK_STATE         *WalkState,
115    ACPI_PARSE_OBJECT       *Op)
116{
117    return (AE_OK);
118}
119
120ACPI_STATUS
121AcpiDsMethodDataInitArgs (
122    ACPI_OPERAND_OBJECT     **Params,
123    UINT32                  MaxParamCount,
124    ACPI_WALK_STATE         *WalkState)
125{
126    return (AE_OK);
127}
128
129
130static ACPI_TABLE_DESC      LocalTables[1];
131ACPI_PARSE_OBJECT    *AcpiGbl_ParseOpRoot;
132
133
134/*******************************************************************************
135 *
136 * FUNCTION:    AdInitialize
137 *
138 * PARAMETERS:  None
139 *
140 * RETURN:      Status
141 *
142 * DESCRIPTION: ACPICA and local initialization
143 *
144 ******************************************************************************/
145
146ACPI_STATUS
147AdInitialize (
148    void)
149{
150    ACPI_STATUS             Status;
151
152
153    /* ACPICA subsystem initialization */
154
155    Status = AcpiOsInitialize ();
156    if (ACPI_FAILURE (Status))
157    {
158        return (Status);
159    }
160
161    Status = AcpiUtInitGlobals ();
162    if (ACPI_FAILURE (Status))
163    {
164        return (Status);
165    }
166
167    Status = AcpiUtMutexInitialize ();
168    if (ACPI_FAILURE (Status))
169    {
170        return (Status);
171    }
172
173    Status = AcpiNsRootInitialize ();
174    if (ACPI_FAILURE (Status))
175    {
176        return (Status);
177    }
178
179    /* Setup the Table Manager (cheat - there is no RSDT) */
180
181    AcpiGbl_RootTableList.MaxTableCount = 1;
182    AcpiGbl_RootTableList.CurrentTableCount = 0;
183    AcpiGbl_RootTableList.Tables = LocalTables;
184
185    return (Status);
186}
187
188
189/******************************************************************************
190 *
191 * FUNCTION:    AdAmlDisassemble
192 *
193 * PARAMETERS:  Filename            - AML input filename
194 *              OutToFile           - TRUE if output should go to a file
195 *              Prefix              - Path prefix for output
196 *              OutFilename         - where the filename is returned
197 *
198 * RETURN:      Status
199 *
200 * DESCRIPTION: Disassemble an entire ACPI table
201 *
202 *****************************************************************************/
203
204ACPI_STATUS
205AdAmlDisassemble (
206    BOOLEAN                 OutToFile,
207    char                    *Filename,
208    char                    *Prefix,
209    char                    **OutFilename)
210{
211    ACPI_STATUS             Status;
212    char                    *DisasmFilename = NULL;
213    char                    *ExternalFilename;
214    ACPI_EXTERNAL_FILE      *ExternalFileList = AcpiGbl_ExternalFileList;
215    FILE                    *File = NULL;
216    ACPI_TABLE_HEADER       *Table = NULL;
217    ACPI_TABLE_HEADER       *ExternalTable;
218    ACPI_OWNER_ID           OwnerId;
219
220
221    /*
222     * Input: AML code from either a file or via GetTables (memory or
223     * registry)
224     */
225    if (Filename)
226    {
227        Status = AcpiDbGetTableFromFile (Filename, &Table);
228        if (ACPI_FAILURE (Status))
229        {
230            return (Status);
231        }
232
233        /*
234         * External filenames separated by commas
235         * Example: iasl -e file1,file2,file3 -d xxx.aml
236         */
237        while (ExternalFileList)
238        {
239            ExternalFilename = ExternalFileList->Path;
240            if (!ACPI_STRCMP (ExternalFilename, Filename))
241            {
242                /* Next external file */
243
244                ExternalFileList = ExternalFileList->Next;
245                continue;
246            }
247
248            Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable);
249            if (ACPI_FAILURE (Status))
250            {
251                return (Status);
252            }
253
254            /* Load external table for symbol resolution */
255
256            if (ExternalTable)
257            {
258                Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE);
259                if (ACPI_FAILURE (Status))
260                {
261                    AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
262                        AcpiFormatException (Status));
263                    return (Status);
264                }
265
266                /*
267                 * Load namespace from names created within control methods
268                 * Set owner id of nodes in external table
269                 */
270                AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
271                    AcpiGbl_RootNode, OwnerId);
272                AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
273            }
274
275            /* Next external file */
276
277            ExternalFileList = ExternalFileList->Next;
278        }
279
280        /* Clear external list generated by Scope in external tables */
281
282        if (AcpiGbl_ExternalFileList)
283        {
284            AcpiDmClearExternalList ();
285        }
286
287        /* Load any externals defined in the optional external ref file */
288
289        AcpiDmGetExternalsFromFile ();
290    }
291    else
292    {
293        Status = AdGetLocalTables ();
294        if (ACPI_FAILURE (Status))
295        {
296            AcpiOsPrintf ("Could not get ACPI tables, %s\n",
297                AcpiFormatException (Status));
298            return (Status);
299        }
300
301        if (!AcpiGbl_DbOpt_disasm)
302        {
303            return (AE_OK);
304        }
305
306        /* Obtained the local tables, just disassemble the DSDT */
307
308        Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
309        if (ACPI_FAILURE (Status))
310        {
311            AcpiOsPrintf ("Could not get DSDT, %s\n",
312                AcpiFormatException (Status));
313            return (Status);
314        }
315
316        AcpiOsPrintf ("\nDisassembly of DSDT\n");
317        Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
318    }
319
320    /*
321     * Output: ASL code. Redirect to a file if requested
322     */
323    if (OutToFile)
324    {
325        /* Create/Open a disassembly output file */
326
327        DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
328        if (!DisasmFilename)
329        {
330            fprintf (stderr, "Could not generate output filename\n");
331            Status = AE_ERROR;
332            goto Cleanup;
333        }
334
335        File = fopen (DisasmFilename, "w+");
336        if (!File)
337        {
338            fprintf (stderr, "Could not open output file %s\n", DisasmFilename);
339            Status = AE_ERROR;
340            ACPI_FREE (DisasmFilename);
341            goto Cleanup;
342        }
343
344        AcpiOsRedirectOutput (File);
345    }
346
347    *OutFilename = DisasmFilename;
348
349    if (!AcpiUtIsAmlTable (Table))
350    {
351        AdDisassemblerHeader (Filename);
352        AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
353            Table->Signature);
354        AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]  "
355            "FieldName : FieldValue\n */\n\n");
356
357        AcpiDmDumpDataTable (Table);
358        fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n",
359            Table->Signature);
360
361        if (File)
362        {
363            fprintf (stderr, "Formatted output:  %s - %u bytes\n",
364                DisasmFilename, CmGetFileSize (File));
365        }
366    }
367    else
368    {
369        /* Always parse the tables, only option is what to display */
370
371        Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
372        if (ACPI_FAILURE (Status))
373        {
374            AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
375                AcpiFormatException (Status));
376            goto Cleanup;
377        }
378
379        if (AslCompilerdebug)
380        {
381            AcpiOsPrintf ("/**** Before second load\n");
382
383            if (File)
384            {
385                NsSetupNamespaceListing (File);
386                NsDisplayNamespace ();
387            }
388            AcpiOsPrintf ("*****/\n");
389        }
390
391        /* Load namespace from names created within control methods */
392
393        AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
394            AcpiGbl_RootNode, OwnerId);
395
396        /*
397         * Cross reference the namespace here, in order to
398         * generate External() statements
399         */
400        AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
401            AcpiGbl_RootNode, OwnerId);
402
403        if (AslCompilerdebug)
404        {
405            AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
406        }
407
408        /* Find possible calls to external control methods */
409
410        AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
411
412        /*
413         * If we found any external control methods, we must reparse
414         * the entire tree with the new information (namely, the
415         * number of arguments per method)
416         */
417        if (AcpiDmGetExternalMethodCount ())
418        {
419            fprintf (stderr,
420                "\nFound %u external control methods, "
421                "reparsing with new information\n",
422                AcpiDmGetExternalMethodCount ());
423
424            /* Reparse, rebuild namespace */
425
426            AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
427            AcpiGbl_ParseOpRoot = NULL;
428            AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
429
430            AcpiGbl_RootNode                    = NULL;
431            AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
432            AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
433            AcpiGbl_RootNodeStruct.Type         = ACPI_TYPE_DEVICE;
434            AcpiGbl_RootNodeStruct.Parent       = NULL;
435            AcpiGbl_RootNodeStruct.Child        = NULL;
436            AcpiGbl_RootNodeStruct.Peer         = NULL;
437            AcpiGbl_RootNodeStruct.Object       = NULL;
438            AcpiGbl_RootNodeStruct.Flags        = 0;
439
440            Status = AcpiNsRootInitialize ();
441
442            /* New namespace, add the external definitions first */
443
444            AcpiDmAddExternalsToNamespace ();
445
446            /* Parse the table again. No need to reload it, however */
447
448            Status = AdParseTable (Table, NULL, FALSE, FALSE);
449            if (ACPI_FAILURE (Status))
450            {
451                AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
452                    AcpiFormatException (Status));
453                goto Cleanup;
454            }
455
456            /* Cross reference the namespace again */
457
458            AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
459                AcpiGbl_RootNode, OwnerId);
460
461            AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
462                AcpiGbl_RootNode, OwnerId);
463
464            if (AslCompilerdebug)
465            {
466                AcpiOsPrintf ("/**** After second load and resource conversion\n");
467                if (File)
468                {
469                    NsSetupNamespaceListing (File);
470                    NsDisplayNamespace ();
471                }
472                AcpiOsPrintf ("*****/\n");
473
474                AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
475            }
476        }
477
478        /*
479         * Now that the namespace is finalized, we can perform namespace
480         * transforms.
481         *
482         * 1) Convert fixed-offset references to resource descriptors
483         *    to symbolic references (Note: modifies namespace)
484         */
485        AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
486
487        /* Optional displays */
488
489        if (AcpiGbl_DbOpt_disasm)
490        {
491            /* This is the real disassembly */
492
493            AdDisplayTables (Filename, Table);
494
495            /* Dump hex table if requested (-vt) */
496
497            AcpiDmDumpDataTable (Table);
498
499            fprintf (stderr, "Disassembly completed\n");
500            if (File)
501            {
502                fprintf (stderr, "ASL Output:    %s - %u bytes\n",
503                    DisasmFilename, CmGetFileSize (File));
504            }
505
506            if (Gbl_MapfileFlag)
507            {
508                fprintf (stderr, "%14s %s - %u bytes\n",
509                    Gbl_Files[ASL_FILE_MAP_OUTPUT].ShortDescription,
510                    Gbl_Files[ASL_FILE_MAP_OUTPUT].Filename,
511                    FlGetFileSize (ASL_FILE_MAP_OUTPUT));
512            }
513        }
514    }
515
516Cleanup:
517
518    if (Table && !AcpiUtIsAmlTable (Table))
519    {
520        ACPI_FREE (Table);
521    }
522
523    if (File)
524    {
525        if (AslCompilerdebug) /* Display final namespace, with transforms */
526        {
527            NsSetupNamespaceListing (File);
528            NsDisplayNamespace ();
529        }
530
531        fclose (File);
532        AcpiOsRedirectOutput (stdout);
533    }
534
535    AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
536    AcpiGbl_ParseOpRoot = NULL;
537    return (Status);
538}
539
540
541/******************************************************************************
542 *
543 * FUNCTION:    AdDisassemblerHeader
544 *
545 * PARAMETERS:  Filename            - Input file for the table
546 *
547 * RETURN:      None
548 *
549 * DESCRIPTION: Create the disassembler header, including ACPICA signon with
550 *              current time and date.
551 *
552 *****************************************************************************/
553
554void
555AdDisassemblerHeader (
556    char                    *Filename)
557{
558    time_t                  Timer;
559
560
561    time (&Timer);
562
563    /* Header and input table info */
564
565    AcpiOsPrintf ("/*\n");
566    AcpiOsPrintf (ACPI_COMMON_HEADER (AML_DISASSEMBLER_NAME, " * "));
567
568    if (AcpiGbl_CstyleDisassembly)
569    {
570        AcpiOsPrintf (
571            " * Disassembling to symbolic ASL+ operators\n"
572            " *\n");
573    }
574    else
575    {
576        AcpiOsPrintf (
577            " * Disassembling to non-symbolic legacy ASL operators\n"
578            " *\n");
579    }
580
581    AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer));
582    AcpiOsPrintf (" *\n");
583}
584
585
586/******************************************************************************
587 *
588 * FUNCTION:    AdCreateTableHeader
589 *
590 * PARAMETERS:  Filename            - Input file for the table
591 *              Table               - Pointer to the raw table
592 *
593 * RETURN:      None
594 *
595 * DESCRIPTION: Create the ASL table header, including ACPICA signon with
596 *              current time and date.
597 *
598 *****************************************************************************/
599
600static void
601AdCreateTableHeader (
602    char                    *Filename,
603    ACPI_TABLE_HEADER       *Table)
604{
605    char                    *NewFilename;
606    UINT8                   Checksum;
607
608
609    /*
610     * Print file header and dump original table header
611     */
612    AdDisassemblerHeader (Filename);
613
614    AcpiOsPrintf (" * Original Table Header:\n");
615    AcpiOsPrintf (" *     Signature        \"%4.4s\"\n",    Table->Signature);
616    AcpiOsPrintf (" *     Length           0x%8.8X (%u)\n", Table->Length, Table->Length);
617
618    /* Print and validate the revision */
619
620    AcpiOsPrintf (" *     Revision         0x%2.2X",      Table->Revision);
621
622    switch (Table->Revision)
623    {
624    case 0:
625
626        AcpiOsPrintf (" **** Invalid Revision");
627        break;
628
629    case 1:
630
631        /* Revision of DSDT controls the ACPI integer width */
632
633        if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT))
634        {
635            AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support");
636        }
637        break;
638
639    default:
640
641        break;
642    }
643    AcpiOsPrintf ("\n");
644
645    /* Print and validate the table checksum */
646
647    AcpiOsPrintf (" *     Checksum         0x%2.2X",        Table->Checksum);
648
649    Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length);
650    if (Checksum)
651    {
652        AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X",
653            (UINT8) (Table->Checksum - Checksum));
654    }
655    AcpiOsPrintf ("\n");
656
657    AcpiOsPrintf (" *     OEM ID           \"%.6s\"\n",     Table->OemId);
658    AcpiOsPrintf (" *     OEM Table ID     \"%.8s\"\n",     Table->OemTableId);
659    AcpiOsPrintf (" *     OEM Revision     0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision);
660    AcpiOsPrintf (" *     Compiler ID      \"%.4s\"\n",     Table->AslCompilerId);
661    AcpiOsPrintf (" *     Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision);
662    AcpiOsPrintf (" */\n");
663
664    /* Create AML output filename based on input filename */
665
666    if (Filename)
667    {
668        NewFilename = FlGenerateFilename (Filename, "aml");
669    }
670    else
671    {
672        NewFilename = UtStringCacheCalloc (9);
673        if (NewFilename)
674        {
675            strncat (NewFilename, Table->Signature, 4);
676            strcat (NewFilename, ".aml");
677        }
678    }
679
680    if (!NewFilename)
681    {
682        AcpiOsPrintf (" **** Could not generate AML output filename\n");
683        return;
684    }
685
686    /* Open the ASL definition block */
687
688    AcpiOsPrintf (
689        "DefinitionBlock (\"%s\", \"%4.4s\", %hu, \"%.6s\", \"%.8s\", 0x%8.8X)\n",
690        NewFilename, Table->Signature, Table->Revision,
691        Table->OemId, Table->OemTableId, Table->OemRevision);
692}
693
694
695/******************************************************************************
696 *
697 * FUNCTION:    AdDisplayTables
698 *
699 * PARAMETERS:  Filename            - Input file for the table
700 *              Table               - Pointer to the raw table
701 *
702 * RETURN:      Status
703 *
704 * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
705 *
706 *****************************************************************************/
707
708ACPI_STATUS
709AdDisplayTables (
710    char                    *Filename,
711    ACPI_TABLE_HEADER       *Table)
712{
713
714
715    if (!AcpiGbl_ParseOpRoot)
716    {
717        return (AE_NOT_EXIST);
718    }
719
720    if (!AcpiGbl_DbOpt_verbose)
721    {
722        AdCreateTableHeader (Filename, Table);
723    }
724
725    AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX);
726    MpEmitMappingInfo ();
727
728    if (AcpiGbl_DbOpt_verbose)
729    {
730        AcpiOsPrintf ("\n\nTable Header:\n");
731        AcpiUtDebugDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
732            DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
733
734        AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
735        AcpiUtDebugDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)),
736            Table->Length, DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
737    }
738
739    return (AE_OK);
740}
741
742
743/******************************************************************************
744 *
745 * FUNCTION:    AdGetLocalTables
746 *
747 * PARAMETERS:  None
748 *
749 * RETURN:      Status
750 *
751 * DESCRIPTION: Get the ACPI tables from either memory or a file
752 *
753 *****************************************************************************/
754
755ACPI_STATUS
756AdGetLocalTables (
757    void)
758{
759    ACPI_STATUS             Status;
760    ACPI_TABLE_HEADER       TableHeader;
761    ACPI_TABLE_HEADER       *NewTable;
762    UINT32                  TableIndex;
763
764
765    /* Get the DSDT via table override */
766
767    ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT);
768    AcpiOsTableOverride (&TableHeader, &NewTable);
769    if (!NewTable)
770    {
771        fprintf (stderr, "Could not obtain DSDT\n");
772        return (AE_NO_ACPI_TABLES);
773    }
774
775    AdWriteTable (NewTable, NewTable->Length,
776        ACPI_SIG_DSDT, NewTable->OemTableId);
777
778    /* Store DSDT in the Table Manager */
779
780    Status = AcpiTbStoreTable (0, NewTable, NewTable->Length,
781                0, &TableIndex);
782    if (ACPI_FAILURE (Status))
783    {
784        fprintf (stderr, "Could not store DSDT\n");
785        return (AE_NO_ACPI_TABLES);
786    }
787
788    return (AE_OK);
789}
790
791
792/******************************************************************************
793 *
794 * FUNCTION:    AdParseTable
795 *
796 * PARAMETERS:  Table               - Pointer to the raw table
797 *              OwnerId             - Returned OwnerId of the table
798 *              LoadTable           - If add table to the global table list
799 *              External            - If this is an external table
800 *
801 * RETURN:      Status
802 *
803 * DESCRIPTION: Parse the DSDT.
804 *
805 *****************************************************************************/
806
807ACPI_STATUS
808AdParseTable (
809    ACPI_TABLE_HEADER       *Table,
810    ACPI_OWNER_ID           *OwnerId,
811    BOOLEAN                 LoadTable,
812    BOOLEAN                 External)
813{
814    ACPI_STATUS             Status = AE_OK;
815    ACPI_WALK_STATE         *WalkState;
816    UINT8                   *AmlStart;
817    UINT32                  AmlLength;
818    UINT32                  TableIndex;
819
820
821    if (!Table)
822    {
823        return (AE_NOT_EXIST);
824    }
825
826    /* Pass 1:  Parse everything except control method bodies */
827
828    fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
829
830    AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
831    AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
832
833    /* Create the root object */
834
835    AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp ();
836    if (!AcpiGbl_ParseOpRoot)
837    {
838        return (AE_NO_MEMORY);
839    }
840
841    /* Create and initialize a new walk state */
842
843    WalkState = AcpiDsCreateWalkState (0,
844                        AcpiGbl_ParseOpRoot, NULL, NULL);
845    if (!WalkState)
846    {
847        return (AE_NO_MEMORY);
848    }
849
850    Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot,
851                NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
852    if (ACPI_FAILURE (Status))
853    {
854        return (Status);
855    }
856
857    WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
858    WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
859
860    Status = AcpiPsParseAml (WalkState);
861    if (ACPI_FAILURE (Status))
862    {
863        return (Status);
864    }
865
866    /* If LoadTable is FALSE, we are parsing the last loaded table */
867
868    TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1;
869
870    /* Pass 2 */
871
872    if (LoadTable)
873    {
874        Status = AcpiTbStoreTable ((ACPI_PHYSICAL_ADDRESS) Table, Table,
875                    Table->Length, ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
876                    &TableIndex);
877        if (ACPI_FAILURE (Status))
878        {
879            return (Status);
880        }
881        Status = AcpiTbAllocateOwnerId (TableIndex);
882        if (ACPI_FAILURE (Status))
883        {
884            return (Status);
885        }
886        if (OwnerId)
887        {
888            Status = AcpiTbGetOwnerId (TableIndex, OwnerId);
889            if (ACPI_FAILURE (Status))
890            {
891                return (Status);
892            }
893        }
894    }
895
896    fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
897
898    Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL);
899    if (ACPI_FAILURE (Status))
900    {
901        return (Status);
902    }
903
904    /* No need to parse control methods of external table */
905
906    if (External)
907    {
908        return (AE_OK);
909    }
910
911    /*
912     * Pass 3: Parse control methods and link their parse trees
913     * into the main parse tree
914     */
915    fprintf (stderr,
916        "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
917    Status = AcpiDmParseDeferredOps (AcpiGbl_ParseOpRoot);
918    fprintf (stderr, "\n");
919
920    /* Process Resource Templates */
921
922    AcpiDmFindResources (AcpiGbl_ParseOpRoot);
923
924    fprintf (stderr, "Parsing completed\n");
925    return (AE_OK);
926}
927