xref: /freebsd/sys/contrib/dev/acpica/common/adisasm.c (revision 145992504973bd16cf3518af9ba5ce185fefa82a)
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 
315                 continue;
316             }
317 
318             Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable);
319             if (ACPI_FAILURE (Status))
320             {
321                 return Status;
322             }
323 
324             /* Load external table for symbol resolution */
325 
326             if (ExternalTable)
327             {
328                 Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE);
329                 if (ACPI_FAILURE (Status))
330                 {
331                     AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
332                         AcpiFormatException (Status));
333                     return Status;
334                 }
335 
336                 /*
337                  * Load namespace from names created within control methods
338                  * Set owner id of nodes in external table
339                  */
340                 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
341                     AcpiGbl_RootNode, OwnerId);
342                 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
343             }
344 
345             /* Next external file */
346 
347             ExternalFileList = ExternalFileList->Next;
348         }
349 
350         /* Clear external list generated by Scope in external tables */
351 
352         if (AcpiGbl_ExternalFileList)
353         {
354             AcpiDmClearExternalList ();
355         }
356     }
357     else
358     {
359         Status = AdGetLocalTables (Filename, GetAllTables);
360         if (ACPI_FAILURE (Status))
361         {
362             AcpiOsPrintf ("Could not get ACPI tables, %s\n",
363                 AcpiFormatException (Status));
364             return Status;
365         }
366 
367         if (!AcpiGbl_DbOpt_disasm)
368         {
369             return AE_OK;
370         }
371 
372         /* Obtained the local tables, just disassemble the DSDT */
373 
374         Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
375         if (ACPI_FAILURE (Status))
376         {
377             AcpiOsPrintf ("Could not get DSDT, %s\n",
378                 AcpiFormatException (Status));
379             return Status;
380         }
381 
382         AcpiOsPrintf ("\nDisassembly of DSDT\n");
383         Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
384     }
385 
386     /*
387      * Output:  ASL code. Redirect to a file if requested
388      */
389     if (OutToFile)
390     {
391         /* Create/Open a disassembly output file */
392 
393         DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
394         if (!OutFilename)
395         {
396             fprintf (stderr, "Could not generate output filename\n");
397             Status = AE_ERROR;
398             goto Cleanup;
399         }
400 
401         File = fopen (DisasmFilename, "w+");
402         if (!File)
403         {
404             fprintf (stderr, "Could not open output file %s\n", DisasmFilename);
405             Status = AE_ERROR;
406             goto Cleanup;
407         }
408 
409         AcpiOsRedirectOutput (File);
410     }
411 
412     *OutFilename = DisasmFilename;
413 
414     if (!AcpiUtIsAmlTable (Table))
415     {
416         AdDisassemblerHeader (Filename);
417         AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
418             Table->Signature);
419         AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]  "
420             "FieldName : FieldValue\n */\n\n");
421 
422         AcpiDmDumpDataTable (Table);
423         fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n",
424             Table->Signature);
425         fprintf (stderr, "Formatted output:  %s - %u bytes\n",
426             DisasmFilename, AdGetFileSize (File));
427     }
428     else
429     {
430         /* Always parse the tables, only option is what to display */
431 
432         Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
433         if (ACPI_FAILURE (Status))
434         {
435             AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
436                 AcpiFormatException (Status));
437             goto Cleanup;
438         }
439 
440         if (AslCompilerdebug)
441         {
442             AcpiOsPrintf ("/**** Before second load\n");
443 
444             LsSetupNsList (File);
445             LsDisplayNamespace ();
446             AcpiOsPrintf ("*****/\n");
447         }
448 
449         /* Load namespace from names created within control methods */
450 
451         AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
452             AcpiGbl_RootNode, OwnerId);
453 
454         /*
455          * Cross reference the namespace here, in order to
456          * generate External() statements
457          */
458         AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
459             AcpiGbl_RootNode, OwnerId);
460 
461         if (AslCompilerdebug)
462         {
463             AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
464         }
465 
466         /* Find possible calls to external control methods */
467 
468         AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
469 
470         /*
471          * If we found any external control methods, we must reparse
472          * the entire tree with the new information (namely, the
473          * number of arguments per method)
474          */
475         if (AcpiDmGetExternalMethodCount ())
476         {
477             fprintf (stderr,
478                 "\nFound %u external control methods, "
479                 "reparsing with new information\n",
480                 AcpiDmGetExternalMethodCount ());
481 
482             /* Reparse, rebuild namespace. no need to xref namespace */
483 
484             AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
485             AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
486 
487             AcpiGbl_RootNode                    = NULL;
488             AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
489             AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
490             AcpiGbl_RootNodeStruct.Type         = ACPI_TYPE_DEVICE;
491             AcpiGbl_RootNodeStruct.Parent       = NULL;
492             AcpiGbl_RootNodeStruct.Child        = NULL;
493             AcpiGbl_RootNodeStruct.Peer         = NULL;
494             AcpiGbl_RootNodeStruct.Object       = NULL;
495             AcpiGbl_RootNodeStruct.Flags        = 0;
496 
497             Status = AcpiNsRootInitialize ();
498             AcpiDmAddExternalsToNamespace ();
499 
500             /* Parse the table again. No need to reload it, however */
501 
502             Status = AdParseTable (Table, NULL, FALSE, FALSE);
503             if (ACPI_FAILURE (Status))
504             {
505                 AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
506                     AcpiFormatException (Status));
507                 goto Cleanup;
508             }
509 
510             if (AslCompilerdebug)
511             {
512                 AcpiOsPrintf ("/**** After second load and resource conversion\n");
513                 LsSetupNsList (File);
514                 LsDisplayNamespace ();
515                 AcpiOsPrintf ("*****/\n");
516 
517                 AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
518             }
519         }
520 
521         /*
522          * Now that the namespace is finalized, we can perform namespace
523          * transforms.
524          *
525          * 1) Convert fixed-offset references to resource descriptors
526          *    to symbolic references (Note: modifies namespace)
527          */
528         AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
529 
530         /* Optional displays */
531 
532         if (AcpiGbl_DbOpt_disasm)
533         {
534             AdDisplayTables (Filename, Table);
535             fprintf (stderr, "Disassembly completed\n");
536             fprintf (stderr, "ASL Output:    %s - %u bytes\n",
537                 DisasmFilename, AdGetFileSize (File));
538         }
539     }
540 
541 Cleanup:
542 
543     if (Table && !AcpiUtIsAmlTable (Table))
544     {
545         ACPI_FREE (Table);
546     }
547 
548     if (DisasmFilename)
549     {
550         ACPI_FREE (DisasmFilename);
551     }
552 
553     if (OutToFile && File)
554     {
555         if (AslCompilerdebug) /* Display final namespace, with transforms */
556         {
557             LsSetupNsList (File);
558             LsDisplayNamespace ();
559         }
560 
561         fclose (File);
562         AcpiOsRedirectOutput (stdout);
563     }
564 
565     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
566     AcpiGbl_ParseOpRoot = NULL;
567     return (Status);
568 }
569 
570 
571 /******************************************************************************
572  *
573  * FUNCTION:    AdDisassemblerHeader
574  *
575  * PARAMETERS:  Filename            - Input file for the table
576  *
577  * RETURN:      None
578  *
579  * DESCRIPTION: Create the disassembler header, including ACPI CA signon with
580  *              current time and date.
581  *
582  *****************************************************************************/
583 
584 void
585 AdDisassemblerHeader (
586     char                    *Filename)
587 {
588     time_t                  Timer;
589 
590     time (&Timer);
591 
592     /* Header and input table info */
593 
594     AcpiOsPrintf ("/*\n");
595     AcpiOsPrintf (ACPI_COMMON_HEADER ("AML Disassembler", " * "));
596 
597     AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer));
598     AcpiOsPrintf (" *\n");
599 }
600 
601 
602 /******************************************************************************
603  *
604  * FUNCTION:    AdCreateTableHeader
605  *
606  * PARAMETERS:  Filename            - Input file for the table
607  *              Table               - Pointer to the raw table
608  *
609  * RETURN:      None
610  *
611  * DESCRIPTION: Create the ASL table header, including ACPI CA signon with
612  *              current time and date.
613  *
614  *****************************************************************************/
615 
616 static void
617 AdCreateTableHeader (
618     char                    *Filename,
619     ACPI_TABLE_HEADER       *Table)
620 {
621     char                    *NewFilename;
622     UINT8                   Checksum;
623 
624 
625     /*
626      * Print file header and dump original table header
627      */
628     AdDisassemblerHeader (Filename);
629 
630     AcpiOsPrintf (" * Original Table Header:\n");
631     AcpiOsPrintf (" *     Signature        \"%4.4s\"\n",    Table->Signature);
632     AcpiOsPrintf (" *     Length           0x%8.8X (%u)\n", Table->Length, Table->Length);
633 
634     /* Print and validate the revision */
635 
636     AcpiOsPrintf (" *     Revision         0x%2.2X",      Table->Revision);
637 
638     switch (Table->Revision)
639     {
640     case 0:
641         AcpiOsPrintf (" **** Invalid Revision");
642         break;
643 
644     case 1:
645         /* Revision of DSDT controls the ACPI integer width */
646 
647         if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT))
648         {
649             AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support");
650         }
651         break;
652 
653     default:
654         break;
655     }
656     AcpiOsPrintf ("\n");
657 
658     /* Print and validate the table checksum */
659 
660     AcpiOsPrintf (" *     Checksum         0x%2.2X",        Table->Checksum);
661 
662     Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length);
663     if (Checksum)
664     {
665         AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X",
666             (UINT8) (Table->Checksum - Checksum));
667     }
668     AcpiOsPrintf ("\n");
669 
670     AcpiOsPrintf (" *     OEM ID           \"%.6s\"\n",     Table->OemId);
671     AcpiOsPrintf (" *     OEM Table ID     \"%.8s\"\n",     Table->OemTableId);
672     AcpiOsPrintf (" *     OEM Revision     0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision);
673     AcpiOsPrintf (" *     Compiler ID      \"%.4s\"\n",     Table->AslCompilerId);
674     AcpiOsPrintf (" *     Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision);
675     AcpiOsPrintf (" */\n\n");
676 
677     /* Create AML output filename based on input filename */
678 
679     if (Filename)
680     {
681         NewFilename = FlGenerateFilename (Filename, "aml");
682     }
683     else
684     {
685         NewFilename = ACPI_ALLOCATE_ZEROED (9);
686         strncat (NewFilename, Table->Signature, 4);
687         strcat (NewFilename, ".aml");
688     }
689 
690     /* Open the ASL definition block */
691 
692     AcpiOsPrintf (
693         "DefinitionBlock (\"%s\", \"%4.4s\", %hu, \"%.6s\", \"%.8s\", 0x%8.8X)\n",
694         NewFilename, Table->Signature, Table->Revision,
695         Table->OemId, Table->OemTableId, Table->OemRevision);
696 
697     ACPI_FREE (NewFilename);
698 }
699 
700 
701 /******************************************************************************
702  *
703  * FUNCTION:    AdDisplayTables
704  *
705  * PARAMETERS:  Filename            - Input file for the table
706  *              Table               - Pointer to the raw table
707  *
708  * RETURN:      Status
709  *
710  * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
711  *
712  *****************************************************************************/
713 
714 ACPI_STATUS
715 AdDisplayTables (
716     char                    *Filename,
717     ACPI_TABLE_HEADER       *Table)
718 {
719 
720 
721     if (!AcpiGbl_ParseOpRoot)
722     {
723         return AE_NOT_EXIST;
724     }
725 
726     if (!AcpiGbl_DbOpt_verbose)
727     {
728         AdCreateTableHeader (Filename, Table);
729     }
730 
731     AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX);
732 
733     if (AcpiGbl_DbOpt_verbose)
734     {
735         AcpiOsPrintf ("\n\nTable Header:\n");
736         AcpiUtDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
737             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
738 
739         AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
740         AcpiUtDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)), Table->Length,
741             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
742     }
743 
744     return AE_OK;
745 }
746 
747 
748 /******************************************************************************
749  *
750  * FUNCTION:    AdDeferredParse
751  *
752  * PARAMETERS:  Op                  - Root Op of the deferred opcode
753  *              Aml                 - Pointer to the raw AML
754  *              AmlLength           - Length of the AML
755  *
756  * RETURN:      Status
757  *
758  * DESCRIPTION: Parse one deferred opcode
759  *              (Methods, operation regions, etc.)
760  *
761  *****************************************************************************/
762 
763 static ACPI_STATUS
764 AdDeferredParse (
765     ACPI_PARSE_OBJECT       *Op,
766     UINT8                   *Aml,
767     UINT32                  AmlLength)
768 {
769     ACPI_WALK_STATE         *WalkState;
770     ACPI_STATUS             Status;
771     ACPI_PARSE_OBJECT       *SearchOp;
772     ACPI_PARSE_OBJECT       *StartOp;
773     UINT32                  BaseAmlOffset;
774     ACPI_PARSE_OBJECT       *ExtraOp;
775 
776 
777     ACPI_FUNCTION_TRACE (AdDeferredParse);
778 
779 
780     fprintf (stderr, ".");
781 
782     if (!Aml || !AmlLength)
783     {
784         return_ACPI_STATUS (AE_OK);
785     }
786 
787     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing %s [%4.4s]\n",
788         Op->Common.AmlOpName, (char *) &Op->Named.Name));
789 
790     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
791     if (!WalkState)
792     {
793         return_ACPI_STATUS (AE_NO_MEMORY);
794     }
795 
796     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml,
797                     AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
798     if (ACPI_FAILURE (Status))
799     {
800         return_ACPI_STATUS (Status);
801     }
802 
803     /* Parse the method */
804 
805     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
806     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
807     Status = AcpiPsParseAml (WalkState);
808 
809     /*
810      * We need to update all of the Aml offsets, since the parser thought
811      * that the method began at offset zero.  In reality, it began somewhere
812      * within the ACPI table, at the BaseAmlOffset.  Walk the entire tree that
813      * was just created and update the AmlOffset in each Op
814      */
815     BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1;
816     StartOp = (Op->Common.Value.Arg)->Common.Next;
817     SearchOp = StartOp;
818 
819     /* Walk the parse tree */
820 
821     while (SearchOp)
822     {
823         SearchOp->Common.AmlOffset += BaseAmlOffset;
824         SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
825     }
826 
827     /*
828      * Link the newly parsed subtree into the main parse tree
829      */
830     switch (Op->Common.AmlOpcode)
831     {
832     case AML_BUFFER_OP:
833     case AML_PACKAGE_OP:
834     case AML_VAR_PACKAGE_OP:
835 
836         switch (Op->Common.AmlOpcode)
837         {
838         case AML_PACKAGE_OP:
839             ExtraOp = Op->Common.Value.Arg;
840             ExtraOp = ExtraOp->Common.Next;
841             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
842             break;
843 
844         case AML_VAR_PACKAGE_OP:
845         case AML_BUFFER_OP:
846         default:
847             ExtraOp = Op->Common.Value.Arg;
848             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
849             break;
850         }
851 
852         /* Must point all parents to the main tree */
853 
854         StartOp = Op;
855         SearchOp = StartOp;
856         while (SearchOp)
857         {
858             if (SearchOp->Common.Parent == ExtraOp)
859             {
860                 SearchOp->Common.Parent = Op;
861             }
862             SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
863         }
864         break;
865 
866     default:
867         break;
868     }
869 
870     return_ACPI_STATUS (AE_OK);
871 }
872 
873 
874 /******************************************************************************
875  *
876  * FUNCTION:    AdParseDeferredOps
877  *
878  * PARAMETERS:  Root                - Root of the parse tree
879  *
880  * RETURN:      Status
881  *
882  * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.)
883  *
884  *****************************************************************************/
885 
886 static ACPI_STATUS
887 AdParseDeferredOps (
888     ACPI_PARSE_OBJECT       *Root)
889 {
890     ACPI_PARSE_OBJECT       *Op = Root;
891     ACPI_STATUS             Status = AE_OK;
892     const ACPI_OPCODE_INFO  *OpInfo;
893 
894 
895     ACPI_FUNCTION_NAME (AdParseDeferredOps);
896     fprintf (stderr, "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
897 
898     while (Op)
899     {
900         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
901         if (!(OpInfo->Flags & AML_DEFER))
902         {
903             Op = AcpiPsGetDepthNext (Root, Op);
904             continue;
905         }
906 
907         switch (Op->Common.AmlOpcode)
908         {
909         case AML_METHOD_OP:
910         case AML_BUFFER_OP:
911         case AML_PACKAGE_OP:
912         case AML_VAR_PACKAGE_OP:
913 
914             Status = AdDeferredParse (Op, Op->Named.Data, Op->Named.Length);
915             if (ACPI_FAILURE (Status))
916             {
917                 return_ACPI_STATUS (Status);
918             }
919             break;
920 
921         case AML_REGION_OP:
922         case AML_DATA_REGION_OP:
923         case AML_CREATE_QWORD_FIELD_OP:
924         case AML_CREATE_DWORD_FIELD_OP:
925         case AML_CREATE_WORD_FIELD_OP:
926         case AML_CREATE_BYTE_FIELD_OP:
927         case AML_CREATE_BIT_FIELD_OP:
928         case AML_CREATE_FIELD_OP:
929         case AML_BANK_FIELD_OP:
930 
931             /* Nothing to do in these cases */
932 
933             break;
934 
935         default:
936             ACPI_ERROR ((AE_INFO, "Unhandled deferred opcode [%s]",
937                 Op->Common.AmlOpName));
938             break;
939         }
940 
941         Op = AcpiPsGetDepthNext (Root, Op);
942     }
943 
944     fprintf (stderr, "\n");
945     return Status;
946 }
947 
948 
949 /******************************************************************************
950  *
951  * FUNCTION:    AdGetLocalTables
952  *
953  * PARAMETERS:  Filename            - Not used
954  *              GetAllTables        - TRUE if all tables are desired
955  *
956  * RETURN:      Status
957  *
958  * DESCRIPTION: Get the ACPI tables from either memory or a file
959  *
960  *****************************************************************************/
961 
962 ACPI_STATUS
963 AdGetLocalTables (
964     char                    *Filename,
965     BOOLEAN                 GetAllTables)
966 {
967     ACPI_STATUS             Status;
968     ACPI_TABLE_HEADER       TableHeader;
969     ACPI_TABLE_HEADER       *NewTable;
970     UINT32                  NumTables;
971     UINT32                  PointerSize;
972     UINT32                  TableIndex;
973 
974 
975     if (GetAllTables)
976     {
977         ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_RSDT);
978         AcpiOsTableOverride (&TableHeader, &NewTable);
979         if (!NewTable)
980         {
981             fprintf (stderr, "Could not obtain RSDT\n");
982             return AE_NO_ACPI_TABLES;
983         }
984         else
985         {
986             AdWriteTable (NewTable, NewTable->Length,
987                 ACPI_SIG_RSDT, NewTable->OemTableId);
988         }
989 
990         if (ACPI_COMPARE_NAME (NewTable->Signature, ACPI_SIG_RSDT))
991         {
992             PointerSize = sizeof (UINT32);
993         }
994         else
995         {
996             PointerSize = sizeof (UINT64);
997         }
998 
999         /*
1000          * Determine the number of tables pointed to by the RSDT/XSDT.
1001          * This is defined by the ACPI Specification to be the number of
1002          * pointers contained within the RSDT/XSDT.  The size of the pointers
1003          * is architecture-dependent.
1004          */
1005         NumTables = (NewTable->Length - sizeof (ACPI_TABLE_HEADER)) / PointerSize;
1006         AcpiOsPrintf ("There are %u tables defined in the %4.4s\n\n",
1007             NumTables, NewTable->Signature);
1008 
1009         /* Get the FADT */
1010 
1011         ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_FADT);
1012         AcpiOsTableOverride (&TableHeader, &NewTable);
1013         if (NewTable)
1014         {
1015             AdWriteTable (NewTable, NewTable->Length,
1016                 ACPI_SIG_FADT, NewTable->OemTableId);
1017         }
1018         AcpiOsPrintf ("\n");
1019 
1020         /* Don't bother with FACS, it is usually all zeros */
1021     }
1022 
1023     /* Always get the DSDT */
1024 
1025     ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT);
1026     AcpiOsTableOverride (&TableHeader, &NewTable);
1027     if (NewTable)
1028     {
1029         AdWriteTable (NewTable, NewTable->Length,
1030             ACPI_SIG_DSDT, NewTable->OemTableId);
1031 
1032         /* Store DSDT in the Table Manager */
1033 
1034         Status = AcpiTbStoreTable (0, NewTable, NewTable->Length,
1035                     0, &TableIndex);
1036         if (ACPI_FAILURE (Status))
1037         {
1038             fprintf (stderr, "Could not store DSDT\n");
1039             return AE_NO_ACPI_TABLES;
1040         }
1041     }
1042     else
1043     {
1044         fprintf (stderr, "Could not obtain DSDT\n");
1045         return AE_NO_ACPI_TABLES;
1046     }
1047 
1048 #if 0
1049     /* TBD: Future implementation */
1050 
1051     AcpiOsPrintf ("\n");
1052 
1053     /* Get all SSDTs */
1054 
1055     ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_SSDT);
1056     do
1057     {
1058         NewTable = NULL;
1059         Status = AcpiOsTableOverride (&TableHeader, &NewTable);
1060 
1061     } while (NewTable);
1062 #endif
1063 
1064     return AE_OK;
1065 }
1066 
1067 
1068 /******************************************************************************
1069  *
1070  * FUNCTION:    AdParseTable
1071  *
1072  * PARAMETERS:  Table               - Pointer to the raw table
1073  *              OwnerId             - Returned OwnerId of the table
1074  *              LoadTable           - If add table to the global table list
1075  *              External            - If this is an external table
1076  *
1077  * RETURN:      Status
1078  *
1079  * DESCRIPTION: Parse the DSDT.
1080  *
1081  *****************************************************************************/
1082 
1083 ACPI_STATUS
1084 AdParseTable (
1085     ACPI_TABLE_HEADER       *Table,
1086     ACPI_OWNER_ID           *OwnerId,
1087     BOOLEAN                 LoadTable,
1088     BOOLEAN                 External)
1089 {
1090     ACPI_STATUS             Status = AE_OK;
1091     ACPI_WALK_STATE         *WalkState;
1092     UINT8                   *AmlStart;
1093     UINT32                  AmlLength;
1094     UINT32                  TableIndex;
1095 
1096 
1097     if (!Table)
1098     {
1099         return AE_NOT_EXIST;
1100     }
1101 
1102     /* Pass 1:  Parse everything except control method bodies */
1103 
1104     fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
1105 
1106     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
1107     AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
1108 
1109     /* Create the root object */
1110 
1111     AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp ();
1112     if (!AcpiGbl_ParseOpRoot)
1113     {
1114         return AE_NO_MEMORY;
1115     }
1116 
1117     /* Create and initialize a new walk state */
1118 
1119     WalkState = AcpiDsCreateWalkState (0,
1120                         AcpiGbl_ParseOpRoot, NULL, NULL);
1121     if (!WalkState)
1122     {
1123         return (AE_NO_MEMORY);
1124     }
1125 
1126     Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot,
1127                 NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
1128     if (ACPI_FAILURE (Status))
1129     {
1130         return (Status);
1131     }
1132 
1133     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
1134     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
1135 
1136     Status = AcpiPsParseAml (WalkState);
1137     if (ACPI_FAILURE (Status))
1138     {
1139         return Status;
1140     }
1141 
1142     /* If LoadTable is FALSE, we are parsing the last loaded table */
1143 
1144     TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1;
1145 
1146     /* Pass 2 */
1147 
1148     if (LoadTable)
1149     {
1150         Status = AcpiTbStoreTable ((ACPI_PHYSICAL_ADDRESS) Table, Table,
1151                     Table->Length, ACPI_TABLE_ORIGIN_ALLOCATED, &TableIndex);
1152         if (ACPI_FAILURE (Status))
1153         {
1154             return Status;
1155         }
1156         Status = AcpiTbAllocateOwnerId (TableIndex);
1157         if (ACPI_FAILURE (Status))
1158         {
1159             return Status;
1160         }
1161         if (OwnerId)
1162         {
1163             Status = AcpiTbGetOwnerId (TableIndex, OwnerId);
1164             if (ACPI_FAILURE (Status))
1165             {
1166                 return Status;
1167             }
1168         }
1169     }
1170 
1171     fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
1172 
1173     Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL);
1174     if (ACPI_FAILURE (Status))
1175     {
1176         return (Status);
1177     }
1178 
1179     /* No need to parse control methods of external table */
1180 
1181     if (External)
1182     {
1183         return AE_OK;
1184     }
1185 
1186     /* Pass 3: Parse control methods and link their parse trees into the main parse tree */
1187 
1188     Status = AdParseDeferredOps (AcpiGbl_ParseOpRoot);
1189 
1190     /* Process Resource Templates */
1191 
1192     AcpiDmFindResources (AcpiGbl_ParseOpRoot);
1193 
1194     fprintf (stderr, "Parsing completed\n");
1195     return AE_OK;
1196 }
1197 
1198 
1199