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