Merge from vendor branch OPENSSH:
[dragonfly.git] / sys / contrib / dev / acpica-unix-20040527 / common / adisasm.c
1 /******************************************************************************
2  *
3  * Module Name: adisasm - Application-level disassembler routines
4  *              $Revision: 67 $
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 ACPI_STATUS
150 AcpiDsRestartControlMethod (
151     ACPI_WALK_STATE         *WalkState,
152     ACPI_OPERAND_OBJECT     *ReturnDesc)
153 {
154     return (AE_OK);
155 }
156
157 ACPI_STATUS
158 AcpiDsTerminateControlMethod (
159     ACPI_WALK_STATE         *WalkState)
160 {
161     return (AE_OK);
162 }
163
164 ACPI_STATUS
165 AcpiDsCallControlMethod (
166     ACPI_THREAD_STATE       *Thread,
167     ACPI_WALK_STATE         *WalkState,
168     ACPI_PARSE_OBJECT       *Op)
169 {
170     return (AE_OK);
171 }
172
173 ACPI_STATUS
174 AcpiDsMethodDataInitArgs (
175     ACPI_OPERAND_OBJECT     **Params,
176     UINT32                  MaxParamCount,
177     ACPI_WALK_STATE         *WalkState)
178 {
179     return (AE_OK);
180 }
181
182
183 #define FILE_SUFFIX_DISASSEMBLY     "dsl"
184 #define ACPI_TABLE_FILE_SUFFIX      ".dat"
185 char                        FilenameBuf[20];
186
187 /******************************************************************************
188  *
189  * FUNCTION:    AfGenerateFilename
190  *
191  * PARAMETERS:
192  *
193  * RETURN:
194  *
195  * DESCRIPTION: Build an output filename from an ACPI table ID string
196  *
197  ******************************************************************************/
198
199 char *
200 AdGenerateFilename (
201     char                    *Prefix,
202     char                    *TableId)
203 {
204     ACPI_NATIVE_UINT         i;
205     ACPI_NATIVE_UINT         j;
206
207
208     for (i = 0; Prefix[i]; i++)
209     {
210         FilenameBuf[i] = Prefix[i];
211     }
212
213     FilenameBuf[i] = '_';
214     i++;
215
216     for (j = 0; j < 8 && (TableId[j] != ' ') && (TableId[j] != 0); i++, j++)
217     {
218         FilenameBuf[i] = TableId[j];
219     }
220
221     FilenameBuf[i] = 0;
222     strcat (FilenameBuf, ACPI_TABLE_FILE_SUFFIX);
223     return FilenameBuf;
224 }
225
226
227 /******************************************************************************
228  *
229  * FUNCTION:    AfWriteBuffer
230  *
231  * PARAMETERS:
232  *
233  * RETURN:
234  *
235  * DESCRIPTION: Open a file and write out a single buffer
236  *
237  ******************************************************************************/
238
239 ACPI_NATIVE_INT
240 AdWriteBuffer (
241     char                *Filename,
242     char                *Buffer,
243     UINT32              Length)
244 {
245     FILE                *fp;
246     ACPI_NATIVE_INT     Actual;
247
248
249     fp = fopen (Filename, "wb");
250     if (!fp)
251     {
252         printf ("Couldn't open %s\n", Filename);
253         return -1;
254     }
255
256     Actual = fwrite (Buffer, (size_t) Length, 1, fp);
257     fclose (fp);
258     return Actual;
259 }
260
261
262 /******************************************************************************
263  *
264  * FUNCTION:    AfWriteTable
265  *
266  * PARAMETERS:
267  *
268  * RETURN:
269  *
270  * DESCRIPTION: Dump the loaded tables to a file (or files)
271  *
272  ******************************************************************************/
273
274 void
275 AdWriteTable (
276     ACPI_TABLE_HEADER       *Table,
277     UINT32                  Length,
278     char                    *TableName,
279     char                    *OemTableId)
280 {
281     char                    *Filename;
282
283
284     Filename = AdGenerateFilename (TableName, OemTableId);
285     AdWriteBuffer (Filename, (char *) Table, Length);
286
287     AcpiOsPrintf ("Table [%s] written to \"%s\"\n", TableName, Filename);
288 }
289
290
291 /*******************************************************************************
292  *
293  * FUNCTION:    AdInitialize
294  *
295  * PARAMETERS:  None.
296  *
297  * RETURN:      Status
298  *
299  * DESCRIPTION: CA initialization
300  *
301  ******************************************************************************/
302
303 ACPI_STATUS
304 AdInitialize (
305     void)
306 {
307     ACPI_STATUS             Status;
308
309
310     /* ACPI CA subsystem initialization */
311
312     AcpiUtInitGlobals ();
313     Status = AcpiUtMutexInitialize ();
314     if (ACPI_FAILURE (Status))
315     {
316         return Status;
317     }
318
319     Status = AcpiNsRootInitialize ();
320     return Status;
321 }
322
323
324 /*******************************************************************************
325  *
326  * FUNCTION:    FlGenerateFilename
327  *
328  * PARAMETERS:  InputFilename       - Original ASL source filename
329  *              Suffix              - New extension.
330  *
331  * RETURN:      New filename containing the original base + the new suffix
332  *
333  * DESCRIPTION: Generate a new filename from the ASL source filename and a new
334  *              extension.  Used to create the *.LST, *.TXT, etc. files.
335  *
336  ******************************************************************************/
337
338 char *
339 FlGenerateFilename (
340     char                    *InputFilename,
341     char                    *Suffix)
342 {
343     char                    *Position;
344     char                    *NewFilename;
345
346
347     /* Copy the original filename to a new buffer */
348
349     NewFilename = ACPI_MEM_CALLOCATE (strlen (InputFilename) + strlen (Suffix));
350     strcpy (NewFilename, InputFilename);
351
352     /* Try to find the last dot in the filename */
353
354     Position = strrchr (NewFilename, '.');
355     if (Position)
356     {
357         /* Tack on the new suffix */
358
359         Position++;
360         *Position = 0;
361         strcat (Position, Suffix);
362     }
363     else
364     {
365         /* No dot, add one and then the suffix */
366
367         strcat (NewFilename, ".");
368         strcat (NewFilename, Suffix);
369     }
370
371     return NewFilename;
372 }
373
374
375 /*******************************************************************************
376  *
377  * FUNCTION:    FlSplitInputPathname
378  *
379  * PARAMETERS:  InputFilename       - The user-specified ASL source file to be
380  *                                    compiled
381  *
382  * RETURN:      Status
383  *
384  * DESCRIPTION: Split the input path into a directory and filename part
385  *              1) Directory part used to open include files
386  *              2) Filename part used to generate output filenames
387  *
388  ******************************************************************************/
389
390 ACPI_STATUS
391 FlSplitInputPathname (
392     char                    *InputPath,
393     char                    **OutDirectoryPath,
394     char                    **OutFilename)
395 {
396     char                    *Substring;
397     char                    *DirectoryPath;
398     char                    *Filename;
399
400
401     *OutDirectoryPath = NULL;
402     *OutFilename = NULL;
403
404     if (!InputPath)
405     {
406         return (AE_OK);
407     }
408
409     /* Get the path to the input filename's directory */
410
411     DirectoryPath = strdup (InputPath);
412     if (!DirectoryPath)
413     {
414         return (AE_NO_MEMORY);
415     }
416
417     Substring = strrchr (DirectoryPath, '\\');
418     if (!Substring)
419     {
420         Substring = strrchr (DirectoryPath, '/');
421         if (!Substring)
422         {
423             Substring = strrchr (DirectoryPath, ':');
424         }
425     }
426
427     if (!Substring)
428     {
429         DirectoryPath[0] = 0;
430         Filename = strdup (InputPath);
431     }
432     else
433     {
434         Filename = strdup (Substring + 1);
435         *(Substring+1) = 0;
436     }
437
438     if (!Filename)
439     {
440         return (AE_NO_MEMORY);
441     }
442
443     *OutDirectoryPath = DirectoryPath;
444     *OutFilename = Filename;
445
446     return (AE_OK);
447 }
448
449
450 /******************************************************************************
451  *
452  * FUNCTION:    AdAmlDisassemble
453  *
454  * PARAMETERS:  OutToFile       - TRUE if output should go to a file
455  *              Filename        - AML input filename
456  *
457  * RETURN:      Status
458  *
459  * DESCRIPTION: Disassemble an entire ACPI table
460  *
461  *****************************************************************************/
462
463 ACPI_STATUS
464 AdAmlDisassemble (
465     BOOLEAN                 OutToFile,
466     char                    *Filename,
467     char                    *Prefix,
468     char                    **OutFilename,
469     BOOLEAN                 GetAllTables)
470 {
471     ACPI_STATUS             Status;
472     char                    *DisasmFilename = NULL;
473     FILE                    *File = NULL;
474     ACPI_TABLE_HEADER       *Table;
475
476
477     /*
478      * Input:  AML Code from either a file,
479      *         or via GetTables (memory or registry)
480      */
481     if (Filename)
482     {
483         Status = AcpiDbGetTableFromFile (Filename, &Table);
484         if (ACPI_FAILURE (Status))
485         {
486             return Status;
487         }
488     }
489     else
490     {
491         Status = AdGetLocalTables (Filename, GetAllTables);
492         if (ACPI_FAILURE (Status))
493         {
494             AcpiOsPrintf ("Could not get ACPI tables, %s\n",
495                 AcpiFormatException (Status));
496             return Status;
497         }
498
499         if (!AcpiGbl_DbOpt_disasm)
500         {
501             return AE_OK;
502         }
503
504         /* Obtained the local tables, just disassmeble the DSDT */
505
506         Table = AcpiGbl_DSDT;
507         AcpiOsPrintf ("\nDisassembly of DSDT\n");
508         Prefix = AdGenerateFilename ("dsdt", AcpiGbl_DSDT->OemTableId);
509     }
510
511     /*
512      * Output:  ASL code.
513      *          Redirect to a file if requested
514      */
515     if (OutToFile)
516     {
517         /* Create/Open a disassembly output file */
518
519         DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
520         if (!OutFilename)
521         {
522             fprintf (stderr, "Could not generate output filename\n");
523             Status = AE_ERROR;
524             goto Cleanup;
525         }
526
527         File = fopen (DisasmFilename, "w+");
528         if (!File)
529         {
530             fprintf (stderr, "Could not open output file\n");
531             Status = AE_ERROR;
532             goto Cleanup;
533         }
534
535         AcpiOsRedirectOutput (File);
536     }
537
538     *OutFilename = DisasmFilename;
539
540     /* Always parse the tables, only option is what to display */
541
542     Status = AdParseTable (Table);
543     if (ACPI_FAILURE (Status))
544     {
545         AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
546             AcpiFormatException (Status));
547         goto Cleanup;
548     }
549
550     /*
551      * TBD: We want to cross reference the namespace here, in order to
552      * generate External() statements.  The problem is that the parse
553      * tree is in run-time (interpreter) format, not compiler format,
554      * so we cannot directly use the function below:
555      *
556      *    Status = LkCrossReferenceNamespace ();
557      *
558      * We need to either convert the parse tree or create a new
559      * cross ref function that can handle interpreter parse trees
560      */
561
562     /* Optional displays */
563
564     if (AcpiGbl_DbOpt_disasm)
565     {
566         AdDisplayTables (Filename, Table);
567         fprintf (stderr, "Disassembly completed, written to \"%s\"\n", DisasmFilename);
568     }
569
570 Cleanup:
571     if (OutToFile)
572     {
573         fclose (File);
574         AcpiOsRedirectOutput (stdout);
575     }
576
577     AcpiPsDeleteParseTree (AcpiGbl_ParsedNamespaceRoot);
578     return Status;
579 }
580
581
582 /******************************************************************************
583  *
584  * FUNCTION:    AdCreateTableHeader
585  *
586  * PARAMETERS:  Filename            - Input file for the table
587  *              Table               - Pointer to the raw table
588  *
589  * RETURN:      None
590  *
591  * DESCRIPTION: Create the ASL table header, including ACPI CA signon with
592  *              current time and date.
593  *
594  *****************************************************************************/
595
596 void
597 AdCreateTableHeader (
598     char                    *Filename,
599     ACPI_TABLE_HEADER       *Table)
600 {
601     time_t                  Timer;
602
603
604     time (&Timer);
605
606     AcpiOsPrintf ("/*\n * Intel ACPI Component Architecture\n");
607     AcpiOsPrintf (" * AML Disassembler version %8.8X\n", ACPI_CA_VERSION);
608     AcpiOsPrintf (" *\n * Disassembly of %s, %s */\n", Filename, ctime (&Timer));
609
610     AcpiOsPrintf (
611         "DefinitionBlock (\"%4.4s.aml\", \"%4.4s\", %hd, \"%.6s\", \"%.8s\", %u)\n",
612         Table->Signature, Table->Signature, Table->Revision,
613         Table->OemId, Table->OemTableId, Table->OemRevision);
614 }
615
616
617 /******************************************************************************
618  *
619  * FUNCTION:    AdDisplayTables
620  *
621  * PARAMETERS:  Filename            - Input file for the table
622  *
623  * RETURN:      Status
624  *
625  * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
626  *
627  *****************************************************************************/
628
629 ACPI_STATUS
630 AdDisplayTables (
631     char                    *Filename,
632     ACPI_TABLE_HEADER       *Table)
633 {
634
635
636     if (!AcpiGbl_ParsedNamespaceRoot)
637     {
638         return AE_NOT_EXIST;
639     }
640
641     if (!AcpiGbl_DbOpt_verbose)
642     {
643         AdCreateTableHeader (Filename, Table);
644     }
645
646     AcpiDmDisassemble (NULL, AcpiGbl_ParsedNamespaceRoot, ACPI_UINT32_MAX);
647
648     if (AcpiGbl_DbOpt_verbose)
649     {
650         AcpiOsPrintf ("\n\nTable Header:\n");
651         AcpiUtDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
652             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
653
654         AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
655         AcpiUtDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)), Table->Length,
656             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
657     }
658
659     return AE_OK;
660 }
661
662
663 /******************************************************************************
664  *
665  * FUNCTION:    AdDeferredParse
666  *
667  * PARAMETERS:  Op              - Root Op of the deferred opcode
668  *              Aml             - Pointer to the raw AML
669  *              AmlLength       - Length of the AML
670  *
671  * RETURN:      Status
672  *
673  * DESCRIPTION: Parse one deferred opcode
674  *              (Methods, operation regions, etc.)
675  *
676  *****************************************************************************/
677
678 ACPI_STATUS
679 AdDeferredParse (
680     ACPI_PARSE_OBJECT       *Op,
681     UINT8                   *Aml,
682     UINT32                  AmlLength)
683 {
684     ACPI_WALK_STATE         *WalkState;
685     ACPI_STATUS             Status;
686     ACPI_PARSE_OBJECT       *SearchOp;
687     ACPI_PARSE_OBJECT       *StartOp;
688     UINT32                  BaseAmlOffset;
689     ACPI_PARSE_OBJECT       *ExtraOp;
690
691
692     ACPI_FUNCTION_TRACE ("AdDeferredParse");
693
694
695     fprintf (stderr, ".");
696
697     if (!Aml || !AmlLength)
698     {
699         return_ACPI_STATUS (AE_OK);
700     }
701
702     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing %s [%4.4s]\n",
703         Op->Common.AmlOpName, (char *) &Op->Named.Name));
704
705     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
706     if (!WalkState)
707     {
708         return_ACPI_STATUS (AE_NO_MEMORY);
709     }
710
711     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml,
712                     AmlLength, NULL, 1);
713     if (ACPI_FAILURE (Status))
714     {
715         return_ACPI_STATUS (Status);
716     }
717
718     /* Parse the method */
719
720     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
721     Status = AcpiPsParseAml (WalkState);
722
723     /*
724      * We need to update all of the Aml offsets, since the parser thought
725      * that the method began at offset zero.  In reality, it began somewhere
726      * within the ACPI table, at the BaseAmlOffset.  Walk the entire tree that
727      * was just created and update the AmlOffset in each Op
728      */
729     BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1;
730     StartOp = (Op->Common.Value.Arg)->Common.Next;
731     SearchOp = StartOp;
732
733     /* Walk the parse tree */
734
735     while (SearchOp)
736     {
737         SearchOp->Common.AmlOffset += BaseAmlOffset;
738         SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
739     }
740
741     /*
742      * Link the newly parsed subtree into the main parse tree
743      */
744     switch (Op->Common.AmlOpcode)
745     {
746     case AML_BUFFER_OP:
747     case AML_PACKAGE_OP:
748     case AML_VAR_PACKAGE_OP:
749
750         switch (Op->Common.AmlOpcode)
751         {
752         case AML_PACKAGE_OP:
753         case AML_VAR_PACKAGE_OP:
754             ExtraOp = Op->Common.Value.Arg;
755             ExtraOp = ExtraOp->Common.Next;
756             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
757             break;
758
759         case AML_BUFFER_OP:
760         default:
761             ExtraOp = Op->Common.Value.Arg;
762             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
763             break;
764         }
765
766         /* Must point all parents to the main tree */
767
768         StartOp = Op;
769         SearchOp = StartOp;
770         while (SearchOp)
771         {
772             if (SearchOp->Common.Parent == ExtraOp)
773             {
774                 SearchOp->Common.Parent = Op;
775             }
776             SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
777         }
778         break;
779
780     default:
781         break;
782     }
783
784     return_ACPI_STATUS (AE_OK);
785 }
786
787
788 /******************************************************************************
789  *
790  * FUNCTION:    AdParseDeferredOps
791  *
792  * PARAMETERS:  Root            - Root of the parse tree
793  *
794  * RETURN:      Status
795  *
796  * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.)
797  *
798  *****************************************************************************/
799
800 ACPI_STATUS
801 AdParseDeferredOps (
802     ACPI_PARSE_OBJECT       *Root)
803 {
804     ACPI_PARSE_OBJECT       *Op = Root;
805     ACPI_STATUS             Status = AE_OK;
806     const ACPI_OPCODE_INFO  *OpInfo;
807
808
809     ACPI_FUNCTION_NAME ("AdParseDeferredOps");
810     fprintf (stderr, "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
811
812     while (Op)
813     {
814         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
815         if (!(OpInfo->Flags & AML_DEFER))
816         {
817             Op = AcpiPsGetDepthNext (Root, Op);
818             continue;
819         }
820
821         switch (Op->Common.AmlOpcode)
822         {
823         case AML_METHOD_OP:
824         case AML_BUFFER_OP:
825         case AML_PACKAGE_OP:
826         case AML_VAR_PACKAGE_OP:
827
828             Status = AdDeferredParse (Op, Op->Named.Data, Op->Named.Length);
829             if (ACPI_FAILURE (Status))
830             {
831                 return_ACPI_STATUS (Status);
832             }
833             break;
834
835         case AML_REGION_OP:
836         case AML_CREATE_QWORD_FIELD_OP:
837         case AML_CREATE_DWORD_FIELD_OP:
838         case AML_CREATE_WORD_FIELD_OP:
839         case AML_CREATE_BYTE_FIELD_OP:
840         case AML_CREATE_BIT_FIELD_OP:
841         case AML_CREATE_FIELD_OP:
842
843             /* Nothing to do in these cases */
844
845             break;
846
847         default:
848             ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unhandled deferred opcode [%s]\n",
849                 Op->Common.AmlOpName));
850             break;
851         }
852
853         Op = AcpiPsGetDepthNext (Root, Op);
854     }
855
856     fprintf (stderr, "\n");
857     return Status;
858 }
859
860
861 /******************************************************************************
862  *
863  * FUNCTION:    AdGetLocalTables
864  *
865  * PARAMETERS:
866  *
867  * RETURN:      None
868  *
869  * DESCRIPTION: Get the ACPI tables from either memory or a file
870  *
871  *****************************************************************************/
872
873 ACPI_STATUS
874 AdGetLocalTables (
875     char                    *Filename,
876     BOOLEAN                 GetAllTables)
877 {
878     ACPI_STATUS             Status;
879     ACPI_TABLE_HEADER       TableHeader;
880     ACPI_TABLE_HEADER       *NewTable;
881     UINT32                  NumTables;
882     UINT32                  PointerSize;
883
884
885     if (GetAllTables)
886     {
887         ACPI_STRNCPY (TableHeader.Signature, RSDT_SIG, 4);
888         AcpiOsTableOverride (&TableHeader, &NewTable);
889         if (!NewTable)
890         {
891             fprintf (stderr, "Could not obtain RSDT\n");
892             return AE_NO_ACPI_TABLES;
893         }
894
895 #if ACPI_MACHINE_WIDTH != 64
896
897         if (!ACPI_STRNCMP (NewTable->Signature, RSDT_SIG, 4))
898         {
899             PointerSize = sizeof (UINT32);
900         }
901         else
902 #endif
903         {
904             PointerSize = sizeof (UINT64);
905         }
906
907         /*
908          * Determine the number of tables pointed to by the RSDT/XSDT.
909          * This is defined by the ACPI Specification to be the number of
910          * pointers contained within the RSDT/XSDT.  The size of the pointers
911          * is architecture-dependent.
912          */
913         NumTables = (NewTable->Length - sizeof (ACPI_TABLE_HEADER)) / PointerSize;
914         AcpiOsPrintf ("There are %d tables defined in the %4.4s\n\n",
915             NumTables, NewTable->Signature);
916
917         /* Get the FADT */
918
919         ACPI_STRNCPY (TableHeader.Signature, FADT_SIG, 4);
920         AcpiOsTableOverride (&TableHeader, &NewTable);
921         if (NewTable)
922         {
923             AcpiGbl_FADT = (void *) NewTable;
924             AdWriteTable (NewTable, NewTable->Length,
925                 FADT_SIG, NewTable->OemTableId);
926         }
927         AcpiOsPrintf ("\n");
928
929         /* Get the FACS */
930
931         ACPI_STRNCPY (TableHeader.Signature, FACS_SIG, 4);
932         AcpiOsTableOverride (&TableHeader, &NewTable);
933         if (NewTable)
934         {
935             AcpiGbl_FACS = (void *) NewTable;
936             AdWriteTable (NewTable, AcpiGbl_FACS->Length,
937                 FACS_SIG, AcpiGbl_FADT->OemTableId);
938         }
939         AcpiOsPrintf ("\n");
940     }
941
942     /* Always get the DSDT */
943
944     ACPI_STRNCPY (TableHeader.Signature, DSDT_SIG, 4);
945     AcpiOsTableOverride (&TableHeader, &NewTable);
946     if (NewTable)
947     {
948         Status = AE_OK;
949         AcpiGbl_DSDT = NewTable;
950         AdWriteTable (AcpiGbl_DSDT, AcpiGbl_DSDT->Length,
951             "DSDT", AcpiGbl_DSDT->OemTableId);
952     }
953     else
954     {
955         fprintf (stderr, "Could not obtain DSDT\n");
956         return AE_NO_ACPI_TABLES;
957     }
958
959     AcpiOsPrintf ("\n");
960
961     /* Get all SSDTs */
962
963     ACPI_STRNCPY (TableHeader.Signature, SSDT_SIG, 4);
964     Status = AcpiOsTableOverride (&TableHeader, &NewTable);
965     if (NewTable)
966     {
967         while (NewTable)
968         {
969             Status = AcpiOsTableOverride (&TableHeader, &NewTable);
970         }
971     }
972
973     return AE_OK;
974 }
975
976 /******************************************************************************
977  *
978  * FUNCTION:    AdParseTable
979  *
980  * PARAMETERS:  None
981  *
982  * RETURN:      Status
983  *
984  * DESCRIPTION: Parse the DSDT.
985  *
986  *****************************************************************************/
987
988 ACPI_STATUS
989 AdParseTable (
990     ACPI_TABLE_HEADER       *Table)
991 {
992     ACPI_STATUS             Status = AE_OK;
993     ACPI_WALK_STATE         *WalkState;
994     ACPI_TABLE_DESC         TableDesc;
995     UINT8                   *AmlStart;
996     UINT32                  AmlLength;
997
998
999     if (!Table)
1000     {
1001         return AE_NOT_EXIST;
1002     }
1003
1004     /* Pass 1:  Parse everything except control method bodies */
1005
1006     fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
1007
1008     AmlLength  = Table->Length  - sizeof (ACPI_TABLE_HEADER);
1009     AmlStart   = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
1010
1011     /* Create the root object */
1012
1013     AcpiGbl_ParsedNamespaceRoot = AcpiPsCreateScopeOp ();
1014     if (!AcpiGbl_ParsedNamespaceRoot)
1015     {
1016         return AE_NO_MEMORY;
1017     }
1018
1019     /* Create and initialize a new walk state */
1020
1021     WalkState = AcpiDsCreateWalkState (0,
1022                         AcpiGbl_ParsedNamespaceRoot, NULL, NULL);
1023     if (!WalkState)
1024     {
1025         return (AE_NO_MEMORY);
1026     }
1027
1028     Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParsedNamespaceRoot,
1029                 NULL, AmlStart, AmlLength, NULL, 1);
1030     if (ACPI_FAILURE (Status))
1031     {
1032         return (Status);
1033     }
1034
1035     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
1036
1037     Status = AcpiPsParseAml (WalkState);
1038     if (ACPI_FAILURE (Status))
1039     {
1040         return Status;
1041     }
1042
1043     /* Pass 2 */
1044
1045     TableDesc.AmlStart = AmlStart;
1046     TableDesc.AmlLength = AmlLength;
1047     fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
1048
1049     Status = AcpiNsOneCompleteParse (2, &TableDesc);
1050     if (ACPI_FAILURE (Status))
1051     {
1052         return (Status);
1053     }
1054
1055     /* Pass 3: Parse control methods and link their parse trees into the main parse tree */
1056
1057     Status = AdParseDeferredOps (AcpiGbl_ParsedNamespaceRoot);
1058
1059     fprintf (stderr, "Parsing completed\n");
1060     return AE_OK;
1061 }
1062
1063