1 /******************************************************************************
3 * Module Name: asllength - Tree walk to determine package and opcode lengths
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2013, 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.
45 #include "aslcompiler.h"
46 #include "aslcompiler.y.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
+= (Op
->Asl
.AmlLength
+
137 Op
->Asl
.AmlOpcodeLength
+
138 Op
->Asl
.AmlPkgLenBytes
+
139 Op
->Asl
.AmlSubtreeLength
);
145 /*******************************************************************************
147 * FUNCTION: CgGetPackageLenByteCount
149 * PARAMETERS: Op - Parse node
150 * PackageLength - Length to be encoded
152 * RETURN: Required length of the package length encoding
154 * DESCRIPTION: Calculate the number of bytes required to encode the given
157 ******************************************************************************/
160 CgGetPackageLenByteCount (
161 ACPI_PARSE_OBJECT
*Op
,
162 UINT32 PackageLength
)
166 * Determine the number of bytes required to encode the package length
167 * Note: the package length includes the number of bytes used to encode
168 * the package length, so we must account for this also.
170 if (PackageLength
<= (0x0000003F - 1))
174 else if (PackageLength
<= (0x00000FFF - 2))
178 else if (PackageLength
<= (0x000FFFFF - 3))
182 else if (PackageLength
<= (0x0FFFFFFF - 4))
188 /* Fatal error - the package length is too large to encode */
190 AslError (ASL_ERROR
, ASL_MSG_ENCODING_LENGTH
, Op
, NULL
);
197 /*******************************************************************************
199 * FUNCTION: CgGenerateAmlOpcodeLength
201 * PARAMETERS: Op - Parse node whose AML opcode lengths will be
206 * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength
207 * fields for this node.
209 ******************************************************************************/
212 CgGenerateAmlOpcodeLength (
213 ACPI_PARSE_OBJECT
*Op
)
216 /* Check for two-byte opcode */
218 if (Op
->Asl
.AmlOpcode
> 0x00FF)
220 Op
->Asl
.AmlOpcodeLength
= 2;
224 Op
->Asl
.AmlOpcodeLength
= 1;
227 /* Does this opcode have an associated "PackageLength" field? */
229 Op
->Asl
.AmlPkgLenBytes
= 0;
230 if (Op
->Asl
.CompileFlags
& NODE_AML_PACKAGE
)
232 Op
->Asl
.AmlPkgLenBytes
= CgGetPackageLenByteCount (
233 Op
, Op
->Asl
.AmlSubtreeLength
);
236 /* Data opcode lengths are easy */
238 switch (Op
->Asl
.AmlOpcode
)
242 Op
->Asl
.AmlLength
= 1;
247 Op
->Asl
.AmlLength
= 2;
252 Op
->Asl
.AmlLength
= 4;
257 Op
->Asl
.AmlLength
= 8;
262 /* All data opcodes must be above */
268 /*******************************************************************************
270 * FUNCTION: CgGenerateAmlLengths
272 * PARAMETERS: Op - Parse node
276 * DESCRIPTION: Generate internal length fields based on the AML opcode or
279 ******************************************************************************/
282 CgGenerateAmlLengths (
283 ACPI_PARSE_OBJECT
*Op
)
289 switch (Op
->Asl
.AmlOpcode
)
291 case AML_RAW_DATA_BYTE
:
293 Op
->Asl
.AmlOpcodeLength
= 0;
294 Op
->Asl
.AmlLength
= 1;
297 case AML_RAW_DATA_WORD
:
299 Op
->Asl
.AmlOpcodeLength
= 0;
300 Op
->Asl
.AmlLength
= 2;
303 case AML_RAW_DATA_DWORD
:
305 Op
->Asl
.AmlOpcodeLength
= 0;
306 Op
->Asl
.AmlLength
= 4;
309 case AML_RAW_DATA_QWORD
:
311 Op
->Asl
.AmlOpcodeLength
= 0;
312 Op
->Asl
.AmlLength
= 8;
315 case AML_RAW_DATA_BUFFER
:
317 /* Aml length is/was set by creator */
319 Op
->Asl
.AmlOpcodeLength
= 0;
322 case AML_RAW_DATA_CHAIN
:
324 /* Aml length is/was set by creator */
326 Op
->Asl
.AmlOpcodeLength
= 0;
334 switch (Op
->Asl
.ParseOpcode
)
336 case PARSEOP_DEFINITIONBLOCK
:
338 Gbl_TableLength
= sizeof (ACPI_TABLE_HEADER
) +
339 Op
->Asl
.AmlSubtreeLength
;
342 case PARSEOP_NAMESEG
:
344 Op
->Asl
.AmlOpcodeLength
= 0;
345 Op
->Asl
.AmlLength
= 4;
346 Op
->Asl
.ExternalName
= Op
->Asl
.Value
.String
;
349 case PARSEOP_NAMESTRING
:
350 case PARSEOP_METHODCALL
:
352 if (Op
->Asl
.CompileFlags
& NODE_NAME_INTERNALIZED
)
357 Op
->Asl
.AmlOpcodeLength
= 0;
358 Status
= UtInternalizeName (Op
->Asl
.Value
.String
, &Buffer
);
359 if (ACPI_FAILURE (Status
))
361 DbgPrint (ASL_DEBUG_OUTPUT
,
362 "Failure from internalize name %X\n", Status
);
366 Op
->Asl
.ExternalName
= Op
->Asl
.Value
.String
;
367 Op
->Asl
.Value
.String
= Buffer
;
368 Op
->Asl
.CompileFlags
|= NODE_NAME_INTERNALIZED
;
370 Op
->Asl
.AmlLength
= strlen (Buffer
);
373 * Check for single backslash reference to root,
374 * make it a null terminated string in the AML
376 if (Op
->Asl
.AmlLength
== 1)
378 Op
->Asl
.AmlLength
= 2;
382 case PARSEOP_STRING_LITERAL
:
384 Op
->Asl
.AmlOpcodeLength
= 1;
386 /* Get null terminator */
388 Op
->Asl
.AmlLength
= strlen (Op
->Asl
.Value
.String
) + 1;
391 case PARSEOP_PACKAGE_LENGTH
:
393 Op
->Asl
.AmlOpcodeLength
= 0;
394 Op
->Asl
.AmlPkgLenBytes
= CgGetPackageLenByteCount (Op
,
395 (UINT32
) Op
->Asl
.Value
.Integer
);
398 case PARSEOP_RAW_DATA
:
400 Op
->Asl
.AmlOpcodeLength
= 0;
403 case PARSEOP_DEFAULT_ARG
:
404 case PARSEOP_EXTERNAL
:
405 case PARSEOP_INCLUDE
:
406 case PARSEOP_INCLUDE_END
:
408 /* Ignore the "default arg" nodes, they are extraneous at this point */
414 CgGenerateAmlOpcodeLength (Op
);
420 #ifdef ACPI_OBSOLETE_FUNCTIONS
421 /*******************************************************************************
423 * FUNCTION: LnAdjustLengthToRoot
425 * PARAMETERS: Op - Node whose Length was changed
429 * DESCRIPTION: Change the Subtree length of the given node, and bubble the
430 * change all the way up to the root node. This allows for
431 * last second changes to a package length (for example, if the
432 * package length encoding gets shorter or longer.)
434 ******************************************************************************/
437 LnAdjustLengthToRoot (
438 ACPI_PARSE_OBJECT
*SubtreeOp
,
441 ACPI_PARSE_OBJECT
*Op
;
444 /* Adjust all subtree lengths up to the root */
446 Op
= SubtreeOp
->Asl
.Parent
;
449 Op
->Asl
.AmlSubtreeLength
-= LengthDelta
;
453 /* Adjust the global table length */
455 Gbl_TableLength
-= LengthDelta
;