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