Merge branch 'vendor/OPENSSL'
[dragonfly.git] / sys / contrib / dev / acpica / source / 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 - 2016, 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 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47
48
49 #define _COMPONENT          ACPI_COMPILER
50         ACPI_MODULE_NAME    ("asllength")
51
52 /* Local prototypes */
53
54 static UINT8
55 CgGetPackageLenByteCount (
56     ACPI_PARSE_OBJECT       *Op,
57     UINT32                  PackageLength);
58
59 static void
60 CgGenerateAmlOpcodeLength (
61     ACPI_PARSE_OBJECT       *Op);
62
63
64 #ifdef ACPI_OBSOLETE_FUNCTIONS
65 void
66 LnAdjustLengthToRoot (
67     ACPI_PARSE_OBJECT       *Op,
68     UINT32                  LengthDelta);
69 #endif
70
71
72 /*******************************************************************************
73  *
74  * FUNCTION:    LnInitLengthsWalk
75  *
76  * PARAMETERS:  ASL_WALK_CALLBACK
77  *
78  * RETURN:      Status
79  *
80  * DESCRIPTION: Walk callback to initialize (and re-initialize) the node
81  *              subtree length(s) to zero. The Subtree lengths are bubbled
82  *              up to the root node in order to get a total AML length.
83  *
84  ******************************************************************************/
85
86 ACPI_STATUS
87 LnInitLengthsWalk (
88     ACPI_PARSE_OBJECT       *Op,
89     UINT32                  Level,
90     void                    *Context)
91 {
92
93     Op->Asl.AmlSubtreeLength = 0;
94     return (AE_OK);
95 }
96
97
98 /*******************************************************************************
99  *
100  * FUNCTION:    LnPackageLengthWalk
101  *
102  * PARAMETERS:  ASL_WALK_CALLBACK
103  *
104  * RETURN:      Status
105  *
106  * DESCRIPTION: Walk callback to calculate the total AML length.
107  *              1) Calculate the AML lengths (opcode, package length, etc.) for
108  *                 THIS node.
109  *              2) Bubbble up all of these lengths to the parent node by summing
110  *                 them all into the parent subtree length.
111  *
112  * Note:  The SubtreeLength represents the total AML length of all child nodes
113  *        in all subtrees under a given node. Therefore, once this walk is
114  *        complete, the Root Node subtree length is the AML length of the entire
115  *        tree (and thus, the entire ACPI table)
116  *
117  ******************************************************************************/
118
119 ACPI_STATUS
120 LnPackageLengthWalk (
121     ACPI_PARSE_OBJECT       *Op,
122     UINT32                  Level,
123     void                    *Context)
124 {
125
126     /* Generate the AML lengths for this node */
127
128     CgGenerateAmlLengths (Op);
129
130     /* Bubble up all lengths (this node and all below it) to the parent */
131
132     if ((Op->Asl.Parent) &&
133         (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
134     {
135         Op->Asl.Parent->Asl.AmlSubtreeLength += (
136             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_DEFINITION_BLOCK:
337
338         Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) + 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         Op->Asl.AmlLength = strlen (Buffer);
369
370         /*
371          * Check for single backslash reference to root,
372          * make it a null terminated string in the AML
373          */
374         if (Op->Asl.AmlLength == 1)
375         {
376             Op->Asl.AmlLength = 2;
377         }
378         break;
379
380     case PARSEOP_STRING_LITERAL:
381
382         Op->Asl.AmlOpcodeLength = 1;
383
384         /* Get null terminator */
385
386         Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1;
387         break;
388
389     case PARSEOP_PACKAGE_LENGTH:
390
391         Op->Asl.AmlOpcodeLength = 0;
392         Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op,
393             (UINT32) Op->Asl.Value.Integer);
394         break;
395
396     case PARSEOP_RAW_DATA:
397
398         Op->Asl.AmlOpcodeLength = 0;
399         break;
400
401     case PARSEOP_DEFAULT_ARG:
402     case PARSEOP_EXTERNAL:
403     case PARSEOP_INCLUDE:
404     case PARSEOP_INCLUDE_END:
405
406         /* Ignore the "default arg" nodes, they are extraneous at this point */
407
408         break;
409
410     default:
411
412         CgGenerateAmlOpcodeLength (Op);
413         break;
414     }
415 }
416
417
418 #ifdef ACPI_OBSOLETE_FUNCTIONS
419 /*******************************************************************************
420  *
421  * FUNCTION:    LnAdjustLengthToRoot
422  *
423  * PARAMETERS:  Op      - Node whose Length was changed
424  *
425  * RETURN:      None.
426  *
427  * DESCRIPTION: Change the Subtree length of the given node, and bubble the
428  *              change all the way up to the root node. This allows for
429  *              last second changes to a package length (for example, if the
430  *              package length encoding gets shorter or longer.)
431  *
432  ******************************************************************************/
433
434 void
435 LnAdjustLengthToRoot (
436     ACPI_PARSE_OBJECT       *SubtreeOp,
437     UINT32                  LengthDelta)
438 {
439     ACPI_PARSE_OBJECT       *Op;
440
441
442     /* Adjust all subtree lengths up to the root */
443
444     Op = SubtreeOp->Asl.Parent;
445     while (Op)
446     {
447         Op->Asl.AmlSubtreeLength -= LengthDelta;
448         Op = Op->Asl.Parent;
449     }
450
451     /* Adjust the global table length */
452
453     Gbl_TableLength -= LengthDelta;
454 }
455 #endif