]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - sys/contrib/dev/acpica/common/adisasm.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / sys / contrib / dev / acpica / common / adisasm.c
1 /******************************************************************************
2  *
3  * Module Name: adisasm - Application-level disassembler routines
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights.  You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code.  No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision.  In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change.  Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee.  Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution.  In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government.  In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115
116
117 #include <contrib/dev/acpica/include/acpi.h>
118 #include <contrib/dev/acpica/include/accommon.h>
119 #include <contrib/dev/acpica/include/acparser.h>
120 #include <contrib/dev/acpica/include/amlcode.h>
121 #include <contrib/dev/acpica/include/acdebug.h>
122 #include <contrib/dev/acpica/include/acdisasm.h>
123 #include <contrib/dev/acpica/include/acdispat.h>
124 #include <contrib/dev/acpica/include/acnamesp.h>
125 #include <contrib/dev/acpica/include/actables.h>
126 #include <contrib/dev/acpica/include/acapps.h>
127
128 #include <stdio.h>
129 #include <time.h>
130
131
132 #define _COMPONENT          ACPI_TOOLS
133         ACPI_MODULE_NAME    ("adisasm")
134
135 extern int                          AslCompilerdebug;
136
137 ACPI_STATUS
138 LsDisplayNamespace (
139     void);
140
141 void
142 LsSetupNsList (void * Handle);
143
144
145 /* Local prototypes */
146
147 void
148 AdCreateTableHeader (
149     char                    *Filename,
150     ACPI_TABLE_HEADER       *Table);
151
152 void
153 AdDisassemblerHeader (
154     char                    *Filename);
155
156 void
157 AdAddExternalsToNamespace (
158     void);
159
160 UINT32
161 AdMethodExternalCount (
162     void);
163
164 ACPI_STATUS
165 AdDeferredParse (
166     ACPI_PARSE_OBJECT       *Op,
167     UINT8                   *Aml,
168     UINT32                  AmlLength);
169
170 ACPI_STATUS
171 AdParseDeferredOps (
172     ACPI_PARSE_OBJECT       *Root);
173
174 ACPI_PARSE_OBJECT           *AcpiGbl_ParseOpRoot;
175
176
177 /* Stubs for ASL compiler */
178
179 #ifndef ACPI_ASL_COMPILER
180 BOOLEAN
181 AcpiDsIsResultUsed (
182     ACPI_PARSE_OBJECT       *Op,
183     ACPI_WALK_STATE         *WalkState)
184 {
185     return TRUE;
186 }
187
188 ACPI_STATUS
189 AcpiDsMethodError (
190     ACPI_STATUS             Status,
191     ACPI_WALK_STATE         *WalkState)
192 {
193     return (Status);
194 }
195
196 #endif
197
198 ACPI_STATUS
199 AcpiNsLoadTable (
200     UINT32                  TableIndex,
201     ACPI_NAMESPACE_NODE     *Node)
202 {
203     return (AE_NOT_IMPLEMENTED);
204 }
205
206 ACPI_STATUS
207 AcpiDsRestartControlMethod (
208     ACPI_WALK_STATE         *WalkState,
209     ACPI_OPERAND_OBJECT     *ReturnDesc)
210 {
211     return (AE_OK);
212 }
213
214 void
215 AcpiDsTerminateControlMethod (
216     ACPI_OPERAND_OBJECT     *MethodDesc,
217     ACPI_WALK_STATE         *WalkState)
218 {
219     return;
220 }
221
222 ACPI_STATUS
223 AcpiDsCallControlMethod (
224     ACPI_THREAD_STATE       *Thread,
225     ACPI_WALK_STATE         *WalkState,
226     ACPI_PARSE_OBJECT       *Op)
227 {
228     return (AE_OK);
229 }
230
231 ACPI_STATUS
232 AcpiDsMethodDataInitArgs (
233     ACPI_OPERAND_OBJECT     **Params,
234     UINT32                  MaxParamCount,
235     ACPI_WALK_STATE         *WalkState)
236 {
237     return (AE_OK);
238 }
239
240
241 ACPI_TABLE_DESC             LocalTables[1];
242
243
244 /*******************************************************************************
245  *
246  * FUNCTION:    AdInitialize
247  *
248  * PARAMETERS:  None.
249  *
250  * RETURN:      Status
251  *
252  * DESCRIPTION: CA initialization
253  *
254  ******************************************************************************/
255
256 ACPI_STATUS
257 AdInitialize (
258     void)
259 {
260     ACPI_STATUS             Status;
261
262
263     /* ACPI CA subsystem initialization */
264
265     Status = AcpiOsInitialize ();
266     if (ACPI_FAILURE (Status))
267     {
268         return (Status);
269     }
270
271     Status = AcpiUtInitGlobals ();
272     if (ACPI_FAILURE (Status))
273     {
274         return (Status);
275     }
276
277     Status = AcpiUtMutexInitialize ();
278     if (ACPI_FAILURE (Status))
279     {
280         return (Status);
281     }
282
283     Status = AcpiNsRootInitialize ();
284     if (ACPI_FAILURE (Status))
285     {
286         return (Status);
287     }
288
289     /* Setup the Table Manager (cheat - there is no RSDT) */
290
291     AcpiGbl_RootTableList.Size = 1;
292     AcpiGbl_RootTableList.Count = 0;
293     AcpiGbl_RootTableList.Tables = LocalTables;
294
295     return (Status);
296 }
297
298
299 /*******************************************************************************
300  *
301  * FUNCTION:    AdAddExternalsToNamespace
302  *
303  * PARAMETERS:
304  *
305  * RETURN:      None
306  *
307  * DESCRIPTION:
308  *
309  ******************************************************************************/
310
311 void
312 AdAddExternalsToNamespace (
313     void)
314 {
315     ACPI_STATUS             Status;
316     ACPI_NAMESPACE_NODE     *Node;
317     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
318     ACPI_OPERAND_OBJECT     *MethodDesc;
319
320
321     while (External)
322     {
323         Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
324                    ACPI_IMODE_LOAD_PASS1, ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
325                    NULL, &Node);
326
327         if (External->Type == ACPI_TYPE_METHOD)
328         {
329             MethodDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
330             MethodDesc->Method.ParamCount = (UINT8) External->Value;
331             Node->Object = MethodDesc;
332         }
333
334         External = External->Next;
335     }
336 }
337
338
339 /*******************************************************************************
340  *
341  * FUNCTION:    AdMethodExternalCount
342  *
343  * PARAMETERS:  None
344  *
345  * RETURN:      Status
346  *
347  * DESCRIPTION: Return the number of externals that have been generated
348  *
349  ******************************************************************************/
350
351 UINT32
352 AdMethodExternalCount (
353     void)
354 {
355     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
356     UINT32                  Count = 0;
357
358
359     while (External)
360     {
361         if (External->Type == ACPI_TYPE_METHOD)
362         {
363             Count++;
364         }
365
366         External = External->Next;
367     }
368
369     return (Count);
370 }
371
372
373 /******************************************************************************
374  *
375  * FUNCTION:    AdAmlDisassemble
376  *
377  * PARAMETERS:  Filename        - AML input filename
378  *              OutToFile       - TRUE if output should go to a file
379  *              Prefix          - Path prefix for output
380  *              OutFilename     - where the filename is returned
381  *              GetAllTables    - TRUE if all tables are desired
382  *
383  * RETURN:      Status
384  *
385  * DESCRIPTION: Disassemble an entire ACPI table
386  *
387  *****************************************************************************/
388
389 extern char *Gbl_ExternalFilename;
390
391 ACPI_STATUS
392 AdAmlDisassemble (
393     BOOLEAN                 OutToFile,
394     char                    *Filename,
395     char                    *Prefix,
396     char                    **OutFilename,
397     BOOLEAN                 GetAllTables)
398 {
399     ACPI_STATUS             Status;
400     char                    *DisasmFilename = NULL;
401     char                    *ExternalFilename;
402     FILE                    *File = NULL;
403     ACPI_TABLE_HEADER       *Table = NULL;
404     ACPI_TABLE_HEADER       *ExternalTable;
405     ACPI_OWNER_ID           OwnerId;
406     ACPI_EXTERNAL_LIST      *NextExternal;
407
408
409     /*
410      * Input: AML Code from either a file,
411      *        or via GetTables (memory or registry)
412      */
413     if (Filename)
414     {
415         Status = AcpiDbGetTableFromFile (Filename, &Table);
416         if (ACPI_FAILURE (Status))
417         {
418             return Status;
419         }
420
421         /*
422          * External filenames separated by commas
423          * Example: iasl -e file1,file2,file3 -d xxx.aml
424          */
425         if (Gbl_ExternalFilename)
426         {
427             ExternalFilename = strtok (Gbl_ExternalFilename, ",");
428
429             while (ExternalFilename)
430             {
431                 Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable);
432                 if (ACPI_FAILURE (Status))
433                 {
434                     return Status;
435                 }
436
437                 /* Load external table for symbol resolution */
438
439                 if (ExternalTable)
440                 {
441                     Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE);
442                     if (ACPI_FAILURE (Status))
443                     {
444                         AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
445                             AcpiFormatException (Status));
446                         return Status;
447                     }
448
449                     /*
450                      * Load namespace from names created within control methods
451                      * Set owner id of nodes in external table
452                      */
453                     AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
454                         AcpiGbl_RootNode, OwnerId);
455                     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
456                 }
457
458                 /* Next external file name */
459
460                 ExternalFilename = strtok (NULL, ",");
461             }
462
463             /* Clear external list generated by Scope in external tables */
464
465             while (AcpiGbl_ExternalList)
466             {
467                 NextExternal = AcpiGbl_ExternalList->Next;
468                 ACPI_FREE (AcpiGbl_ExternalList->Path);
469                 ACPI_FREE (AcpiGbl_ExternalList);
470                 AcpiGbl_ExternalList = NextExternal;
471             }
472         }
473     }
474     else
475     {
476         Status = AdGetLocalTables (Filename, GetAllTables);
477         if (ACPI_FAILURE (Status))
478         {
479             AcpiOsPrintf ("Could not get ACPI tables, %s\n",
480                 AcpiFormatException (Status));
481             return Status;
482         }
483
484         if (!AcpiGbl_DbOpt_disasm)
485         {
486             return AE_OK;
487         }
488
489         /* Obtained the local tables, just disassemble the DSDT */
490
491         Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
492         if (ACPI_FAILURE (Status))
493         {
494             AcpiOsPrintf ("Could not get DSDT, %s\n",
495                 AcpiFormatException (Status));
496             return Status;
497         }
498
499         AcpiOsPrintf ("\nDisassembly of DSDT\n");
500         Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
501     }
502
503     /*
504      * Output:  ASL code.
505      *          Redirect to a file if requested
506      */
507     if (OutToFile)
508     {
509         /* Create/Open a disassembly output file */
510
511         DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
512         if (!OutFilename)
513         {
514             fprintf (stderr, "Could not generate output filename\n");
515             Status = AE_ERROR;
516             goto Cleanup;
517         }
518
519         File = fopen (DisasmFilename, "w+");
520         if (!File)
521         {
522             fprintf (stderr, "Could not open output file %s\n", DisasmFilename);
523             Status = AE_ERROR;
524             goto Cleanup;
525         }
526
527         AcpiOsRedirectOutput (File);
528     }
529
530     *OutFilename = DisasmFilename;
531
532     if (!AcpiUtIsAmlTable (Table))
533     {
534         AdDisassemblerHeader (Filename);
535         AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
536             Table->Signature);
537         AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue\n */\n\n");
538
539         AcpiDmDumpDataTable (Table);
540         fprintf (stderr, "Acpi Data Table [%4.4s] decoded, written to \"%s\"\n",
541             Table->Signature, DisasmFilename);
542     }
543     else
544     {
545         /* Always parse the tables, only option is what to display */
546
547         Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
548         if (ACPI_FAILURE (Status))
549         {
550             AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
551                 AcpiFormatException (Status));
552             goto Cleanup;
553         }
554
555         if (AslCompilerdebug)
556         {
557             AcpiOsPrintf ("/**** Before second load\n");
558
559             LsSetupNsList (File);
560             LsDisplayNamespace ();
561             AcpiOsPrintf ("*****/\n");
562         }
563
564         /*
565          * Load namespace from names created within control methods
566          */
567         AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId);
568
569         /*
570          * Cross reference the namespace here, in order to generate External() statements
571          */
572         AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId);
573
574         if (AslCompilerdebug)
575         {
576             AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
577         }
578
579         /* Find possible calls to external control methods */
580
581         AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
582
583         /* Convert fixed-offset references to resource descriptors to symbolic references */
584
585         AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
586
587         /*
588          * If we found any external control methods, we must reparse the entire
589          * tree with the new information (namely, the number of arguments per
590          * method)
591          */
592         if (AdMethodExternalCount ())
593         {
594             fprintf (stderr,
595                 "\nFound %d external control methods, reparsing with new information\n",
596                 AdMethodExternalCount());
597
598             /*
599              * Reparse, rebuild namespace. no need to xref namespace
600              */
601             AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
602             AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
603
604             AcpiGbl_RootNode                    = NULL;
605             AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
606             AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
607             AcpiGbl_RootNodeStruct.Type         = ACPI_TYPE_DEVICE;
608             AcpiGbl_RootNodeStruct.Child        = NULL;
609             AcpiGbl_RootNodeStruct.Peer         = NULL;
610             AcpiGbl_RootNodeStruct.Object       = NULL;
611             AcpiGbl_RootNodeStruct.Flags        = ANOBJ_END_OF_PEER_LIST;
612
613             Status = AcpiNsRootInitialize ();
614             AdAddExternalsToNamespace ();
615
616             /* Parse table. No need to reload it, however (FALSE) */
617
618             Status = AdParseTable (Table, NULL, FALSE, FALSE);
619             if (ACPI_FAILURE (Status))
620             {
621                 AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
622                     AcpiFormatException (Status));
623                 goto Cleanup;
624             }
625
626             if (AslCompilerdebug)
627             {
628                 AcpiOsPrintf ("/**** After second load and resource conversion\n");
629                 LsSetupNsList (File);
630                 LsDisplayNamespace ();
631                 AcpiOsPrintf ("*****/\n");
632
633                 AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
634             }
635         }
636
637         /* Optional displays */
638
639         if (AcpiGbl_DbOpt_disasm)
640         {
641             AdDisplayTables (Filename, Table);
642             fprintf (stderr,
643                 "Disassembly completed, written to \"%s\"\n",
644                 DisasmFilename);
645         }
646     }
647
648 Cleanup:
649
650     if (Table && !AcpiUtIsAmlTable (Table))
651     {
652         ACPI_FREE (Table);
653     }
654
655     if (DisasmFilename)
656     {
657         ACPI_FREE (DisasmFilename);
658     }
659
660     if (OutToFile && File)
661     {
662
663 #ifdef ASL_DISASM_DEBUG
664         LsSetupNsList (File);
665         LsDisplayNamespace ();
666 #endif
667         fclose (File);
668         AcpiOsRedirectOutput (stdout);
669     }
670
671     AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
672     AcpiGbl_ParseOpRoot = NULL;
673     return (Status);
674 }
675
676
677 /******************************************************************************
678  *
679  * FUNCTION:    AdDisassemblerHeader
680  *
681  * PARAMETERS:  Filename            - Input file for the table
682  *
683  * RETURN:      None
684  *
685  * DESCRIPTION: Create the disassembler header, including ACPI CA signon with
686  *              current time and date.
687  *
688  *****************************************************************************/
689
690 void
691 AdDisassemblerHeader (
692     char                    *Filename)
693 {
694     time_t                  Timer;
695
696     time (&Timer);
697
698     /* Header and input table info */
699
700     AcpiOsPrintf ("/*\n * Intel ACPI Component Architecture\n");
701     AcpiOsPrintf (" * AML Disassembler version %8.8X\n", ACPI_CA_VERSION);
702
703     AcpiOsPrintf (" *\n * Disassembly of %s, %s", Filename, ctime (&Timer));
704     AcpiOsPrintf (" *\n");
705 }
706
707
708 /******************************************************************************
709  *
710  * FUNCTION:    AdCreateTableHeader
711  *
712  * PARAMETERS:  Filename            - Input file for the table
713  *              Table               - Pointer to the raw table
714  *
715  * RETURN:      None
716  *
717  * DESCRIPTION: Create the ASL table header, including ACPI CA signon with
718  *              current time and date.
719  *
720  *****************************************************************************/
721
722 void
723 AdCreateTableHeader (
724     char                    *Filename,
725     ACPI_TABLE_HEADER       *Table)
726 {
727     char                    *NewFilename;
728     UINT8                   Checksum;
729
730
731     /*
732      * Print file header and dump original table header
733      */
734     AdDisassemblerHeader (Filename);
735
736     AcpiOsPrintf (" *\n * Original Table Header:\n");
737     AcpiOsPrintf (" *     Signature        \"%4.4s\"\n",    Table->Signature);
738     AcpiOsPrintf (" *     Length           0x%8.8X (%u)\n", Table->Length, Table->Length);
739
740     /* Print and validate the revision */
741
742     AcpiOsPrintf (" *     Revision         0x%2.2X",      Table->Revision);
743
744     switch (Table->Revision)
745     {
746     case 0:
747         AcpiOsPrintf (" **** Invalid Revision");
748         break;
749
750     case 1:
751         /* Revision of DSDT controls the ACPI integer width */
752
753         if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT))
754         {
755             AcpiOsPrintf (" **** ACPI 1.0, no 64-bit math support");
756         }
757         break;
758
759     default:
760         break;
761     }
762     AcpiOsPrintf ("\n");
763
764     /* Print and validate the table checksum */
765
766     AcpiOsPrintf (" *     Checksum         0x%2.2X",        Table->Checksum);
767
768     Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length);
769     if (Checksum)
770     {
771         AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X",
772             (UINT8) (Table->Checksum - Checksum));
773     }
774     AcpiOsPrintf ("\n");
775
776     AcpiOsPrintf (" *     OEM ID           \"%.6s\"\n",     Table->OemId);
777     AcpiOsPrintf (" *     OEM Table ID     \"%.8s\"\n",     Table->OemTableId);
778     AcpiOsPrintf (" *     OEM Revision     0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision);
779     AcpiOsPrintf (" *     Compiler ID      \"%.4s\"\n",     Table->AslCompilerId);
780     AcpiOsPrintf (" *     Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision);
781     AcpiOsPrintf (" */\n");
782
783     /* Create AML output filename based on input filename */
784
785     if (Filename)
786     {
787         NewFilename = FlGenerateFilename (Filename, "aml");
788     }
789     else
790     {
791         NewFilename = ACPI_ALLOCATE_ZEROED (9);
792         strncat (NewFilename, Table->Signature, 4);
793         strcat (NewFilename, ".aml");
794     }
795
796     /* Open the ASL definition block */
797
798     AcpiOsPrintf (
799         "DefinitionBlock (\"%s\", \"%4.4s\", %hd, \"%.6s\", \"%.8s\", 0x%8.8X)\n",
800         NewFilename, Table->Signature, Table->Revision,
801         Table->OemId, Table->OemTableId, Table->OemRevision);
802
803     ACPI_FREE (NewFilename);
804 }
805
806
807 /******************************************************************************
808  *
809  * FUNCTION:    AdDisplayTables
810  *
811  * PARAMETERS:  Filename            - Input file for the table
812  *              Table               - Pointer to the raw table
813  *
814  * RETURN:      Status
815  *
816  * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables
817  *
818  *****************************************************************************/
819
820 ACPI_STATUS
821 AdDisplayTables (
822     char                    *Filename,
823     ACPI_TABLE_HEADER       *Table)
824 {
825
826
827     if (!AcpiGbl_ParseOpRoot)
828     {
829         return AE_NOT_EXIST;
830     }
831
832     if (!AcpiGbl_DbOpt_verbose)
833     {
834         AdCreateTableHeader (Filename, Table);
835     }
836
837     AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX);
838
839     if (AcpiGbl_DbOpt_verbose)
840     {
841         AcpiOsPrintf ("\n\nTable Header:\n");
842         AcpiUtDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER),
843             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
844
845         AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length);
846         AcpiUtDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)), Table->Length,
847             DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
848     }
849
850     return AE_OK;
851 }
852
853
854 /******************************************************************************
855  *
856  * FUNCTION:    AdDeferredParse
857  *
858  * PARAMETERS:  Op              - Root Op of the deferred opcode
859  *              Aml             - Pointer to the raw AML
860  *              AmlLength       - Length of the AML
861  *
862  * RETURN:      Status
863  *
864  * DESCRIPTION: Parse one deferred opcode
865  *              (Methods, operation regions, etc.)
866  *
867  *****************************************************************************/
868
869 ACPI_STATUS
870 AdDeferredParse (
871     ACPI_PARSE_OBJECT       *Op,
872     UINT8                   *Aml,
873     UINT32                  AmlLength)
874 {
875     ACPI_WALK_STATE         *WalkState;
876     ACPI_STATUS             Status;
877     ACPI_PARSE_OBJECT       *SearchOp;
878     ACPI_PARSE_OBJECT       *StartOp;
879     UINT32                  BaseAmlOffset;
880     ACPI_PARSE_OBJECT       *ExtraOp;
881
882
883     ACPI_FUNCTION_TRACE (AdDeferredParse);
884
885
886     fprintf (stderr, ".");
887
888     if (!Aml || !AmlLength)
889     {
890         return_ACPI_STATUS (AE_OK);
891     }
892
893     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing %s [%4.4s]\n",
894         Op->Common.AmlOpName, (char *) &Op->Named.Name));
895
896     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
897     if (!WalkState)
898     {
899         return_ACPI_STATUS (AE_NO_MEMORY);
900     }
901
902     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml,
903                     AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
904     if (ACPI_FAILURE (Status))
905     {
906         return_ACPI_STATUS (Status);
907     }
908
909     /* Parse the method */
910
911     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
912     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
913     Status = AcpiPsParseAml (WalkState);
914
915     /*
916      * We need to update all of the Aml offsets, since the parser thought
917      * that the method began at offset zero.  In reality, it began somewhere
918      * within the ACPI table, at the BaseAmlOffset.  Walk the entire tree that
919      * was just created and update the AmlOffset in each Op
920      */
921     BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1;
922     StartOp = (Op->Common.Value.Arg)->Common.Next;
923     SearchOp = StartOp;
924
925     /* Walk the parse tree */
926
927     while (SearchOp)
928     {
929         SearchOp->Common.AmlOffset += BaseAmlOffset;
930         SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
931     }
932
933     /*
934      * Link the newly parsed subtree into the main parse tree
935      */
936     switch (Op->Common.AmlOpcode)
937     {
938     case AML_BUFFER_OP:
939     case AML_PACKAGE_OP:
940     case AML_VAR_PACKAGE_OP:
941
942         switch (Op->Common.AmlOpcode)
943         {
944         case AML_PACKAGE_OP:
945             ExtraOp = Op->Common.Value.Arg;
946             ExtraOp = ExtraOp->Common.Next;
947             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
948             break;
949
950         case AML_VAR_PACKAGE_OP:
951         case AML_BUFFER_OP:
952         default:
953             ExtraOp = Op->Common.Value.Arg;
954             Op->Common.Value.Arg = ExtraOp->Common.Value.Arg;
955             break;
956         }
957
958         /* Must point all parents to the main tree */
959
960         StartOp = Op;
961         SearchOp = StartOp;
962         while (SearchOp)
963         {
964             if (SearchOp->Common.Parent == ExtraOp)
965             {
966                 SearchOp->Common.Parent = Op;
967             }
968             SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
969         }
970         break;
971
972     default:
973         break;
974     }
975
976     return_ACPI_STATUS (AE_OK);
977 }
978
979
980 /******************************************************************************
981  *
982  * FUNCTION:    AdParseDeferredOps
983  *
984  * PARAMETERS:  Root            - Root of the parse tree
985  *
986  * RETURN:      Status
987  *
988  * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.)
989  *
990  *****************************************************************************/
991
992 ACPI_STATUS
993 AdParseDeferredOps (
994     ACPI_PARSE_OBJECT       *Root)
995 {
996     ACPI_PARSE_OBJECT       *Op = Root;
997     ACPI_STATUS             Status = AE_OK;
998     const ACPI_OPCODE_INFO  *OpInfo;
999
1000
1001     ACPI_FUNCTION_NAME (AdParseDeferredOps);
1002     fprintf (stderr, "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");
1003
1004     while (Op)
1005     {
1006         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1007         if (!(OpInfo->Flags & AML_DEFER))
1008         {
1009             Op = AcpiPsGetDepthNext (Root, Op);
1010             continue;
1011         }
1012
1013         switch (Op->Common.AmlOpcode)
1014         {
1015         case AML_METHOD_OP:
1016         case AML_BUFFER_OP:
1017         case AML_PACKAGE_OP:
1018         case AML_VAR_PACKAGE_OP:
1019
1020             Status = AdDeferredParse (Op, Op->Named.Data, Op->Named.Length);
1021             if (ACPI_FAILURE (Status))
1022             {
1023                 return_ACPI_STATUS (Status);
1024             }
1025             break;
1026
1027         case AML_REGION_OP:
1028         case AML_CREATE_QWORD_FIELD_OP:
1029         case AML_CREATE_DWORD_FIELD_OP:
1030         case AML_CREATE_WORD_FIELD_OP:
1031         case AML_CREATE_BYTE_FIELD_OP:
1032         case AML_CREATE_BIT_FIELD_OP:
1033         case AML_CREATE_FIELD_OP:
1034         case AML_BANK_FIELD_OP:
1035
1036             /* Nothing to do in these cases */
1037
1038             break;
1039
1040         default:
1041             ACPI_ERROR ((AE_INFO, "Unhandled deferred opcode [%s]",
1042                 Op->Common.AmlOpName));
1043             break;
1044         }
1045
1046         Op = AcpiPsGetDepthNext (Root, Op);
1047     }
1048
1049     fprintf (stderr, "\n");
1050     return Status;
1051 }
1052
1053
1054 /******************************************************************************
1055  *
1056  * FUNCTION:    AdGetLocalTables
1057  *
1058  * PARAMETERS:  Filename        - Not used
1059  *              GetAllTables    - TRUE if all tables are desired
1060  *
1061  * RETURN:      Status
1062  *
1063  * DESCRIPTION: Get the ACPI tables from either memory or a file
1064  *
1065  *****************************************************************************/
1066
1067 ACPI_STATUS
1068 AdGetLocalTables (
1069     char                    *Filename,
1070     BOOLEAN                 GetAllTables)
1071 {
1072     ACPI_STATUS             Status;
1073     ACPI_TABLE_HEADER       TableHeader;
1074     ACPI_TABLE_HEADER       *NewTable;
1075     UINT32                  NumTables;
1076     UINT32                  PointerSize;
1077     UINT32                  TableIndex;
1078
1079
1080     if (GetAllTables)
1081     {
1082         ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_RSDT);
1083         AcpiOsTableOverride (&TableHeader, &NewTable);
1084         if (!NewTable)
1085         {
1086             fprintf (stderr, "Could not obtain RSDT\n");
1087             return AE_NO_ACPI_TABLES;
1088         }
1089         else
1090         {
1091             AdWriteTable (NewTable, NewTable->Length,
1092                 ACPI_SIG_RSDT, NewTable->OemTableId);
1093         }
1094
1095         if (ACPI_COMPARE_NAME (NewTable->Signature, ACPI_SIG_RSDT))
1096         {
1097             PointerSize = sizeof (UINT32);
1098         }
1099         else
1100         {
1101             PointerSize = sizeof (UINT64);
1102         }
1103
1104         /*
1105          * Determine the number of tables pointed to by the RSDT/XSDT.
1106          * This is defined by the ACPI Specification to be the number of
1107          * pointers contained within the RSDT/XSDT.  The size of the pointers
1108          * is architecture-dependent.
1109          */
1110         NumTables = (NewTable->Length - sizeof (ACPI_TABLE_HEADER)) / PointerSize;
1111         AcpiOsPrintf ("There are %d tables defined in the %4.4s\n\n",
1112             NumTables, NewTable->Signature);
1113
1114         /* Get the FADT */
1115
1116         ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_FADT);
1117         AcpiOsTableOverride (&TableHeader, &NewTable);
1118         if (NewTable)
1119         {
1120             AdWriteTable (NewTable, NewTable->Length,
1121                 ACPI_SIG_FADT, NewTable->OemTableId);
1122         }
1123         AcpiOsPrintf ("\n");
1124
1125         /* Don't bother with FACS, it is usually all zeros */
1126     }
1127
1128     /* Always get the DSDT */
1129
1130     ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT);
1131     AcpiOsTableOverride (&TableHeader, &NewTable);
1132     if (NewTable)
1133     {
1134         AdWriteTable (NewTable, NewTable->Length,
1135             ACPI_SIG_DSDT, NewTable->OemTableId);
1136
1137         /* Store DSDT in the Table Manager */
1138
1139         Status = AcpiTbStoreTable (0, NewTable, NewTable->Length,
1140                     0, &TableIndex);
1141     }
1142     else
1143     {
1144         fprintf (stderr, "Could not obtain DSDT\n");
1145         return AE_NO_ACPI_TABLES;
1146     }
1147
1148 #if 0
1149     /* TBD: Future implementation */
1150
1151     AcpiOsPrintf ("\n");
1152
1153     /* Get all SSDTs */
1154
1155     ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_SSDT);
1156     do
1157     {
1158         NewTable = NULL;
1159         Status = AcpiOsTableOverride (&TableHeader, &NewTable);
1160
1161     } while (NewTable);
1162 #endif
1163
1164     return AE_OK;
1165 }
1166
1167
1168 /******************************************************************************
1169  *
1170  * FUNCTION:    AdParseTable
1171  *
1172  * PARAMETERS:  Table           - Pointer to the raw table
1173  *              OwnerId         - Returned OwnerId of the table
1174  *              LoadTable       - If add table to the global table list
1175  *              External        - If this is an external table
1176  *
1177  * RETURN:      Status
1178  *
1179  * DESCRIPTION: Parse the DSDT.
1180  *
1181  *****************************************************************************/
1182
1183 ACPI_STATUS
1184 AdParseTable (
1185     ACPI_TABLE_HEADER       *Table,
1186     ACPI_OWNER_ID           *OwnerId,
1187     BOOLEAN                 LoadTable,
1188     BOOLEAN                 External)
1189 {
1190     ACPI_STATUS             Status = AE_OK;
1191     ACPI_WALK_STATE         *WalkState;
1192     UINT8                   *AmlStart;
1193     UINT32                  AmlLength;
1194     UINT32                  TableIndex;
1195
1196
1197     if (!Table)
1198     {
1199         return AE_NOT_EXIST;
1200     }
1201
1202     /* Pass 1:  Parse everything except control method bodies */
1203
1204     fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature);
1205
1206     AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
1207     AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
1208
1209     /* Create the root object */
1210
1211     AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp ();
1212     if (!AcpiGbl_ParseOpRoot)
1213     {
1214         return AE_NO_MEMORY;
1215     }
1216
1217     /* Create and initialize a new walk state */
1218
1219     WalkState = AcpiDsCreateWalkState (0,
1220                         AcpiGbl_ParseOpRoot, NULL, NULL);
1221     if (!WalkState)
1222     {
1223         return (AE_NO_MEMORY);
1224     }
1225
1226     Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot,
1227                 NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
1228     if (ACPI_FAILURE (Status))
1229     {
1230         return (Status);
1231     }
1232
1233     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
1234     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
1235
1236     Status = AcpiPsParseAml (WalkState);
1237     if (ACPI_FAILURE (Status))
1238     {
1239         return Status;
1240     }
1241
1242     /* If LoadTable is FALSE, we are parsing the last loaded table */
1243
1244     TableIndex = AcpiGbl_RootTableList.Count - 1;
1245
1246     /* Pass 2 */
1247
1248     if (LoadTable)
1249     {
1250         Status = AcpiTbStoreTable ((ACPI_PHYSICAL_ADDRESS) Table, Table,
1251                     Table->Length, ACPI_TABLE_ORIGIN_ALLOCATED, &TableIndex);
1252         if (ACPI_FAILURE (Status))
1253         {
1254             return Status;
1255         }
1256         Status = AcpiTbAllocateOwnerId (TableIndex);
1257         if (ACPI_FAILURE (Status))
1258         {
1259             return Status;
1260         }
1261         if (OwnerId)
1262         {
1263             Status = AcpiTbGetOwnerId (TableIndex, OwnerId);
1264             if (ACPI_FAILURE (Status))
1265             {
1266                 return Status;
1267             }
1268         }
1269     }
1270
1271     fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature);
1272
1273     Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL);
1274     if (ACPI_FAILURE (Status))
1275     {
1276         return (Status);
1277     }
1278
1279     /* No need to parse control methods of external table */
1280
1281     if (External)
1282     {
1283         return AE_OK;
1284     }
1285
1286     /* Pass 3: Parse control methods and link their parse trees into the main parse tree */
1287
1288     Status = AdParseDeferredOps (AcpiGbl_ParseOpRoot);
1289
1290     /* Process Resource Templates */
1291
1292     AcpiDmFindResources (AcpiGbl_ParseOpRoot);
1293
1294     fprintf (stderr, "Parsing completed\n");
1295     return AE_OK;
1296 }
1297
1298