OSDN Git Service

klibc基本機能実装. ACPICAの準備
[vaneos/DivergeMirror.git] / drivers / acpi / compiler / aslcodegen.c
1 /******************************************************************************
2  *
3  * Module Name: aslcodegen - AML code generation
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2015, 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 #include "aslcompiler.h"
117 #include "aslcompiler.y.h"
118 #include "amlcode.h"
119
120 #define _COMPONENT          ACPI_COMPILER
121         ACPI_MODULE_NAME    ("aslcodegen")
122
123 /* Local prototypes */
124
125 static ACPI_STATUS
126 CgAmlWriteWalk (
127     ACPI_PARSE_OBJECT       *Op,
128     UINT32                  Level,
129     void                    *Context);
130
131 static void
132 CgLocalWriteAmlData (
133     ACPI_PARSE_OBJECT       *Op,
134     void                    *Buffer,
135     UINT32                  Length);
136
137 static void
138 CgWriteAmlOpcode (
139     ACPI_PARSE_OBJECT       *Op);
140
141 static void
142 CgWriteTableHeader (
143     ACPI_PARSE_OBJECT       *Op);
144
145 static void
146 CgCloseTable (
147     void);
148
149 static void
150 CgWriteNode (
151     ACPI_PARSE_OBJECT       *Op);
152
153
154 /*******************************************************************************
155  *
156  * FUNCTION:    CgGenerateAmlOutput
157  *
158  * PARAMETERS:  None.
159  *
160  * RETURN:      None
161  *
162  * DESCRIPTION: Generate AML code. Currently generates the listing file
163  *              simultaneously.
164  *
165  ******************************************************************************/
166
167 void
168 CgGenerateAmlOutput (
169     void)
170 {
171
172     DbgPrint (ASL_DEBUG_OUTPUT, "\nWriting AML\n\n");
173
174     /* Generate the AML output file */
175
176     FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
177     Gbl_SourceLine = 0;
178     Gbl_NextError = Gbl_ErrorLog;
179
180     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
181         CgAmlWriteWalk, NULL, NULL);
182
183     DbgPrint (ASL_TREE_OUTPUT,
184         "%*s Value    P_Op A_Op OpLen PByts Len  SubLen PSubLen OpPtr"
185         "    Parent   Child    Next     Flags    AcTyp    Final Col L\n",
186         76, " ");
187
188     CgCloseTable ();
189 }
190
191
192 /*******************************************************************************
193  *
194  * FUNCTION:    CgAmlWriteWalk
195  *
196  * PARAMETERS:  ASL_WALK_CALLBACK
197  *
198  * RETURN:      Status
199  *
200  * DESCRIPTION: Parse tree walk to generate the AML code.
201  *
202  ******************************************************************************/
203
204 static ACPI_STATUS
205 CgAmlWriteWalk (
206     ACPI_PARSE_OBJECT       *Op,
207     UINT32                  Level,
208     void                    *Context)
209 {
210
211     /*
212      * Print header at level 0. Alignment assumes 32-bit pointers
213      */
214     if (!Level)
215     {
216         DbgPrint (ASL_TREE_OUTPUT,
217             "Final parse tree used for AML output:\n");
218         DbgPrint (ASL_TREE_OUTPUT,
219             "%*s Value    P_Op A_Op OpLen PByts Len  SubLen PSubLen OpPtr"
220             "    Parent   Child    Next     Flags    AcTyp    Final Col L\n",
221             76, " ");
222     }
223
224     /* Debug output */
225
226     DbgPrint (ASL_TREE_OUTPUT,
227         "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level);
228     UtPrintFormattedName (Op->Asl.ParseOpcode, Level);
229
230     if (Op->Asl.ParseOpcode == PARSEOP_NAMESEG    ||
231         Op->Asl.ParseOpcode == PARSEOP_NAMESTRING ||
232         Op->Asl.ParseOpcode == PARSEOP_METHODCALL)
233     {
234         DbgPrint (ASL_TREE_OUTPUT,
235             "%10.32s      ", Op->Asl.ExternalName);
236     }
237     else
238     {
239         DbgPrint (ASL_TREE_OUTPUT, "                ");
240     }
241
242     DbgPrint (ASL_TREE_OUTPUT,
243     "%08X %04X %04X %01X     %04X  %04X %04X   %04X    "
244     "%08X %08X %08X %08X %08X %08X %04X  %02d  %02d\n",
245             /* 1  */ (UINT32) Op->Asl.Value.Integer,
246             /* 2  */ Op->Asl.ParseOpcode,
247             /* 3  */ Op->Asl.AmlOpcode,
248             /* 4  */ Op->Asl.AmlOpcodeLength,
249             /* 5  */ Op->Asl.AmlPkgLenBytes,
250             /* 6  */ Op->Asl.AmlLength,
251             /* 7  */ Op->Asl.AmlSubtreeLength,
252             /* 8  */ Op->Asl.Parent ? Op->Asl.Parent->Asl.AmlSubtreeLength : 0,
253             /* 9  */ Op,
254             /* 10 */ Op->Asl.Parent,
255             /* 11 */ Op->Asl.Child,
256             /* 12 */ Op->Asl.Next,
257             /* 13 */ Op->Asl.CompileFlags,
258             /* 14 */ Op->Asl.AcpiBtype,
259             /* 15 */ Op->Asl.FinalAmlLength,
260             /* 16 */ Op->Asl.Column,
261             /* 17 */ Op->Asl.LineNumber);
262
263     /* Generate the AML for this node */
264
265     CgWriteNode (Op);
266     return (AE_OK);
267 }
268
269
270 /*******************************************************************************
271  *
272  * FUNCTION:    CgLocalWriteAmlData
273  *
274  * PARAMETERS:  Op              - Current parse op
275  *              Buffer          - Buffer to write
276  *              Length          - Size of data in buffer
277  *
278  * RETURN:      None
279  *
280  * DESCRIPTION: Write a buffer of AML data to the AML output file.
281  *
282  ******************************************************************************/
283
284 static void
285 CgLocalWriteAmlData (
286     ACPI_PARSE_OBJECT       *Op,
287     void                    *Buffer,
288     UINT32                  Length)
289 {
290
291     /* Write the raw data to the AML file */
292
293     FlWriteFile (ASL_FILE_AML_OUTPUT, Buffer, Length);
294
295     /* Update the final AML length for this node (used for listings) */
296
297     if (Op)
298     {
299         Op->Asl.FinalAmlLength += Length;
300     }
301 }
302
303
304 /*******************************************************************************
305  *
306  * FUNCTION:    CgWriteAmlOpcode
307  *
308  * PARAMETERS:  Op            - Parse node with an AML opcode
309  *
310  * RETURN:      None.
311  *
312  * DESCRIPTION: Write the AML opcode corresponding to a parse node.
313  *
314  ******************************************************************************/
315
316 static void
317 CgWriteAmlOpcode (
318     ACPI_PARSE_OBJECT       *Op)
319 {
320     UINT8                   PkgLenFirstByte;
321     UINT32                  i;
322     union {
323         UINT16                  Opcode;
324         UINT8                   OpcodeBytes[2];
325     } Aml;
326     union {
327         UINT32                  Len;
328         UINT8                   LenBytes[4];
329     } PkgLen;
330
331
332     /* We expect some DEFAULT_ARGs, just ignore them */
333
334     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
335     {
336         return;
337     }
338
339     switch (Op->Asl.AmlOpcode)
340     {
341     case AML_UNASSIGNED_OPCODE:
342
343         /* These opcodes should not get here */
344
345         printf ("Found a node with an unassigned AML opcode\n");
346         FlPrintFile (ASL_FILE_STDERR, "Found a node with an unassigned AML opcode\n");
347         return;
348
349     case AML_INT_RESERVEDFIELD_OP:
350
351         /* Special opcodes for within a field definition */
352
353         Aml.Opcode = AML_FIELD_OFFSET_OP;
354         break;
355
356     case AML_INT_ACCESSFIELD_OP:
357
358         Aml.Opcode = AML_FIELD_ACCESS_OP;
359         break;
360
361     case AML_INT_CONNECTION_OP:
362
363         Aml.Opcode = AML_FIELD_CONNECTION_OP;
364         break;
365
366     default:
367
368         Aml.Opcode = Op->Asl.AmlOpcode;
369         break;
370     }
371
372
373     switch (Aml.Opcode)
374     {
375     case AML_PACKAGE_LENGTH:
376
377         /* Value is the length to be encoded (Used in field definitions) */
378
379         PkgLen.Len = (UINT32) Op->Asl.Value.Integer;
380         break;
381
382     default:
383
384         /* Check for two-byte opcode */
385
386         if (Aml.Opcode > 0x00FF)
387         {
388             /* Write the high byte first */
389
390             CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[1], 1);
391         }
392
393         CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[0], 1);
394
395         /* Subtreelength doesn't include length of package length bytes */
396
397         PkgLen.Len = Op->Asl.AmlSubtreeLength + Op->Asl.AmlPkgLenBytes;
398         break;
399     }
400
401     /* Does this opcode have an associated "PackageLength" field? */
402
403     if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
404     {
405         if (Op->Asl.AmlPkgLenBytes == 1)
406         {
407             /* Simplest case -- no bytes to follow, just write the count */
408
409             CgLocalWriteAmlData (Op, &PkgLen.LenBytes[0], 1);
410         }
411         else if (Op->Asl.AmlPkgLenBytes != 0)
412         {
413             /*
414              * Encode the "bytes to follow" in the first byte, top two bits.
415              * The low-order nybble of the length is in the bottom 4 bits
416              */
417             PkgLenFirstByte = (UINT8)
418                 (((UINT32) (Op->Asl.AmlPkgLenBytes - 1) << 6) |
419                 (PkgLen.LenBytes[0] & 0x0F));
420
421             CgLocalWriteAmlData (Op, &PkgLenFirstByte, 1);
422
423             /*
424              * Shift the length over by the 4 bits we just stuffed
425              * in the first byte
426              */
427             PkgLen.Len >>= 4;
428
429             /* Now we can write the remaining bytes - either 1, 2, or 3 bytes */
430
431             for (i = 0; i < (UINT32) (Op->Asl.AmlPkgLenBytes - 1); i++)
432             {
433                 CgLocalWriteAmlData (Op, &PkgLen.LenBytes[i], 1);
434             }
435         }
436     }
437
438     switch (Aml.Opcode)
439     {
440     case AML_BYTE_OP:
441
442         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 1);
443         break;
444
445     case AML_WORD_OP:
446
447         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 2);
448        break;
449
450     case AML_DWORD_OP:
451
452         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 4);
453         break;
454
455     case AML_QWORD_OP:
456
457         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 8);
458         break;
459
460     case AML_STRING_OP:
461
462         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
463         break;
464
465     default:
466
467         /* All data opcodes must appear above */
468
469         break;
470     }
471 }
472
473
474 /*******************************************************************************
475  *
476  * FUNCTION:    CgWriteTableHeader
477  *
478  * PARAMETERS:  Op        - The DEFINITIONBLOCK node
479  *
480  * RETURN:      None
481  *
482  * DESCRIPTION: Write a table header corresponding to the DEFINITIONBLOCK
483  *
484  ******************************************************************************/
485
486 static void
487 CgWriteTableHeader (
488     ACPI_PARSE_OBJECT       *Op)
489 {
490     ACPI_PARSE_OBJECT       *Child;
491
492
493     /* AML filename */
494
495     Child = Op->Asl.Child;
496
497     /* Signature */
498
499     Child = Child->Asl.Next;
500     strncpy (TableHeader.Signature, Child->Asl.Value.String, 4);
501
502     /* Revision */
503
504     Child = Child->Asl.Next;
505     TableHeader.Revision = (UINT8) Child->Asl.Value.Integer;
506
507     /* Command-line Revision override */
508
509     if (Gbl_RevisionOverride)
510     {
511         TableHeader.Revision = Gbl_RevisionOverride;
512     }
513
514     /* OEMID */
515
516     Child = Child->Asl.Next;
517     strncpy (TableHeader.OemId, Child->Asl.Value.String, 6);
518
519     /* OEM TableID */
520
521     Child = Child->Asl.Next;
522     strncpy (TableHeader.OemTableId, Child->Asl.Value.String, 8);
523
524     /* OEM Revision */
525
526     Child = Child->Asl.Next;
527     TableHeader.OemRevision = (UINT32) Child->Asl.Value.Integer;
528
529     /* Compiler ID */
530
531     ACPI_MOVE_NAME (TableHeader.AslCompilerId, ASL_CREATOR_ID);
532
533     /* Compiler version */
534
535     TableHeader.AslCompilerRevision = ACPI_CA_VERSION;
536
537     /* Table length. Checksum zero for now, will rewrite later */
538
539     TableHeader.Length   = Gbl_TableLength;
540     TableHeader.Checksum = 0;
541
542     CgLocalWriteAmlData (Op, &TableHeader, sizeof (ACPI_TABLE_HEADER));
543 }
544
545
546 /*******************************************************************************
547  *
548  * FUNCTION:    CgCloseTable
549  *
550  * PARAMETERS:  None.
551  *
552  * RETURN:      None.
553  *
554  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
555  *              re-writing the header.
556  *
557  ******************************************************************************/
558
559 static void
560 CgCloseTable (
561     void)
562 {
563     signed char         Sum;
564     UINT8               FileByte;
565
566
567     FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
568     Sum = 0;
569
570     /* Calculate the checksum over the entire file */
571
572     while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) == AE_OK)
573     {
574         Sum = (signed char) (Sum + FileByte);
575     }
576
577     /* Re-write the table header with the checksum */
578
579     TableHeader.Checksum = (UINT8) (0 - Sum);
580
581     FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
582     CgLocalWriteAmlData (NULL, &TableHeader, sizeof (ACPI_TABLE_HEADER));
583 }
584
585
586 /*******************************************************************************
587  *
588  * FUNCTION:    CgWriteNode
589  *
590  * PARAMETERS:  Op            - Parse node to write.
591  *
592  * RETURN:      None.
593  *
594  * DESCRIPTION: Write the AML that corresponds to a parse node.
595  *
596  ******************************************************************************/
597
598 static void
599 CgWriteNode (
600     ACPI_PARSE_OBJECT       *Op)
601 {
602     ASL_RESOURCE_NODE       *Rnode;
603
604
605     /* Always check for DEFAULT_ARG and other "Noop" nodes */
606     /* TBD: this may not be the best place for this check */
607
608     if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)  ||
609         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)     ||
610         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE)      ||
611         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE_END))
612     {
613         return;
614     }
615
616     Op->Asl.FinalAmlLength = 0;
617
618     switch (Op->Asl.AmlOpcode)
619     {
620     case AML_RAW_DATA_BYTE:
621     case AML_RAW_DATA_WORD:
622     case AML_RAW_DATA_DWORD:
623     case AML_RAW_DATA_QWORD:
624
625         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, Op->Asl.AmlLength);
626         return;
627
628
629     case AML_RAW_DATA_BUFFER:
630
631         CgLocalWriteAmlData (Op, Op->Asl.Value.Buffer, Op->Asl.AmlLength);
632         return;
633
634
635     case AML_RAW_DATA_CHAIN:
636
637         Rnode = ACPI_CAST_PTR (ASL_RESOURCE_NODE, Op->Asl.Value.Buffer);
638         while (Rnode)
639         {
640             CgLocalWriteAmlData (Op, Rnode->Buffer, Rnode->BufferLength);
641             Rnode = Rnode->Next;
642         }
643         return;
644
645     default:
646
647         /* Internal data opcodes must all appear above */
648
649         break;
650     }
651
652     switch (Op->Asl.ParseOpcode)
653     {
654     case PARSEOP_DEFAULT_ARG:
655
656         break;
657
658     case PARSEOP_DEFINITIONBLOCK:
659
660         CgWriteTableHeader (Op);
661         break;
662
663     case PARSEOP_NAMESEG:
664     case PARSEOP_NAMESTRING:
665     case PARSEOP_METHODCALL:
666
667         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
668         break;
669
670     default:
671
672         CgWriteAmlOpcode (Op);
673         break;
674     }
675 }