asllength.c revision 1.1.1.2.2.2 1
2 /******************************************************************************
3 *
4 * Module Name: asllength - Tree walk to determine package and opcode lengths
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000 - 2011, Intel Corp.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
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.
26 *
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.
30 *
31 * NO WARRANTY
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.
43 */
44
45
46 #include "aslcompiler.h"
47 #include "aslcompiler.y.h"
48 #include "amlcode.h"
49
50
51 #define _COMPONENT ACPI_COMPILER
52 ACPI_MODULE_NAME ("asllength")
53
54 /* Local prototypes */
55
56 static UINT8
57 CgGetPackageLenByteCount (
58 ACPI_PARSE_OBJECT *Op,
59 UINT32 PackageLength);
60
61 static void
62 CgGenerateAmlOpcodeLength (
63 ACPI_PARSE_OBJECT *Op);
64
65
66 #ifdef ACPI_OBSOLETE_FUNCTIONS
67 void
68 LnAdjustLengthToRoot (
69 ACPI_PARSE_OBJECT *Op,
70 UINT32 LengthDelta);
71 #endif
72
73
74 /*******************************************************************************
75 *
76 * FUNCTION: LnInitLengthsWalk
77 *
78 * PARAMETERS: ASL_WALK_CALLBACK
79 *
80 * RETURN: Status
81 *
82 * DESCRIPTION: Walk callback to initialize (and re-initialize) the node
83 * subtree length(s) to zero. The Subtree lengths are bubbled
84 * up to the root node in order to get a total AML length.
85 *
86 ******************************************************************************/
87
88 ACPI_STATUS
89 LnInitLengthsWalk (
90 ACPI_PARSE_OBJECT *Op,
91 UINT32 Level,
92 void *Context)
93 {
94
95 Op->Asl.AmlSubtreeLength = 0;
96 return (AE_OK);
97 }
98
99
100 /*******************************************************************************
101 *
102 * FUNCTION: LnPackageLengthWalk
103 *
104 * PARAMETERS: ASL_WALK_CALLBACK
105 *
106 * RETURN: Status
107 *
108 * DESCRIPTION: Walk callback to calculate the total AML length.
109 * 1) Calculate the AML lengths (opcode, package length, etc.) for
110 * THIS node.
111 * 2) Bubbble up all of these lengths to the parent node by summing
112 * them all into the parent subtree length.
113 *
114 * Note: The SubtreeLength represents the total AML length of all child nodes
115 * in all subtrees under a given node. Therefore, once this walk is
116 * complete, the Root Node subtree length is the AML length of the entire
117 * tree (and thus, the entire ACPI table)
118 *
119 ******************************************************************************/
120
121 ACPI_STATUS
122 LnPackageLengthWalk (
123 ACPI_PARSE_OBJECT *Op,
124 UINT32 Level,
125 void *Context)
126 {
127
128 /* Generate the AML lengths for this node */
129
130 CgGenerateAmlLengths (Op);
131
132 /* Bubble up all lengths (this node and all below it) to the parent */
133
134 if ((Op->Asl.Parent) &&
135 (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
136 {
137 Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength +
138 Op->Asl.AmlOpcodeLength +
139 Op->Asl.AmlPkgLenBytes +
140 Op->Asl.AmlSubtreeLength);
141 }
142 return (AE_OK);
143 }
144
145
146 /*******************************************************************************
147 *
148 * FUNCTION: CgGetPackageLenByteCount
149 *
150 * PARAMETERS: Op - Parse node
151 * PackageLength - Length to be encoded
152 *
153 * RETURN: Required length of the package length encoding
154 *
155 * DESCRIPTION: Calculate the number of bytes required to encode the given
156 * package length.
157 *
158 ******************************************************************************/
159
160 static UINT8
161 CgGetPackageLenByteCount (
162 ACPI_PARSE_OBJECT *Op,
163 UINT32 PackageLength)
164 {
165
166 /*
167 * Determine the number of bytes required to encode the package length
168 * Note: the package length includes the number of bytes used to encode
169 * the package length, so we must account for this also.
170 */
171 if (PackageLength <= (0x0000003F - 1))
172 {
173 return (1);
174 }
175 else if (PackageLength <= (0x00000FFF - 2))
176 {
177 return (2);
178 }
179 else if (PackageLength <= (0x000FFFFF - 3))
180 {
181 return (3);
182 }
183 else if (PackageLength <= (0x0FFFFFFF - 4))
184 {
185 return (4);
186 }
187 else
188 {
189 /* Fatal error - the package length is too large to encode */
190
191 AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL);
192 }
193
194 return (0);
195 }
196
197
198 /*******************************************************************************
199 *
200 * FUNCTION: CgGenerateAmlOpcodeLength
201 *
202 * PARAMETERS: Op - Parse node whose AML opcode lengths will be
203 * calculated
204 *
205 * RETURN: None.
206 *
207 * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength
208 * fields for this node.
209 *
210 ******************************************************************************/
211
212 static void
213 CgGenerateAmlOpcodeLength (
214 ACPI_PARSE_OBJECT *Op)
215 {
216
217 /* Check for two-byte opcode */
218
219 if (Op->Asl.AmlOpcode > 0x00FF)
220 {
221 Op->Asl.AmlOpcodeLength = 2;
222 }
223 else
224 {
225 Op->Asl.AmlOpcodeLength = 1;
226 }
227
228 /* Does this opcode have an associated "PackageLength" field? */
229
230 Op->Asl.AmlPkgLenBytes = 0;
231 if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
232 {
233 Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (
234 Op, Op->Asl.AmlSubtreeLength);
235 }
236
237 /* Data opcode lengths are easy */
238
239 switch (Op->Asl.AmlOpcode)
240 {
241 case AML_BYTE_OP:
242
243 Op->Asl.AmlLength = 1;
244 break;
245
246 case AML_WORD_OP:
247
248 Op->Asl.AmlLength = 2;
249 break;
250
251 case AML_DWORD_OP:
252
253 Op->Asl.AmlLength = 4;
254 break;
255
256 case AML_QWORD_OP:
257
258 Op->Asl.AmlLength = 8;
259 break;
260
261 default:
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 break;
331 }
332
333 switch (Op->Asl.ParseOpcode)
334 {
335 case PARSEOP_DEFINITIONBLOCK:
336
337 Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) +
338 Op->Asl.AmlSubtreeLength;
339 break;
340
341 case PARSEOP_NAMESEG:
342
343 Op->Asl.AmlOpcodeLength = 0;
344 Op->Asl.AmlLength = 4;
345 Op->Asl.ExternalName = Op->Asl.Value.String;
346 break;
347
348 case PARSEOP_NAMESTRING:
349 case PARSEOP_METHODCALL:
350
351 if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED)
352 {
353 break;
354 }
355
356 Op->Asl.AmlOpcodeLength = 0;
357 Status = UtInternalizeName (Op->Asl.Value.String, &Buffer);
358 if (ACPI_FAILURE (Status))
359 {
360 DbgPrint (ASL_DEBUG_OUTPUT,
361 "Failure from internalize name %X\n", Status);
362 break;
363 }
364
365 Op->Asl.ExternalName = Op->Asl.Value.String;
366 Op->Asl.Value.String = Buffer;
367 Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED;
368
369 Op->Asl.AmlLength = strlen (Buffer);
370
371 /*
372 * Check for single backslash reference to root,
373 * make it a null terminated string in the AML
374 */
375 if (Op->Asl.AmlLength == 1)
376 {
377 Op->Asl.AmlLength = 2;
378 }
379 break;
380
381 case PARSEOP_STRING_LITERAL:
382
383 Op->Asl.AmlOpcodeLength = 1;
384
385 /* Get null terminator */
386
387 Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1;
388 break;
389
390 case PARSEOP_PACKAGE_LENGTH:
391
392 Op->Asl.AmlOpcodeLength = 0;
393 Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op,
394 (UINT32) Op->Asl.Value.Integer);
395 break;
396
397 case PARSEOP_RAW_DATA:
398
399 Op->Asl.AmlOpcodeLength = 0;
400 break;
401
402 case PARSEOP_DEFAULT_ARG:
403 case PARSEOP_EXTERNAL:
404 case PARSEOP_INCLUDE:
405 case PARSEOP_INCLUDE_END:
406
407 /* Ignore the "default arg" nodes, they are extraneous at this point */
408
409 break;
410
411 default:
412
413 CgGenerateAmlOpcodeLength (Op);
414 break;
415 }
416 }
417
418
419 #ifdef ACPI_OBSOLETE_FUNCTIONS
420 /*******************************************************************************
421 *
422 * FUNCTION: LnAdjustLengthToRoot
423 *
424 * PARAMETERS: Op - Node whose Length was changed
425 *
426 * RETURN: None.
427 *
428 * DESCRIPTION: Change the Subtree length of the given node, and bubble the
429 * change all the way up to the root node. This allows for
430 * last second changes to a package length (for example, if the
431 * package length encoding gets shorter or longer.)
432 *
433 ******************************************************************************/
434
435 void
436 LnAdjustLengthToRoot (
437 ACPI_PARSE_OBJECT *SubtreeOp,
438 UINT32 LengthDelta)
439 {
440 ACPI_PARSE_OBJECT *Op;
441
442
443 /* Adjust all subtree lengths up to the root */
444
445 Op = SubtreeOp->Asl.Parent;
446 while (Op)
447 {
448 Op->Asl.AmlSubtreeLength -= LengthDelta;
449 Op = Op->Asl.Parent;
450 }
451
452 /* Adjust the global table length */
453
454 Gbl_TableLength -= LengthDelta;
455 }
456 #endif
457
458
459