Home | History | Annotate | Line # | Download | only in compiler
aslcodegen.c revision 1.1.1.20
      1 /******************************************************************************
      2  *
      3  * Module Name: aslcodegen - AML code generation
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2022, 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
     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
    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
    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
    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
    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
    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
    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
    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