xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslcodegen.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
1 /******************************************************************************
2  *
3  * Module Name: aslcodegen - AML code generation
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47 #include "acconvert.h"
48 #include "actbinfo.h"
49 
50 #define _COMPONENT          ACPI_COMPILER
51         ACPI_MODULE_NAME    ("aslcodegen")
52 
53 /* Local prototypes */
54 
55 static ACPI_STATUS
56 CgAmlWriteWalk (
57     ACPI_PARSE_OBJECT       *Op,
58     UINT32                  Level,
59     void                    *Context);
60 
61 static void
62 CgWriteAmlOpcode (
63     ACPI_PARSE_OBJECT       *Op);
64 
65 static void
66 CgWriteTableHeader (
67     ACPI_PARSE_OBJECT       *Op);
68 
69 static void
70 CgWriteNode (
71     ACPI_PARSE_OBJECT       *Op);
72 
73 static void
74 CgUpdateHeader (
75     ACPI_PARSE_OBJECT       *Op);
76 
77 static void
78 CgUpdateCdatHeader (
79     ACPI_PARSE_OBJECT       *Op);
80 
81 
82 /*******************************************************************************
83  *
84  * FUNCTION:    CgGenerateAmlOutput
85  *
86  * PARAMETERS:  None.
87  *
88  * RETURN:      None
89  *
90  * DESCRIPTION: Generate AML code. Currently generates the listing file
91  *              simultaneously.
92  *
93  ******************************************************************************/
94 
95 void
CgGenerateAmlOutput(void)96 CgGenerateAmlOutput (
97     void)
98 {
99 
100     /* Generate the AML output file */
101 
102     TrWalkParseTree (AslGbl_CurrentDB,
103         ASL_WALK_VISIT_DOWNWARD | ASL_WALK_VISIT_DB_SEPARATELY,
104         CgAmlWriteWalk, NULL, NULL);
105 
106     DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER2);
107     if (AcpiGbl_CDAT)
108     {
109         CgUpdateCdatHeader (AslGbl_CurrentDB);
110     }
111     else
112     {
113         CgUpdateHeader (AslGbl_CurrentDB);
114     }
115 }
116 
117 
118 /*******************************************************************************
119  *
120  * FUNCTION:    CgAmlWriteWalk
121  *
122  * PARAMETERS:  ASL_WALK_CALLBACK
123  *
124  * RETURN:      Status
125  *
126  * DESCRIPTION: Parse tree walk to generate the AML code.
127  *
128  ******************************************************************************/
129 
130 static ACPI_STATUS
CgAmlWriteWalk(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)131 CgAmlWriteWalk (
132     ACPI_PARSE_OBJECT       *Op,
133     UINT32                  Level,
134     void                    *Context)
135 {
136 
137     /* Generate the AML for this node */
138 
139     CgWriteNode (Op);
140 
141     if (!AslGbl_DebugFlag)
142     {
143         return (AE_OK);
144     }
145 
146     /* Print header at level 0. Alignment assumes 32-bit pointers */
147 
148     if (!Level)
149     {
150         DbgPrint (ASL_TREE_OUTPUT,
151             "\nFinal parse tree used for AML output:\n");
152         DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER2);
153     }
154 
155     /* Dump ParseOp name and possible value */
156 
157     switch (Op->Asl.ParseOpcode)
158     {
159     case PARSEOP_NAMESEG:
160     case PARSEOP_NAMESTRING:
161     case PARSEOP_METHODCALL:
162     case PARSEOP_STRING_LITERAL:
163 
164         UtDumpStringOp (Op, Level);
165         break;
166 
167     default:
168 
169         UtDumpBasicOp (Op, Level);
170         break;
171     }
172 
173     DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_DEBUG2,
174         /* 1  */ (UINT32) Op->Asl.Value.Integer,
175         /* 2  */ Op->Asl.ParseOpcode,
176         /* 3  */ Op->Asl.AmlOpcode,
177         /* 4  */ Op->Asl.AmlOpcodeLength,
178         /* 5  */ Op->Asl.AmlPkgLenBytes,
179         /* 6  */ Op->Asl.AmlLength,
180         /* 7  */ Op->Asl.AmlSubtreeLength,
181         /* 8  */ Op->Asl.Parent ? Op->Asl.Parent->Asl.AmlSubtreeLength : 0,
182         /* 9  */ Op,
183         /* 10 */ Op->Asl.Parent,
184         /* 11 */ Op->Asl.Child,
185         /* 12 */ Op->Asl.Next,
186         /* 13 */ Op->Asl.CompileFlags,
187         /* 14 */ Op->Asl.AcpiBtype,
188         /* 15 */ Op->Asl.FinalAmlLength,
189         /* 16 */ Op->Asl.Column,
190         /* 17 */ Op->Asl.LineNumber,
191         /* 18 */ Op->Asl.EndLine,
192         /* 19 */ Op->Asl.LogicalLineNumber,
193         /* 20 */ Op->Asl.EndLogicalLine);
194 
195     TrPrintOpFlags (Op->Asl.CompileFlags, ASL_TREE_OUTPUT);
196     DbgPrint (ASL_TREE_OUTPUT, "\n");
197     return (AE_OK);
198 }
199 
200 
201 /*******************************************************************************
202  *
203  * FUNCTION:    CgLocalWriteAmlData
204  *
205  * PARAMETERS:  Op              - Current parse op
206  *              Buffer          - Buffer to write
207  *              Length          - Size of data in buffer
208  *
209  * RETURN:      None
210  *
211  * DESCRIPTION: Write a buffer of AML data to the AML output file.
212  *
213  ******************************************************************************/
214 
215 void
CgLocalWriteAmlData(ACPI_PARSE_OBJECT * Op,void * Buffer,UINT32 Length)216 CgLocalWriteAmlData (
217     ACPI_PARSE_OBJECT       *Op,
218     void                    *Buffer,
219     UINT32                  Length)
220 {
221 
222     /* Write the raw data to the AML file */
223 
224     FlWriteFile (ASL_FILE_AML_OUTPUT, Buffer, Length);
225 
226     /* Update the final AML length for this node (used for listings) */
227 
228     if (Op)
229     {
230         Op->Asl.FinalAmlLength += Length;
231     }
232 }
233 
234 
235 /*******************************************************************************
236  *
237  * FUNCTION:    CgWriteAmlOpcode
238  *
239  * PARAMETERS:  Op            - Parse node with an AML opcode
240  *
241  * RETURN:      None.
242  *
243  * DESCRIPTION: Write the AML opcode corresponding to a parse node.
244  *
245  ******************************************************************************/
246 
247 static void
CgWriteAmlOpcode(ACPI_PARSE_OBJECT * Op)248 CgWriteAmlOpcode (
249     ACPI_PARSE_OBJECT       *Op)
250 {
251     UINT8                   PkgLenFirstByte;
252     UINT32                  i;
253     union {
254         UINT16                  Opcode;
255         UINT8                   OpcodeBytes[2];
256     } Aml;
257     union {
258         UINT32                  Len;
259         UINT8                   LenBytes[4];
260     } PkgLen;
261 
262 
263     /* We expect some DEFAULT_ARGs, just ignore them */
264 
265     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
266     {
267         return;
268     }
269 
270     /*
271      * Before printing the bytecode, generate comment byte codes
272      * associated with this node.
273      */
274     if (AcpiGbl_CaptureComments)
275     {
276         CgWriteAmlComment(Op);
277     }
278 
279     switch (Op->Asl.AmlOpcode)
280     {
281     case AML_UNASSIGNED_OPCODE:
282 
283         /* These opcodes should not get here */
284 
285         printf ("Found a node with an unassigned AML opcode\n");
286         FlPrintFile (ASL_FILE_STDERR,
287             "Found a node with an unassigned AML opcode\n");
288         return;
289 
290     case AML_INT_RESERVEDFIELD_OP:
291 
292         /* Special opcodes for within a field definition */
293 
294         Aml.Opcode = AML_FIELD_OFFSET_OP;
295         break;
296 
297     case AML_INT_ACCESSFIELD_OP:
298 
299         Aml.Opcode = AML_FIELD_ACCESS_OP;
300         break;
301 
302     case AML_INT_CONNECTION_OP:
303 
304         Aml.Opcode = AML_FIELD_CONNECTION_OP;
305         break;
306 
307     default:
308 
309         Aml.Opcode = Op->Asl.AmlOpcode;
310         break;
311     }
312 
313 
314     switch (Aml.Opcode)
315     {
316     case AML_PACKAGE_LENGTH:
317 
318         /* Value is the length to be encoded (Used in field definitions) */
319 
320         PkgLen.Len = (UINT32) Op->Asl.Value.Integer;
321         break;
322 
323     default:
324 
325         /* Check for two-byte opcode */
326 
327         if (Aml.Opcode > 0x00FF)
328         {
329             /* Write the high byte first */
330 
331             CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[1], 1);
332         }
333 
334         CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[0], 1);
335 
336         /* Subtreelength doesn't include length of package length bytes */
337 
338         PkgLen.Len = Op->Asl.AmlSubtreeLength + Op->Asl.AmlPkgLenBytes;
339         break;
340     }
341 
342     /* Does this opcode have an associated "PackageLength" field? */
343 
344     if (Op->Asl.CompileFlags & OP_AML_PACKAGE)
345     {
346         if (Op->Asl.AmlPkgLenBytes == 1)
347         {
348             /* Simplest case -- no bytes to follow, just write the count */
349 
350             CgLocalWriteAmlData (Op, &PkgLen.LenBytes[0], 1);
351         }
352         else if (Op->Asl.AmlPkgLenBytes != 0)
353         {
354             /*
355              * Encode the "bytes to follow" in the first byte, top two bits.
356              * The low-order nybble of the length is in the bottom 4 bits
357              */
358             PkgLenFirstByte = (UINT8)
359                 (((UINT32) (Op->Asl.AmlPkgLenBytes - 1) << 6) |
360                 (PkgLen.LenBytes[0] & 0x0F));
361 
362             CgLocalWriteAmlData (Op, &PkgLenFirstByte, 1);
363 
364             /*
365              * Shift the length over by the 4 bits we just stuffed
366              * in the first byte
367              */
368             PkgLen.Len >>= 4;
369 
370             /*
371              * Now we can write the remaining bytes -
372              * either 1, 2, or 3 bytes
373              */
374             for (i = 0; i < (UINT32) (Op->Asl.AmlPkgLenBytes - 1); i++)
375             {
376                 CgLocalWriteAmlData (Op, &PkgLen.LenBytes[i], 1);
377             }
378         }
379     }
380 
381     switch (Aml.Opcode)
382     {
383     case AML_BYTE_OP:
384 
385         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 1);
386         break;
387 
388     case AML_WORD_OP:
389 
390         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 2);
391        break;
392 
393     case AML_DWORD_OP:
394 
395         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 4);
396         break;
397 
398     case AML_QWORD_OP:
399 
400         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 8);
401         break;
402 
403     case AML_STRING_OP:
404 
405         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
406         break;
407 
408     default:
409 
410         /* All data opcodes must appear above */
411 
412         break;
413     }
414 }
415 
416 
417 /*******************************************************************************
418  *
419  * FUNCTION:    CgWriteTableHeader
420  *
421  * PARAMETERS:  Op        - The DEFINITIONBLOCK node
422  *
423  * RETURN:      None
424  *
425  * DESCRIPTION: Write a table header corresponding to the DEFINITIONBLOCK
426  *
427  * NOTE: Input strings should be validated before this function is invoked.
428  *
429  ******************************************************************************/
430 
431 static void
CgWriteTableHeader(ACPI_PARSE_OBJECT * Op)432 CgWriteTableHeader (
433     ACPI_PARSE_OBJECT       *Op)
434 {
435     ACPI_PARSE_OBJECT       *Child;
436     UINT32                  CommentLength;
437     ACPI_COMMENT_NODE       *Current;
438 
439 
440     memset (&AslGbl_TableHeader, 0, sizeof (ACPI_TABLE_HEADER));
441 
442     /* AML filename */
443 
444     Child = Op->Asl.Child;
445 
446     /* Signature */
447 
448     Child = Child->Asl.Next;
449 
450     /*
451      * For ASL-/ASL+ converter: replace the table signature with
452      * "XXXX" and save the original table signature. This results in an AML
453      * file with the signature "XXXX". The converter should remove this AML
454      * file. In the event where this AML file does not get deleted, the
455      * "XXXX" table signature prevents this AML file from running on the AML
456      * interpreter.
457      */
458     if (AcpiGbl_CaptureComments)
459     {
460         ACPI_COPY_NAMESEG (AcpiGbl_TableSig, Child->Asl.Value.String);
461         Child->Asl.Value.String = ACPI_SIG_XXXX;
462     }
463 
464     ACPI_COPY_NAMESEG (AslGbl_TableHeader.Signature, Child->Asl.Value.String);
465 
466     /* Revision */
467 
468     Child = Child->Asl.Next;
469     AslGbl_TableHeader.Revision = (UINT8) Child->Asl.Value.Integer;
470 
471     /* Command-line Revision override */
472 
473     if (AslGbl_RevisionOverride)
474     {
475         AslGbl_TableHeader.Revision = AslGbl_RevisionOverride;
476     }
477 
478     /* OEMID */
479 
480     Child = Child->Asl.Next;
481     memcpy (AslGbl_TableHeader.OemId, Child->Asl.Value.String,
482         strlen (Child->Asl.Value.String));
483 
484     /* OEM TableID */
485 
486     Child = Child->Asl.Next;
487     memcpy (AslGbl_TableHeader.OemTableId, Child->Asl.Value.String,
488         strlen (Child->Asl.Value.String));
489 
490     /* OEM Revision */
491 
492     Child = Child->Asl.Next;
493     AslGbl_TableHeader.OemRevision = (UINT32) Child->Asl.Value.Integer;
494 
495     /* Compiler ID */
496 
497     ACPI_COPY_NAMESEG (AslGbl_TableHeader.AslCompilerId, ASL_CREATOR_ID);
498 
499     /* Compiler version */
500 
501     AslGbl_TableHeader.AslCompilerRevision = ACPI_CA_VERSION;
502 
503     /* Table length. Checksum zero for now, will rewrite later */
504 
505     AslGbl_TableHeader.Length = sizeof (ACPI_TABLE_HEADER) +
506         Op->Asl.AmlSubtreeLength;
507 
508     /* Calculate the comment lengths for this definition block parseOp */
509 
510     if (AcpiGbl_CaptureComments)
511     {
512         CvDbgPrint ("Calculating comment lengths for %s in write header\n",
513             Op->Asl.ParseOpName);
514 
515         /*
516          * Take the filename without extensions, add 3 for the new extension
517          * and another 3 for the a908 bytecode and null terminator.
518          */
519         AslGbl_TableHeader.Length += strrchr (AslGbl_ParseTreeRoot->Asl.Filename, '.')
520             - AslGbl_ParseTreeRoot->Asl.Filename + 1 + 3 + 3;
521 
522         Op->Asl.AmlSubtreeLength +=
523             strlen (AslGbl_ParseTreeRoot->Asl.Filename) + 3;
524 
525         CvDbgPrint ("     Length: %u\n",
526             (UINT32) strlen (AslGbl_ParseTreeRoot->Asl.Filename) + 3);
527 
528         if (Op->Asl.CommentList)
529         {
530             Current = Op->Asl.CommentList;
531             while (Current)
532             {
533                 CommentLength = strlen (Current->Comment)+3;
534                 CvDbgPrint ("Length of standard comment): %d\n", CommentLength);
535                 CvDbgPrint ("    Comment string: %s\n\n", Current->Comment);
536                 AslGbl_TableHeader.Length += CommentLength;
537                 Op->Asl.AmlSubtreeLength += CommentLength;
538                 Current = Current->Next;
539                 CvDbgPrint ("    Length: %u\n", CommentLength);
540             }
541         }
542         if (Op->Asl.CloseBraceComment)
543         {
544             CommentLength = strlen (Op->Asl.CloseBraceComment)+3;
545             CvDbgPrint ("Length of inline comment +3: %d\n", CommentLength);
546             CvDbgPrint ("    Comment string: %s\n\n", Op->Asl.CloseBraceComment);
547             AslGbl_TableHeader.Length += CommentLength;
548             Op->Asl.AmlSubtreeLength += CommentLength;
549             CvDbgPrint ("    Length: %u\n", CommentLength);
550         }
551     }
552 
553     AslGbl_TableHeader.Checksum = 0;
554     Op->Asl.FinalAmlOffset = ftell (AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle);
555 
556     /* Write entire header and clear the table header global */
557 
558     CgLocalWriteAmlData (Op, &AslGbl_TableHeader, sizeof (ACPI_TABLE_HEADER));
559     memset (&AslGbl_TableHeader, 0, sizeof (ACPI_TABLE_HEADER));
560 }
561 
562 
563 /*******************************************************************************
564  *
565  * FUNCTION:    CgUpdateCdatHeader
566  *
567  * PARAMETERS:  Op                  - Op for the Definition Block
568  *
569  * RETURN:      None.
570  *
571  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
572  *              re-writing the header for the input definition block
573  *
574  ******************************************************************************/
575 
576 static void
CgUpdateCdatHeader(ACPI_PARSE_OBJECT * Op)577 CgUpdateCdatHeader (
578     ACPI_PARSE_OBJECT       *Op)
579 {
580     signed char             Sum;
581     UINT32                  i;
582     UINT32                  Length;
583     UINT8                   FileByte;
584     UINT8                   Checksum;
585 
586 
587     /* Calculate the checksum over the entire definition block */
588 
589     Sum = 0;
590     Length = sizeof (ACPI_TABLE_CDAT) + Op->Asl.AmlSubtreeLength;
591     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset);
592 
593     for (i = 0; i < Length; i++)
594     {
595         if (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) != AE_OK)
596         {
597             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
598                 "Table length is greater than size of the input file");
599             return;
600         }
601 
602         Sum = (signed char) (Sum + FileByte);
603     }
604 
605     Checksum = (UINT8) (0 - Sum);
606 
607     DbgPrint (ASL_DEBUG_OUTPUT, "Computed checksum = %X\n", Checksum);
608 
609     /* Re-write the checksum byte */
610 
611     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset +
612         ACPI_CDAT_OFFSET (Checksum));
613 
614     FlWriteFile (ASL_FILE_AML_OUTPUT, &Checksum, 1);
615 
616     /*
617      * Seek to the end of the file. This is done to support multiple file
618      * compilation. Doing this simplifies other parts of the codebase because
619      * it eliminates the need to seek for a different starting place.
620      */
621     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset + Length);
622 }
623 
624 /*******************************************************************************
625  *
626  * FUNCTION:    CgUpdateHeader
627  *
628  * PARAMETERS:  Op                  - Op for the Definition Block
629  *
630  * RETURN:      None.
631  *
632  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
633  *              re-writing the header for the input definition block
634  *
635  ******************************************************************************/
636 
637 static void
CgUpdateHeader(ACPI_PARSE_OBJECT * Op)638 CgUpdateHeader (
639     ACPI_PARSE_OBJECT       *Op)
640 {
641     signed char             Sum;
642     UINT32                  i;
643     UINT32                  Length;
644     UINT8                   FileByte;
645     UINT8                   Checksum;
646 
647 
648     /* Calculate the checksum over the entire definition block */
649 
650     Sum = 0;
651     Length = sizeof (ACPI_TABLE_HEADER) + Op->Asl.AmlSubtreeLength;
652     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset);
653 
654     for (i = 0; i < Length; i++)
655     {
656         if (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) != AE_OK)
657         {
658             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
659                 "Table length is greater than size of the input file");
660             return;
661         }
662 
663         Sum = (signed char) (Sum + FileByte);
664     }
665 
666     Checksum = (UINT8) (0 - Sum);
667 
668     /* Re-write the checksum byte */
669 
670     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset +
671         ACPI_OFFSET (ACPI_TABLE_HEADER, Checksum));
672 
673     FlWriteFile (ASL_FILE_AML_OUTPUT, &Checksum, 1);
674 
675     /*
676      * Seek to the end of the file. This is done to support multiple file
677      * compilation. Doing this simplifies other parts of the codebase because
678      * it eliminates the need to seek for a different starting place.
679      */
680     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset + Length);
681 }
682 
683 
684 /*******************************************************************************
685  *
686  * FUNCTION:    CgWriteNode
687  *
688  * PARAMETERS:  Op            - Parse node to write.
689  *
690  * RETURN:      None.
691  *
692  * DESCRIPTION: Write the AML that corresponds to a parse node.
693  *
694  ******************************************************************************/
695 
696 static void
CgWriteNode(ACPI_PARSE_OBJECT * Op)697 CgWriteNode (
698     ACPI_PARSE_OBJECT       *Op)
699 {
700     ASL_RESOURCE_NODE       *Rnode;
701 
702 
703     /* Write all comments here. */
704 
705     if (AcpiGbl_CaptureComments)
706     {
707         CgWriteAmlComment(Op);
708     }
709 
710     /* Always check for DEFAULT_ARG and other "Noop" nodes */
711     /* TBD: this may not be the best place for this check */
712 
713     if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)  ||
714         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE)      ||
715         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE_END))
716     {
717         return;
718     }
719 
720     Op->Asl.FinalAmlLength = 0;
721 
722     switch (Op->Asl.AmlOpcode)
723     {
724     case AML_RAW_DATA_BYTE:
725     case AML_RAW_DATA_WORD:
726     case AML_RAW_DATA_DWORD:
727     case AML_RAW_DATA_QWORD:
728 
729         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, Op->Asl.AmlLength);
730         return;
731 
732 
733     case AML_RAW_DATA_BUFFER:
734 
735         CgLocalWriteAmlData (Op, Op->Asl.Value.Buffer, Op->Asl.AmlLength);
736         return;
737 
738 
739     case AML_RAW_DATA_CHAIN:
740 
741         Rnode = ACPI_CAST_PTR (ASL_RESOURCE_NODE, Op->Asl.Value.Buffer);
742         while (Rnode)
743         {
744             CgLocalWriteAmlData (Op, Rnode->Buffer, Rnode->BufferLength);
745             Rnode = Rnode->Next;
746         }
747         return;
748 
749     default:
750 
751         /* Internal data opcodes must all appear above */
752 
753         break;
754     }
755 
756     switch (Op->Asl.ParseOpcode)
757     {
758     case PARSEOP_DEFAULT_ARG:
759 
760         break;
761 
762     case PARSEOP_DEFINITION_BLOCK:
763 
764         CgWriteTableHeader (Op);
765         if (AcpiGbl_CaptureComments)
766         {
767             CgWriteAmlDefBlockComment (Op);
768         }
769         break;
770 
771     case PARSEOP_NAMESEG:
772     case PARSEOP_NAMESTRING:
773     case PARSEOP_METHODCALL:
774 
775         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
776         break;
777 
778     default:
779 
780         CgWriteAmlOpcode (Op);
781         break;
782     }
783 }
784