xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslcodegen.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho  *
328c506b8Sjruoho  * Module Name: aslcodegen - AML code generation
428c506b8Sjruoho  *
528c506b8Sjruoho  *****************************************************************************/
628c506b8Sjruoho 
7124f4c82Sjruoho /*
8*046a2985Schristos  * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho  * All rights reserved.
1028c506b8Sjruoho  *
11124f4c82Sjruoho  * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho  * modification, are permitted provided that the following conditions
13124f4c82Sjruoho  * are met:
14124f4c82Sjruoho  * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho  *    notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho  *    without modification.
17124f4c82Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho  *    including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho  *    binary redistribution.
22124f4c82Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho  *    of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho  *    from this software without specific prior written permission.
2528c506b8Sjruoho  *
26124f4c82Sjruoho  * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho  * Software Foundation.
2928c506b8Sjruoho  *
30124f4c82Sjruoho  * NO WARRANTY
31124f4c82Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho  */
4328c506b8Sjruoho 
4428c506b8Sjruoho #include "aslcompiler.h"
4528c506b8Sjruoho #include "aslcompiler.y.h"
4628c506b8Sjruoho #include "amlcode.h"
47835858a6Schristos #include "acconvert.h"
4882065f3bSchristos #include "actbinfo.h"
4928c506b8Sjruoho 
5028c506b8Sjruoho #define _COMPONENT          ACPI_COMPILER
5128c506b8Sjruoho         ACPI_MODULE_NAME    ("aslcodegen")
5228c506b8Sjruoho 
5328c506b8Sjruoho /* Local prototypes */
5428c506b8Sjruoho 
5528c506b8Sjruoho static ACPI_STATUS
5628c506b8Sjruoho CgAmlWriteWalk (
5728c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op,
5828c506b8Sjruoho     UINT32                  Level,
5928c506b8Sjruoho     void                    *Context);
6028c506b8Sjruoho 
6128c506b8Sjruoho static void
6228c506b8Sjruoho CgWriteAmlOpcode (
6328c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op);
6428c506b8Sjruoho 
6528c506b8Sjruoho static void
6628c506b8Sjruoho CgWriteTableHeader (
6728c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op);
6828c506b8Sjruoho 
6928c506b8Sjruoho static void
7094783addSchristos CgWriteNode (
7194783addSchristos     ACPI_PARSE_OBJECT       *Op);
7228c506b8Sjruoho 
7328c506b8Sjruoho static void
7494783addSchristos CgUpdateHeader (
7528c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op);
7628c506b8Sjruoho 
7782065f3bSchristos static void
7882065f3bSchristos CgUpdateCdatHeader (
7982065f3bSchristos     ACPI_PARSE_OBJECT       *Op);
8082065f3bSchristos 
8128c506b8Sjruoho 
8228c506b8Sjruoho /*******************************************************************************
8328c506b8Sjruoho  *
8428c506b8Sjruoho  * FUNCTION:    CgGenerateAmlOutput
8528c506b8Sjruoho  *
8628c506b8Sjruoho  * PARAMETERS:  None.
8728c506b8Sjruoho  *
8828c506b8Sjruoho  * RETURN:      None
8928c506b8Sjruoho  *
9028c506b8Sjruoho  * DESCRIPTION: Generate AML code. Currently generates the listing file
9128c506b8Sjruoho  *              simultaneously.
9228c506b8Sjruoho  *
9328c506b8Sjruoho  ******************************************************************************/
9428c506b8Sjruoho 
9528c506b8Sjruoho void
CgGenerateAmlOutput(void)9628c506b8Sjruoho CgGenerateAmlOutput (
9728c506b8Sjruoho     void)
9828c506b8Sjruoho {
9928c506b8Sjruoho 
10028c506b8Sjruoho     /* Generate the AML output file */
10128c506b8Sjruoho 
10294783addSchristos     TrWalkParseTree (AslGbl_CurrentDB,
10394783addSchristos         ASL_WALK_VISIT_DOWNWARD | ASL_WALK_VISIT_DB_SEPARATELY,
10428c506b8Sjruoho         CgAmlWriteWalk, NULL, NULL);
105679c17fdSchristos 
106cfbb7280Schristos     DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER2);
10782065f3bSchristos     if (AcpiGbl_CDAT)
10882065f3bSchristos     {
10982065f3bSchristos         CgUpdateCdatHeader (AslGbl_CurrentDB);
11082065f3bSchristos     }
11182065f3bSchristos     else
11282065f3bSchristos     {
11394783addSchristos         CgUpdateHeader (AslGbl_CurrentDB);
11428c506b8Sjruoho     }
11582065f3bSchristos }
11628c506b8Sjruoho 
11728c506b8Sjruoho 
11828c506b8Sjruoho /*******************************************************************************
11928c506b8Sjruoho  *
12028c506b8Sjruoho  * FUNCTION:    CgAmlWriteWalk
12128c506b8Sjruoho  *
12228c506b8Sjruoho  * PARAMETERS:  ASL_WALK_CALLBACK
12328c506b8Sjruoho  *
12428c506b8Sjruoho  * RETURN:      Status
12528c506b8Sjruoho  *
12628c506b8Sjruoho  * DESCRIPTION: Parse tree walk to generate the AML code.
12728c506b8Sjruoho  *
12828c506b8Sjruoho  ******************************************************************************/
12928c506b8Sjruoho 
13028c506b8Sjruoho static ACPI_STATUS
CgAmlWriteWalk(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)13128c506b8Sjruoho CgAmlWriteWalk (
13228c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op,
13328c506b8Sjruoho     UINT32                  Level,
13428c506b8Sjruoho     void                    *Context)
13528c506b8Sjruoho {
13628c506b8Sjruoho 
137cfbb7280Schristos     /* Generate the AML for this node */
138cfbb7280Schristos 
139cfbb7280Schristos     CgWriteNode (Op);
140cfbb7280Schristos 
1414c4e8184Schristos     if (!AslGbl_DebugFlag)
142cfbb7280Schristos     {
143cfbb7280Schristos         return (AE_OK);
144cfbb7280Schristos     }
145cfbb7280Schristos 
146cfbb7280Schristos     /* Print header at level 0. Alignment assumes 32-bit pointers */
147cfbb7280Schristos 
14828c506b8Sjruoho     if (!Level)
14928c506b8Sjruoho     {
15028c506b8Sjruoho         DbgPrint (ASL_TREE_OUTPUT,
151cfbb7280Schristos             "\nFinal parse tree used for AML output:\n");
152cfbb7280Schristos         DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER2);
15328c506b8Sjruoho     }
15428c506b8Sjruoho 
155cfbb7280Schristos     /* Dump ParseOp name and possible value */
15628c506b8Sjruoho 
157cfbb7280Schristos     switch (Op->Asl.ParseOpcode)
15828c506b8Sjruoho     {
159cfbb7280Schristos     case PARSEOP_NAMESEG:
160cfbb7280Schristos     case PARSEOP_NAMESTRING:
161cfbb7280Schristos     case PARSEOP_METHODCALL:
162cfbb7280Schristos     case PARSEOP_STRING_LITERAL:
163cfbb7280Schristos 
164cfbb7280Schristos         UtDumpStringOp (Op, Level);
165cfbb7280Schristos         break;
166cfbb7280Schristos 
167cfbb7280Schristos     default:
168cfbb7280Schristos 
169cfbb7280Schristos         UtDumpBasicOp (Op, Level);
170cfbb7280Schristos         break;
17128c506b8Sjruoho     }
17228c506b8Sjruoho 
173cfbb7280Schristos     DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_DEBUG2,
17428c506b8Sjruoho         /* 1  */ (UINT32) Op->Asl.Value.Integer,
17528c506b8Sjruoho         /* 2  */ Op->Asl.ParseOpcode,
17628c506b8Sjruoho         /* 3  */ Op->Asl.AmlOpcode,
17728c506b8Sjruoho         /* 4  */ Op->Asl.AmlOpcodeLength,
17828c506b8Sjruoho         /* 5  */ Op->Asl.AmlPkgLenBytes,
17928c506b8Sjruoho         /* 6  */ Op->Asl.AmlLength,
18028c506b8Sjruoho         /* 7  */ Op->Asl.AmlSubtreeLength,
18128c506b8Sjruoho         /* 8  */ Op->Asl.Parent ? Op->Asl.Parent->Asl.AmlSubtreeLength : 0,
18228c506b8Sjruoho         /* 9  */ Op,
183679c17fdSchristos         /* 10 */ Op->Asl.Parent,
184679c17fdSchristos         /* 11 */ Op->Asl.Child,
185679c17fdSchristos         /* 12 */ Op->Asl.Next,
186679c17fdSchristos         /* 13 */ Op->Asl.CompileFlags,
187679c17fdSchristos         /* 14 */ Op->Asl.AcpiBtype,
188679c17fdSchristos         /* 15 */ Op->Asl.FinalAmlLength,
189679c17fdSchristos         /* 16 */ Op->Asl.Column,
190c72da027Schristos         /* 17 */ Op->Asl.LineNumber,
191c72da027Schristos         /* 18 */ Op->Asl.EndLine,
192c72da027Schristos         /* 19 */ Op->Asl.LogicalLineNumber,
193c72da027Schristos         /* 20 */ Op->Asl.EndLogicalLine);
19428c506b8Sjruoho 
19589b8eb6cSchristos     TrPrintOpFlags (Op->Asl.CompileFlags, ASL_TREE_OUTPUT);
19689b8eb6cSchristos     DbgPrint (ASL_TREE_OUTPUT, "\n");
19728c506b8Sjruoho     return (AE_OK);
19828c506b8Sjruoho }
19928c506b8Sjruoho 
20028c506b8Sjruoho 
20128c506b8Sjruoho /*******************************************************************************
20228c506b8Sjruoho  *
20328c506b8Sjruoho  * FUNCTION:    CgLocalWriteAmlData
20428c506b8Sjruoho  *
20528c506b8Sjruoho  * PARAMETERS:  Op              - Current parse op
20628c506b8Sjruoho  *              Buffer          - Buffer to write
20728c506b8Sjruoho  *              Length          - Size of data in buffer
20828c506b8Sjruoho  *
20928c506b8Sjruoho  * RETURN:      None
21028c506b8Sjruoho  *
21128c506b8Sjruoho  * DESCRIPTION: Write a buffer of AML data to the AML output file.
21228c506b8Sjruoho  *
21328c506b8Sjruoho  ******************************************************************************/
21428c506b8Sjruoho 
215835858a6Schristos void
CgLocalWriteAmlData(ACPI_PARSE_OBJECT * Op,void * Buffer,UINT32 Length)21628c506b8Sjruoho CgLocalWriteAmlData (
21728c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op,
21828c506b8Sjruoho     void                    *Buffer,
21928c506b8Sjruoho     UINT32                  Length)
22028c506b8Sjruoho {
22128c506b8Sjruoho 
22228c506b8Sjruoho     /* Write the raw data to the AML file */
22328c506b8Sjruoho 
22428c506b8Sjruoho     FlWriteFile (ASL_FILE_AML_OUTPUT, Buffer, Length);
22528c506b8Sjruoho 
22628c506b8Sjruoho     /* Update the final AML length for this node (used for listings) */
22728c506b8Sjruoho 
22828c506b8Sjruoho     if (Op)
22928c506b8Sjruoho     {
23028c506b8Sjruoho         Op->Asl.FinalAmlLength += Length;
23128c506b8Sjruoho     }
23228c506b8Sjruoho }
23328c506b8Sjruoho 
23428c506b8Sjruoho 
23528c506b8Sjruoho /*******************************************************************************
23628c506b8Sjruoho  *
23728c506b8Sjruoho  * FUNCTION:    CgWriteAmlOpcode
23828c506b8Sjruoho  *
23928c506b8Sjruoho  * PARAMETERS:  Op            - Parse node with an AML opcode
24028c506b8Sjruoho  *
24128c506b8Sjruoho  * RETURN:      None.
24228c506b8Sjruoho  *
24328c506b8Sjruoho  * DESCRIPTION: Write the AML opcode corresponding to a parse node.
24428c506b8Sjruoho  *
24528c506b8Sjruoho  ******************************************************************************/
24628c506b8Sjruoho 
24728c506b8Sjruoho static void
CgWriteAmlOpcode(ACPI_PARSE_OBJECT * Op)24828c506b8Sjruoho CgWriteAmlOpcode (
24928c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op)
25028c506b8Sjruoho {
25128c506b8Sjruoho     UINT8                   PkgLenFirstByte;
25228c506b8Sjruoho     UINT32                  i;
25328c506b8Sjruoho     union {
25428c506b8Sjruoho         UINT16                  Opcode;
25528c506b8Sjruoho         UINT8                   OpcodeBytes[2];
25628c506b8Sjruoho     } Aml;
25728c506b8Sjruoho     union {
25828c506b8Sjruoho         UINT32                  Len;
25928c506b8Sjruoho         UINT8                   LenBytes[4];
26028c506b8Sjruoho     } PkgLen;
26128c506b8Sjruoho 
26228c506b8Sjruoho 
26328c506b8Sjruoho     /* We expect some DEFAULT_ARGs, just ignore them */
26428c506b8Sjruoho 
26528c506b8Sjruoho     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
26628c506b8Sjruoho     {
26728c506b8Sjruoho         return;
26828c506b8Sjruoho     }
26928c506b8Sjruoho 
270835858a6Schristos     /*
271835858a6Schristos      * Before printing the bytecode, generate comment byte codes
272835858a6Schristos      * associated with this node.
273835858a6Schristos      */
274062782b3Schristos     if (AcpiGbl_CaptureComments)
275835858a6Schristos     {
276835858a6Schristos         CgWriteAmlComment(Op);
277835858a6Schristos     }
278835858a6Schristos 
27928c506b8Sjruoho     switch (Op->Asl.AmlOpcode)
28028c506b8Sjruoho     {
28128c506b8Sjruoho     case AML_UNASSIGNED_OPCODE:
28228c506b8Sjruoho 
28328c506b8Sjruoho         /* These opcodes should not get here */
28428c506b8Sjruoho 
28528c506b8Sjruoho         printf ("Found a node with an unassigned AML opcode\n");
28671e38f1dSchristos         FlPrintFile (ASL_FILE_STDERR,
28771e38f1dSchristos             "Found a node with an unassigned AML opcode\n");
28828c506b8Sjruoho         return;
28928c506b8Sjruoho 
29028c506b8Sjruoho     case AML_INT_RESERVEDFIELD_OP:
29128c506b8Sjruoho 
29228c506b8Sjruoho         /* Special opcodes for within a field definition */
29328c506b8Sjruoho 
294ff4a156dSchristos         Aml.Opcode = AML_FIELD_OFFSET_OP;
29528c506b8Sjruoho         break;
29628c506b8Sjruoho 
29728c506b8Sjruoho     case AML_INT_ACCESSFIELD_OP:
29828c506b8Sjruoho 
299ff4a156dSchristos         Aml.Opcode = AML_FIELD_ACCESS_OP;
300ff4a156dSchristos         break;
301ff4a156dSchristos 
302ff4a156dSchristos     case AML_INT_CONNECTION_OP:
303ff4a156dSchristos 
304ff4a156dSchristos         Aml.Opcode = AML_FIELD_CONNECTION_OP;
30528c506b8Sjruoho         break;
30628c506b8Sjruoho 
30728c506b8Sjruoho     default:
308ff4a156dSchristos 
30928c506b8Sjruoho         Aml.Opcode = Op->Asl.AmlOpcode;
31028c506b8Sjruoho         break;
31128c506b8Sjruoho     }
31228c506b8Sjruoho 
31328c506b8Sjruoho 
31428c506b8Sjruoho     switch (Aml.Opcode)
31528c506b8Sjruoho     {
31628c506b8Sjruoho     case AML_PACKAGE_LENGTH:
31728c506b8Sjruoho 
31828c506b8Sjruoho         /* Value is the length to be encoded (Used in field definitions) */
31928c506b8Sjruoho 
32028c506b8Sjruoho         PkgLen.Len = (UINT32) Op->Asl.Value.Integer;
32128c506b8Sjruoho         break;
32228c506b8Sjruoho 
32328c506b8Sjruoho     default:
32428c506b8Sjruoho 
32528c506b8Sjruoho         /* Check for two-byte opcode */
32628c506b8Sjruoho 
32728c506b8Sjruoho         if (Aml.Opcode > 0x00FF)
32828c506b8Sjruoho         {
32928c506b8Sjruoho             /* Write the high byte first */
33028c506b8Sjruoho 
33128c506b8Sjruoho             CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[1], 1);
33228c506b8Sjruoho         }
33328c506b8Sjruoho 
33428c506b8Sjruoho         CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[0], 1);
33528c506b8Sjruoho 
33628c506b8Sjruoho         /* Subtreelength doesn't include length of package length bytes */
33728c506b8Sjruoho 
33828c506b8Sjruoho         PkgLen.Len = Op->Asl.AmlSubtreeLength + Op->Asl.AmlPkgLenBytes;
33928c506b8Sjruoho         break;
34028c506b8Sjruoho     }
34128c506b8Sjruoho 
34228c506b8Sjruoho     /* Does this opcode have an associated "PackageLength" field? */
34328c506b8Sjruoho 
34489b8eb6cSchristos     if (Op->Asl.CompileFlags & OP_AML_PACKAGE)
34528c506b8Sjruoho     {
34628c506b8Sjruoho         if (Op->Asl.AmlPkgLenBytes == 1)
34728c506b8Sjruoho         {
34828c506b8Sjruoho             /* Simplest case -- no bytes to follow, just write the count */
34928c506b8Sjruoho 
35028c506b8Sjruoho             CgLocalWriteAmlData (Op, &PkgLen.LenBytes[0], 1);
35128c506b8Sjruoho         }
35228c506b8Sjruoho         else if (Op->Asl.AmlPkgLenBytes != 0)
35328c506b8Sjruoho         {
35428c506b8Sjruoho             /*
35528c506b8Sjruoho              * Encode the "bytes to follow" in the first byte, top two bits.
35628c506b8Sjruoho              * The low-order nybble of the length is in the bottom 4 bits
35728c506b8Sjruoho              */
35828c506b8Sjruoho             PkgLenFirstByte = (UINT8)
35928c506b8Sjruoho                 (((UINT32) (Op->Asl.AmlPkgLenBytes - 1) << 6) |
36028c506b8Sjruoho                 (PkgLen.LenBytes[0] & 0x0F));
36128c506b8Sjruoho 
36228c506b8Sjruoho             CgLocalWriteAmlData (Op, &PkgLenFirstByte, 1);
36328c506b8Sjruoho 
36428c506b8Sjruoho             /*
36528c506b8Sjruoho              * Shift the length over by the 4 bits we just stuffed
36628c506b8Sjruoho              * in the first byte
36728c506b8Sjruoho              */
36828c506b8Sjruoho             PkgLen.Len >>= 4;
36928c506b8Sjruoho 
37071e38f1dSchristos             /*
37171e38f1dSchristos              * Now we can write the remaining bytes -
37271e38f1dSchristos              * either 1, 2, or 3 bytes
37371e38f1dSchristos              */
37428c506b8Sjruoho             for (i = 0; i < (UINT32) (Op->Asl.AmlPkgLenBytes - 1); i++)
37528c506b8Sjruoho             {
37628c506b8Sjruoho                 CgLocalWriteAmlData (Op, &PkgLen.LenBytes[i], 1);
37728c506b8Sjruoho             }
37828c506b8Sjruoho         }
37928c506b8Sjruoho     }
38028c506b8Sjruoho 
38128c506b8Sjruoho     switch (Aml.Opcode)
38228c506b8Sjruoho     {
38328c506b8Sjruoho     case AML_BYTE_OP:
38428c506b8Sjruoho 
38528c506b8Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 1);
38628c506b8Sjruoho         break;
38728c506b8Sjruoho 
38828c506b8Sjruoho     case AML_WORD_OP:
38928c506b8Sjruoho 
39028c506b8Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 2);
39128c506b8Sjruoho        break;
39228c506b8Sjruoho 
39328c506b8Sjruoho     case AML_DWORD_OP:
39428c506b8Sjruoho 
39528c506b8Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 4);
39628c506b8Sjruoho         break;
39728c506b8Sjruoho 
39828c506b8Sjruoho     case AML_QWORD_OP:
39928c506b8Sjruoho 
40028c506b8Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 8);
40128c506b8Sjruoho         break;
40228c506b8Sjruoho 
40328c506b8Sjruoho     case AML_STRING_OP:
40428c506b8Sjruoho 
40528c506b8Sjruoho         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
40628c506b8Sjruoho         break;
40728c506b8Sjruoho 
40828c506b8Sjruoho     default:
409ff4a156dSchristos 
41028c506b8Sjruoho         /* All data opcodes must appear above */
411ff4a156dSchristos 
41228c506b8Sjruoho         break;
41328c506b8Sjruoho     }
41428c506b8Sjruoho }
41528c506b8Sjruoho 
41628c506b8Sjruoho 
41728c506b8Sjruoho /*******************************************************************************
41828c506b8Sjruoho  *
41928c506b8Sjruoho  * FUNCTION:    CgWriteTableHeader
42028c506b8Sjruoho  *
42128c506b8Sjruoho  * PARAMETERS:  Op        - The DEFINITIONBLOCK node
42228c506b8Sjruoho  *
42328c506b8Sjruoho  * RETURN:      None
42428c506b8Sjruoho  *
42528c506b8Sjruoho  * DESCRIPTION: Write a table header corresponding to the DEFINITIONBLOCK
42628c506b8Sjruoho  *
42794783addSchristos  * NOTE: Input strings should be validated before this function is invoked.
42894783addSchristos  *
42928c506b8Sjruoho  ******************************************************************************/
43028c506b8Sjruoho 
43128c506b8Sjruoho static void
CgWriteTableHeader(ACPI_PARSE_OBJECT * Op)43228c506b8Sjruoho CgWriteTableHeader (
43328c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op)
43428c506b8Sjruoho {
43528c506b8Sjruoho     ACPI_PARSE_OBJECT       *Child;
436835858a6Schristos     UINT32                  CommentLength;
437835858a6Schristos     ACPI_COMMENT_NODE       *Current;
43828c506b8Sjruoho 
43928c506b8Sjruoho 
44094783addSchristos     memset (&AslGbl_TableHeader, 0, sizeof (ACPI_TABLE_HEADER));
44194783addSchristos 
44228c506b8Sjruoho     /* AML filename */
44328c506b8Sjruoho 
44428c506b8Sjruoho     Child = Op->Asl.Child;
44528c506b8Sjruoho 
44628c506b8Sjruoho     /* Signature */
44728c506b8Sjruoho 
44828c506b8Sjruoho     Child = Child->Asl.Next;
449835858a6Schristos 
450835858a6Schristos     /*
451835858a6Schristos      * For ASL-/ASL+ converter: replace the table signature with
452835858a6Schristos      * "XXXX" and save the original table signature. This results in an AML
453835858a6Schristos      * file with the signature "XXXX". The converter should remove this AML
454835858a6Schristos      * file. In the event where this AML file does not get deleted, the
455835858a6Schristos      * "XXXX" table signature prevents this AML file from running on the AML
456835858a6Schristos      * interpreter.
457835858a6Schristos      */
458062782b3Schristos     if (AcpiGbl_CaptureComments)
459835858a6Schristos     {
46094783addSchristos         ACPI_COPY_NAMESEG (AcpiGbl_TableSig, Child->Asl.Value.String);
461835858a6Schristos         Child->Asl.Value.String = ACPI_SIG_XXXX;
462835858a6Schristos     }
463835858a6Schristos 
46494783addSchristos     ACPI_COPY_NAMESEG (AslGbl_TableHeader.Signature, Child->Asl.Value.String);
46528c506b8Sjruoho 
46628c506b8Sjruoho     /* Revision */
46728c506b8Sjruoho 
46828c506b8Sjruoho     Child = Child->Asl.Next;
4694c4e8184Schristos     AslGbl_TableHeader.Revision = (UINT8) Child->Asl.Value.Integer;
47028c506b8Sjruoho 
47128c506b8Sjruoho     /* Command-line Revision override */
47228c506b8Sjruoho 
4734c4e8184Schristos     if (AslGbl_RevisionOverride)
47428c506b8Sjruoho     {
4754c4e8184Schristos         AslGbl_TableHeader.Revision = AslGbl_RevisionOverride;
47628c506b8Sjruoho     }
47728c506b8Sjruoho 
47828c506b8Sjruoho     /* OEMID */
47928c506b8Sjruoho 
48028c506b8Sjruoho     Child = Child->Asl.Next;
48194783addSchristos     memcpy (AslGbl_TableHeader.OemId, Child->Asl.Value.String,
48294783addSchristos         strlen (Child->Asl.Value.String));
48328c506b8Sjruoho 
48428c506b8Sjruoho     /* OEM TableID */
48528c506b8Sjruoho 
48628c506b8Sjruoho     Child = Child->Asl.Next;
48794783addSchristos     memcpy (AslGbl_TableHeader.OemTableId, Child->Asl.Value.String,
48894783addSchristos         strlen (Child->Asl.Value.String));
48928c506b8Sjruoho 
49028c506b8Sjruoho     /* OEM Revision */
49128c506b8Sjruoho 
49228c506b8Sjruoho     Child = Child->Asl.Next;
4934c4e8184Schristos     AslGbl_TableHeader.OemRevision = (UINT32) Child->Asl.Value.Integer;
49428c506b8Sjruoho 
49528c506b8Sjruoho     /* Compiler ID */
49628c506b8Sjruoho 
49794783addSchristos     ACPI_COPY_NAMESEG (AslGbl_TableHeader.AslCompilerId, ASL_CREATOR_ID);
49828c506b8Sjruoho 
49928c506b8Sjruoho     /* Compiler version */
50028c506b8Sjruoho 
5014c4e8184Schristos     AslGbl_TableHeader.AslCompilerRevision = ACPI_CA_VERSION;
50228c506b8Sjruoho 
50328c506b8Sjruoho     /* Table length. Checksum zero for now, will rewrite later */
50428c506b8Sjruoho 
5054c4e8184Schristos     AslGbl_TableHeader.Length = sizeof (ACPI_TABLE_HEADER) +
50671e38f1dSchristos         Op->Asl.AmlSubtreeLength;
507835858a6Schristos 
508835858a6Schristos     /* Calculate the comment lengths for this definition block parseOp */
509835858a6Schristos 
510062782b3Schristos     if (AcpiGbl_CaptureComments)
511835858a6Schristos     {
512835858a6Schristos         CvDbgPrint ("Calculating comment lengths for %s in write header\n",
513835858a6Schristos             Op->Asl.ParseOpName);
514835858a6Schristos 
515835858a6Schristos         /*
516835858a6Schristos          * Take the filename without extensions, add 3 for the new extension
517835858a6Schristos          * and another 3 for the a908 bytecode and null terminator.
518835858a6Schristos          */
5194c4e8184Schristos         AslGbl_TableHeader.Length += strrchr (AslGbl_ParseTreeRoot->Asl.Filename, '.')
5204c4e8184Schristos             - AslGbl_ParseTreeRoot->Asl.Filename + 1 + 3 + 3;
5214c4e8184Schristos 
522835858a6Schristos         Op->Asl.AmlSubtreeLength +=
5234c4e8184Schristos             strlen (AslGbl_ParseTreeRoot->Asl.Filename) + 3;
5244c4e8184Schristos 
525783af925Schristos         CvDbgPrint ("     Length: %u\n",
526783af925Schristos             (UINT32) strlen (AslGbl_ParseTreeRoot->Asl.Filename) + 3);
527835858a6Schristos 
528835858a6Schristos         if (Op->Asl.CommentList)
529835858a6Schristos         {
530835858a6Schristos             Current = Op->Asl.CommentList;
531835858a6Schristos             while (Current)
532835858a6Schristos             {
533835858a6Schristos                 CommentLength = strlen (Current->Comment)+3;
534835858a6Schristos                 CvDbgPrint ("Length of standard comment): %d\n", CommentLength);
535835858a6Schristos                 CvDbgPrint ("    Comment string: %s\n\n", Current->Comment);
5364c4e8184Schristos                 AslGbl_TableHeader.Length += CommentLength;
537835858a6Schristos                 Op->Asl.AmlSubtreeLength += CommentLength;
538835858a6Schristos                 Current = Current->Next;
539835858a6Schristos                 CvDbgPrint ("    Length: %u\n", CommentLength);
540835858a6Schristos             }
541835858a6Schristos         }
542835858a6Schristos         if (Op->Asl.CloseBraceComment)
543835858a6Schristos         {
544835858a6Schristos             CommentLength = strlen (Op->Asl.CloseBraceComment)+3;
545835858a6Schristos             CvDbgPrint ("Length of inline comment +3: %d\n", CommentLength);
546835858a6Schristos             CvDbgPrint ("    Comment string: %s\n\n", Op->Asl.CloseBraceComment);
5474c4e8184Schristos             AslGbl_TableHeader.Length += CommentLength;
548835858a6Schristos             Op->Asl.AmlSubtreeLength += CommentLength;
549835858a6Schristos             CvDbgPrint ("    Length: %u\n", CommentLength);
550835858a6Schristos         }
551835858a6Schristos     }
552835858a6Schristos 
5534c4e8184Schristos     AslGbl_TableHeader.Checksum = 0;
5544c4e8184Schristos     Op->Asl.FinalAmlOffset = ftell (AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle);
55571e38f1dSchristos 
55671e38f1dSchristos     /* Write entire header and clear the table header global */
55771e38f1dSchristos 
5584c4e8184Schristos     CgLocalWriteAmlData (Op, &AslGbl_TableHeader, sizeof (ACPI_TABLE_HEADER));
5594c4e8184Schristos     memset (&AslGbl_TableHeader, 0, sizeof (ACPI_TABLE_HEADER));
56071e38f1dSchristos }
56171e38f1dSchristos 
56271e38f1dSchristos 
56371e38f1dSchristos /*******************************************************************************
56471e38f1dSchristos  *
56582065f3bSchristos  * FUNCTION:    CgUpdateCdatHeader
56682065f3bSchristos  *
56782065f3bSchristos  * PARAMETERS:  Op                  - Op for the Definition Block
56882065f3bSchristos  *
56982065f3bSchristos  * RETURN:      None.
57082065f3bSchristos  *
57182065f3bSchristos  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
57282065f3bSchristos  *              re-writing the header for the input definition block
57382065f3bSchristos  *
57482065f3bSchristos  ******************************************************************************/
57582065f3bSchristos 
57682065f3bSchristos static void
CgUpdateCdatHeader(ACPI_PARSE_OBJECT * Op)57782065f3bSchristos CgUpdateCdatHeader (
57882065f3bSchristos     ACPI_PARSE_OBJECT       *Op)
57982065f3bSchristos {
58082065f3bSchristos     signed char             Sum;
58182065f3bSchristos     UINT32                  i;
58282065f3bSchristos     UINT32                  Length;
58382065f3bSchristos     UINT8                   FileByte;
58482065f3bSchristos     UINT8                   Checksum;
58582065f3bSchristos 
58682065f3bSchristos 
58782065f3bSchristos     /* Calculate the checksum over the entire definition block */
58882065f3bSchristos 
58982065f3bSchristos     Sum = 0;
59082065f3bSchristos     Length = sizeof (ACPI_TABLE_CDAT) + Op->Asl.AmlSubtreeLength;
59182065f3bSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset);
59282065f3bSchristos 
59382065f3bSchristos     for (i = 0; i < Length; i++)
59482065f3bSchristos     {
59582065f3bSchristos         if (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) != AE_OK)
59682065f3bSchristos         {
59782065f3bSchristos             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
59882065f3bSchristos                 "Table length is greater than size of the input file");
59982065f3bSchristos             return;
60082065f3bSchristos         }
60182065f3bSchristos 
60282065f3bSchristos         Sum = (signed char) (Sum + FileByte);
60382065f3bSchristos     }
60482065f3bSchristos 
60582065f3bSchristos     Checksum = (UINT8) (0 - Sum);
60682065f3bSchristos 
60782065f3bSchristos     DbgPrint (ASL_DEBUG_OUTPUT, "Computed checksum = %X\n", Checksum);
60882065f3bSchristos 
60982065f3bSchristos     /* Re-write the checksum byte */
61082065f3bSchristos 
61182065f3bSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset +
61282065f3bSchristos         ACPI_CDAT_OFFSET (Checksum));
61382065f3bSchristos 
61482065f3bSchristos     FlWriteFile (ASL_FILE_AML_OUTPUT, &Checksum, 1);
61582065f3bSchristos 
61682065f3bSchristos     /*
61782065f3bSchristos      * Seek to the end of the file. This is done to support multiple file
61882065f3bSchristos      * compilation. Doing this simplifies other parts of the codebase because
61982065f3bSchristos      * it eliminates the need to seek for a different starting place.
62082065f3bSchristos      */
62182065f3bSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset + Length);
62282065f3bSchristos }
62382065f3bSchristos 
62482065f3bSchristos /*******************************************************************************
62582065f3bSchristos  *
62671e38f1dSchristos  * FUNCTION:    CgUpdateHeader
62771e38f1dSchristos  *
62871e38f1dSchristos  * PARAMETERS:  Op                  - Op for the Definition Block
62971e38f1dSchristos  *
63071e38f1dSchristos  * RETURN:      None.
63171e38f1dSchristos  *
63271e38f1dSchristos  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
63371e38f1dSchristos  *              re-writing the header for the input definition block
63471e38f1dSchristos  *
63571e38f1dSchristos  ******************************************************************************/
63671e38f1dSchristos 
63771e38f1dSchristos static void
CgUpdateHeader(ACPI_PARSE_OBJECT * Op)63871e38f1dSchristos CgUpdateHeader (
63971e38f1dSchristos     ACPI_PARSE_OBJECT       *Op)
64071e38f1dSchristos {
64171e38f1dSchristos     signed char             Sum;
64271e38f1dSchristos     UINT32                  i;
64371e38f1dSchristos     UINT32                  Length;
64471e38f1dSchristos     UINT8                   FileByte;
64571e38f1dSchristos     UINT8                   Checksum;
64671e38f1dSchristos 
64771e38f1dSchristos 
64871e38f1dSchristos     /* Calculate the checksum over the entire definition block */
64971e38f1dSchristos 
65071e38f1dSchristos     Sum = 0;
65171e38f1dSchristos     Length = sizeof (ACPI_TABLE_HEADER) + Op->Asl.AmlSubtreeLength;
65271e38f1dSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset);
65371e38f1dSchristos 
65471e38f1dSchristos     for (i = 0; i < Length; i++)
65571e38f1dSchristos     {
65671e38f1dSchristos         if (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) != AE_OK)
65771e38f1dSchristos         {
658783af925Schristos             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
659783af925Schristos                 "Table length is greater than size of the input file");
66071e38f1dSchristos             return;
66171e38f1dSchristos         }
66271e38f1dSchristos 
66371e38f1dSchristos         Sum = (signed char) (Sum + FileByte);
66471e38f1dSchristos     }
66571e38f1dSchristos 
66671e38f1dSchristos     Checksum = (UINT8) (0 - Sum);
66771e38f1dSchristos 
668360a9019Schristos     /* Re-write the checksum byte */
66971e38f1dSchristos 
67071e38f1dSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset +
67171e38f1dSchristos         ACPI_OFFSET (ACPI_TABLE_HEADER, Checksum));
67271e38f1dSchristos 
67371e38f1dSchristos     FlWriteFile (ASL_FILE_AML_OUTPUT, &Checksum, 1);
67428c506b8Sjruoho 
67594783addSchristos     /*
67694783addSchristos      * Seek to the end of the file. This is done to support multiple file
67794783addSchristos      * compilation. Doing this simplifies other parts of the codebase because
67894783addSchristos      * it eliminates the need to seek for a different starting place.
67994783addSchristos      */
68094783addSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset + Length);
68128c506b8Sjruoho }
68228c506b8Sjruoho 
68328c506b8Sjruoho 
68428c506b8Sjruoho /*******************************************************************************
68528c506b8Sjruoho  *
68628c506b8Sjruoho  * FUNCTION:    CgWriteNode
68728c506b8Sjruoho  *
68828c506b8Sjruoho  * PARAMETERS:  Op            - Parse node to write.
68928c506b8Sjruoho  *
69028c506b8Sjruoho  * RETURN:      None.
69128c506b8Sjruoho  *
69228c506b8Sjruoho  * DESCRIPTION: Write the AML that corresponds to a parse node.
69328c506b8Sjruoho  *
69428c506b8Sjruoho  ******************************************************************************/
69528c506b8Sjruoho 
69628c506b8Sjruoho static void
CgWriteNode(ACPI_PARSE_OBJECT * Op)69728c506b8Sjruoho CgWriteNode (
69828c506b8Sjruoho     ACPI_PARSE_OBJECT       *Op)
69928c506b8Sjruoho {
70028c506b8Sjruoho     ASL_RESOURCE_NODE       *Rnode;
70128c506b8Sjruoho 
70228c506b8Sjruoho 
703835858a6Schristos     /* Write all comments here. */
704062782b3Schristos 
705062782b3Schristos     if (AcpiGbl_CaptureComments)
706835858a6Schristos     {
707835858a6Schristos         CgWriteAmlComment(Op);
708835858a6Schristos     }
709835858a6Schristos 
71028c506b8Sjruoho     /* Always check for DEFAULT_ARG and other "Noop" nodes */
71128c506b8Sjruoho     /* TBD: this may not be the best place for this check */
71228c506b8Sjruoho 
71328c506b8Sjruoho     if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)  ||
71428c506b8Sjruoho         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE)      ||
71528c506b8Sjruoho         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE_END))
71628c506b8Sjruoho     {
71728c506b8Sjruoho         return;
71828c506b8Sjruoho     }
71928c506b8Sjruoho 
72028c506b8Sjruoho     Op->Asl.FinalAmlLength = 0;
72128c506b8Sjruoho 
72228c506b8Sjruoho     switch (Op->Asl.AmlOpcode)
72328c506b8Sjruoho     {
72428c506b8Sjruoho     case AML_RAW_DATA_BYTE:
72528c506b8Sjruoho     case AML_RAW_DATA_WORD:
72628c506b8Sjruoho     case AML_RAW_DATA_DWORD:
72728c506b8Sjruoho     case AML_RAW_DATA_QWORD:
72828c506b8Sjruoho 
72928c506b8Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, Op->Asl.AmlLength);
73028c506b8Sjruoho         return;
73128c506b8Sjruoho 
73228c506b8Sjruoho 
73328c506b8Sjruoho     case AML_RAW_DATA_BUFFER:
73428c506b8Sjruoho 
73528c506b8Sjruoho         CgLocalWriteAmlData (Op, Op->Asl.Value.Buffer, Op->Asl.AmlLength);
73628c506b8Sjruoho         return;
73728c506b8Sjruoho 
73828c506b8Sjruoho 
73928c506b8Sjruoho     case AML_RAW_DATA_CHAIN:
74028c506b8Sjruoho 
74128c506b8Sjruoho         Rnode = ACPI_CAST_PTR (ASL_RESOURCE_NODE, Op->Asl.Value.Buffer);
74228c506b8Sjruoho         while (Rnode)
74328c506b8Sjruoho         {
74428c506b8Sjruoho             CgLocalWriteAmlData (Op, Rnode->Buffer, Rnode->BufferLength);
74528c506b8Sjruoho             Rnode = Rnode->Next;
74628c506b8Sjruoho         }
74728c506b8Sjruoho         return;
74828c506b8Sjruoho 
74928c506b8Sjruoho     default:
750ff4a156dSchristos 
75128c506b8Sjruoho         /* Internal data opcodes must all appear above */
752ff4a156dSchristos 
75328c506b8Sjruoho         break;
75428c506b8Sjruoho     }
75528c506b8Sjruoho 
75628c506b8Sjruoho     switch (Op->Asl.ParseOpcode)
75728c506b8Sjruoho     {
75828c506b8Sjruoho     case PARSEOP_DEFAULT_ARG:
75928c506b8Sjruoho 
76028c506b8Sjruoho         break;
76128c506b8Sjruoho 
76271e38f1dSchristos     case PARSEOP_DEFINITION_BLOCK:
76328c506b8Sjruoho 
76428c506b8Sjruoho         CgWriteTableHeader (Op);
765062782b3Schristos         if (AcpiGbl_CaptureComments)
766835858a6Schristos         {
767835858a6Schristos             CgWriteAmlDefBlockComment (Op);
768835858a6Schristos         }
76928c506b8Sjruoho         break;
77028c506b8Sjruoho 
77128c506b8Sjruoho     case PARSEOP_NAMESEG:
77228c506b8Sjruoho     case PARSEOP_NAMESTRING:
77328c506b8Sjruoho     case PARSEOP_METHODCALL:
77428c506b8Sjruoho 
77528c506b8Sjruoho         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
77628c506b8Sjruoho         break;
77728c506b8Sjruoho 
77828c506b8Sjruoho     default:
77928c506b8Sjruoho 
78028c506b8Sjruoho         CgWriteAmlOpcode (Op);
78128c506b8Sjruoho         break;
78228c506b8Sjruoho     }
78328c506b8Sjruoho }
784