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