asllength.c revision 245582
1145557Sharti/******************************************************************************
2145557Sharti *
3145557Sharti * Module Name: asllength - Tree walk to determine package and opcode lengths
4145557Sharti *
5145557Sharti *****************************************************************************/
6145557Sharti
7145557Sharti/*
8145557Sharti * Copyright (C) 2000 - 2013, Intel Corp.
9145557Sharti * All rights reserved.
10145557Sharti *
11145557Sharti * Redistribution and use in source and binary forms, with or without
12145557Sharti * modification, are permitted provided that the following conditions
13145557Sharti * are met:
14145557Sharti * 1. Redistributions of source code must retain the above copyright
15145557Sharti *    notice, this list of conditions, and the following disclaimer,
16145557Sharti *    without modification.
17145557Sharti * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18145557Sharti *    substantially similar to the "NO WARRANTY" disclaimer below
19145557Sharti *    ("Disclaimer") and any redistribution must be conditioned upon
20145557Sharti *    including a substantially similar Disclaimer requirement for further
21145557Sharti *    binary redistribution.
22145557Sharti * 3. Neither the names of the above-listed copyright holders nor the names
23145557Sharti *    of any contributors may be used to endorse or promote products derived
24145557Sharti *    from this software without specific prior written permission.
25145557Sharti *
26145557Sharti * Alternatively, this software may be distributed under the terms of the
27145557Sharti * GNU General Public License ("GPL") version 2 as published by the Free
28145557Sharti * Software Foundation.
29145557Sharti *
30156066Sharti * NO WARRANTY
31145557Sharti * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32145557Sharti * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33145557Sharti * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34145557Sharti * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35145557Sharti * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36145557Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37145557Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38145557Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39145557Sharti * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40145557Sharti * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41145557Sharti * POSSIBILITY OF SUCH DAMAGES.
42145557Sharti */
43150920Sharti
44145557Sharti
45150920Sharti#include <contrib/dev/acpica/compiler/aslcompiler.h>
46150920Sharti#include "aslcompiler.y.h"
47150920Sharti#include <contrib/dev/acpica/include/amlcode.h>
48145557Sharti
49145557Sharti
50145557Sharti#define _COMPONENT          ACPI_COMPILER
51145557Sharti        ACPI_MODULE_NAME    ("asllength")
52145557Sharti
53145557Sharti/* Local prototypes */
54156066Sharti
55145557Shartistatic UINT8
56145557ShartiCgGetPackageLenByteCount (
57145557Sharti    ACPI_PARSE_OBJECT       *Op,
58145557Sharti    UINT32                  PackageLength);
59145557Sharti
60145557Shartistatic void
61145557ShartiCgGenerateAmlOpcodeLength (
62145557Sharti    ACPI_PARSE_OBJECT       *Op);
63145557Sharti
64145557Sharti
65145557Sharti#ifdef ACPI_OBSOLETE_FUNCTIONS
66145557Shartivoid
67145557ShartiLnAdjustLengthToRoot (
68145557Sharti    ACPI_PARSE_OBJECT       *Op,
69145557Sharti    UINT32                  LengthDelta);
70145557Sharti#endif
71145557Sharti
72145557Sharti
73145557Sharti/*******************************************************************************
74145557Sharti *
75145557Sharti * FUNCTION:    LnInitLengthsWalk
76145557Sharti *
77145557Sharti * PARAMETERS:  ASL_WALK_CALLBACK
78145557Sharti *
79145557Sharti * RETURN:      Status
80145557Sharti *
81145557Sharti * DESCRIPTION: Walk callback to initialize (and re-initialize) the node
82145557Sharti *              subtree length(s) to zero. The Subtree lengths are bubbled
83145557Sharti *              up to the root node in order to get a total AML length.
84145557Sharti *
85145557Sharti ******************************************************************************/
86145557Sharti
87146525ShartiACPI_STATUS
88145557ShartiLnInitLengthsWalk (
89145557Sharti    ACPI_PARSE_OBJECT       *Op,
90145557Sharti    UINT32                  Level,
91145557Sharti    void                    *Context)
92145557Sharti{
93145557Sharti
94145557Sharti    Op->Asl.AmlSubtreeLength = 0;
95145557Sharti    return (AE_OK);
96145557Sharti}
97145557Sharti
98145557Sharti
99145557Sharti/*******************************************************************************
100145557Sharti *
101145557Sharti * FUNCTION:    LnPackageLengthWalk
102145557Sharti *
103145557Sharti * PARAMETERS:  ASL_WALK_CALLBACK
104145557Sharti *
105145557Sharti * RETURN:      Status
106145557Sharti *
107145557Sharti * DESCRIPTION: Walk callback to calculate the total AML length.
108145557Sharti *              1) Calculate the AML lengths (opcode, package length, etc.) for
109145557Sharti *                 THIS node.
110145557Sharti *              2) Bubbble up all of these lengths to the parent node by summing
111145557Sharti *                 them all into the parent subtree length.
112145557Sharti *
113145557Sharti * Note:  The SubtreeLength represents the total AML length of all child nodes
114145557Sharti *        in all subtrees under a given node. Therefore, once this walk is
115146525Sharti *        complete, the Root Node subtree length is the AML length of the entire
116145557Sharti *        tree (and thus, the entire ACPI table)
117145557Sharti *
118145557Sharti ******************************************************************************/
119145557Sharti
120145557ShartiACPI_STATUS
121145557ShartiLnPackageLengthWalk (
122145557Sharti    ACPI_PARSE_OBJECT       *Op,
123145557Sharti    UINT32                  Level,
124145557Sharti    void                    *Context)
125145557Sharti{
126145557Sharti
127145557Sharti    /* Generate the AML lengths for this node */
128145557Sharti
129145557Sharti    CgGenerateAmlLengths (Op);
130145557Sharti
131145557Sharti    /* Bubble up all lengths (this node and all below it) to the parent */
132145557Sharti
133145557Sharti    if ((Op->Asl.Parent) &&
134145557Sharti        (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
135145557Sharti    {
136145557Sharti        Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength +
137145557Sharti                                           Op->Asl.AmlOpcodeLength +
138145557Sharti                                           Op->Asl.AmlPkgLenBytes +
139145557Sharti                                           Op->Asl.AmlSubtreeLength);
140145557Sharti    }
141145557Sharti    return (AE_OK);
142145557Sharti}
143145557Sharti
144145557Sharti
145145557Sharti/*******************************************************************************
146145557Sharti *
147145557Sharti * FUNCTION:    CgGetPackageLenByteCount
148145557Sharti *
149145557Sharti * PARAMETERS:  Op              - Parse node
150145557Sharti *              PackageLength   - Length to be encoded
151145557Sharti *
152145557Sharti * RETURN:      Required length of the package length encoding
153145557Sharti *
154145557Sharti * DESCRIPTION: Calculate the number of bytes required to encode the given
155145557Sharti *              package length.
156145557Sharti *
157145557Sharti ******************************************************************************/
158145557Sharti
159145557Shartistatic UINT8
160145557ShartiCgGetPackageLenByteCount (
161145557Sharti    ACPI_PARSE_OBJECT       *Op,
162145557Sharti    UINT32                  PackageLength)
163145557Sharti{
164145557Sharti
165145557Sharti    /*
166145557Sharti     * Determine the number of bytes required to encode the package length
167145557Sharti     * Note: the package length includes the number of bytes used to encode
168145557Sharti     * the package length, so we must account for this also.
169145557Sharti     */
170145557Sharti    if (PackageLength <= (0x0000003F - 1))
171145557Sharti    {
172145557Sharti        return (1);
173145557Sharti    }
174145557Sharti    else if (PackageLength <= (0x00000FFF - 2))
175145557Sharti    {
176145557Sharti        return (2);
177145557Sharti    }
178145557Sharti    else if (PackageLength <= (0x000FFFFF - 3))
179145557Sharti    {
180145557Sharti        return (3);
181150920Sharti    }
182145557Sharti    else if (PackageLength <= (0x0FFFFFFF - 4))
183145557Sharti    {
184145557Sharti        return (4);
185145557Sharti    }
186145557Sharti    else
187145557Sharti    {
188145557Sharti        /* Fatal error - the package length is too large to encode */
189145557Sharti
190145557Sharti        AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL);
191145557Sharti    }
192145557Sharti
193145557Sharti    return (0);
194145557Sharti}
195145557Sharti
196145557Sharti
197145557Sharti/*******************************************************************************
198145557Sharti *
199145557Sharti * FUNCTION:    CgGenerateAmlOpcodeLength
200145557Sharti *
201145557Sharti * PARAMETERS:  Op          - Parse node whose AML opcode lengths will be
202145557Sharti *                            calculated
203145557Sharti *
204145557Sharti * RETURN:      None.
205145557Sharti *
206145557Sharti * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength
207145557Sharti *              fields for this node.
208145557Sharti *
209145557Sharti ******************************************************************************/
210145557Sharti
211145557Shartistatic void
212145557ShartiCgGenerateAmlOpcodeLength (
213145557Sharti    ACPI_PARSE_OBJECT       *Op)
214145557Sharti{
215145557Sharti
216145557Sharti    /* Check for two-byte opcode */
217145557Sharti
218145557Sharti    if (Op->Asl.AmlOpcode > 0x00FF)
219145557Sharti    {
220145557Sharti        Op->Asl.AmlOpcodeLength = 2;
221145557Sharti    }
222145557Sharti    else
223145557Sharti    {
224145557Sharti        Op->Asl.AmlOpcodeLength = 1;
225145557Sharti    }
226145557Sharti
227145557Sharti    /* Does this opcode have an associated "PackageLength" field? */
228145557Sharti
229145557Sharti    Op->Asl.AmlPkgLenBytes = 0;
230145557Sharti    if (Op->Asl.CompileFlags & NODE_AML_PACKAGE)
231145557Sharti    {
232145557Sharti        Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (
233145557Sharti                                    Op, Op->Asl.AmlSubtreeLength);
234145557Sharti    }
235145557Sharti
236145557Sharti    /* Data opcode lengths are easy */
237145557Sharti
238145557Sharti    switch (Op->Asl.AmlOpcode)
239145557Sharti    {
240145557Sharti    case AML_BYTE_OP:
241145557Sharti
242145557Sharti        Op->Asl.AmlLength = 1;
243145557Sharti        break;
244145557Sharti
245145557Sharti    case AML_WORD_OP:
246145557Sharti
247145557Sharti        Op->Asl.AmlLength = 2;
248145557Sharti        break;
249145557Sharti
250145557Sharti    case AML_DWORD_OP:
251145557Sharti
252145557Sharti        Op->Asl.AmlLength = 4;
253145557Sharti        break;
254145557Sharti
255145557Sharti    case AML_QWORD_OP:
256145557Sharti
257145557Sharti        Op->Asl.AmlLength = 8;
258145557Sharti        break;
259145557Sharti
260145557Sharti    default:
261145557Sharti        /* All data opcodes must be above */
262145557Sharti        break;
263145557Sharti    }
264145557Sharti}
265145557Sharti
266145557Sharti
267145557Sharti/*******************************************************************************
268145557Sharti *
269145557Sharti * FUNCTION:    CgGenerateAmlLengths
270145557Sharti *
271145557Sharti * PARAMETERS:  Op        - Parse node
272145557Sharti *
273145557Sharti * RETURN:      None.
274145557Sharti *
275145557Sharti * DESCRIPTION: Generate internal length fields based on the AML opcode or
276145557Sharti *              parse opcode.
277145557Sharti *
278145557Sharti ******************************************************************************/
279145557Sharti
280145557Shartivoid
281145557ShartiCgGenerateAmlLengths (
282145557Sharti    ACPI_PARSE_OBJECT       *Op)
283145557Sharti{
284145557Sharti    char                    *Buffer;
285145557Sharti    ACPI_STATUS             Status;
286145557Sharti
287145557Sharti
288145557Sharti    switch (Op->Asl.AmlOpcode)
289145557Sharti    {
290145557Sharti    case AML_RAW_DATA_BYTE:
291145557Sharti
292145557Sharti        Op->Asl.AmlOpcodeLength = 0;
293145557Sharti        Op->Asl.AmlLength = 1;
294145557Sharti        return;
295145557Sharti
296145557Sharti    case AML_RAW_DATA_WORD:
297145557Sharti
298145557Sharti        Op->Asl.AmlOpcodeLength = 0;
299145557Sharti        Op->Asl.AmlLength = 2;
300145557Sharti        return;
301145557Sharti
302145557Sharti    case AML_RAW_DATA_DWORD:
303145557Sharti
304145557Sharti        Op->Asl.AmlOpcodeLength = 0;
305145557Sharti        Op->Asl.AmlLength = 4;
306145557Sharti        return;
307145557Sharti
308145557Sharti    case AML_RAW_DATA_QWORD:
309145557Sharti
310145557Sharti        Op->Asl.AmlOpcodeLength = 0;
311145557Sharti        Op->Asl.AmlLength = 8;
312145557Sharti        return;
313145557Sharti
314145557Sharti    case AML_RAW_DATA_BUFFER:
315145557Sharti
316145557Sharti        /* Aml length is/was set by creator */
317145557Sharti
318145557Sharti        Op->Asl.AmlOpcodeLength = 0;
319145557Sharti        return;
320145557Sharti
321145557Sharti    case AML_RAW_DATA_CHAIN:
322145557Sharti
323145557Sharti        /* Aml length is/was set by creator */
324145557Sharti
325145557Sharti        Op->Asl.AmlOpcodeLength = 0;
326145557Sharti        return;
327145557Sharti
328145557Sharti    default:
329145557Sharti        break;
330145557Sharti    }
331145557Sharti
332145557Sharti    switch (Op->Asl.ParseOpcode)
333145557Sharti    {
334145557Sharti    case PARSEOP_DEFINITIONBLOCK:
335145557Sharti
336145557Sharti        Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) +
337145557Sharti                            Op->Asl.AmlSubtreeLength;
338145557Sharti        break;
339145557Sharti
340145557Sharti    case PARSEOP_NAMESEG:
341145557Sharti
342145557Sharti        Op->Asl.AmlOpcodeLength = 0;
343145557Sharti        Op->Asl.AmlLength = 4;
344145557Sharti        Op->Asl.ExternalName = Op->Asl.Value.String;
345145557Sharti        break;
346145557Sharti
347145557Sharti    case PARSEOP_NAMESTRING:
348145557Sharti    case PARSEOP_METHODCALL:
349145557Sharti
350145557Sharti        if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED)
351145557Sharti        {
352145557Sharti            break;
353145557Sharti        }
354145557Sharti
355145557Sharti        Op->Asl.AmlOpcodeLength = 0;
356145557Sharti        Status = UtInternalizeName (Op->Asl.Value.String, &Buffer);
357145557Sharti        if (ACPI_FAILURE (Status))
358145557Sharti        {
359145557Sharti            DbgPrint (ASL_DEBUG_OUTPUT,
360145557Sharti                "Failure from internalize name %X\n", Status);
361145557Sharti            break;
362145557Sharti        }
363145557Sharti
364145557Sharti        Op->Asl.ExternalName = Op->Asl.Value.String;
365145557Sharti        Op->Asl.Value.String = Buffer;
366145557Sharti        Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED;
367145557Sharti
368150920Sharti        Op->Asl.AmlLength = strlen (Buffer);
369145557Sharti
370145557Sharti        /*
371145557Sharti         * Check for single backslash reference to root,
372145557Sharti         * make it a null terminated string in the AML
373145557Sharti         */
374145557Sharti        if (Op->Asl.AmlLength == 1)
375145557Sharti        {
376145557Sharti            Op->Asl.AmlLength = 2;
377145557Sharti        }
378145557Sharti        break;
379145557Sharti
380145557Sharti    case PARSEOP_STRING_LITERAL:
381145557Sharti
382145557Sharti        Op->Asl.AmlOpcodeLength = 1;
383145557Sharti
384145557Sharti        /* Get null terminator */
385145557Sharti
386145557Sharti        Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1;
387145557Sharti        break;
388145557Sharti
389145557Sharti    case PARSEOP_PACKAGE_LENGTH:
390145557Sharti
391145557Sharti        Op->Asl.AmlOpcodeLength = 0;
392145557Sharti        Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op,
393145557Sharti                                    (UINT32) Op->Asl.Value.Integer);
394145557Sharti        break;
395145557Sharti
396145557Sharti    case PARSEOP_RAW_DATA:
397145557Sharti
398145557Sharti        Op->Asl.AmlOpcodeLength = 0;
399145557Sharti        break;
400145557Sharti
401145557Sharti    case PARSEOP_DEFAULT_ARG:
402145557Sharti    case PARSEOP_EXTERNAL:
403145557Sharti    case PARSEOP_INCLUDE:
404145557Sharti    case PARSEOP_INCLUDE_END:
405145557Sharti
406145557Sharti        /* Ignore the "default arg" nodes, they are extraneous at this point */
407145557Sharti
408145557Sharti        break;
409145557Sharti
410145557Sharti    default:
411145557Sharti
412145557Sharti        CgGenerateAmlOpcodeLength (Op);
413145557Sharti        break;
414145557Sharti    }
415145557Sharti}
416145557Sharti
417145557Sharti
418145557Sharti#ifdef ACPI_OBSOLETE_FUNCTIONS
419145557Sharti/*******************************************************************************
420145557Sharti *
421145557Sharti * FUNCTION:    LnAdjustLengthToRoot
422145557Sharti *
423145557Sharti * PARAMETERS:  Op      - Node whose Length was changed
424145557Sharti *
425145557Sharti * RETURN:      None.
426145557Sharti *
427145557Sharti * DESCRIPTION: Change the Subtree length of the given node, and bubble the
428145557Sharti *              change all the way up to the root node. This allows for
429145557Sharti *              last second changes to a package length (for example, if the
430145557Sharti *              package length encoding gets shorter or longer.)
431145557Sharti *
432145557Sharti ******************************************************************************/
433145557Sharti
434145557Shartivoid
435145557ShartiLnAdjustLengthToRoot (
436145557Sharti    ACPI_PARSE_OBJECT       *SubtreeOp,
437145557Sharti    UINT32                  LengthDelta)
438145557Sharti{
439145557Sharti    ACPI_PARSE_OBJECT       *Op;
440150920Sharti
441145557Sharti
442145557Sharti    /* Adjust all subtree lengths up to the root */
443145557Sharti
444145557Sharti    Op = SubtreeOp->Asl.Parent;
445145557Sharti    while (Op)
446145557Sharti    {
447145557Sharti        Op->Asl.AmlSubtreeLength -= LengthDelta;
448145557Sharti        Op = Op->Asl.Parent;
449145557Sharti    }
450145557Sharti
451145557Sharti    /* Adjust the global table length */
452145557Sharti
453145557Sharti    Gbl_TableLength -= LengthDelta;
454145557Sharti}
455145557Sharti#endif
456145557Sharti