1149703c7Sjruoho /******************************************************************************
2149703c7Sjruoho  *
3149703c7Sjruoho  * Module Name: aslcodegen - AML code generation
4149703c7Sjruoho  *
5149703c7Sjruoho  *****************************************************************************/
6149703c7Sjruoho 
768471b32Sjruoho /*
8e5631441Schristos  * Copyright (C) 2000 - 2022, Intel Corp.
9149703c7Sjruoho  * All rights reserved.
10149703c7Sjruoho  *
1168471b32Sjruoho  * Redistribution and use in source and binary forms, with or without
1268471b32Sjruoho  * modification, are permitted provided that the following conditions
1368471b32Sjruoho  * are met:
1468471b32Sjruoho  * 1. Redistributions of source code must retain the above copyright
1568471b32Sjruoho  *    notice, this list of conditions, and the following disclaimer,
1668471b32Sjruoho  *    without modification.
1768471b32Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1868471b32Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
1968471b32Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
2068471b32Sjruoho  *    including a substantially similar Disclaimer requirement for further
2168471b32Sjruoho  *    binary redistribution.
2268471b32Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
2368471b32Sjruoho  *    of any contributors may be used to endorse or promote products derived
2468471b32Sjruoho  *    from this software without specific prior written permission.
25149703c7Sjruoho  *
2668471b32Sjruoho  * Alternatively, this software may be distributed under the terms of the
2768471b32Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
2868471b32Sjruoho  * Software Foundation.
29149703c7Sjruoho  *
3068471b32Sjruoho  * NO WARRANTY
3168471b32Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3268471b32Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33d4291bf2Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3468471b32Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3568471b32Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3668471b32Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3768471b32Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3868471b32Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3968471b32Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4068471b32Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4168471b32Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
4268471b32Sjruoho  */
43149703c7Sjruoho 
44149703c7Sjruoho #include "aslcompiler.h"
45149703c7Sjruoho #include "aslcompiler.y.h"
46149703c7Sjruoho #include "amlcode.h"
471a3716ccSchristos #include "acconvert.h"
48*ae04e23cSchristos #include "actbinfo.h"
49149703c7Sjruoho 
50149703c7Sjruoho #define _COMPONENT          ACPI_COMPILER
51149703c7Sjruoho         ACPI_MODULE_NAME    ("aslcodegen")
52149703c7Sjruoho 
53149703c7Sjruoho /* Local prototypes */
54149703c7Sjruoho 
55149703c7Sjruoho static ACPI_STATUS
56149703c7Sjruoho CgAmlWriteWalk (
57149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op,
58149703c7Sjruoho     UINT32                  Level,
59149703c7Sjruoho     void                    *Context);
60149703c7Sjruoho 
61149703c7Sjruoho static void
62149703c7Sjruoho CgWriteAmlOpcode (
63149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op);
64149703c7Sjruoho 
65149703c7Sjruoho static void
66149703c7Sjruoho CgWriteTableHeader (
67149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op);
68149703c7Sjruoho 
69149703c7Sjruoho static void
7001bd6626Schristos CgWriteNode (
7101bd6626Schristos     ACPI_PARSE_OBJECT       *Op);
72149703c7Sjruoho 
73149703c7Sjruoho static void
7401bd6626Schristos CgUpdateHeader (
75149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op);
76149703c7Sjruoho 
77*ae04e23cSchristos static void
78*ae04e23cSchristos CgUpdateCdatHeader (
79*ae04e23cSchristos     ACPI_PARSE_OBJECT       *Op);
80*ae04e23cSchristos 
81149703c7Sjruoho 
82149703c7Sjruoho /*******************************************************************************
83149703c7Sjruoho  *
84149703c7Sjruoho  * FUNCTION:    CgGenerateAmlOutput
85149703c7Sjruoho  *
86149703c7Sjruoho  * PARAMETERS:  None.
87149703c7Sjruoho  *
88149703c7Sjruoho  * RETURN:      None
89149703c7Sjruoho  *
90149703c7Sjruoho  * DESCRIPTION: Generate AML code. Currently generates the listing file
91149703c7Sjruoho  *              simultaneously.
92149703c7Sjruoho  *
93149703c7Sjruoho  ******************************************************************************/
94149703c7Sjruoho 
95149703c7Sjruoho void
CgGenerateAmlOutput(void)96149703c7Sjruoho CgGenerateAmlOutput (
97149703c7Sjruoho     void)
98149703c7Sjruoho {
99149703c7Sjruoho 
100149703c7Sjruoho     /* Generate the AML output file */
101149703c7Sjruoho 
10201bd6626Schristos     TrWalkParseTree (AslGbl_CurrentDB,
10301bd6626Schristos         ASL_WALK_VISIT_DOWNWARD | ASL_WALK_VISIT_DB_SEPARATELY,
104149703c7Sjruoho         CgAmlWriteWalk, NULL, NULL);
1054e4949bdSchristos 
106e1e2165cSchristos     DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER2);
107*ae04e23cSchristos     if (AcpiGbl_CDAT)
108*ae04e23cSchristos     {
109*ae04e23cSchristos         CgUpdateCdatHeader (AslGbl_CurrentDB);
110*ae04e23cSchristos     }
111*ae04e23cSchristos     else
112*ae04e23cSchristos     {
11301bd6626Schristos         CgUpdateHeader (AslGbl_CurrentDB);
114149703c7Sjruoho     }
115*ae04e23cSchristos }
116149703c7Sjruoho 
117149703c7Sjruoho 
118149703c7Sjruoho /*******************************************************************************
119149703c7Sjruoho  *
120149703c7Sjruoho  * FUNCTION:    CgAmlWriteWalk
121149703c7Sjruoho  *
122149703c7Sjruoho  * PARAMETERS:  ASL_WALK_CALLBACK
123149703c7Sjruoho  *
124149703c7Sjruoho  * RETURN:      Status
125149703c7Sjruoho  *
126149703c7Sjruoho  * DESCRIPTION: Parse tree walk to generate the AML code.
127149703c7Sjruoho  *
128149703c7Sjruoho  ******************************************************************************/
129149703c7Sjruoho 
130149703c7Sjruoho static ACPI_STATUS
CgAmlWriteWalk(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)131149703c7Sjruoho CgAmlWriteWalk (
132149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op,
133149703c7Sjruoho     UINT32                  Level,
134149703c7Sjruoho     void                    *Context)
135149703c7Sjruoho {
136149703c7Sjruoho 
137e1e2165cSchristos     /* Generate the AML for this node */
138e1e2165cSchristos 
139e1e2165cSchristos     CgWriteNode (Op);
140e1e2165cSchristos 
1414e4e259fSchristos     if (!AslGbl_DebugFlag)
142e1e2165cSchristos     {
143e1e2165cSchristos         return (AE_OK);
144e1e2165cSchristos     }
145e1e2165cSchristos 
146e1e2165cSchristos     /* Print header at level 0. Alignment assumes 32-bit pointers */
147e1e2165cSchristos 
148149703c7Sjruoho     if (!Level)
149149703c7Sjruoho     {
150149703c7Sjruoho         DbgPrint (ASL_TREE_OUTPUT,
151e1e2165cSchristos             "\nFinal parse tree used for AML output:\n");
152e1e2165cSchristos         DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER2);
153149703c7Sjruoho     }
154149703c7Sjruoho 
155e1e2165cSchristos     /* Dump ParseOp name and possible value */
156149703c7Sjruoho 
157e1e2165cSchristos     switch (Op->Asl.ParseOpcode)
158149703c7Sjruoho     {
159e1e2165cSchristos     case PARSEOP_NAMESEG:
160e1e2165cSchristos     case PARSEOP_NAMESTRING:
161e1e2165cSchristos     case PARSEOP_METHODCALL:
162e1e2165cSchristos     case PARSEOP_STRING_LITERAL:
163e1e2165cSchristos 
164e1e2165cSchristos         UtDumpStringOp (Op, Level);
165e1e2165cSchristos         break;
166e1e2165cSchristos 
167e1e2165cSchristos     default:
168e1e2165cSchristos 
169e1e2165cSchristos         UtDumpBasicOp (Op, Level);
170e1e2165cSchristos         break;
171149703c7Sjruoho     }
172149703c7Sjruoho 
173e1e2165cSchristos     DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_DEBUG2,
174149703c7Sjruoho         /* 1  */ (UINT32) Op->Asl.Value.Integer,
175149703c7Sjruoho         /* 2  */ Op->Asl.ParseOpcode,
176149703c7Sjruoho         /* 3  */ Op->Asl.AmlOpcode,
177149703c7Sjruoho         /* 4  */ Op->Asl.AmlOpcodeLength,
178149703c7Sjruoho         /* 5  */ Op->Asl.AmlPkgLenBytes,
179149703c7Sjruoho         /* 6  */ Op->Asl.AmlLength,
180149703c7Sjruoho         /* 7  */ Op->Asl.AmlSubtreeLength,
181149703c7Sjruoho         /* 8  */ Op->Asl.Parent ? Op->Asl.Parent->Asl.AmlSubtreeLength : 0,
182149703c7Sjruoho         /* 9  */ Op,
1834e4949bdSchristos         /* 10 */ Op->Asl.Parent,
1844e4949bdSchristos         /* 11 */ Op->Asl.Child,
1854e4949bdSchristos         /* 12 */ Op->Asl.Next,
1864e4949bdSchristos         /* 13 */ Op->Asl.CompileFlags,
1874e4949bdSchristos         /* 14 */ Op->Asl.AcpiBtype,
1884e4949bdSchristos         /* 15 */ Op->Asl.FinalAmlLength,
1894e4949bdSchristos         /* 16 */ Op->Asl.Column,
190db5c6ae1Schristos         /* 17 */ Op->Asl.LineNumber,
191db5c6ae1Schristos         /* 18 */ Op->Asl.EndLine,
192db5c6ae1Schristos         /* 19 */ Op->Asl.LogicalLineNumber,
193db5c6ae1Schristos         /* 20 */ Op->Asl.EndLogicalLine);
194149703c7Sjruoho 
195d382fe7fSchristos     TrPrintOpFlags (Op->Asl.CompileFlags, ASL_TREE_OUTPUT);
196d382fe7fSchristos     DbgPrint (ASL_TREE_OUTPUT, "\n");
197149703c7Sjruoho     return (AE_OK);
198149703c7Sjruoho }
199149703c7Sjruoho 
200149703c7Sjruoho 
201149703c7Sjruoho /*******************************************************************************
202149703c7Sjruoho  *
203149703c7Sjruoho  * FUNCTION:    CgLocalWriteAmlData
204149703c7Sjruoho  *
205149703c7Sjruoho  * PARAMETERS:  Op              - Current parse op
206149703c7Sjruoho  *              Buffer          - Buffer to write
207149703c7Sjruoho  *              Length          - Size of data in buffer
208149703c7Sjruoho  *
209149703c7Sjruoho  * RETURN:      None
210149703c7Sjruoho  *
211149703c7Sjruoho  * DESCRIPTION: Write a buffer of AML data to the AML output file.
212149703c7Sjruoho  *
213149703c7Sjruoho  ******************************************************************************/
214149703c7Sjruoho 
2151a3716ccSchristos void
CgLocalWriteAmlData(ACPI_PARSE_OBJECT * Op,void * Buffer,UINT32 Length)216149703c7Sjruoho CgLocalWriteAmlData (
217149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op,
218149703c7Sjruoho     void                    *Buffer,
219149703c7Sjruoho     UINT32                  Length)
220149703c7Sjruoho {
221149703c7Sjruoho 
222149703c7Sjruoho     /* Write the raw data to the AML file */
223149703c7Sjruoho 
224149703c7Sjruoho     FlWriteFile (ASL_FILE_AML_OUTPUT, Buffer, Length);
225149703c7Sjruoho 
226149703c7Sjruoho     /* Update the final AML length for this node (used for listings) */
227149703c7Sjruoho 
228149703c7Sjruoho     if (Op)
229149703c7Sjruoho     {
230149703c7Sjruoho         Op->Asl.FinalAmlLength += Length;
231149703c7Sjruoho     }
232149703c7Sjruoho }
233149703c7Sjruoho 
234149703c7Sjruoho 
235149703c7Sjruoho /*******************************************************************************
236149703c7Sjruoho  *
237149703c7Sjruoho  * FUNCTION:    CgWriteAmlOpcode
238149703c7Sjruoho  *
239149703c7Sjruoho  * PARAMETERS:  Op            - Parse node with an AML opcode
240149703c7Sjruoho  *
241149703c7Sjruoho  * RETURN:      None.
242149703c7Sjruoho  *
243149703c7Sjruoho  * DESCRIPTION: Write the AML opcode corresponding to a parse node.
244149703c7Sjruoho  *
245149703c7Sjruoho  ******************************************************************************/
246149703c7Sjruoho 
247149703c7Sjruoho static void
CgWriteAmlOpcode(ACPI_PARSE_OBJECT * Op)248149703c7Sjruoho CgWriteAmlOpcode (
249149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op)
250149703c7Sjruoho {
251149703c7Sjruoho     UINT8                   PkgLenFirstByte;
252149703c7Sjruoho     UINT32                  i;
253149703c7Sjruoho     union {
254149703c7Sjruoho         UINT16                  Opcode;
255149703c7Sjruoho         UINT8                   OpcodeBytes[2];
256149703c7Sjruoho     } Aml;
257149703c7Sjruoho     union {
258149703c7Sjruoho         UINT32                  Len;
259149703c7Sjruoho         UINT8                   LenBytes[4];
260149703c7Sjruoho     } PkgLen;
261149703c7Sjruoho 
262149703c7Sjruoho 
263149703c7Sjruoho     /* We expect some DEFAULT_ARGs, just ignore them */
264149703c7Sjruoho 
265149703c7Sjruoho     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
266149703c7Sjruoho     {
267149703c7Sjruoho         return;
268149703c7Sjruoho     }
269149703c7Sjruoho 
2701a3716ccSchristos     /*
2711a3716ccSchristos      * Before printing the bytecode, generate comment byte codes
2721a3716ccSchristos      * associated with this node.
2731a3716ccSchristos      */
274e32744fcSchristos     if (AcpiGbl_CaptureComments)
2751a3716ccSchristos     {
2761a3716ccSchristos         CgWriteAmlComment(Op);
2771a3716ccSchristos     }
2781a3716ccSchristos 
279149703c7Sjruoho     switch (Op->Asl.AmlOpcode)
280149703c7Sjruoho     {
281149703c7Sjruoho     case AML_UNASSIGNED_OPCODE:
282149703c7Sjruoho 
283149703c7Sjruoho         /* These opcodes should not get here */
284149703c7Sjruoho 
285149703c7Sjruoho         printf ("Found a node with an unassigned AML opcode\n");
2865fe1040dSchristos         FlPrintFile (ASL_FILE_STDERR,
2875fe1040dSchristos             "Found a node with an unassigned AML opcode\n");
288149703c7Sjruoho         return;
289149703c7Sjruoho 
290149703c7Sjruoho     case AML_INT_RESERVEDFIELD_OP:
291149703c7Sjruoho 
292149703c7Sjruoho         /* Special opcodes for within a field definition */
293149703c7Sjruoho 
29473d4e80bSchristos         Aml.Opcode = AML_FIELD_OFFSET_OP;
295149703c7Sjruoho         break;
296149703c7Sjruoho 
297149703c7Sjruoho     case AML_INT_ACCESSFIELD_OP:
298149703c7Sjruoho 
29973d4e80bSchristos         Aml.Opcode = AML_FIELD_ACCESS_OP;
30073d4e80bSchristos         break;
30173d4e80bSchristos 
30273d4e80bSchristos     case AML_INT_CONNECTION_OP:
30373d4e80bSchristos 
30473d4e80bSchristos         Aml.Opcode = AML_FIELD_CONNECTION_OP;
305149703c7Sjruoho         break;
306149703c7Sjruoho 
307149703c7Sjruoho     default:
30873d4e80bSchristos 
309149703c7Sjruoho         Aml.Opcode = Op->Asl.AmlOpcode;
310149703c7Sjruoho         break;
311149703c7Sjruoho     }
312149703c7Sjruoho 
313149703c7Sjruoho 
314149703c7Sjruoho     switch (Aml.Opcode)
315149703c7Sjruoho     {
316149703c7Sjruoho     case AML_PACKAGE_LENGTH:
317149703c7Sjruoho 
318149703c7Sjruoho         /* Value is the length to be encoded (Used in field definitions) */
319149703c7Sjruoho 
320149703c7Sjruoho         PkgLen.Len = (UINT32) Op->Asl.Value.Integer;
321149703c7Sjruoho         break;
322149703c7Sjruoho 
323149703c7Sjruoho     default:
324149703c7Sjruoho 
325149703c7Sjruoho         /* Check for two-byte opcode */
326149703c7Sjruoho 
327149703c7Sjruoho         if (Aml.Opcode > 0x00FF)
328149703c7Sjruoho         {
329149703c7Sjruoho             /* Write the high byte first */
330149703c7Sjruoho 
331149703c7Sjruoho             CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[1], 1);
332149703c7Sjruoho         }
333149703c7Sjruoho 
334149703c7Sjruoho         CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[0], 1);
335149703c7Sjruoho 
336149703c7Sjruoho         /* Subtreelength doesn't include length of package length bytes */
337149703c7Sjruoho 
338149703c7Sjruoho         PkgLen.Len = Op->Asl.AmlSubtreeLength + Op->Asl.AmlPkgLenBytes;
339149703c7Sjruoho         break;
340149703c7Sjruoho     }
341149703c7Sjruoho 
342149703c7Sjruoho     /* Does this opcode have an associated "PackageLength" field? */
343149703c7Sjruoho 
344d382fe7fSchristos     if (Op->Asl.CompileFlags & OP_AML_PACKAGE)
345149703c7Sjruoho     {
346149703c7Sjruoho         if (Op->Asl.AmlPkgLenBytes == 1)
347149703c7Sjruoho         {
348149703c7Sjruoho             /* Simplest case -- no bytes to follow, just write the count */
349149703c7Sjruoho 
350149703c7Sjruoho             CgLocalWriteAmlData (Op, &PkgLen.LenBytes[0], 1);
351149703c7Sjruoho         }
352149703c7Sjruoho         else if (Op->Asl.AmlPkgLenBytes != 0)
353149703c7Sjruoho         {
354149703c7Sjruoho             /*
355149703c7Sjruoho              * Encode the "bytes to follow" in the first byte, top two bits.
356149703c7Sjruoho              * The low-order nybble of the length is in the bottom 4 bits
357149703c7Sjruoho              */
358149703c7Sjruoho             PkgLenFirstByte = (UINT8)
359149703c7Sjruoho                 (((UINT32) (Op->Asl.AmlPkgLenBytes - 1) << 6) |
360149703c7Sjruoho                 (PkgLen.LenBytes[0] & 0x0F));
361149703c7Sjruoho 
362149703c7Sjruoho             CgLocalWriteAmlData (Op, &PkgLenFirstByte, 1);
363149703c7Sjruoho 
364149703c7Sjruoho             /*
365149703c7Sjruoho              * Shift the length over by the 4 bits we just stuffed
366149703c7Sjruoho              * in the first byte
367149703c7Sjruoho              */
368149703c7Sjruoho             PkgLen.Len >>= 4;
369149703c7Sjruoho 
3705fe1040dSchristos             /*
3715fe1040dSchristos              * Now we can write the remaining bytes -
3725fe1040dSchristos              * either 1, 2, or 3 bytes
3735fe1040dSchristos              */
374149703c7Sjruoho             for (i = 0; i < (UINT32) (Op->Asl.AmlPkgLenBytes - 1); i++)
375149703c7Sjruoho             {
376149703c7Sjruoho                 CgLocalWriteAmlData (Op, &PkgLen.LenBytes[i], 1);
377149703c7Sjruoho             }
378149703c7Sjruoho         }
379149703c7Sjruoho     }
380149703c7Sjruoho 
381149703c7Sjruoho     switch (Aml.Opcode)
382149703c7Sjruoho     {
383149703c7Sjruoho     case AML_BYTE_OP:
384149703c7Sjruoho 
385149703c7Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 1);
386149703c7Sjruoho         break;
387149703c7Sjruoho 
388149703c7Sjruoho     case AML_WORD_OP:
389149703c7Sjruoho 
390149703c7Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 2);
391149703c7Sjruoho        break;
392149703c7Sjruoho 
393149703c7Sjruoho     case AML_DWORD_OP:
394149703c7Sjruoho 
395149703c7Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 4);
396149703c7Sjruoho         break;
397149703c7Sjruoho 
398149703c7Sjruoho     case AML_QWORD_OP:
399149703c7Sjruoho 
400149703c7Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 8);
401149703c7Sjruoho         break;
402149703c7Sjruoho 
403149703c7Sjruoho     case AML_STRING_OP:
404149703c7Sjruoho 
405149703c7Sjruoho         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
406149703c7Sjruoho         break;
407149703c7Sjruoho 
408149703c7Sjruoho     default:
40973d4e80bSchristos 
410149703c7Sjruoho         /* All data opcodes must appear above */
41173d4e80bSchristos 
412149703c7Sjruoho         break;
413149703c7Sjruoho     }
414149703c7Sjruoho }
415149703c7Sjruoho 
416149703c7Sjruoho 
417149703c7Sjruoho /*******************************************************************************
418149703c7Sjruoho  *
419149703c7Sjruoho  * FUNCTION:    CgWriteTableHeader
420149703c7Sjruoho  *
421149703c7Sjruoho  * PARAMETERS:  Op        - The DEFINITIONBLOCK node
422149703c7Sjruoho  *
423149703c7Sjruoho  * RETURN:      None
424149703c7Sjruoho  *
425149703c7Sjruoho  * DESCRIPTION: Write a table header corresponding to the DEFINITIONBLOCK
426149703c7Sjruoho  *
42701bd6626Schristos  * NOTE: Input strings should be validated before this function is invoked.
42801bd6626Schristos  *
429149703c7Sjruoho  ******************************************************************************/
430149703c7Sjruoho 
431149703c7Sjruoho static void
CgWriteTableHeader(ACPI_PARSE_OBJECT * Op)432149703c7Sjruoho CgWriteTableHeader (
433149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op)
434149703c7Sjruoho {
435149703c7Sjruoho     ACPI_PARSE_OBJECT       *Child;
4361a3716ccSchristos     UINT32                  CommentLength;
4371a3716ccSchristos     ACPI_COMMENT_NODE       *Current;
438149703c7Sjruoho 
439149703c7Sjruoho 
44001bd6626Schristos     memset (&AslGbl_TableHeader, 0, sizeof (ACPI_TABLE_HEADER));
44101bd6626Schristos 
442149703c7Sjruoho     /* AML filename */
443149703c7Sjruoho 
444149703c7Sjruoho     Child = Op->Asl.Child;
445149703c7Sjruoho 
446149703c7Sjruoho     /* Signature */
447149703c7Sjruoho 
448149703c7Sjruoho     Child = Child->Asl.Next;
4491a3716ccSchristos 
4501a3716ccSchristos     /*
4511a3716ccSchristos      * For ASL-/ASL+ converter: replace the table signature with
4521a3716ccSchristos      * "XXXX" and save the original table signature. This results in an AML
4531a3716ccSchristos      * file with the signature "XXXX". The converter should remove this AML
4541a3716ccSchristos      * file. In the event where this AML file does not get deleted, the
4551a3716ccSchristos      * "XXXX" table signature prevents this AML file from running on the AML
4561a3716ccSchristos      * interpreter.
4571a3716ccSchristos      */
458e32744fcSchristos     if (AcpiGbl_CaptureComments)
4591a3716ccSchristos     {
46001bd6626Schristos         ACPI_COPY_NAMESEG (AcpiGbl_TableSig, Child->Asl.Value.String);
4611a3716ccSchristos         Child->Asl.Value.String = ACPI_SIG_XXXX;
4621a3716ccSchristos     }
4631a3716ccSchristos 
46401bd6626Schristos     ACPI_COPY_NAMESEG (AslGbl_TableHeader.Signature, Child->Asl.Value.String);
465149703c7Sjruoho 
466149703c7Sjruoho     /* Revision */
467149703c7Sjruoho 
468149703c7Sjruoho     Child = Child->Asl.Next;
4694e4e259fSchristos     AslGbl_TableHeader.Revision = (UINT8) Child->Asl.Value.Integer;
470149703c7Sjruoho 
471149703c7Sjruoho     /* Command-line Revision override */
472149703c7Sjruoho 
4734e4e259fSchristos     if (AslGbl_RevisionOverride)
474149703c7Sjruoho     {
4754e4e259fSchristos         AslGbl_TableHeader.Revision = AslGbl_RevisionOverride;
476149703c7Sjruoho     }
477149703c7Sjruoho 
478149703c7Sjruoho     /* OEMID */
479149703c7Sjruoho 
480149703c7Sjruoho     Child = Child->Asl.Next;
48101bd6626Schristos     memcpy (AslGbl_TableHeader.OemId, Child->Asl.Value.String,
48201bd6626Schristos         strlen (Child->Asl.Value.String));
483149703c7Sjruoho 
484149703c7Sjruoho     /* OEM TableID */
485149703c7Sjruoho 
486149703c7Sjruoho     Child = Child->Asl.Next;
48701bd6626Schristos     memcpy (AslGbl_TableHeader.OemTableId, Child->Asl.Value.String,
48801bd6626Schristos         strlen (Child->Asl.Value.String));
489149703c7Sjruoho 
490149703c7Sjruoho     /* OEM Revision */
491149703c7Sjruoho 
492149703c7Sjruoho     Child = Child->Asl.Next;
4934e4e259fSchristos     AslGbl_TableHeader.OemRevision = (UINT32) Child->Asl.Value.Integer;
494149703c7Sjruoho 
495149703c7Sjruoho     /* Compiler ID */
496149703c7Sjruoho 
49701bd6626Schristos     ACPI_COPY_NAMESEG (AslGbl_TableHeader.AslCompilerId, ASL_CREATOR_ID);
498149703c7Sjruoho 
499149703c7Sjruoho     /* Compiler version */
500149703c7Sjruoho 
5014e4e259fSchristos     AslGbl_TableHeader.AslCompilerRevision = ACPI_CA_VERSION;
502149703c7Sjruoho 
503149703c7Sjruoho     /* Table length. Checksum zero for now, will rewrite later */
504149703c7Sjruoho 
5054e4e259fSchristos     AslGbl_TableHeader.Length = sizeof (ACPI_TABLE_HEADER) +
5065fe1040dSchristos         Op->Asl.AmlSubtreeLength;
5071a3716ccSchristos 
5081a3716ccSchristos     /* Calculate the comment lengths for this definition block parseOp */
5091a3716ccSchristos 
510e32744fcSchristos     if (AcpiGbl_CaptureComments)
5111a3716ccSchristos     {
5121a3716ccSchristos         CvDbgPrint ("Calculating comment lengths for %s in write header\n",
5131a3716ccSchristos             Op->Asl.ParseOpName);
5141a3716ccSchristos 
5151a3716ccSchristos         /*
5161a3716ccSchristos          * Take the filename without extensions, add 3 for the new extension
5171a3716ccSchristos          * and another 3 for the a908 bytecode and null terminator.
5181a3716ccSchristos          */
5194e4e259fSchristos         AslGbl_TableHeader.Length += strrchr (AslGbl_ParseTreeRoot->Asl.Filename, '.')
5204e4e259fSchristos             - AslGbl_ParseTreeRoot->Asl.Filename + 1 + 3 + 3;
5214e4e259fSchristos 
5221a3716ccSchristos         Op->Asl.AmlSubtreeLength +=
5234e4e259fSchristos             strlen (AslGbl_ParseTreeRoot->Asl.Filename) + 3;
5244e4e259fSchristos 
525517d1194Schristos         CvDbgPrint ("     Length: %u\n",
526517d1194Schristos             (UINT32) strlen (AslGbl_ParseTreeRoot->Asl.Filename) + 3);
5271a3716ccSchristos 
5281a3716ccSchristos         if (Op->Asl.CommentList)
5291a3716ccSchristos         {
5301a3716ccSchristos             Current = Op->Asl.CommentList;
5311a3716ccSchristos             while (Current)
5321a3716ccSchristos             {
5331a3716ccSchristos                 CommentLength = strlen (Current->Comment)+3;
5341a3716ccSchristos                 CvDbgPrint ("Length of standard comment): %d\n", CommentLength);
5351a3716ccSchristos                 CvDbgPrint ("    Comment string: %s\n\n", Current->Comment);
5364e4e259fSchristos                 AslGbl_TableHeader.Length += CommentLength;
5371a3716ccSchristos                 Op->Asl.AmlSubtreeLength += CommentLength;
5381a3716ccSchristos                 Current = Current->Next;
5391a3716ccSchristos                 CvDbgPrint ("    Length: %u\n", CommentLength);
5401a3716ccSchristos             }
5411a3716ccSchristos         }
5421a3716ccSchristos         if (Op->Asl.CloseBraceComment)
5431a3716ccSchristos         {
5441a3716ccSchristos             CommentLength = strlen (Op->Asl.CloseBraceComment)+3;
5451a3716ccSchristos             CvDbgPrint ("Length of inline comment +3: %d\n", CommentLength);
5461a3716ccSchristos             CvDbgPrint ("    Comment string: %s\n\n", Op->Asl.CloseBraceComment);
5474e4e259fSchristos             AslGbl_TableHeader.Length += CommentLength;
5481a3716ccSchristos             Op->Asl.AmlSubtreeLength += CommentLength;
5491a3716ccSchristos             CvDbgPrint ("    Length: %u\n", CommentLength);
5501a3716ccSchristos         }
5511a3716ccSchristos     }
5521a3716ccSchristos 
5534e4e259fSchristos     AslGbl_TableHeader.Checksum = 0;
5544e4e259fSchristos     Op->Asl.FinalAmlOffset = ftell (AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle);
5555fe1040dSchristos 
5565fe1040dSchristos     /* Write entire header and clear the table header global */
5575fe1040dSchristos 
5584e4e259fSchristos     CgLocalWriteAmlData (Op, &AslGbl_TableHeader, sizeof (ACPI_TABLE_HEADER));
5594e4e259fSchristos     memset (&AslGbl_TableHeader, 0, sizeof (ACPI_TABLE_HEADER));
5605fe1040dSchristos }
5615fe1040dSchristos 
5625fe1040dSchristos 
5635fe1040dSchristos /*******************************************************************************
5645fe1040dSchristos  *
565*ae04e23cSchristos  * FUNCTION:    CgUpdateCdatHeader
566*ae04e23cSchristos  *
567*ae04e23cSchristos  * PARAMETERS:  Op                  - Op for the Definition Block
568*ae04e23cSchristos  *
569*ae04e23cSchristos  * RETURN:      None.
570*ae04e23cSchristos  *
571*ae04e23cSchristos  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
572*ae04e23cSchristos  *              re-writing the header for the input definition block
573*ae04e23cSchristos  *
574*ae04e23cSchristos  ******************************************************************************/
575*ae04e23cSchristos 
576*ae04e23cSchristos static void
CgUpdateCdatHeader(ACPI_PARSE_OBJECT * Op)577*ae04e23cSchristos CgUpdateCdatHeader (
578*ae04e23cSchristos     ACPI_PARSE_OBJECT       *Op)
579*ae04e23cSchristos {
580*ae04e23cSchristos     signed char             Sum;
581*ae04e23cSchristos     UINT32                  i;
582*ae04e23cSchristos     UINT32                  Length;
583*ae04e23cSchristos     UINT8                   FileByte;
584*ae04e23cSchristos     UINT8                   Checksum;
585*ae04e23cSchristos 
586*ae04e23cSchristos 
587*ae04e23cSchristos     /* Calculate the checksum over the entire definition block */
588*ae04e23cSchristos 
589*ae04e23cSchristos     Sum = 0;
590*ae04e23cSchristos     Length = sizeof (ACPI_TABLE_CDAT) + Op->Asl.AmlSubtreeLength;
591*ae04e23cSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset);
592*ae04e23cSchristos 
593*ae04e23cSchristos     for (i = 0; i < Length; i++)
594*ae04e23cSchristos     {
595*ae04e23cSchristos         if (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) != AE_OK)
596*ae04e23cSchristos         {
597*ae04e23cSchristos             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
598*ae04e23cSchristos                 "Table length is greater than size of the input file");
599*ae04e23cSchristos             return;
600*ae04e23cSchristos         }
601*ae04e23cSchristos 
602*ae04e23cSchristos         Sum = (signed char) (Sum + FileByte);
603*ae04e23cSchristos     }
604*ae04e23cSchristos 
605*ae04e23cSchristos     Checksum = (UINT8) (0 - Sum);
606*ae04e23cSchristos 
607*ae04e23cSchristos     DbgPrint (ASL_DEBUG_OUTPUT, "Computed checksum = %X\n", Checksum);
608*ae04e23cSchristos 
609*ae04e23cSchristos     /* Re-write the checksum byte */
610*ae04e23cSchristos 
611*ae04e23cSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset +
612*ae04e23cSchristos         ACPI_CDAT_OFFSET (Checksum));
613*ae04e23cSchristos 
614*ae04e23cSchristos     FlWriteFile (ASL_FILE_AML_OUTPUT, &Checksum, 1);
615*ae04e23cSchristos 
616*ae04e23cSchristos     /*
617*ae04e23cSchristos      * Seek to the end of the file. This is done to support multiple file
618*ae04e23cSchristos      * compilation. Doing this simplifies other parts of the codebase because
619*ae04e23cSchristos      * it eliminates the need to seek for a different starting place.
620*ae04e23cSchristos      */
621*ae04e23cSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset + Length);
622*ae04e23cSchristos }
623*ae04e23cSchristos 
624*ae04e23cSchristos /*******************************************************************************
625*ae04e23cSchristos  *
6265fe1040dSchristos  * FUNCTION:    CgUpdateHeader
6275fe1040dSchristos  *
6285fe1040dSchristos  * PARAMETERS:  Op                  - Op for the Definition Block
6295fe1040dSchristos  *
6305fe1040dSchristos  * RETURN:      None.
6315fe1040dSchristos  *
6325fe1040dSchristos  * DESCRIPTION: Complete the ACPI table by calculating the checksum and
6335fe1040dSchristos  *              re-writing the header for the input definition block
6345fe1040dSchristos  *
6355fe1040dSchristos  ******************************************************************************/
6365fe1040dSchristos 
6375fe1040dSchristos static void
CgUpdateHeader(ACPI_PARSE_OBJECT * Op)6385fe1040dSchristos CgUpdateHeader (
6395fe1040dSchristos     ACPI_PARSE_OBJECT       *Op)
6405fe1040dSchristos {
6415fe1040dSchristos     signed char             Sum;
6425fe1040dSchristos     UINT32                  i;
6435fe1040dSchristos     UINT32                  Length;
6445fe1040dSchristos     UINT8                   FileByte;
6455fe1040dSchristos     UINT8                   Checksum;
6465fe1040dSchristos 
6475fe1040dSchristos 
6485fe1040dSchristos     /* Calculate the checksum over the entire definition block */
6495fe1040dSchristos 
6505fe1040dSchristos     Sum = 0;
6515fe1040dSchristos     Length = sizeof (ACPI_TABLE_HEADER) + Op->Asl.AmlSubtreeLength;
6525fe1040dSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset);
6535fe1040dSchristos 
6545fe1040dSchristos     for (i = 0; i < Length; i++)
6555fe1040dSchristos     {
6565fe1040dSchristos         if (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) != AE_OK)
6575fe1040dSchristos         {
658517d1194Schristos             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
659517d1194Schristos                 "Table length is greater than size of the input file");
6605fe1040dSchristos             return;
6615fe1040dSchristos         }
6625fe1040dSchristos 
6635fe1040dSchristos         Sum = (signed char) (Sum + FileByte);
6645fe1040dSchristos     }
6655fe1040dSchristos 
6665fe1040dSchristos     Checksum = (UINT8) (0 - Sum);
6675fe1040dSchristos 
6687cf8bdb9Schristos     /* Re-write the checksum byte */
6695fe1040dSchristos 
6705fe1040dSchristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset +
6715fe1040dSchristos         ACPI_OFFSET (ACPI_TABLE_HEADER, Checksum));
6725fe1040dSchristos 
6735fe1040dSchristos     FlWriteFile (ASL_FILE_AML_OUTPUT, &Checksum, 1);
674149703c7Sjruoho 
67501bd6626Schristos     /*
67601bd6626Schristos      * Seek to the end of the file. This is done to support multiple file
67701bd6626Schristos      * compilation. Doing this simplifies other parts of the codebase because
67801bd6626Schristos      * it eliminates the need to seek for a different starting place.
67901bd6626Schristos      */
68001bd6626Schristos     FlSeekFile (ASL_FILE_AML_OUTPUT, Op->Asl.FinalAmlOffset + Length);
681149703c7Sjruoho }
682149703c7Sjruoho 
683149703c7Sjruoho 
684149703c7Sjruoho /*******************************************************************************
685149703c7Sjruoho  *
686149703c7Sjruoho  * FUNCTION:    CgWriteNode
687149703c7Sjruoho  *
688149703c7Sjruoho  * PARAMETERS:  Op            - Parse node to write.
689149703c7Sjruoho  *
690149703c7Sjruoho  * RETURN:      None.
691149703c7Sjruoho  *
692149703c7Sjruoho  * DESCRIPTION: Write the AML that corresponds to a parse node.
693149703c7Sjruoho  *
694149703c7Sjruoho  ******************************************************************************/
695149703c7Sjruoho 
696149703c7Sjruoho static void
CgWriteNode(ACPI_PARSE_OBJECT * Op)697149703c7Sjruoho CgWriteNode (
698149703c7Sjruoho     ACPI_PARSE_OBJECT       *Op)
699149703c7Sjruoho {
700149703c7Sjruoho     ASL_RESOURCE_NODE       *Rnode;
701149703c7Sjruoho 
702149703c7Sjruoho 
7031a3716ccSchristos     /* Write all comments here. */
704e32744fcSchristos 
705e32744fcSchristos     if (AcpiGbl_CaptureComments)
7061a3716ccSchristos     {
7071a3716ccSchristos         CgWriteAmlComment(Op);
7081a3716ccSchristos     }
7091a3716ccSchristos 
710149703c7Sjruoho     /* Always check for DEFAULT_ARG and other "Noop" nodes */
711149703c7Sjruoho     /* TBD: this may not be the best place for this check */
712149703c7Sjruoho 
713149703c7Sjruoho     if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)  ||
714149703c7Sjruoho         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE)      ||
715149703c7Sjruoho         (Op->Asl.ParseOpcode == PARSEOP_INCLUDE_END))
716149703c7Sjruoho     {
717149703c7Sjruoho         return;
718149703c7Sjruoho     }
719149703c7Sjruoho 
720149703c7Sjruoho     Op->Asl.FinalAmlLength = 0;
721149703c7Sjruoho 
722149703c7Sjruoho     switch (Op->Asl.AmlOpcode)
723149703c7Sjruoho     {
724149703c7Sjruoho     case AML_RAW_DATA_BYTE:
725149703c7Sjruoho     case AML_RAW_DATA_WORD:
726149703c7Sjruoho     case AML_RAW_DATA_DWORD:
727149703c7Sjruoho     case AML_RAW_DATA_QWORD:
728149703c7Sjruoho 
729149703c7Sjruoho         CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, Op->Asl.AmlLength);
730149703c7Sjruoho         return;
731149703c7Sjruoho 
732149703c7Sjruoho 
733149703c7Sjruoho     case AML_RAW_DATA_BUFFER:
734149703c7Sjruoho 
735149703c7Sjruoho         CgLocalWriteAmlData (Op, Op->Asl.Value.Buffer, Op->Asl.AmlLength);
736149703c7Sjruoho         return;
737149703c7Sjruoho 
738149703c7Sjruoho 
739149703c7Sjruoho     case AML_RAW_DATA_CHAIN:
740149703c7Sjruoho 
741149703c7Sjruoho         Rnode = ACPI_CAST_PTR (ASL_RESOURCE_NODE, Op->Asl.Value.Buffer);
742149703c7Sjruoho         while (Rnode)
743149703c7Sjruoho         {
744149703c7Sjruoho             CgLocalWriteAmlData (Op, Rnode->Buffer, Rnode->BufferLength);
745149703c7Sjruoho             Rnode = Rnode->Next;
746149703c7Sjruoho         }
747149703c7Sjruoho         return;
748149703c7Sjruoho 
749149703c7Sjruoho     default:
75073d4e80bSchristos 
751149703c7Sjruoho         /* Internal data opcodes must all appear above */
75273d4e80bSchristos 
753149703c7Sjruoho         break;
754149703c7Sjruoho     }
755149703c7Sjruoho 
756149703c7Sjruoho     switch (Op->Asl.ParseOpcode)
757149703c7Sjruoho     {
758149703c7Sjruoho     case PARSEOP_DEFAULT_ARG:
759149703c7Sjruoho 
760149703c7Sjruoho         break;
761149703c7Sjruoho 
7625fe1040dSchristos     case PARSEOP_DEFINITION_BLOCK:
763149703c7Sjruoho 
764149703c7Sjruoho         CgWriteTableHeader (Op);
765e32744fcSchristos         if (AcpiGbl_CaptureComments)
7661a3716ccSchristos         {
7671a3716ccSchristos             CgWriteAmlDefBlockComment (Op);
7681a3716ccSchristos         }
769149703c7Sjruoho         break;
770149703c7Sjruoho 
771149703c7Sjruoho     case PARSEOP_NAMESEG:
772149703c7Sjruoho     case PARSEOP_NAMESTRING:
773149703c7Sjruoho     case PARSEOP_METHODCALL:
774149703c7Sjruoho 
775149703c7Sjruoho         CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
776149703c7Sjruoho         break;
777149703c7Sjruoho 
778149703c7Sjruoho     default:
779149703c7Sjruoho 
780149703c7Sjruoho         CgWriteAmlOpcode (Op);
781149703c7Sjruoho         break;
782149703c7Sjruoho     }
783149703c7Sjruoho }
784