asllength.c revision 1.1.1.2.20.1 1 /******************************************************************************
2 *
3 * Module Name: asllength - Tree walk to determine package and opcode lengths
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
25 *
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.
29 *
30 * NO WARRANTY
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.
42 */
43
44
45 #include "aslcompiler.h"
46 #include "aslcompiler.y.h"
47 #include "amlcode.h"
48
49
50 #define _COMPONENT ACPI_COMPILER
51 ACPI_MODULE_NAME ("asllength")
52
53 /* Local prototypes */
54
55 static UINT8
56 CgGetPackageLenByteCount (
57 ACPI_PARSE_OBJECT *Op,
58 UINT32 PackageLength);
59
60 static void
61 CgGenerateAmlOpcodeLength (
62 ACPI_PARSE_OBJECT *Op);
63
64
65 #ifdef ACPI_OBSOLETE_FUNCTIONS
66 void
67 LnAdjustLengthToRoot (
68 ACPI_PARSE_OBJECT *Op,
69 UINT32 LengthDelta);
70 #endif
71
72
73 /*******************************************************************************
74 *
75 * FUNCTION: LnInitLengthsWalk
76 *
77 * PARAMETERS: ASL_WALK_CALLBACK
78 *
79 * RETURN: Status
80 *
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.
84 *
85 ******************************************************************************/
86
87 ACPI_STATUS
88 LnInitLengthsWalk (
89 ACPI_PARSE_OBJECT *Op,
90 UINT32 Level,
91 void *Context)
92 {
93
94 Op->Asl.AmlSubtreeLength = 0;
95 return (AE_OK);
96 }
97
98
99 /*******************************************************************************
100 *
101 * FUNCTION: LnPackageLengthWalk
102 *
103 * PARAMETERS: ASL_WALK_CALLBACK
104 *
105 * RETURN: Status
106 *
107 * DESCRIPTION: Walk callback to calculate the total AML length.
108 * 1) Calculate the AML lengths (opcode, package length, etc.) for
109 * THIS node.
110 * 2) Bubbble up all of these lengths to the parent node by summing
111 * them all into the parent subtree length.
112 *
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)
117 *
118 ******************************************************************************/
119
120 ACPI_STATUS
121 LnPackageLengthWalk (
122 ACPI_PARSE_OBJECT *Op,
123 UINT32 Level,
124 void *Context)
125 {
126
127 /* Generate the AML lengths for this node */
128
129 CgGenerateAmlLengths (Op);
130
131 /* Bubble up all lengths (this node and all below it) to the parent */
132
133 if ((Op->Asl.Parent) &&
134 (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
135 {
136 Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength +
137 Op->Asl.AmlOpcodeLength +
138 Op->Asl.AmlPkgLenBytes +
139 Op->Asl.AmlSubtreeLength);
140 }
141 return (AE_OK);
142 }
143
144
145 /*******************************************************************************
146 *
147 * FUNCTION: CgGetPackageLenByteCount
148 *
149 * PARAMETERS: Op - Parse node
150 * PackageLength - Length to be encoded
151 *
152 * RETURN: Required length of the package length encoding
153 *
154 * DESCRIPTION: Calculate the number of bytes required to encode the given
155 * package length.
156 *
157 ******************************************************************************/
158
159 static UINT8
160 CgGetPackageLenByteCount (
161 ACPI_PARSE_OBJECT *Op,
162 UINT32 PackageLength)
163 {
164
165 /*
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.
169 */
170 if (PackageLength <= (0x0000003F - 1))
171 {
172 return (1);
173 }
174 else if (PackageLength <= (0x00000FFF - 2))
175 {
176 return (2);
177 }
178 else if (PackageLength <= (0x000FFFFF - 3))
179 {
180 return (3);
181 }
182 else if (PackageLength <= (0x0FFFFFFF - 4))
183 {
184 return (4);
185 }
186 else
187 {
188 /* Fatal error - the package length is too large to encode */
189
190 AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL);
191 }
192
193 return (0);
194 }
195
196
197 /*******************************************************************************
198 *
199 * FUNCTION: CgGenerateAmlOpcodeLength
200 *
201 * PARAMETERS: Op - Parse node whose AML opcode lengths will be
202 * calculated
203 *
204 * RETURN: None.
205 *
206 * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength
207 * fields for this node.
208 *
209 ******************************************************************************/
210
211 static void
212 CgGenerateAmlOpcodeLength (
213 ACPI_PARSE_OBJECT *Op)
214 {
215
216 /* Check for two-byte opcode */
217
218 if (Op->Asl.AmlOpcode > 0x00FF)
219 {
220 Op->Asl.AmlOpcodeLength = 2;
221 }
222 else
223 {
224 Op->Asl.AmlOpcodeLength = 1;
225 }
226
227 /* Does this opcode have an associated "PackageLength" field? */
228
229 Op->Asl.AmlPkgLenBytes = 0;
230 if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
231 {
232 Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (
233 Op, Op->Asl.AmlSubtreeLength);
234 }
235
236 /* Data opcode lengths are easy */
237
238 switch (Op->Asl.AmlOpcode)
239 {
240 case AML_BYTE_OP:
241
242 Op->Asl.AmlLength = 1;
243 break;
244
245 case AML_WORD_OP:
246
247 Op->Asl.AmlLength = 2;
248 break;
249
250 case AML_DWORD_OP:
251
252 Op->Asl.AmlLength = 4;
253 break;
254
255 case AML_QWORD_OP:
256
257 Op->Asl.AmlLength = 8;
258 break;
259
260 default:
261
262 /* All data opcodes must be above */
263 break;
264 }
265 }
266
267
268 /*******************************************************************************
269 *
270 * FUNCTION: CgGenerateAmlLengths
271 *
272 * PARAMETERS: Op - Parse node
273 *
274 * RETURN: None.
275 *
276 * DESCRIPTION: Generate internal length fields based on the AML opcode or
277 * parse opcode.
278 *
279 ******************************************************************************/
280
281 void
282 CgGenerateAmlLengths (
283 ACPI_PARSE_OBJECT *Op)
284 {
285 char *Buffer;
286 ACPI_STATUS Status;
287
288
289 switch (Op->Asl.AmlOpcode)
290 {
291 case AML_RAW_DATA_BYTE:
292
293 Op->Asl.AmlOpcodeLength = 0;
294 Op->Asl.AmlLength = 1;
295 return;
296
297 case AML_RAW_DATA_WORD:
298
299 Op->Asl.AmlOpcodeLength = 0;
300 Op->Asl.AmlLength = 2;
301 return;
302
303 case AML_RAW_DATA_DWORD:
304
305 Op->Asl.AmlOpcodeLength = 0;
306 Op->Asl.AmlLength = 4;
307 return;
308
309 case AML_RAW_DATA_QWORD:
310
311 Op->Asl.AmlOpcodeLength = 0;
312 Op->Asl.AmlLength = 8;
313 return;
314
315 case AML_RAW_DATA_BUFFER:
316
317 /* Aml length is/was set by creator */
318
319 Op->Asl.AmlOpcodeLength = 0;
320 return;
321
322 case AML_RAW_DATA_CHAIN:
323
324 /* Aml length is/was set by creator */
325
326 Op->Asl.AmlOpcodeLength = 0;
327 return;
328
329 default:
330
331 break;
332 }
333
334 switch (Op->Asl.ParseOpcode)
335 {
336 case PARSEOP_DEFINITIONBLOCK:
337
338 Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) +
339 Op->Asl.AmlSubtreeLength;
340 break;
341
342 case PARSEOP_NAMESEG:
343
344 Op->Asl.AmlOpcodeLength = 0;
345 Op->Asl.AmlLength = 4;
346 Op->Asl.ExternalName = Op->Asl.Value.String;
347 break;
348
349 case PARSEOP_NAMESTRING:
350 case PARSEOP_METHODCALL:
351
352 if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED)
353 {
354 break;
355 }
356
357 Op->Asl.AmlOpcodeLength = 0;
358 Status = UtInternalizeName (Op->Asl.Value.String, &Buffer);
359 if (ACPI_FAILURE (Status))
360 {
361 DbgPrint (ASL_DEBUG_OUTPUT,
362 "Failure from internalize name %X\n", Status);
363 break;
364 }
365
366 Op->Asl.ExternalName = Op->Asl.Value.String;
367 Op->Asl.Value.String = Buffer;
368 Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED;
369
370 Op->Asl.AmlLength = strlen (Buffer);
371
372 /*
373 * Check for single backslash reference to root,
374 * make it a null terminated string in the AML
375 */
376 if (Op->Asl.AmlLength == 1)
377 {
378 Op->Asl.AmlLength = 2;
379 }
380 break;
381
382 case PARSEOP_STRING_LITERAL:
383
384 Op->Asl.AmlOpcodeLength = 1;
385
386 /* Get null terminator */
387
388 Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1;
389 break;
390
391 case PARSEOP_PACKAGE_LENGTH:
392
393 Op->Asl.AmlOpcodeLength = 0;
394 Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op,
395 (UINT32) Op->Asl.Value.Integer);
396 break;
397
398 case PARSEOP_RAW_DATA:
399
400 Op->Asl.AmlOpcodeLength = 0;
401 break;
402
403 case PARSEOP_DEFAULT_ARG:
404 case PARSEOP_EXTERNAL:
405 case PARSEOP_INCLUDE:
406 case PARSEOP_INCLUDE_END:
407
408 /* Ignore the "default arg" nodes, they are extraneous at this point */
409
410 break;
411
412 default:
413
414 CgGenerateAmlOpcodeLength (Op);
415 break;
416 }
417 }
418
419
420 #ifdef ACPI_OBSOLETE_FUNCTIONS
421 /*******************************************************************************
422 *
423 * FUNCTION: LnAdjustLengthToRoot
424 *
425 * PARAMETERS: Op - Node whose Length was changed
426 *
427 * RETURN: None.
428 *
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.)
433 *
434 ******************************************************************************/
435
436 void
437 LnAdjustLengthToRoot (
438 ACPI_PARSE_OBJECT *SubtreeOp,
439 UINT32 LengthDelta)
440 {
441 ACPI_PARSE_OBJECT *Op;
442
443
444 /* Adjust all subtree lengths up to the root */
445
446 Op = SubtreeOp->Asl.Parent;
447 while (Op)
448 {
449 Op->Asl.AmlSubtreeLength -= LengthDelta;
450 Op = Op->Asl.Parent;
451 }
452
453 /* Adjust the global table length */
454
455 Gbl_TableLength -= LengthDelta;
456 }
457 #endif
458