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