xref: /freebsd/sys/contrib/dev/acpica/common/adisasm.c (revision 090bc474c990f2be7db7660523576361508ef36d)
1 /******************************************************************************
2  *
3  * Module Name: adisasm - Application-level disassembler routines
4  *              $Revision: 64 $
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2004, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 
117 
118 #include "acpi.h"
119 #include "acparser.h"
120 #include "amlcode.h"
121 #include "acdebug.h"
122 #include "acdisasm.h"
123 #include "acdispat.h"
124 #include "acnamesp.h"
125 #include "acapps.h"
126 
127 #include <stdio.h>
128 #include <string.h>
129 #include <time.h>
130 
131 
132 #define _COMPONENT          ACPI_TOOLS
133         ACPI_MODULE_NAME    ("adisasm")
134 
135 
136 ACPI_PARSE_OBJECT       *AcpiGbl_ParsedNamespaceRoot;
137 
138 
139 #ifndef _ACPI_ASL_COMPILER
140 BOOLEAN
141 AcpiDsIsResultUsed (
142     ACPI_PARSE_OBJECT       *Op,
143     ACPI_WALK_STATE         *WalkState)
144 {
145     return TRUE;
146 }
147 #endif
148 
149 
150 ACPI_STATUS
151 AcpiDsRestartControlMethod (
152     ACPI_WALK_STATE         *WalkState,
153     ACPI_OPERAND_OBJECT     *ReturnDesc)
154 {
155     return (AE_OK);
156 }
157 
158 ACPI_STATUS
159 AcpiDsTerminateControlMethod (
160     ACPI_WALK_STATE         *WalkState)
161 {
162     return (AE_OK);
163 }
164 
165 ACPI_STATUS
166 AcpiDsCallControlMethod (
167     ACPI_THREAD_STATE       *Thread,
168     ACPI_WALK_STATE         *WalkState,
169     ACPI_PARSE_OBJECT       *Op)
170 {
171     return (AE_OK);
172 }
173 
174 ACPI_STATUS
175 AcpiDsMethodDataInitArgs (
176     ACPI_OPERAND_OBJECT     **Params,
177     UINT32                  MaxParamCount,
178     ACPI_WALK_STATE         *WalkState)
179 {
180     return (AE_OK);
181 }
182 
183 
184 #define FILE_SUFFIX_DISASSEMBLY     "dsl"
185 #define ACPI_TABLE_FILE_SUFFIX      ".dat"
186 char                        FilenameBuf[20];
187 
188 /******************************************************************************
189  *
190  * FUNCTION:    AfGenerateFilename
191  *
192  * PARAMETERS:
193  *
194  * RETURN:
195  *
196  * DESCRIPTION: Build an output filename from an ACPI table ID string
197  *
198  ******************************************************************************/
199 
200 char *
201 AdGenerateFilename (
202     char                    *Prefix,
203     char                    *TableId)
204 {
205     ACPI_NATIVE_UINT         i;
206     ACPI_NATIVE_UINT         j;
207 
208 
209     for (i = 0; Prefix[i]; i++)
210     {
211         FilenameBuf[i] = Prefix[i];
212     }
213 
214     FilenameBuf[i] = '_';
215     i++;
216 
217     for (j = 0; j < 8 && (TableId[j] != ' ') && (TableId[j] != 0); i++, j++)
218     {
219         FilenameBuf[i] = TableId[j];
220     }
221 
222     FilenameBuf[i] = 0;
223     strcat (FilenameBuf, ACPI_TABLE_FILE_SUFFIX);
224     return FilenameBuf;
225 }
226 
227 
228 /******************************************************************************
229  *
230  * FUNCTION:    AfWriteBuffer
231  *
232  * PARAMETERS:
233  *
234  * RETURN:
235  *
236  * DESCRIPTION: Open a file and write out a single buffer
237  *
238  ******************************************************************************/
239 
240 ACPI_NATIVE_INT
241 AdWriteBuffer (
242     char                *Filename,
243     char                *Buffer,
244     UINT32              Length)
245 {
246     FILE                *fp;
247     ACPI_NATIVE_INT     Actual;
248 
249 
250     fp = fopen (Filename, "wb");
251     if (!fp)
252     {
253         printf ("Couldn't open %s\n", Filename);
254         return -1;
255     }
256 
257     Actual = fwrite (Buffer, (size_t) Length, 1, fp);
258     fclose (fp);
259     return Actual;
260 }
261 
262 
263 /******************************************************************************
264  *
265  * FUNCTION:    AfWriteTable
266  *
267  * PARAMETERS:
268  *
269  * RETURN:
270  *
271  * DESCRIPTION: Dump the loaded tables to a file (or files)
272  *
273  ******************************************************************************/
274 
275 void
276 AdWriteTable (
277     ACPI_TABLE_HEADER       *Table,
278     UINT32                  Length,
279     char                    *TableName,
280     char                    *OemTableId)
281 {
282     char                    *Filename;
283 
284 
285     Filename = AdGenerateFilename (TableName, OemTableId);
286     AdWriteBuffer (Filename, (char *) Table, Length);
287 
288     AcpiOsPrintf ("Table [%s] written to \"%s\"\n", TableName, Filename);
289 }
290 
291 
292 /*******************************************************************************
293  *
294  * FUNCTION:    AdInitialize
295  *
296  * PARAMETERS:  None.
297  *
298  * RETURN:      Status
299  *
300  * DESCRIPTION: CA initialization
301  *
302  ******************************************************************************/
303 
304 ACPI_STATUS
305 AdInitialize (
306     void)
307 {
308     ACPI_STATUS             Status;
309 
310 
311     /* ACPI CA subsystem initialization */
312 
313     AcpiUtInitGlobals ();
314     Status = AcpiUtMutexInitialize ();
315     if (ACPI_FAILURE (Status))
316     {
317         return Status;
318     }
319 
320     Status = AcpiNsRootInitialize ();
321     return Status;
322 }
323 
324 
325 /*******************************************************************************
326  *
327  * FUNCTION:    FlGenerateFilename
328  *
329  * PARAMETERS:  InputFilename       - Original ASL source filename
330  *              Suffix              - New extension.
331  *
332  * RETURN:      New filename containing the original base + the new suffix
333  *
334  * DESCRIPTION: Generate a new filename from the ASL source filename and a new
335  *              extension.  Used to create the *.LST, *.TXT, etc. files.
336  *
337  ******************************************************************************/
338 
339 char *
340 FlGenerateFilename (
341     char                    *InputFilename,
342     char                    *Suffix)
343 {
344     char                    *Position;
345     char                    *NewFilename;
346 
347 
348     /* Copy the original filename to a new buffer */
349 
350     NewFilename = ACPI_MEM_CALLOCATE (strlen (InputFilename) + strlen (Suffix));
351     strcpy (NewFilename, InputFilename);
352 
353     /* Try to find the last dot in the filename */
354 
355     Position = strrchr (NewFilename, '.');
356     if (Position)
357     {
358         /* Tack on the new suffix */
359 
360         Position++;
361         *Position = 0;
362         strcat (Position, Suffix);
363     }
364     else
365     {
366         /* No dot, add one and then the suffix */
367 
368         strcat (NewFilename, ".");
369         strcat (NewFilename, Suffix);
370     }
371 
372     return NewFilename;
373 }
374 
375 
376 /*******************************************************************************
377  *
378  * FUNCTION:    FlSplitInputPathname
379  *
380  * PARAMETERS:  InputFilename       - The user-specified ASL source file to be
381  *                                    compiled
382  *
383  * RETURN:      Status
384  *
385  * DESCRIPTION: Split the input path into a directory and filename part
386  *              1) Directory part used to open include files
387  *              2) Filename part used to generate output filenames
388  *
389  ******************************************************************************/
390 
391 ACPI_STATUS
392 FlSplitInputPathname (
393     char                    *InputPath,
394     char                    **OutDirectoryPath,
395     char                    **OutFilename)
396 {
397     char                    *Substring;
398     char                    *DirectoryPath;
399     char                    *Filename;
400 
401 
402     *OutDirectoryPath = NULL;
403     *OutFilename = NULL;
404 
405     if (!InputPath)
406     {
407         return (AE_OK);
408     }
409 
410     /* Get the path to the input filename's directory */
411 
412     DirectoryPath = strdup (InputPath);
413     if (!DirectoryPath)
414     {
415         return (AE_NO_MEMORY);
416     }
417 
418     Substring = strrchr (DirectoryPath, '\\');
419     if (!Substring)
420     {
421         Substring = strrchr (DirectoryPath, '/');
422         if (!Substring)
423         {
424             Substring = strrchr (DirectoryPath, ':');
425         }
426     }
427 
428     if (!Substring)
429     {
430         DirectoryPath[0] = 0;
431         Filename = strdup (InputPath);
432     }
433     else
434     {
435         Filename = strdup (Substring + 1);
436         *(Substring+1) = 0;
437     }
438 
439     if (!Filename)
440     {
441         return (AE_NO_MEMORY);
442     }
443 
444     *OutDirectoryPath = DirectoryPath;
445     *OutFilename = Filename;
446 
447     return (AE_OK);
448 }
449 
450 
451 /******************************************************************************
452  *
453  * FUNCTION:    AdAmlDisassemble
454  *
455  * PARAMETERS:  OutToFile       - TRUE if output should go to a file
456  *              Filename        - AML input filename
457  *
458  * RETURN:      Status
459  *
460  * DESCRIPTION: Disassemble an entire ACPI table
461  *
462  *****************************************************************************/
463 
464 ACPI_STATUS
465 AdAmlDisassemble (
466     BOOLEAN                 OutToFile,
467     char                    *Filename,
468     char                    *Prefix,
469     char                    **OutFilename,
470     BOOLEAN                 GetAllTables)
471 {
472     ACPI_STATUS             Status;
473     char                    *DisasmFilename = NULL;
474     FILE                    *File = NULL;
475     ACPI_TABLE_HEADER       *Table;
476 
477 
478     /*
479      * Input:  AML Code from either a file,
480      *         or via GetTables (memory or registry)
481      */
482     if (Filename)
483     {
484         Status = AcpiDbGetTableFromFile (Filename, &Table);
485         if (ACPI_FAILURE (Status))
486         {
487             return Status;
488         }
489     }
490     else
491     {
492         Status = AdGetLocalTables (Filename, GetAllTables);
493         if (ACPI_FAILURE (Status))
494         {
495             AcpiOsPrintf ("Could not get ACPI tables, %s\n",
496                 AcpiFormatException (Status));
497             return Status;
498         }
499 
500         if (!AcpiGbl_DbOpt_disasm)
501         {
502             return AE_OK;
503         }
504 
505         /* Obtained the local tables, just disassmeble the DSDT */
506 
507         Table = AcpiGbl_DSDT;
508         AcpiOsPrintf ("\nDisassembly of DSDT\n");
509         Prefix = AdGenerateFilename ("dsdt", AcpiGbl_DSDT->OemTableId);
510     }
511 
512     /*
513      * Output:  ASL code.
514      *          Redirect to a file if requested
515      */
516     if (OutToFile)
517     {
518         /* Create/Open a disassembly output file */
519 
520         DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
521         if (!OutFilename)
522         {
523             fprintf (stderr, "Could not generate output filename\n");
524             Status = AE_ERROR;
525             goto Cleanup;
526         }
527 
528         File = fopen (DisasmFilename, "w+");
529         if (!File)
530         {
531             fprintf (stderr, "Could not open output file\n");
532             Status = AE_ERROR;
533             goto Cleanup;
534         }
535 
536         AcpiOsRedirectOutput (File);
537     }
538 
539     *OutFilename = DisasmFilename;
540 
541     /* Always parse the tables, only option is what to display */
542 
543     Status = AdParseTable (Table);
544     if (ACPI_FAILURE (Status))
545     {
546         AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
547             AcpiFormatException (Status));
548         goto Cleanup;
549     }
550 
551     /* Optional displays */
552 
553     if (AcpiGbl_DbOpt_disasm)
554     {
555         AdDisplayTables (Filename, Table);
556         fprintf (stderr, "Disassembly completed, written to \"%s\"\n", DisasmFilename);
557     }
558 
559 Cleanup:
560     if (OutToFile)
561     {
562         fclose (File);
563         AcpiOsRedirectOutput (stdout);
564     }
565 
566     AcpiPsDeleteParseTree (AcpiGbl_ParsedNamespaceRoot);
567     return Status;
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 ACPI CA signon with
581  *              current time and date.
582  *
583  *****************************************************************************/
584 
585 void
586 AdCreateTableHeader (
587     char                    *Filename,
588     ACPI_TABLE_HEADER       *Table)
589 {
590     time_t                  Timer;
591 
592 
593     time (&Timer);
594 
595     AcpiOsPrintf ("/*\n * Intel ACPI Component Architecture\n");
596     AcpiOsPrintf (" * AML Disassembler version %8.8X\n", ACPI_CA_VERSION);
597     AcpiOsPrintf (" *\n * Disassembly of %s, %s */\n", Filename, ctime (&Timer));
598 
599     AcpiOsPrintf (
600         "DefinitionBlock (\"%4.4s.aml\", \"%4.4s\", %hd, \"%.6s\", \"%.8s\", %u)\n",
601         Table->Signature, Table->Signature, Table->Revision,
602         Table->OemId, Table->OemTableId, Table->OemRevision);
603 }
604 
605 
606 /******************************************************************************
607  *
608  * FUNCTION:    AdDisplayTables
609  *
610  * PARAMETERS:  Filename            - Input file for the table
611  *
612  * RETURN:      Status
613  *
614  * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
615  *
616  *****************************************************************************/
617 
618 ACPI_STATUS
619 AdDisplayTables (
620     char                    *Filename,
621     ACPI_TABLE_HEADER       *Table)
622 {
623 
624 
625     if (!AcpiGbl_ParsedNamespaceRoot)
626     {
627         return AE_NOT_EXIST;
628     }
629 
630     if (!AcpiGbl_DbOpt_verbose)
631     {
632         AdCreateTableHeader (Filename, Table);
633     }
634 
635     AcpiDmDisassemble (NULL, AcpiGbl_ParsedNamespaceRoot, ACPI_UINT32_MAX);
636 
637     if (AcpiGbl_DbOpt_verbose)
638     {
639         AcpiOsPrintf ("\n\nTable Header:\n");
640         AcpiUtDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
641             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
642 
643         AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
644         AcpiUtDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)), Table->Length,
645             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
646     }
647 
648     return AE_OK;
649 }
650 
651 
652 /******************************************************************************
653  *
654  * FUNCTION:    AdDeferredParse
655  *
656  * PARAMETERS:  Op              - Root Op of the deferred opcode
657  *              Aml             - Pointer to the raw AML
658  *              AmlLength       - Length of the AML
659  *
660  * RETURN:      Status
661  *
662  * DESCRIPTION: Parse one deferred opcode
663  *              (Methods, operation regions, etc.)
664  *
665  *****************************************************************************/
666 
667 ACPI_STATUS
668 AdDeferredParse (
669     ACPI_PARSE_OBJECT       *Op,
670     UINT8                   *Aml,
671     UINT32                  AmlLength)
672 {
673     ACPI_WALK_STATE         *WalkState;
674     ACPI_STATUS             Status;
675     ACPI_PARSE_OBJECT       *SearchOp;
676     ACPI_PARSE_OBJECT       *StartOp;
677     UINT32                  BaseAmlOffset;
678     ACPI_PARSE_OBJECT       *ExtraOp;
679 
680 
681     ACPI_FUNCTION_TRACE ("AdDeferredParse");
682 
683 
684     fprintf (stderr, ".");
685 
686     if (!Aml || !AmlLength)
687     {
688         return_ACPI_STATUS (AE_OK);
689     }
690 
691     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing %s [%4.4s]\n",
692         Op->Common.AmlOpName, (char *) &Op->Named.Name));
693 
694     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
695     if (!WalkState)
696     {
697         return_ACPI_STATUS (AE_NO_MEMORY);
698     }
699 
700     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml,
701                     AmlLength, NULL, NULL, 1);
702     if (ACPI_FAILURE (Status))
703     {
704         return_ACPI_STATUS (Status);
705     }
706 
707     /* Parse the method */
708 
709     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
710     Status = AcpiPsParseAml (WalkState);
711 
712     /*
713      * We need to update all of the Aml offsets, since the parser thought
714      * that the method began at offset zero.  In reality, it began somewhere
715      * within the ACPI table, at the BaseAmlOffset.  Walk the entire tree that
716      * was just created and update the AmlOffset in each Op
717      */
718     BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1;
719     StartOp = (Op->Common.Value.Arg)->Common.Next;
720     SearchOp = StartOp;
721 
722     /* Walk the parse tree */
723 
724     while (SearchOp)
725     {
726         SearchOp->Common.AmlOffset += BaseAmlOffset;
727         SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
728     }
729 
730     /*
731      * Link the newly parsed subtree into the main parse tree
732      */
733     switch (Op->Common.AmlOpcode)
734     {
735     case AML_BUFFER_OP:
736     case AML_PACKAGE_OP:
737     case AML_VAR_PACKAGE_OP:
738 
739         switch (Op->Common.AmlOpcode)
740         {
741         case AML_PACKAGE_OP:
742         case AML_VAR_PACKAGE_OP:
743             ExtraOp = Op->Common.Value.Arg;
744             ExtraOp = ExtraOp->Common.Next;
745             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
746             break;
747 
748         case AML_BUFFER_OP:
749         default:
750             ExtraOp = Op->Common.Value.Arg;
751             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
752             break;
753         }
754 
755         /* Must point all parents to the main tree */
756 
757         StartOp = Op;
758         SearchOp = StartOp;
759         while (SearchOp)
760         {
761             if (SearchOp->Common.Parent == ExtraOp)
762             {
763                 SearchOp->Common.Parent = Op;
764             }
765             SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
766         }
767         break;
768 
769     default:
770         break;
771     }
772 
773     return_ACPI_STATUS (AE_OK);
774 }
775 
776 
777 /******************************************************************************
778  *
779  * FUNCTION:    AdParseDeferredOps
780  *
781  * PARAMETERS:  Root            - Root of the parse tree
782  *
783  * RETURN:      Status
784  *
785  * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.)
786  *
787  *****************************************************************************/
788 
789 ACPI_STATUS
790 AdParseDeferredOps (
791     ACPI_PARSE_OBJECT       *Root)
792 {
793     ACPI_PARSE_OBJECT       *Op = Root;
794     ACPI_STATUS             Status = AE_OK;
795     const ACPI_OPCODE_INFO  *OpInfo;
796 
797 
798     ACPI_FUNCTION_NAME ("AdParseDeferredOps");
799     fprintf (stderr, "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
800 
801     while (Op)
802     {
803         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
804         if (!(OpInfo->Flags & AML_DEFER))
805         {
806             Op = AcpiPsGetDepthNext (Root, Op);
807             continue;
808         }
809 
810         switch (Op->Common.AmlOpcode)
811         {
812         case AML_METHOD_OP:
813         case AML_BUFFER_OP:
814         case AML_PACKAGE_OP:
815         case AML_VAR_PACKAGE_OP:
816 
817             Status = AdDeferredParse (Op, Op->Named.Data, Op->Named.Length);
818             if (ACPI_FAILURE (Status))
819             {
820                 return_ACPI_STATUS (Status);
821             }
822             break;
823 
824         case AML_REGION_OP:
825         case AML_CREATE_QWORD_FIELD_OP:
826         case AML_CREATE_DWORD_FIELD_OP:
827         case AML_CREATE_WORD_FIELD_OP:
828         case AML_CREATE_BYTE_FIELD_OP:
829         case AML_CREATE_BIT_FIELD_OP:
830         case AML_CREATE_FIELD_OP:
831 
832             /* Nothing to do in these cases */
833 
834             break;
835 
836         default:
837             ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unhandled deferred opcode [%s]\n",
838                 Op->Common.AmlOpName));
839             break;
840         }
841 
842         Op = AcpiPsGetDepthNext (Root, Op);
843     }
844 
845     fprintf (stderr, "\n");
846     return Status;
847 }
848 
849 
850 /******************************************************************************
851  *
852  * FUNCTION:    AdGetLocalTables
853  *
854  * PARAMETERS:
855  *
856  * RETURN:      None
857  *
858  * DESCRIPTION: Get the ACPI tables from either memory or a file
859  *
860  *****************************************************************************/
861 
862 ACPI_STATUS
863 AdGetLocalTables (
864     char                    *Filename,
865     BOOLEAN                 GetAllTables)
866 {
867     ACPI_STATUS             Status;
868     ACPI_TABLE_HEADER       TableHeader;
869     ACPI_TABLE_HEADER       *NewTable;
870     UINT32                  NumTables;
871     UINT32                  PointerSize;
872 
873 
874     if (GetAllTables)
875     {
876         ACPI_STRNCPY (TableHeader.Signature, RSDT_SIG, 4);
877         AcpiOsTableOverride (&TableHeader, &NewTable);
878         if (!NewTable)
879         {
880             fprintf (stderr, "Could not obtain RSDT\n");
881             return AE_NO_ACPI_TABLES;
882         }
883 
884 #if ACPI_MACHINE_WIDTH != 64
885 
886         if (!ACPI_STRNCMP (NewTable->Signature, RSDT_SIG, 4))
887         {
888             PointerSize = sizeof (UINT32);
889         }
890         else
891 #endif
892         {
893             PointerSize = sizeof (UINT64);
894         }
895 
896         /*
897          * Determine the number of tables pointed to by the RSDT/XSDT.
898          * This is defined by the ACPI Specification to be the number of
899          * pointers contained within the RSDT/XSDT.  The size of the pointers
900          * is architecture-dependent.
901          */
902         NumTables = (NewTable->Length - sizeof (ACPI_TABLE_HEADER)) / PointerSize;
903         AcpiOsPrintf ("There are %d tables defined in the %4.4s\n\n",
904             NumTables, NewTable->Signature);
905 
906         /* Get the FADT */
907 
908         ACPI_STRNCPY (TableHeader.Signature, FADT_SIG, 4);
909         AcpiOsTableOverride (&TableHeader, &NewTable);
910         if (NewTable)
911         {
912             AcpiGbl_FADT = (void *) NewTable;
913             AdWriteTable (NewTable, NewTable->Length,
914                 FADT_SIG, NewTable->OemTableId);
915         }
916         AcpiOsPrintf ("\n");
917 
918         /* Get the FACS */
919 
920         ACPI_STRNCPY (TableHeader.Signature, FACS_SIG, 4);
921         AcpiOsTableOverride (&TableHeader, &NewTable);
922         if (NewTable)
923         {
924             AcpiGbl_FACS = (void *) NewTable;
925             AdWriteTable (NewTable, AcpiGbl_FACS->Length,
926                 FACS_SIG, AcpiGbl_FADT->OemTableId);
927         }
928         AcpiOsPrintf ("\n");
929     }
930 
931     /* Always get the DSDT */
932 
933     ACPI_STRNCPY (TableHeader.Signature, DSDT_SIG, 4);
934     AcpiOsTableOverride (&TableHeader, &NewTable);
935     if (NewTable)
936     {
937         Status = AE_OK;
938         AcpiGbl_DSDT = NewTable;
939         AdWriteTable (AcpiGbl_DSDT, AcpiGbl_DSDT->Length,
940             "DSDT", AcpiGbl_DSDT->OemTableId);
941     }
942     else
943     {
944         fprintf (stderr, "Could not obtain DSDT\n");
945         return AE_NO_ACPI_TABLES;
946     }
947 
948     AcpiOsPrintf ("\n");
949 
950     /* Get all SSDTs */
951 
952     ACPI_STRNCPY (TableHeader.Signature, SSDT_SIG, 4);
953     Status = AcpiOsTableOverride (&TableHeader, &NewTable);
954     if (NewTable)
955     {
956         while (NewTable)
957         {
958             Status = AcpiOsTableOverride (&TableHeader, &NewTable);
959         }
960     }
961 
962 #ifdef _HPET
963     AfGetHpet ();
964 #endif
965 
966     return AE_OK;
967 }
968 
969 /******************************************************************************
970  *
971  * FUNCTION:    AdParseTable
972  *
973  * PARAMETERS:  None
974  *
975  * RETURN:      Status
976  *
977  * DESCRIPTION: Parse the DSDT.
978  *
979  *****************************************************************************/
980 
981 ACPI_STATUS
982 AdParseTable (
983     ACPI_TABLE_HEADER       *Table)
984 {
985     ACPI_STATUS             Status = AE_OK;
986     ACPI_WALK_STATE         *WalkState;
987     ACPI_TABLE_DESC         TableDesc;
988     UINT8                   *AmlStart;
989     UINT32                  AmlLength;
990 
991 
992     if (!Table)
993     {
994         return AE_NOT_EXIST;
995     }
996 
997     /* Pass 1:  Parse everything except control method bodies */
998 
999     fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
1000 
1001     AmlLength  = Table->Length  - sizeof (ACPI_TABLE_HEADER);
1002     AmlStart   = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
1003 
1004     /* Create the root object */
1005 
1006     AcpiGbl_ParsedNamespaceRoot = AcpiPsCreateScopeOp ();
1007     if (!AcpiGbl_ParsedNamespaceRoot)
1008     {
1009         return AE_NO_MEMORY;
1010     }
1011 
1012     /* Create and initialize a new walk state */
1013 
1014     WalkState = AcpiDsCreateWalkState (0,
1015                         AcpiGbl_ParsedNamespaceRoot, NULL, NULL);
1016     if (!WalkState)
1017     {
1018         return (AE_NO_MEMORY);
1019     }
1020 
1021     Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParsedNamespaceRoot,
1022                 NULL, AmlStart, AmlLength, NULL, NULL, 1);
1023     if (ACPI_FAILURE (Status))
1024     {
1025         return (Status);
1026     }
1027 
1028     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
1029 
1030     Status = AcpiPsParseAml (WalkState);
1031     if (ACPI_FAILURE (Status))
1032     {
1033         return Status;
1034     }
1035 
1036     /* Pass 2 */
1037 
1038     TableDesc.AmlStart = AmlStart;
1039     TableDesc.AmlLength = AmlLength;
1040     fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
1041 
1042     Status = AcpiNsOneCompleteParse (2, &TableDesc);
1043     if (ACPI_FAILURE (Status))
1044     {
1045         return (Status);
1046     }
1047 
1048     /* Pass 3: Parse control methods and link their parse trees into the main parse tree */
1049 
1050     Status = AdParseDeferredOps (AcpiGbl_ParsedNamespaceRoot);
1051 
1052     fprintf (stderr, "Parsing completed\n");
1053     return AE_OK;
1054 }
1055 
1056 
1057