1 /******************************************************************************
3 * Module Name: asllength - Tree walk to determine package and opcode lengths
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2017, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
47 #include "acconvert.h"
50 #define _COMPONENT ACPI_COMPILER
51 ACPI_MODULE_NAME ("asllength")
53 /* Local prototypes */
56 CgGetPackageLenByteCount (
57 ACPI_PARSE_OBJECT *Op,
58 UINT32 PackageLength);
61 CgGenerateAmlOpcodeLength (
62 ACPI_PARSE_OBJECT *Op);
65 #ifdef ACPI_OBSOLETE_FUNCTIONS
67 LnAdjustLengthToRoot (
68 ACPI_PARSE_OBJECT *Op,
73 /*******************************************************************************
75 * FUNCTION: LnInitLengthsWalk
77 * PARAMETERS: ASL_WALK_CALLBACK
81 * DESCRIPTION: Walk callback to initialize (and re-initialize) the node
82 * subtree length(s) to zero. The Subtree lengths are bubbled
83 * up to the root node in order to get a total AML length.
85 ******************************************************************************/
89 ACPI_PARSE_OBJECT *Op,
94 Op->Asl.AmlSubtreeLength = 0;
99 /*******************************************************************************
101 * FUNCTION: LnPackageLengthWalk
103 * PARAMETERS: ASL_WALK_CALLBACK
107 * DESCRIPTION: Walk callback to calculate the total AML length.
108 * 1) Calculate the AML lengths (opcode, package length, etc.) for
110 * 2) Bubbble up all of these lengths to the parent node by summing
111 * them all into the parent subtree length.
113 * Note: The SubtreeLength represents the total AML length of all child nodes
114 * in all subtrees under a given node. Therefore, once this walk is
115 * complete, the Root Node subtree length is the AML length of the entire
116 * tree (and thus, the entire ACPI table)
118 ******************************************************************************/
121 LnPackageLengthWalk (
122 ACPI_PARSE_OBJECT *Op,
127 /* Generate the AML lengths for this node */
129 CgGenerateAmlLengths (Op);
131 /* Bubble up all lengths (this node and all below it) to the parent */
133 if ((Op->Asl.Parent) &&
134 (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
136 Op->Asl.Parent->Asl.AmlSubtreeLength += (
138 Op->Asl.AmlOpcodeLength +
139 Op->Asl.AmlPkgLenBytes +
140 Op->Asl.AmlSubtreeLength +
141 CvCalculateCommentLengths (Op)
148 /*******************************************************************************
150 * FUNCTION: CgGetPackageLenByteCount
152 * PARAMETERS: Op - Parse node
153 * PackageLength - Length to be encoded
155 * RETURN: Required length of the package length encoding
157 * DESCRIPTION: Calculate the number of bytes required to encode the given
160 ******************************************************************************/
163 CgGetPackageLenByteCount (
164 ACPI_PARSE_OBJECT *Op,
165 UINT32 PackageLength)
169 * Determine the number of bytes required to encode the package length
170 * Note: the package length includes the number of bytes used to encode
171 * the package length, so we must account for this also.
173 if (PackageLength <= (0x0000003F - 1))
177 else if (PackageLength <= (0x00000FFF - 2))
181 else if (PackageLength <= (0x000FFFFF - 3))
185 else if (PackageLength <= (0x0FFFFFFF - 4))
191 /* Fatal error - the package length is too large to encode */
193 AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL);
200 /*******************************************************************************
202 * FUNCTION: CgGenerateAmlOpcodeLength
204 * PARAMETERS: Op - Parse node whose AML opcode lengths will be
209 * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength
210 * fields for this node.
212 ******************************************************************************/
215 CgGenerateAmlOpcodeLength (
216 ACPI_PARSE_OBJECT *Op)
219 /* Check for two-byte opcode */
221 if (Op->Asl.AmlOpcode > 0x00FF)
223 Op->Asl.AmlOpcodeLength = 2;
227 Op->Asl.AmlOpcodeLength = 1;
230 /* Does this opcode have an associated "PackageLength" field? */
232 Op->Asl.AmlPkgLenBytes = 0;
233 if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
235 Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (
236 Op, Op->Asl.AmlSubtreeLength);
239 /* Data opcode lengths are easy */
241 switch (Op->Asl.AmlOpcode)
245 Op->Asl.AmlLength = 1;
250 Op->Asl.AmlLength = 2;
255 Op->Asl.AmlLength = 4;
260 Op->Asl.AmlLength = 8;
265 /* All data opcodes must be above */
271 /*******************************************************************************
273 * FUNCTION: CgGenerateAmlLengths
275 * PARAMETERS: Op - Parse node
279 * DESCRIPTION: Generate internal length fields based on the AML opcode or
282 ******************************************************************************/
285 CgGenerateAmlLengths (
286 ACPI_PARSE_OBJECT *Op)
292 switch (Op->Asl.AmlOpcode)
294 case AML_RAW_DATA_BYTE:
296 Op->Asl.AmlOpcodeLength = 0;
297 Op->Asl.AmlLength = 1;
300 case AML_RAW_DATA_WORD:
302 Op->Asl.AmlOpcodeLength = 0;
303 Op->Asl.AmlLength = 2;
306 case AML_RAW_DATA_DWORD:
308 Op->Asl.AmlOpcodeLength = 0;
309 Op->Asl.AmlLength = 4;
312 case AML_RAW_DATA_QWORD:
314 Op->Asl.AmlOpcodeLength = 0;
315 Op->Asl.AmlLength = 8;
318 case AML_RAW_DATA_BUFFER:
320 /* Aml length is/was set by creator */
322 Op->Asl.AmlOpcodeLength = 0;
325 case AML_RAW_DATA_CHAIN:
327 /* Aml length is/was set by creator */
329 Op->Asl.AmlOpcodeLength = 0;
337 switch (Op->Asl.ParseOpcode)
339 case PARSEOP_DEFINITION_BLOCK:
341 Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) + Op->Asl.AmlSubtreeLength;
344 case PARSEOP_NAMESEG:
346 Op->Asl.AmlOpcodeLength = 0;
347 Op->Asl.AmlLength = 4;
348 Op->Asl.ExternalName = Op->Asl.Value.String;
351 case PARSEOP_NAMESTRING:
352 case PARSEOP_METHODCALL:
354 if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED)
359 Op->Asl.AmlOpcodeLength = 0;
360 Status = UtInternalizeName (Op->Asl.Value.String, &Buffer);
361 if (ACPI_FAILURE (Status))
363 DbgPrint (ASL_DEBUG_OUTPUT,
364 "Failure from internalize name %X\n", Status);
368 Op->Asl.ExternalName = Op->Asl.Value.String;
369 Op->Asl.Value.String = Buffer;
370 Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED;
371 Op->Asl.AmlLength = strlen (Buffer);
374 * Check for single backslash reference to root,
375 * make it a null terminated string in the AML
377 if (Op->Asl.AmlLength == 1)
379 Op->Asl.AmlLength = 2;
383 case PARSEOP_STRING_LITERAL:
385 Op->Asl.AmlOpcodeLength = 1;
387 /* Get null terminator */
389 Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1;
392 case PARSEOP_PACKAGE_LENGTH:
394 Op->Asl.AmlOpcodeLength = 0;
395 Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op,
396 (UINT32) Op->Asl.Value.Integer);
399 case PARSEOP_RAW_DATA:
401 Op->Asl.AmlOpcodeLength = 0;
404 case PARSEOP_DEFAULT_ARG:
405 case PARSEOP_INCLUDE:
406 case PARSEOP_INCLUDE_END:
408 /* Ignore the "default arg" nodes, they are extraneous at this point */
412 case PARSEOP_EXTERNAL:
414 if (Gbl_DoExternals == TRUE)
416 CgGenerateAmlOpcodeLength (Op);
422 CgGenerateAmlOpcodeLength (Op);
428 #ifdef ACPI_OBSOLETE_FUNCTIONS
429 /*******************************************************************************
431 * FUNCTION: LnAdjustLengthToRoot
433 * PARAMETERS: Op - Node whose Length was changed
437 * DESCRIPTION: Change the Subtree length of the given node, and bubble the
438 * change all the way up to the root node. This allows for
439 * last second changes to a package length (for example, if the
440 * package length encoding gets shorter or longer.)
442 ******************************************************************************/
445 LnAdjustLengthToRoot (
446 ACPI_PARSE_OBJECT *SubtreeOp,
449 ACPI_PARSE_OBJECT *Op;
452 /* Adjust all subtree lengths up to the root */
454 Op = SubtreeOp->Asl.Parent;
457 Op->Asl.AmlSubtreeLength -= LengthDelta;
461 /* Adjust the global table length */
463 Gbl_TableLength -= LengthDelta;