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