]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/dev/acpica/compiler/asllength.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / dev / acpica / compiler / asllength.c
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 <contrib/dev/acpica/compiler/aslcompiler.h>
46 #include "aslcompiler.y.h"
47 #include <contrib/dev/acpica/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