xref: /freebsd/sys/contrib/dev/acpica/common/adisasm.c (revision 7cd2dcf07629713e5a3d60472cfe4701b705a167)
1 /******************************************************************************
2  *
3  * Module Name: adisasm - Application-level disassembler routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, 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 <contrib/dev/acpica/include/acpi.h>
46 #include <contrib/dev/acpica/include/accommon.h>
47 #include <contrib/dev/acpica/include/acparser.h>
48 #include <contrib/dev/acpica/include/amlcode.h>
49 #include <contrib/dev/acpica/include/acdebug.h>
50 #include <contrib/dev/acpica/include/acdisasm.h>
51 #include <contrib/dev/acpica/include/acdispat.h>
52 #include <contrib/dev/acpica/include/acnamesp.h>
53 #include <contrib/dev/acpica/include/actables.h>
54 #include <contrib/dev/acpica/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 LsDisplayNamespace (
73     void);
74 
75 void
76 LsSetupNsList (
77     void                    *Handle);
78 
79 
80 /* Local prototypes */
81 
82 static UINT32
83 AdGetFileSize (
84     FILE                    *File);
85 
86 static void
87 AdCreateTableHeader (
88     char                    *Filename,
89     ACPI_TABLE_HEADER       *Table);
90 
91 static ACPI_STATUS
92 AdDeferredParse (
93     ACPI_PARSE_OBJECT       *Op,
94     UINT8                   *Aml,
95     UINT32                  AmlLength);
96 
97 static ACPI_STATUS
98 AdParseDeferredOps (
99     ACPI_PARSE_OBJECT       *Root);
100 
101 
102 /* Stubs for ASL compiler */
103 
104 #ifndef ACPI_ASL_COMPILER
105 BOOLEAN
106 AcpiDsIsResultUsed (
107     ACPI_PARSE_OBJECT       *Op,
108     ACPI_WALK_STATE         *WalkState)
109 {
110     return TRUE;
111 }
112 
113 ACPI_STATUS
114 AcpiDsMethodError (
115     ACPI_STATUS             Status,
116     ACPI_WALK_STATE         *WalkState)
117 {
118     return (Status);
119 }
120 #endif
121 
122 ACPI_STATUS
123 AcpiNsLoadTable (
124     UINT32                  TableIndex,
125     ACPI_NAMESPACE_NODE     *Node)
126 {
127     return (AE_NOT_IMPLEMENTED);
128 }
129 
130 ACPI_STATUS
131 AcpiDsRestartControlMethod (
132     ACPI_WALK_STATE         *WalkState,
133     ACPI_OPERAND_OBJECT     *ReturnDesc)
134 {
135     return (AE_OK);
136 }
137 
138 void
139 AcpiDsTerminateControlMethod (
140     ACPI_OPERAND_OBJECT     *MethodDesc,
141     ACPI_WALK_STATE         *WalkState)
142 {
143     return;
144 }
145 
146 ACPI_STATUS
147 AcpiDsCallControlMethod (
148     ACPI_THREAD_STATE       *Thread,
149     ACPI_WALK_STATE         *WalkState,
150     ACPI_PARSE_OBJECT       *Op)
151 {
152     return (AE_OK);
153 }
154 
155 ACPI_STATUS
156 AcpiDsMethodDataInitArgs (
157     ACPI_OPERAND_OBJECT     **Params,
158     UINT32                  MaxParamCount,
159     ACPI_WALK_STATE         *WalkState)
160 {
161     return (AE_OK);
162 }
163 
164 
165 static ACPI_TABLE_DESC      LocalTables[1];
166 static ACPI_PARSE_OBJECT    *AcpiGbl_ParseOpRoot;
167 
168 
169 /*******************************************************************************
170  *
171  * FUNCTION:    AdGetFileSize
172  *
173  * PARAMETERS:  File                - Open file handle
174  *
175  * RETURN:      File Size
176  *
177  * DESCRIPTION: Get current file size. Uses seek-to-EOF. File must be open.
178  *
179  ******************************************************************************/
180 
181 static UINT32
182 AdGetFileSize (
183     FILE                    *File)
184 {
185     UINT32                  FileSize;
186     long                    Offset;
187 
188 
189     Offset = ftell (File);
190 
191     fseek (File, 0, SEEK_END);
192     FileSize = (UINT32) ftell (File);
193 
194     /* Restore file pointer */
195 
196     fseek (File, Offset, SEEK_SET);
197     return (FileSize);
198 }
199 
200 
201 /*******************************************************************************
202  *
203  * FUNCTION:    AdInitialize
204  *
205  * PARAMETERS:  None
206  *
207  * RETURN:      Status
208  *
209  * DESCRIPTION: ACPICA and local initialization
210  *
211  ******************************************************************************/
212 
213 ACPI_STATUS
214 AdInitialize (
215     void)
216 {
217     ACPI_STATUS             Status;
218 
219 
220     /* ACPI CA subsystem initialization */
221 
222     Status = AcpiOsInitialize ();
223     if (ACPI_FAILURE (Status))
224     {
225         return (Status);
226     }
227 
228     Status = AcpiUtInitGlobals ();
229     if (ACPI_FAILURE (Status))
230     {
231         return (Status);
232     }
233 
234     Status = AcpiUtMutexInitialize ();
235     if (ACPI_FAILURE (Status))
236     {
237         return (Status);
238     }
239 
240     Status = AcpiNsRootInitialize ();
241     if (ACPI_FAILURE (Status))
242     {
243         return (Status);
244     }
245 
246     /* Setup the Table Manager (cheat - there is no RSDT) */
247 
248     AcpiGbl_RootTableList.MaxTableCount = 1;
249     AcpiGbl_RootTableList.CurrentTableCount = 0;
250     AcpiGbl_RootTableList.Tables = LocalTables;
251 
252     return (Status);
253 }
254 
255 
256 /******************************************************************************
257  *
258  * FUNCTION:    AdAmlDisassemble
259  *
260  * PARAMETERS:  Filename            - AML input filename
261  *              OutToFile           - TRUE if output should go to a file
262  *              Prefix              - Path prefix for output
263  *              OutFilename         - where the filename is returned
264  *              GetAllTables        - TRUE if all tables are desired
265  *
266  * RETURN:      Status
267  *
268  * DESCRIPTION: Disassemble an entire ACPI table
269  *
270  *****************************************************************************/
271 
272 ACPI_STATUS
273 AdAmlDisassemble (
274     BOOLEAN                 OutToFile,
275     char                    *Filename,
276     char                    *Prefix,
277     char                    **OutFilename,
278     BOOLEAN                 GetAllTables)
279 {
280     ACPI_STATUS             Status;
281     char                    *DisasmFilename = NULL;
282     char                    *ExternalFilename;
283     ACPI_EXTERNAL_FILE      *ExternalFileList = AcpiGbl_ExternalFileList;
284     FILE                    *File = NULL;
285     ACPI_TABLE_HEADER       *Table = NULL;
286     ACPI_TABLE_HEADER       *ExternalTable;
287     ACPI_OWNER_ID           OwnerId;
288 
289 
290     /*
291      * Input: AML code from either a file or via GetTables (memory or
292      * registry)
293      */
294     if (Filename)
295     {
296         Status = AcpiDbGetTableFromFile (Filename, &Table);
297         if (ACPI_FAILURE (Status))
298         {
299             return (Status);
300         }
301 
302         /*
303          * External filenames separated by commas
304          * Example: iasl -e file1,file2,file3 -d xxx.aml
305          */
306         while (ExternalFileList)
307         {
308             ExternalFilename = ExternalFileList->Path;
309             if (!ACPI_STRCMP (ExternalFilename, Filename))
310             {
311                 /* Next external file */
312 
313                 ExternalFileList = ExternalFileList->Next;
314                 continue;
315             }
316 
317             Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable);
318             if (ACPI_FAILURE (Status))
319             {
320                 return (Status);
321             }
322 
323             /* Load external table for symbol resolution */
324 
325             if (ExternalTable)
326             {
327                 Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE);
328                 if (ACPI_FAILURE (Status))
329                 {
330                     AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
331                         AcpiFormatException (Status));
332                     return (Status);
333                 }
334 
335                 /*
336                  * Load namespace from names created within control methods
337                  * Set owner id of nodes in external table
338                  */
339                 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
340                     AcpiGbl_RootNode, OwnerId);
341                 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
342             }
343 
344             /* Next external file */
345 
346             ExternalFileList = ExternalFileList->Next;
347         }
348 
349         /* Clear external list generated by Scope in external tables */
350 
351         if (AcpiGbl_ExternalFileList)
352         {
353             AcpiDmClearExternalList ();
354         }
355     }
356     else
357     {
358         Status = AdGetLocalTables (Filename, GetAllTables);
359         if (ACPI_FAILURE (Status))
360         {
361             AcpiOsPrintf ("Could not get ACPI tables, %s\n",
362                 AcpiFormatException (Status));
363             return (Status);
364         }
365 
366         if (!AcpiGbl_DbOpt_disasm)
367         {
368             return (AE_OK);
369         }
370 
371         /* Obtained the local tables, just disassemble the DSDT */
372 
373         Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
374         if (ACPI_FAILURE (Status))
375         {
376             AcpiOsPrintf ("Could not get DSDT, %s\n",
377                 AcpiFormatException (Status));
378             return (Status);
379         }
380 
381         AcpiOsPrintf ("\nDisassembly of DSDT\n");
382         Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
383     }
384 
385     /*
386      * Output:  ASL code. Redirect to a file if requested
387      */
388     if (OutToFile)
389     {
390         /* Create/Open a disassembly output file */
391 
392         DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
393         if (!OutFilename)
394         {
395             fprintf (stderr, "Could not generate output filename\n");
396             Status = AE_ERROR;
397             goto Cleanup;
398         }
399 
400         File = fopen (DisasmFilename, "w+");
401         if (!File)
402         {
403             fprintf (stderr, "Could not open output file %s\n", DisasmFilename);
404             Status = AE_ERROR;
405             goto Cleanup;
406         }
407 
408         AcpiOsRedirectOutput (File);
409     }
410 
411     *OutFilename = DisasmFilename;
412 
413     if (!AcpiUtIsAmlTable (Table))
414     {
415         AdDisassemblerHeader (Filename);
416         AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
417             Table->Signature);
418         AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]  "
419             "FieldName : FieldValue\n */\n\n");
420 
421         AcpiDmDumpDataTable (Table);
422         fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n",
423             Table->Signature);
424         fprintf (stderr, "Formatted output:  %s - %u bytes\n",
425             DisasmFilename, AdGetFileSize (File));
426     }
427     else
428     {
429         /* Always parse the tables, only option is what to display */
430 
431         Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
432         if (ACPI_FAILURE (Status))
433         {
434             AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
435                 AcpiFormatException (Status));
436             goto Cleanup;
437         }
438 
439         if (AslCompilerdebug)
440         {
441             AcpiOsPrintf ("/**** Before second load\n");
442 
443             LsSetupNsList (File);
444             LsDisplayNamespace ();
445             AcpiOsPrintf ("*****/\n");
446         }
447 
448         /* Load namespace from names created within control methods */
449 
450         AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
451             AcpiGbl_RootNode, OwnerId);
452 
453         /*
454          * Cross reference the namespace here, in order to
455          * generate External() statements
456          */
457         AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
458             AcpiGbl_RootNode, OwnerId);
459 
460         if (AslCompilerdebug)
461         {
462             AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
463         }
464 
465         /* Find possible calls to external control methods */
466 
467         AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
468 
469         /*
470          * If we found any external control methods, we must reparse
471          * the entire tree with the new information (namely, the
472          * number of arguments per method)
473          */
474         if (AcpiDmGetExternalMethodCount ())
475         {
476             fprintf (stderr,
477                 "\nFound %u external control methods, "
478                 "reparsing with new information\n",
479                 AcpiDmGetExternalMethodCount ());
480 
481             /* Reparse, rebuild namespace. no need to xref namespace */
482 
483             AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
484             AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
485 
486             AcpiGbl_RootNode                    = NULL;
487             AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
488             AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
489             AcpiGbl_RootNodeStruct.Type         = ACPI_TYPE_DEVICE;
490             AcpiGbl_RootNodeStruct.Parent       = NULL;
491             AcpiGbl_RootNodeStruct.Child        = NULL;
492             AcpiGbl_RootNodeStruct.Peer         = NULL;
493             AcpiGbl_RootNodeStruct.Object       = NULL;
494             AcpiGbl_RootNodeStruct.Flags        = 0;
495 
496             Status = AcpiNsRootInitialize ();
497             AcpiDmAddExternalsToNamespace ();
498 
499             /* Parse the table again. No need to reload it, however */
500 
501             Status = AdParseTable (Table, NULL, FALSE, FALSE);
502             if (ACPI_FAILURE (Status))
503             {
504                 AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
505                     AcpiFormatException (Status));
506                 goto Cleanup;
507             }
508 
509             if (AslCompilerdebug)
510             {
511                 AcpiOsPrintf ("/**** After second load and resource conversion\n");
512                 LsSetupNsList (File);
513                 LsDisplayNamespace ();
514                 AcpiOsPrintf ("*****/\n");
515 
516                 AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
517             }
518         }
519 
520         /*
521          * Now that the namespace is finalized, we can perform namespace
522          * transforms.
523          *
524          * 1) Convert fixed-offset references to resource descriptors
525          *    to symbolic references (Note: modifies namespace)
526          */
527         AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
528 
529         /* Optional displays */
530 
531         if (AcpiGbl_DbOpt_disasm)
532         {
533             /* This is the real disassembly */
534 
535             AdDisplayTables (Filename, Table);
536 
537             /* Dump hex table if requested (-vt) */
538 
539             AcpiDmDumpDataTable (Table);
540 
541             fprintf (stderr, "Disassembly completed\n");
542             fprintf (stderr, "ASL Output:    %s - %u bytes\n",
543                 DisasmFilename, AdGetFileSize (File));
544         }
545     }
546 
547 Cleanup:
548 
549     if (Table && !AcpiUtIsAmlTable (Table))
550     {
551         ACPI_FREE (Table);
552     }
553 
554     if (DisasmFilename)
555     {
556         ACPI_FREE (DisasmFilename);
557     }
558 
559     if (OutToFile && File)
560     {
561         if (AslCompilerdebug) /* Display final namespace, with transforms */
562         {
563             LsSetupNsList (File);
564             LsDisplayNamespace ();
565         }
566 
567         fclose (File);
568         AcpiOsRedirectOutput (stdout);
569     }
570 
571     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
572     AcpiGbl_ParseOpRoot = NULL;
573     return (Status);
574 }
575 
576 
577 /******************************************************************************
578  *
579  * FUNCTION:    AdDisassemblerHeader
580  *
581  * PARAMETERS:  Filename            - Input file for the table
582  *
583  * RETURN:      None
584  *
585  * DESCRIPTION: Create the disassembler header, including ACPI CA signon with
586  *              current time and date.
587  *
588  *****************************************************************************/
589 
590 void
591 AdDisassemblerHeader (
592     char                    *Filename)
593 {
594     time_t                  Timer;
595 
596     time (&Timer);
597 
598     /* Header and input table info */
599 
600     AcpiOsPrintf ("/*\n");
601     AcpiOsPrintf (ACPI_COMMON_HEADER ("AML Disassembler", " * "));
602 
603     AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer));
604     AcpiOsPrintf (" *\n");
605 }
606 
607 
608 /******************************************************************************
609  *
610  * FUNCTION:    AdCreateTableHeader
611  *
612  * PARAMETERS:  Filename            - Input file for the table
613  *              Table               - Pointer to the raw table
614  *
615  * RETURN:      None
616  *
617  * DESCRIPTION: Create the ASL table header, including ACPI CA signon with
618  *              current time and date.
619  *
620  *****************************************************************************/
621 
622 static void
623 AdCreateTableHeader (
624     char                    *Filename,
625     ACPI_TABLE_HEADER       *Table)
626 {
627     char                    *NewFilename;
628     UINT8                   Checksum;
629 
630 
631     /*
632      * Print file header and dump original table header
633      */
634     AdDisassemblerHeader (Filename);
635 
636     AcpiOsPrintf (" * Original Table Header:\n");
637     AcpiOsPrintf (" *     Signature        \"%4.4s\"\n",    Table->Signature);
638     AcpiOsPrintf (" *     Length           0x%8.8X (%u)\n", Table->Length, Table->Length);
639 
640     /* Print and validate the revision */
641 
642     AcpiOsPrintf (" *     Revision         0x%2.2X",      Table->Revision);
643 
644     switch (Table->Revision)
645     {
646     case 0:
647         AcpiOsPrintf (" **** Invalid Revision");
648         break;
649 
650     case 1:
651         /* Revision of DSDT controls the ACPI integer width */
652 
653         if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT))
654         {
655             AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support");
656         }
657         break;
658 
659     default:
660         break;
661     }
662     AcpiOsPrintf ("\n");
663 
664     /* Print and validate the table checksum */
665 
666     AcpiOsPrintf (" *     Checksum         0x%2.2X",        Table->Checksum);
667 
668     Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length);
669     if (Checksum)
670     {
671         AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X",
672             (UINT8) (Table->Checksum - Checksum));
673     }
674     AcpiOsPrintf ("\n");
675 
676     AcpiOsPrintf (" *     OEM ID           \"%.6s\"\n",     Table->OemId);
677     AcpiOsPrintf (" *     OEM Table ID     \"%.8s\"\n",     Table->OemTableId);
678     AcpiOsPrintf (" *     OEM Revision     0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision);
679     AcpiOsPrintf (" *     Compiler ID      \"%.4s\"\n",     Table->AslCompilerId);
680     AcpiOsPrintf (" *     Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision);
681     AcpiOsPrintf (" */\n\n");
682 
683     /* Create AML output filename based on input filename */
684 
685     if (Filename)
686     {
687         NewFilename = FlGenerateFilename (Filename, "aml");
688     }
689     else
690     {
691         NewFilename = ACPI_ALLOCATE_ZEROED (9);
692         strncat (NewFilename, Table->Signature, 4);
693         strcat (NewFilename, ".aml");
694     }
695 
696     /* Open the ASL definition block */
697 
698     AcpiOsPrintf (
699         "DefinitionBlock (\"%s\", \"%4.4s\", %hu, \"%.6s\", \"%.8s\", 0x%8.8X)\n",
700         NewFilename, Table->Signature, Table->Revision,
701         Table->OemId, Table->OemTableId, Table->OemRevision);
702 
703     ACPI_FREE (NewFilename);
704 }
705 
706 
707 /******************************************************************************
708  *
709  * FUNCTION:    AdDisplayTables
710  *
711  * PARAMETERS:  Filename            - Input file for the table
712  *              Table               - Pointer to the raw table
713  *
714  * RETURN:      Status
715  *
716  * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
717  *
718  *****************************************************************************/
719 
720 ACPI_STATUS
721 AdDisplayTables (
722     char                    *Filename,
723     ACPI_TABLE_HEADER       *Table)
724 {
725 
726 
727     if (!AcpiGbl_ParseOpRoot)
728     {
729         return (AE_NOT_EXIST);
730     }
731 
732     if (!AcpiGbl_DbOpt_verbose)
733     {
734         AdCreateTableHeader (Filename, Table);
735     }
736 
737     AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX);
738 
739     if (AcpiGbl_DbOpt_verbose)
740     {
741         AcpiOsPrintf ("\n\nTable Header:\n");
742         AcpiUtDebugDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
743             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
744 
745         AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
746         AcpiUtDebugDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)),
747             Table->Length, DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
748     }
749 
750     return (AE_OK);
751 }
752 
753 
754 /******************************************************************************
755  *
756  * FUNCTION:    AdDeferredParse
757  *
758  * PARAMETERS:  Op                  - Root Op of the deferred opcode
759  *              Aml                 - Pointer to the raw AML
760  *              AmlLength           - Length of the AML
761  *
762  * RETURN:      Status
763  *
764  * DESCRIPTION: Parse one deferred opcode
765  *              (Methods, operation regions, etc.)
766  *
767  *****************************************************************************/
768 
769 static ACPI_STATUS
770 AdDeferredParse (
771     ACPI_PARSE_OBJECT       *Op,
772     UINT8                   *Aml,
773     UINT32                  AmlLength)
774 {
775     ACPI_WALK_STATE         *WalkState;
776     ACPI_STATUS             Status;
777     ACPI_PARSE_OBJECT       *SearchOp;
778     ACPI_PARSE_OBJECT       *StartOp;
779     UINT32                  BaseAmlOffset;
780     ACPI_PARSE_OBJECT       *ExtraOp;
781 
782 
783     ACPI_FUNCTION_TRACE (AdDeferredParse);
784 
785 
786     fprintf (stderr, ".");
787 
788     if (!Aml || !AmlLength)
789     {
790         return_ACPI_STATUS (AE_OK);
791     }
792 
793     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing %s [%4.4s]\n",
794         Op->Common.AmlOpName, (char *) &Op->Named.Name));
795 
796     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
797     if (!WalkState)
798     {
799         return_ACPI_STATUS (AE_NO_MEMORY);
800     }
801 
802     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml,
803                     AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
804     if (ACPI_FAILURE (Status))
805     {
806         return_ACPI_STATUS (Status);
807     }
808 
809     /* Parse the method */
810 
811     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
812     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
813     Status = AcpiPsParseAml (WalkState);
814 
815     /*
816      * We need to update all of the Aml offsets, since the parser thought
817      * that the method began at offset zero. In reality, it began somewhere
818      * within the ACPI table, at the BaseAmlOffset. Walk the entire tree that
819      * was just created and update the AmlOffset in each Op
820      */
821     BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1;
822     StartOp = (Op->Common.Value.Arg)->Common.Next;
823     SearchOp = StartOp;
824 
825     /* Walk the parse tree */
826 
827     while (SearchOp)
828     {
829         SearchOp->Common.AmlOffset += BaseAmlOffset;
830         SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
831     }
832 
833     /*
834      * Link the newly parsed subtree into the main parse tree
835      */
836     switch (Op->Common.AmlOpcode)
837     {
838     case AML_BUFFER_OP:
839     case AML_PACKAGE_OP:
840     case AML_VAR_PACKAGE_OP:
841 
842         switch (Op->Common.AmlOpcode)
843         {
844         case AML_PACKAGE_OP:
845             ExtraOp = Op->Common.Value.Arg;
846             ExtraOp = ExtraOp->Common.Next;
847             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
848             break;
849 
850         case AML_VAR_PACKAGE_OP:
851         case AML_BUFFER_OP:
852         default:
853             ExtraOp = Op->Common.Value.Arg;
854             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
855             break;
856         }
857 
858         /* Must point all parents to the main tree */
859 
860         StartOp = Op;
861         SearchOp = StartOp;
862         while (SearchOp)
863         {
864             if (SearchOp->Common.Parent == ExtraOp)
865             {
866                 SearchOp->Common.Parent = Op;
867             }
868             SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
869         }
870         break;
871 
872     default:
873         break;
874     }
875 
876     return_ACPI_STATUS (AE_OK);
877 }
878 
879 
880 /******************************************************************************
881  *
882  * FUNCTION:    AdParseDeferredOps
883  *
884  * PARAMETERS:  Root                - Root of the parse tree
885  *
886  * RETURN:      Status
887  *
888  * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.)
889  *
890  *****************************************************************************/
891 
892 static ACPI_STATUS
893 AdParseDeferredOps (
894     ACPI_PARSE_OBJECT       *Root)
895 {
896     ACPI_PARSE_OBJECT       *Op = Root;
897     ACPI_STATUS             Status = AE_OK;
898     const ACPI_OPCODE_INFO  *OpInfo;
899 
900 
901     ACPI_FUNCTION_NAME (AdParseDeferredOps);
902     fprintf (stderr, "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
903 
904     while (Op)
905     {
906         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
907         if (!(OpInfo->Flags & AML_DEFER))
908         {
909             Op = AcpiPsGetDepthNext (Root, Op);
910             continue;
911         }
912 
913         switch (Op->Common.AmlOpcode)
914         {
915         case AML_METHOD_OP:
916         case AML_BUFFER_OP:
917         case AML_PACKAGE_OP:
918         case AML_VAR_PACKAGE_OP:
919 
920             Status = AdDeferredParse (Op, Op->Named.Data, Op->Named.Length);
921             if (ACPI_FAILURE (Status))
922             {
923                 return (Status);
924             }
925             break;
926 
927         case AML_REGION_OP:
928         case AML_DATA_REGION_OP:
929         case AML_CREATE_QWORD_FIELD_OP:
930         case AML_CREATE_DWORD_FIELD_OP:
931         case AML_CREATE_WORD_FIELD_OP:
932         case AML_CREATE_BYTE_FIELD_OP:
933         case AML_CREATE_BIT_FIELD_OP:
934         case AML_CREATE_FIELD_OP:
935         case AML_BANK_FIELD_OP:
936 
937             /* Nothing to do in these cases */
938 
939             break;
940 
941         default:
942             ACPI_ERROR ((AE_INFO, "Unhandled deferred opcode [%s]",
943                 Op->Common.AmlOpName));
944             break;
945         }
946 
947         Op = AcpiPsGetDepthNext (Root, Op);
948     }
949 
950     fprintf (stderr, "\n");
951     return (Status);
952 }
953 
954 
955 /******************************************************************************
956  *
957  * FUNCTION:    AdGetLocalTables
958  *
959  * PARAMETERS:  Filename            - Not used
960  *              GetAllTables        - TRUE if all tables are desired
961  *
962  * RETURN:      Status
963  *
964  * DESCRIPTION: Get the ACPI tables from either memory or a file
965  *
966  *****************************************************************************/
967 
968 ACPI_STATUS
969 AdGetLocalTables (
970     char                    *Filename,
971     BOOLEAN                 GetAllTables)
972 {
973     ACPI_STATUS             Status;
974     ACPI_TABLE_HEADER       TableHeader;
975     ACPI_TABLE_HEADER       *NewTable;
976     UINT32                  NumTables;
977     UINT32                  PointerSize;
978     UINT32                  TableIndex;
979 
980 
981     if (GetAllTables)
982     {
983         ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_RSDT);
984         AcpiOsTableOverride (&TableHeader, &NewTable);
985         if (!NewTable)
986         {
987             fprintf (stderr, "Could not obtain RSDT\n");
988             return (AE_NO_ACPI_TABLES);
989         }
990         else
991         {
992             AdWriteTable (NewTable, NewTable->Length,
993                 ACPI_SIG_RSDT, NewTable->OemTableId);
994         }
995 
996         if (ACPI_COMPARE_NAME (NewTable->Signature, ACPI_SIG_RSDT))
997         {
998             PointerSize = sizeof (UINT32);
999         }
1000         else
1001         {
1002             PointerSize = sizeof (UINT64);
1003         }
1004 
1005         /*
1006          * Determine the number of tables pointed to by the RSDT/XSDT.
1007          * This is defined by the ACPI Specification to be the number of
1008          * pointers contained within the RSDT/XSDT. The size of the pointers
1009          * is architecture-dependent.
1010          */
1011         NumTables = (NewTable->Length - sizeof (ACPI_TABLE_HEADER)) / PointerSize;
1012         AcpiOsPrintf ("There are %u tables defined in the %4.4s\n\n",
1013             NumTables, NewTable->Signature);
1014 
1015         /* Get the FADT */
1016 
1017         ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_FADT);
1018         AcpiOsTableOverride (&TableHeader, &NewTable);
1019         if (NewTable)
1020         {
1021             AdWriteTable (NewTable, NewTable->Length,
1022                 ACPI_SIG_FADT, NewTable->OemTableId);
1023         }
1024         AcpiOsPrintf ("\n");
1025 
1026         /* Don't bother with FACS, it is usually all zeros */
1027     }
1028 
1029     /* Always get the DSDT */
1030 
1031     ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT);
1032     AcpiOsTableOverride (&TableHeader, &NewTable);
1033     if (NewTable)
1034     {
1035         AdWriteTable (NewTable, NewTable->Length,
1036             ACPI_SIG_DSDT, NewTable->OemTableId);
1037 
1038         /* Store DSDT in the Table Manager */
1039 
1040         Status = AcpiTbStoreTable (0, NewTable, NewTable->Length,
1041                     0, &TableIndex);
1042         if (ACPI_FAILURE (Status))
1043         {
1044             fprintf (stderr, "Could not store DSDT\n");
1045             return (AE_NO_ACPI_TABLES);
1046         }
1047     }
1048     else
1049     {
1050         fprintf (stderr, "Could not obtain DSDT\n");
1051         return (AE_NO_ACPI_TABLES);
1052     }
1053 
1054 #if 0
1055     /* TBD: Future implementation */
1056 
1057     AcpiOsPrintf ("\n");
1058 
1059     /* Get all SSDTs */
1060 
1061     ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_SSDT);
1062     do
1063     {
1064         NewTable = NULL;
1065         Status = AcpiOsTableOverride (&TableHeader, &NewTable);
1066 
1067     } while (NewTable);
1068 #endif
1069 
1070     return (AE_OK);
1071 }
1072 
1073 
1074 /******************************************************************************
1075  *
1076  * FUNCTION:    AdParseTable
1077  *
1078  * PARAMETERS:  Table               - Pointer to the raw table
1079  *              OwnerId             - Returned OwnerId of the table
1080  *              LoadTable           - If add table to the global table list
1081  *              External            - If this is an external table
1082  *
1083  * RETURN:      Status
1084  *
1085  * DESCRIPTION: Parse the DSDT.
1086  *
1087  *****************************************************************************/
1088 
1089 ACPI_STATUS
1090 AdParseTable (
1091     ACPI_TABLE_HEADER       *Table,
1092     ACPI_OWNER_ID           *OwnerId,
1093     BOOLEAN                 LoadTable,
1094     BOOLEAN                 External)
1095 {
1096     ACPI_STATUS             Status = AE_OK;
1097     ACPI_WALK_STATE         *WalkState;
1098     UINT8                   *AmlStart;
1099     UINT32                  AmlLength;
1100     UINT32                  TableIndex;
1101 
1102 
1103     if (!Table)
1104     {
1105         return (AE_NOT_EXIST);
1106     }
1107 
1108     /* Pass 1:  Parse everything except control method bodies */
1109 
1110     fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
1111 
1112     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
1113     AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
1114 
1115     /* Create the root object */
1116 
1117     AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp ();
1118     if (!AcpiGbl_ParseOpRoot)
1119     {
1120         return (AE_NO_MEMORY);
1121     }
1122 
1123     /* Create and initialize a new walk state */
1124 
1125     WalkState = AcpiDsCreateWalkState (0,
1126                         AcpiGbl_ParseOpRoot, NULL, NULL);
1127     if (!WalkState)
1128     {
1129         return (AE_NO_MEMORY);
1130     }
1131 
1132     Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot,
1133                 NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
1134     if (ACPI_FAILURE (Status))
1135     {
1136         return (Status);
1137     }
1138 
1139     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
1140     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
1141 
1142     Status = AcpiPsParseAml (WalkState);
1143     if (ACPI_FAILURE (Status))
1144     {
1145         return (Status);
1146     }
1147 
1148     /* If LoadTable is FALSE, we are parsing the last loaded table */
1149 
1150     TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1;
1151 
1152     /* Pass 2 */
1153 
1154     if (LoadTable)
1155     {
1156         Status = AcpiTbStoreTable ((ACPI_PHYSICAL_ADDRESS) Table, Table,
1157                     Table->Length, ACPI_TABLE_ORIGIN_ALLOCATED, &TableIndex);
1158         if (ACPI_FAILURE (Status))
1159         {
1160             return (Status);
1161         }
1162         Status = AcpiTbAllocateOwnerId (TableIndex);
1163         if (ACPI_FAILURE (Status))
1164         {
1165             return (Status);
1166         }
1167         if (OwnerId)
1168         {
1169             Status = AcpiTbGetOwnerId (TableIndex, OwnerId);
1170             if (ACPI_FAILURE (Status))
1171             {
1172                 return (Status);
1173             }
1174         }
1175     }
1176 
1177     fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
1178 
1179     Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL);
1180     if (ACPI_FAILURE (Status))
1181     {
1182         return (Status);
1183     }
1184 
1185     /* No need to parse control methods of external table */
1186 
1187     if (External)
1188     {
1189         return (AE_OK);
1190     }
1191 
1192     /* Pass 3: Parse control methods and link their parse trees into the main parse tree */
1193 
1194     Status = AdParseDeferredOps (AcpiGbl_ParseOpRoot);
1195 
1196     /* Process Resource Templates */
1197 
1198     AcpiDmFindResources (AcpiGbl_ParseOpRoot);
1199 
1200     fprintf (stderr, "Parsing completed\n");
1201     return (AE_OK);
1202 }
1203