2 /******************************************************************************
4 * Module Name: aslcodegen - AML code generation
6 *****************************************************************************/
9 * Copyright (C) 2000 - 2012, Intel Corp.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
46 #include "aslcompiler.h"
47 #include "aslcompiler.y.h"
50 #define _COMPONENT ACPI_COMPILER
51 ACPI_MODULE_NAME ("aslcodegen")
53 /* Local prototypes */
57 ACPI_PARSE_OBJECT *Op,
63 ACPI_PARSE_OBJECT *Op,
69 ACPI_PARSE_OBJECT *Op);
73 ACPI_PARSE_OBJECT *Op);
81 ACPI_PARSE_OBJECT *Op);
84 /*******************************************************************************
86 * FUNCTION: CgGenerateAmlOutput
92 * DESCRIPTION: Generate AML code. Currently generates the listing file
95 ******************************************************************************/
102 DbgPrint (ASL_DEBUG_OUTPUT, "\nWriting AML\n\n");
104 /* Generate the AML output file */
106 FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
108 Gbl_NextError = Gbl_ErrorLog;
110 TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
111 CgAmlWriteWalk, NULL, NULL);
116 /*******************************************************************************
118 * FUNCTION: CgAmlWriteWalk
120 * PARAMETERS: ASL_WALK_CALLBACK
124 * DESCRIPTION: Parse tree walk to generate the AML code.
126 ******************************************************************************/
130 ACPI_PARSE_OBJECT *Op,
136 * Print header at level 0. Alignment assumes 32-bit pointers
140 DbgPrint (ASL_TREE_OUTPUT,
141 "Final parse tree used for AML output:\n");
142 DbgPrint (ASL_TREE_OUTPUT,
143 "%*s Value P_Op A_Op OpLen PByts Len SubLen PSubLen OpPtr Child Parent Flags AcTyp Final Col L\n",
149 DbgPrint (ASL_TREE_OUTPUT,
150 "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level);
151 UtPrintFormattedName (Op->Asl.ParseOpcode, Level);
153 if (Op->Asl.ParseOpcode == PARSEOP_NAMESEG ||
154 Op->Asl.ParseOpcode == PARSEOP_NAMESTRING ||
155 Op->Asl.ParseOpcode == PARSEOP_METHODCALL)
157 DbgPrint (ASL_TREE_OUTPUT,
158 "%10.32s ", Op->Asl.ExternalName);
162 DbgPrint (ASL_TREE_OUTPUT, " ");
165 DbgPrint (ASL_TREE_OUTPUT,
166 "%08X %04X %04X %01X %04X %04X %04X %04X %08X %08X %08X %08X %08X %04X %02d %02d\n",
167 /* 1 */ (UINT32) Op->Asl.Value.Integer,
168 /* 2 */ Op->Asl.ParseOpcode,
169 /* 3 */ Op->Asl.AmlOpcode,
170 /* 4 */ Op->Asl.AmlOpcodeLength,
171 /* 5 */ Op->Asl.AmlPkgLenBytes,
172 /* 6 */ Op->Asl.AmlLength,
173 /* 7 */ Op->Asl.AmlSubtreeLength,
174 /* 8 */ Op->Asl.Parent ? Op->Asl.Parent->Asl.AmlSubtreeLength : 0,
176 /* 10 */ Op->Asl.Child,
177 /* 11 */ Op->Asl.Parent,
178 /* 12 */ Op->Asl.CompileFlags,
179 /* 13 */ Op->Asl.AcpiBtype,
180 /* 14 */ Op->Asl.FinalAmlLength,
181 /* 15 */ Op->Asl.Column,
182 /* 16 */ Op->Asl.LineNumber);
184 /* Generate the AML for this node */
191 /*******************************************************************************
193 * FUNCTION: CgLocalWriteAmlData
195 * PARAMETERS: Op - Current parse op
196 * Buffer - Buffer to write
197 * Length - Size of data in buffer
201 * DESCRIPTION: Write a buffer of AML data to the AML output file.
203 ******************************************************************************/
206 CgLocalWriteAmlData (
207 ACPI_PARSE_OBJECT *Op,
212 /* Write the raw data to the AML file */
214 FlWriteFile (ASL_FILE_AML_OUTPUT, Buffer, Length);
216 /* Update the final AML length for this node (used for listings) */
220 Op->Asl.FinalAmlLength += Length;
225 /*******************************************************************************
227 * FUNCTION: CgWriteAmlOpcode
229 * PARAMETERS: Op - Parse node with an AML opcode
233 * DESCRIPTION: Write the AML opcode corresponding to a parse node.
235 ******************************************************************************/
239 ACPI_PARSE_OBJECT *Op)
241 UINT8 PkgLenFirstByte;
245 UINT8 OpcodeBytes[2];
253 /* We expect some DEFAULT_ARGs, just ignore them */
255 if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
260 switch (Op->Asl.AmlOpcode)
262 case AML_UNASSIGNED_OPCODE:
264 /* These opcodes should not get here */
266 printf ("Found a node with an unassigned AML opcode\n");
267 FlPrintFile (ASL_FILE_STDERR, "Found a node with an unassigned AML opcode\n");
270 case AML_INT_RESERVEDFIELD_OP:
272 /* Special opcodes for within a field definition */
274 Aml.Opcode = AML_FIELD_OFFSET_OP;
277 case AML_INT_ACCESSFIELD_OP:
279 Aml.Opcode = AML_FIELD_ACCESS_OP;
282 case AML_INT_CONNECTION_OP:
284 Aml.Opcode = AML_FIELD_CONNECTION_OP;
288 Aml.Opcode = Op->Asl.AmlOpcode;
295 case AML_PACKAGE_LENGTH:
297 /* Value is the length to be encoded (Used in field definitions) */
299 PkgLen.Len = (UINT32) Op->Asl.Value.Integer;
304 /* Check for two-byte opcode */
306 if (Aml.Opcode > 0x00FF)
308 /* Write the high byte first */
310 CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[1], 1);
313 CgLocalWriteAmlData (Op, &Aml.OpcodeBytes[0], 1);
315 /* Subtreelength doesn't include length of package length bytes */
317 PkgLen.Len = Op->Asl.AmlSubtreeLength + Op->Asl.AmlPkgLenBytes;
321 /* Does this opcode have an associated "PackageLength" field? */
323 if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
325 if (Op->Asl.AmlPkgLenBytes == 1)
327 /* Simplest case -- no bytes to follow, just write the count */
329 CgLocalWriteAmlData (Op, &PkgLen.LenBytes[0], 1);
331 else if (Op->Asl.AmlPkgLenBytes != 0)
334 * Encode the "bytes to follow" in the first byte, top two bits.
335 * The low-order nybble of the length is in the bottom 4 bits
337 PkgLenFirstByte = (UINT8)
338 (((UINT32) (Op->Asl.AmlPkgLenBytes - 1) << 6) |
339 (PkgLen.LenBytes[0] & 0x0F));
341 CgLocalWriteAmlData (Op, &PkgLenFirstByte, 1);
344 * Shift the length over by the 4 bits we just stuffed
349 /* Now we can write the remaining bytes - either 1, 2, or 3 bytes */
351 for (i = 0; i < (UINT32) (Op->Asl.AmlPkgLenBytes - 1); i++)
353 CgLocalWriteAmlData (Op, &PkgLen.LenBytes[i], 1);
362 CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 1);
367 CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 2);
372 CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 4);
377 CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, 8);
382 CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
386 /* All data opcodes must appear above */
392 /*******************************************************************************
394 * FUNCTION: CgWriteTableHeader
396 * PARAMETERS: Op - The DEFINITIONBLOCK node
400 * DESCRIPTION: Write a table header corresponding to the DEFINITIONBLOCK
402 ******************************************************************************/
406 ACPI_PARSE_OBJECT *Op)
408 ACPI_PARSE_OBJECT *Child;
413 Child = Op->Asl.Child;
417 Child = Child->Asl.Next;
418 strncpy (TableHeader.Signature, Child->Asl.Value.String, 4);
422 Child = Child->Asl.Next;
423 TableHeader.Revision = (UINT8) Child->Asl.Value.Integer;
425 /* Command-line Revision override */
427 if (Gbl_RevisionOverride)
429 TableHeader.Revision = Gbl_RevisionOverride;
434 Child = Child->Asl.Next;
435 strncpy (TableHeader.OemId, Child->Asl.Value.String, 6);
439 Child = Child->Asl.Next;
440 strncpy (TableHeader.OemTableId, Child->Asl.Value.String, 8);
444 Child = Child->Asl.Next;
445 TableHeader.OemRevision = (UINT32) Child->Asl.Value.Integer;
449 strncpy (TableHeader.AslCompilerId, ASL_CREATOR_ID, 4);
451 /* Compiler version */
453 TableHeader.AslCompilerRevision = ASL_REVISION;
455 /* Table length. Checksum zero for now, will rewrite later */
457 TableHeader.Length = Gbl_TableLength;
458 TableHeader.Checksum = 0;
460 CgLocalWriteAmlData (Op, &TableHeader, sizeof (ACPI_TABLE_HEADER));
464 /*******************************************************************************
466 * FUNCTION: CgCloseTable
472 * DESCRIPTION: Complete the ACPI table by calculating the checksum and
473 * re-writing the header.
475 ******************************************************************************/
485 FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
488 /* Calculate the checksum over the entire file */
490 while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1) == AE_OK)
492 Sum = (signed char) (Sum + FileByte);
495 /* Re-write the table header with the checksum */
497 TableHeader.Checksum = (UINT8) (0 - Sum);
499 FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
500 CgLocalWriteAmlData (NULL, &TableHeader, sizeof (ACPI_TABLE_HEADER));
504 /*******************************************************************************
506 * FUNCTION: CgWriteNode
508 * PARAMETERS: Op - Parse node to write.
512 * DESCRIPTION: Write the AML that corresponds to a parse node.
514 ******************************************************************************/
518 ACPI_PARSE_OBJECT *Op)
520 ASL_RESOURCE_NODE *Rnode;
523 /* Always check for DEFAULT_ARG and other "Noop" nodes */
524 /* TBD: this may not be the best place for this check */
526 if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) ||
527 (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) ||
528 (Op->Asl.ParseOpcode == PARSEOP_INCLUDE) ||
529 (Op->Asl.ParseOpcode == PARSEOP_INCLUDE_END))
534 Op->Asl.FinalAmlLength = 0;
536 switch (Op->Asl.AmlOpcode)
538 case AML_RAW_DATA_BYTE:
539 case AML_RAW_DATA_WORD:
540 case AML_RAW_DATA_DWORD:
541 case AML_RAW_DATA_QWORD:
543 CgLocalWriteAmlData (Op, &Op->Asl.Value.Integer, Op->Asl.AmlLength);
547 case AML_RAW_DATA_BUFFER:
549 CgLocalWriteAmlData (Op, Op->Asl.Value.Buffer, Op->Asl.AmlLength);
553 case AML_RAW_DATA_CHAIN:
555 Rnode = ACPI_CAST_PTR (ASL_RESOURCE_NODE, Op->Asl.Value.Buffer);
558 CgLocalWriteAmlData (Op, Rnode->Buffer, Rnode->BufferLength);
564 /* Internal data opcodes must all appear above */
568 switch (Op->Asl.ParseOpcode)
570 case PARSEOP_DEFAULT_ARG:
574 case PARSEOP_DEFINITIONBLOCK:
576 CgWriteTableHeader (Op);
579 case PARSEOP_NAMESEG:
580 case PARSEOP_NAMESTRING:
581 case PARSEOP_METHODCALL:
583 CgLocalWriteAmlData (Op, Op->Asl.Value.String, Op->Asl.AmlLength);
588 CgWriteAmlOpcode (Op);