Home | History | Annotate | Line # | Download | only in compiler
      1 /******************************************************************************
      2  *
      3  * Module Name: aslcodegen - AML code generation
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2026, 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     /* Bound copy to header field size to avoid overflow on malformed input */
    482     strncpy (AslGbl_TableHeader.OemId, Child->Asl.Value.String,
    483         ACPI_OEM_ID_SIZE);
    484 
    485     /* OEM TableID */
    486 
    487     Child = Child->Asl.Next;
    488     /* Bound copy to header field size to avoid overflow on malformed input */
    489     strncpy (AslGbl_TableHeader.OemTableId, Child->Asl.Value.String,
    490         ACPI_OEM_TABLE_ID_SIZE);
    491 
    492     /* OEM Revision */
    493 
    494     Child = Child->Asl.Next;
    495     AslGbl_TableHeader.OemRevision = (UINT32) Child->Asl.Value.Integer;
    496 
    497     /* Compiler ID */
    498 
    499     ACPI_COPY_NAMESEG (AslGbl_TableHeader.AslCompilerId, ASL_CREATOR_ID);
    500 
    501     /* Compiler version */
    502 
    503     AslGbl_TableHeader.AslCompilerRevision = ACPI_CA_VERSION;
    504 
    505     /* Table length. Checksum zero for now, will rewrite later */
    506 
    507     AslGbl_TableHeader.Length = sizeof (ACPI_TABLE_HEADER) +
    508         Op->Asl.AmlSubtreeLength;
    509 
    510     /* Calculate the comment lengths for this definition block parseOp */
    511 
    512     if (AcpiGbl_CaptureComments)
    513     {
    514         CvDbgPrint ("Calculating comment lengths for %s in write header\n",
    515             Op->Asl.ParseOpName);
    516 
    517         /*
    518          * Take the filename without extensions, add 3 for the new extension
    519          * and another 3 for the a908 bytecode and null terminator.
    520          */
    521         AslGbl_TableHeader.Length += strrchr (AslGbl_ParseTreeRoot->Asl.Filename, '.')
    522             - AslGbl_ParseTreeRoot->Asl.Filename + 1 + 3 + 3;
    523 
    524         Op->Asl.AmlSubtreeLength +=
    525             strlen (AslGbl_ParseTreeRoot->Asl.Filename) + 3;
    526 
    527         CvDbgPrint ("     Length: %u\n",
    528             (UINT32) strlen (AslGbl_ParseTreeRoot->Asl.Filename) + 3);
    529 
    530         if (Op->Asl.CommentList)
    531         {
    532             Current = Op->Asl.CommentList;
    533             while (Current)
    534             {
    535                 CommentLength = strlen (Current->Comment)+3;
    536                 CvDbgPrint ("Length of standard comment): %d\n", CommentLength);
    537                 CvDbgPrint ("    Comment string: %s\n\n", Current->Comment);
    538                 AslGbl_TableHeader.Length += CommentLength;
    539                 Op->Asl.AmlSubtreeLength += CommentLength;
    540                 Current = Current->Next;
    541                 CvDbgPrint ("    Length: %u\n", CommentLength);
    542             }
    543         }
    544         if (Op->Asl.CloseBraceComment)
    545         {
    546             CommentLength = strlen (Op->Asl.CloseBraceComment)+3;
    547             CvDbgPrint ("Length of inline comment +3: %d\n", CommentLength);
    548             CvDbgPrint ("    Comment string: %s\n\n", Op->Asl.CloseBraceComment);
    549             AslGbl_TableHeader.Length += CommentLength;
    550             Op->Asl.AmlSubtreeLength += CommentLength;
    551             CvDbgPrint ("    Length: %u\n", CommentLength);
    552         }
    553     }
    554 
    555     AslGbl_TableHeader.Checksum = 0;
    556     Op->Asl.FinalAmlOffset = ftell (AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle);
    557 
    558     /* Write entire header and clear the table header global */
    559 
    560     CgLocalWriteAmlData (Op, &AslGbl_TableHeader, sizeof (ACPI_TABLE_HEADER));
    561     memset (&AslGbl_TableHeader, 0, sizeof (ACPI_TABLE_HEADER));
    562 }
    563 
    564 
    565 /*******************************************************************************
    566  *
    567  * FUNCTION:    CgUpdateCdatHeader
    568  *
    569  * PARAMETERS:  Op                  - Op for the Definition Block
    570  *
    571  * RETURN:      None.
    572  *
    573  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
    574  *              re-writing the header for the input definition block
    575  *
    576  ******************************************************************************/
    577 
    578 static void
    579 CgUpdateCdatHeader (
    580     ACPI_PARSE_OBJECT       *Op)
    581 {
    582     signed char             Sum;
    583     UINT32                  i;
    584     UINT32                  Length;
    585     UINT8                   FileByte;
    586     UINT8                   Checksum;
    587 
    588 
    589     /* Calculate the checksum over the entire definition block */
    590 
    591     Sum = 0;
    592     Length = sizeof (ACPI_TABLE_CDAT) + Op->Asl.AmlSubtreeLength;
    593     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset);
    594 
    595     for (i = 0; i < Length; i++)
    596     {
    597         if (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) != AE_OK)
    598         {
    599             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
    600                 "Table length is greater than size of the input file");
    601             return;
    602         }
    603 
    604         Sum = (signed char) (Sum + FileByte);
    605     }
    606 
    607     Checksum = (UINT8) (0 - Sum);
    608 
    609     DbgPrint (ASL_DEBUG_OUTPUT, "Computed checksum = %X\n", Checksum);
    610 
    611     /* Re-write the checksum byte */
    612 
    613     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset +
    614         ACPI_CDAT_OFFSET (Checksum));
    615 
    616     FlWriteFile (ASL_FILE_AML_OUTPUT, &Checksum, 1);
    617 
    618     /*
    619      * Seek to the end of the file. This is done to support multiple file
    620      * compilation. Doing this simplifies other parts of the codebase because
    621      * it eliminates the need to seek for a different starting place.
    622      */
    623     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset + Length);
    624 }
    625 
    626 /*******************************************************************************
    627  *
    628  * FUNCTION:    CgUpdateHeader
    629  *
    630  * PARAMETERS:  Op                  - Op for the Definition Block
    631  *
    632  * RETURN:      None.
    633  *
    634  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
    635  *              re-writing the header for the input definition block
    636  *
    637  ******************************************************************************/
    638 
    639 static void
    640 CgUpdateHeader (
    641     ACPI_PARSE_OBJECT       *Op)
    642 {
    643     signed char             Sum;
    644     UINT32                  i;
    645     UINT32                  Length;
    646     UINT8                   FileByte;
    647     UINT8                   Checksum;
    648 
    649 
    650     /* Calculate the checksum over the entire definition block */
    651 
    652     Sum = 0;
    653     Length = sizeof (ACPI_TABLE_HEADER) + Op->Asl.AmlSubtreeLength;
    654     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset);
    655 
    656     for (i = 0; i < Length; i++)
    657     {
    658         if (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) != AE_OK)
    659         {
    660             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
    661                 "Table length is greater than size of the input file");
    662             return;
    663         }
    664 
    665         Sum = (signed char) (Sum + FileByte);
    666     }
    667 
    668     Checksum = (UINT8) (0 - Sum);
    669 
    670     /* Re-write the checksum byte */
    671 
    672     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset +
    673         ACPI_OFFSET (ACPI_TABLE_HEADER, Checksum));
    674 
    675     FlWriteFile (ASL_FILE_AML_OUTPUT, &Checksum, 1);
    676 
    677     /*
    678      * Seek to the end of the file. This is done to support multiple file
    679      * compilation. Doing this simplifies other parts of the codebase because
    680      * it eliminates the need to seek for a different starting place.
    681      */
    682     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset + Length);
    683 }
    684 
    685 
    686 /*******************************************************************************
    687  *
    688  * FUNCTION:    CgWriteNode
    689  *
    690  * PARAMETERS:  Op            - Parse node to write.
    691  *
    692  * RETURN:      None.
    693  *
    694  * DESCRIPTION: Write the AML that corresponds to a parse node.
    695  *
    696  ******************************************************************************/
    697 
    698 static void
    699 CgWriteNode (
    700     ACPI_PARSE_OBJECT       *Op)
    701 {
    702     ASL_RESOURCE_NODE       *Rnode;
    703 
    704 
    705     /* Write all comments here. */
    706 
    707     if (AcpiGbl_CaptureComments)
    708     {
    709         CgWriteAmlComment(Op);
    710     }
    711 
    712     /* Always check for DEFAULT_ARG and other "Noop" nodes */
    713     /* TBD: this may not be the best place for this check */
    714 
    715     if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)  ||
    716         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE)      ||
    717         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE_END))
    718     {
    719         return;
    720     }
    721 
    722     Op->Asl.FinalAmlLength = 0;
    723 
    724     switch (Op->Asl.AmlOpcode)
    725     {
    726     case AML_RAW_DATA_BYTE:
    727     case AML_RAW_DATA_WORD:
    728     case AML_RAW_DATA_DWORD:
    729     case AML_RAW_DATA_QWORD:
    730 
    731         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, Op->Asl.AmlLength);
    732         return;
    733 
    734 
    735     case AML_RAW_DATA_BUFFER:
    736 
    737         CgLocalWriteAmlData (Op, Op->Asl.Value.Buffer, Op->Asl.AmlLength);
    738         return;
    739 
    740 
    741     case AML_RAW_DATA_CHAIN:
    742 
    743         Rnode = ACPI_CAST_PTR (ASL_RESOURCE_NODE, Op->Asl.Value.Buffer);
    744         while (Rnode)
    745         {
    746             CgLocalWriteAmlData (Op, Rnode->Buffer, Rnode->BufferLength);
    747             Rnode = Rnode->Next;
    748         }
    749         return;
    750 
    751     default:
    752 
    753         /* Internal data opcodes must all appear above */
    754 
    755         break;
    756     }
    757 
    758     switch (Op->Asl.ParseOpcode)
    759     {
    760     case PARSEOP_DEFAULT_ARG:
    761 
    762         break;
    763 
    764     case PARSEOP_DEFINITION_BLOCK:
    765 
    766         CgWriteTableHeader (Op);
    767         if (AcpiGbl_CaptureComments)
    768         {
    769             CgWriteAmlDefBlockComment (Op);
    770         }
    771         break;
    772 
    773     case PARSEOP_NAMESEG:
    774     case PARSEOP_NAMESTRING:
    775     case PARSEOP_METHODCALL:
    776 
    777         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
    778         break;
    779 
    780     default:
    781 
    782         CgWriteAmlOpcode (Op);
    783         break;
    784     }
    785 }
    786